28
28
#include < system/SystemLayer.h>
29
29
#include < system/SystemLayerImplSelect.h>
30
30
31
+ #include < algorithm>
31
32
#include < errno.h>
32
33
33
34
// Choose an approximation of PTHREAD_NULL if pthread.h doesn't define one.
@@ -370,8 +371,9 @@ CHIP_ERROR LayerImplSelect::StartWatchingSocket(int fd, SocketWatchToken * token
370
371
{
371
372
if (w.mFD == fd)
372
373
{
373
- // Duplicate registration is an error.
374
- return CHIP_ERROR_INVALID_ARGUMENT;
374
+ // Already registered, return the existing token
375
+ *tokenOut = reinterpret_cast <SocketWatchToken>(&w);
376
+ return CHIP_NO_ERROR;
375
377
}
376
378
if ((w.mFD == kInvalidFd ) && (watch == nullptr ))
377
379
{
@@ -608,6 +610,32 @@ SocketEvents LayerImplSelect::SocketEventsFromFDs(int socket, const fd_set & rea
608
610
return res;
609
611
}
610
612
613
+ #if !CHIP_SYSTEM_CONFIG_USE_DISPATCH
614
+ enum : intptr_t
615
+ {
616
+ kLoopHandlerInactive = 0 , // default value for EventLoopHandler::mState
617
+ kLoopHandlerPending ,
618
+ kLoopHandlerActive ,
619
+ };
620
+
621
+ void LayerImplSelect::AddLoopHandler (EventLoopHandler & handler)
622
+ {
623
+ // Add the handler as pending because this method can be called at any point
624
+ // in a PrepareEvents() / WaitForEvents() / HandleEvents() sequence.
625
+ // It will be marked active when we call PrepareEvents() on it for the first time.
626
+ auto & state = LoopHandlerState (handler);
627
+ VerifyOrDie (state == kLoopHandlerInactive );
628
+ state = kLoopHandlerPending ;
629
+ mLoopHandlers .PushBack (&handler);
630
+ }
631
+
632
+ void LayerImplSelect::RemoveLoopHandler (EventLoopHandler & handler)
633
+ {
634
+ mLoopHandlers .Remove (&handler);
635
+ LoopHandlerState (handler) = kLoopHandlerInactive ;
636
+ }
637
+ #endif // !CHIP_SYSTEM_CONFIG_USE_DISPATCH
638
+
611
639
void LayerImplSelect::PrepareEvents ()
612
640
{
613
641
assertChipStackLockedByCurrentThread ();
@@ -616,10 +644,28 @@ void LayerImplSelect::PrepareEvents()
616
644
Clock::Timestamp awakenTime = currentTime + kDefaultMinSleepPeriod ;
617
645
618
646
TimerList::Node * timer = mTimerList .Earliest ();
619
- if (timer && timer->AwakenTime () < awakenTime)
647
+ if (timer)
648
+ {
649
+ awakenTime = std::min (awakenTime, timer->AwakenTime ());
650
+ }
651
+
652
+ #if !CHIP_SYSTEM_CONFIG_USE_DISPATCH
653
+ // Activate added EventLoopHandlers and call PrepareEvents on active handlers.
654
+ auto loopIter = mLoopHandlers .begin ();
655
+ while (loopIter != mLoopHandlers .end ())
620
656
{
621
- awakenTime = timer->AwakenTime ();
657
+ auto & loop = *loopIter++; // advance before calling out, in case a list modification clobbers the `next` pointer
658
+ switch (auto & state = LoopHandlerState (loop))
659
+ {
660
+ case kLoopHandlerPending :
661
+ state = kLoopHandlerActive ;
662
+ [[fallthrough]];
663
+ case kLoopHandlerActive :
664
+ awakenTime = std::min (awakenTime, loop.PrepareEvents (currentTime));
665
+ break ;
666
+ }
622
667
}
668
+ #endif // !CHIP_SYSTEM_CONFIG_USE_DISPATCH
623
669
624
670
const Clock::Timestamp sleepTime = (awakenTime > currentTime) ? (awakenTime - currentTime) : Clock::kZero ;
625
671
Clock::ToTimeval (sleepTime, mNextTimeout );
@@ -683,18 +729,35 @@ void LayerImplSelect::HandleEvents()
683
729
mTimerPool .Invoke (timer);
684
730
}
685
731
686
- for (auto & w : mSocketWatchPool )
732
+ // Process socket events, if any
733
+ if (mSelectResult > 0 )
687
734
{
688
- if (w. mFD != kInvalidFd )
735
+ for ( auto & w : mSocketWatchPool )
689
736
{
690
- SocketEvents events = SocketEventsFromFDs (w.mFD , mSelected .mReadSet , mSelected .mWriteSet , mSelected .mErrorSet );
691
- if (events.HasAny () && w.mCallback != nullptr )
737
+ if (w.mFD != kInvalidFd && w.mCallback != nullptr )
692
738
{
693
- w.mCallback (events, w.mCallbackData );
739
+ SocketEvents events = SocketEventsFromFDs (w.mFD , mSelected .mReadSet , mSelected .mWriteSet , mSelected .mErrorSet );
740
+ if (events.HasAny ())
741
+ {
742
+ w.mCallback (events, w.mCallbackData );
743
+ }
694
744
}
695
745
}
696
746
}
697
747
748
+ #if !CHIP_SYSTEM_CONFIG_USE_DISPATCH
749
+ // Call HandleEvents for active loop handlers
750
+ auto loopIter = mLoopHandlers .begin ();
751
+ while (loopIter != mLoopHandlers .end ())
752
+ {
753
+ auto & loop = *loopIter++; // advance before calling out, in case a list modification clobbers the `next` pointer
754
+ if (LoopHandlerState (loop) == kLoopHandlerActive )
755
+ {
756
+ loop.HandleEvents ();
757
+ }
758
+ }
759
+ #endif // !CHIP_SYSTEM_CONFIG_USE_DISPATCH
760
+
698
761
#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
699
762
mHandleSelectThread = PTHREAD_NULL;
700
763
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING
0 commit comments