Matter SDK Coverage Report
Current view: top level - system - SystemLayer.h (source / functions) Coverage Total Hit
Test: SHA:e98a48c2e59f85a25417956e1d105721433aa5d1 Lines: 87.5 % 8 7
Test Date: 2026-01-09 16:53:50 Functions: 25.7 % 35 9

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    Copyright (c) 2016-2017 Nest Labs, Inc.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      21              :  *      This file contains declarations of the
      22              :  *      chip::System::Layer class and its related types, data and
      23              :  *      functions.
      24              :  */
      25              : 
      26              : #pragma once
      27              : 
      28              : #include <type_traits>
      29              : #include <utility>
      30              : 
      31              : // Include configuration headers
      32              : #include <system/SystemConfig.h>
      33              : 
      34              : #include <lib/core/CHIPCallback.h>
      35              : #include <lib/core/CriticalFailure.h>
      36              : 
      37              : #include <lib/support/CodeUtils.h>
      38              : #include <lib/support/DLLUtil.h>
      39              : #include <lib/support/LambdaBridge.h>
      40              : #include <system/SystemClock.h>
      41              : #include <system/SystemError.h>
      42              : #include <system/SystemEvent.h>
      43              : 
      44              : #include <lib/support/IntrusiveList.h>
      45              : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
      46              : #include <system/SocketEvents.h>
      47              : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
      48              : 
      49              : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH
      50              : #include <dispatch/dispatch.h>
      51              : #elif CHIP_SYSTEM_CONFIG_USE_LIBEV
      52              : #include <ev.h>
      53              : #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV
      54              : 
      55              : namespace chip {
      56              : namespace System {
      57              : 
      58              : class Layer;
      59              : using TimerCompleteCallback = void (*)(Layer * aLayer, void * appState);
      60              : 
      61              : /**
      62              :  * This provides access to timers according to the configured event handling model.
      63              :  *
      64              :  * The abstract class hierarchy is:
      65              :  * - Layer: Core timer methods.
      66              :  *   - LayerFreeRTOS: Adds methods specific to CHIP_SYSTEM_CONFIG_USING_LWIP and CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT.
      67              :  *   - LayerSockets: Adds I/O event methods specific to CHIP_SYSTEM_CONFIG_USING_SOCKETS.
      68              :  *     - LayerSelectLoop: Adds methods for event-loop-based implementations.
      69              :  *
      70              :  * Threading notes:
      71              :  *
      72              :  * The SDK is not generally thread safe. System::Layer methods should only be called from
      73              :  * a single context, or otherwise externally synchronized. For platforms that use a CHIP
      74              :  * event loop thread, timer callbacks are invoked on that thread; for platforms that use
      75              :  * a CHIP lock, the lock is held.
      76              :  */
      77              : class DLL_EXPORT Layer
      78              : {
      79              : public:
      80          108 :     Layer()          = default;
      81          108 :     virtual ~Layer() = default;
      82              : 
      83              :     /**
      84              :      * Initialize the Layer.
      85              :      */
      86              :     virtual CriticalFailure Init() = 0;
      87              : 
      88              :     /**
      89              :      * Shut down the Layer.
      90              :      *
      91              :      * Some other layers hold pointers to System::Layer, so care must be taken
      92              :      * to ensure that they are not used after calling Shutdown().
      93              :      */
      94              :     virtual void Shutdown() = 0;
      95              : 
      96              :     /**
      97              :      * True if this Layer is initialized. No method on Layer or its abstract descendants, other than this and `Init()`,
      98              :      * may be called from general code unless this is true. (Individual Impls may have looser constraints internally.)
      99              :      */
     100              :     virtual bool IsInitialized() const = 0;
     101              : 
     102              :     /**
     103              :      * @brief
     104              :      *   This method starts a one-shot timer.  This method must be called while in the Matter context (from
     105              :      *   the Matter event loop, or while holding the Matter stack lock).
     106              :      *
     107              :      *   @note
     108              :      *       Only a single timer is allowed to be started with the same @a aComplete and @a aAppState
     109              :      *       arguments. If called with @a aComplete and @a aAppState identical to an existing timer,
     110              :      *       the currently-running timer will first be cancelled.
     111              :      *
     112              :      *   @param[in]  aDelay             Time before this timer fires.
     113              :      *   @param[in]  aComplete          A pointer to the function called when timer expires.
     114              :      *   @param[in]  aAppState          A pointer to the application state object used when timer expires.
     115              :      *
     116              :      *   @return CHIP_NO_ERROR On success.
     117              :      *   @return CHIP_ERROR_NO_MEMORY If a timer cannot be allocated.
     118              :      *   @return Other Value indicating timer failed to start.
     119              :      */
     120              :     virtual CriticalFailure StartTimer(Clock::Timeout aDelay, TimerCompleteCallback aComplete, void * aAppState) = 0;
     121              : 
     122              :     /**
     123              :      * @brief
     124              :      *   This method extends the timer expiry to the provided aDelay. This method must be called while in the Matter context
     125              :      *   (from the Matter event loop, or while holding the Matter stack lock).
     126              :      *   aDelay is not added to the Remaining time of the timer. The finish line is pushed back to aDelay.
     127              :      *
     128              :      *   @note The goal of this method is that the timer remaining time cannot be shrunk and only extended to a new time
     129              :      *         If the provided new Delay is smaller than the timer's remaining time, the timer is left untouched.
     130              :      *         In the other case the method acts like StartTimer
     131              :      *
     132              :      *   @param[in]  aDelay             Time before this timer fires.
     133              :      *   @param[in]  aComplete          A pointer to the function called when timer expires.
     134              :      *   @param[in]  aAppState          A pointer to the application state object used when timer expires.
     135              :      *
     136              :      *   @return CHIP_NO_ERROR On success.
     137              :      *   @return CHIP_ERROR_INVALID_ARGUMENT If the provided aDelay value is 0
     138              :      *   @return CHIP_ERROR_NO_MEMORY If a timer cannot be allocated.
     139              :      *   @return Other Value indicating timer failed to start.
     140              :      */
     141              :     virtual CHIP_ERROR ExtendTimerTo(Clock::Timeout aDelay, TimerCompleteCallback aComplete, void * aAppState) = 0;
     142              : 
     143              :     /**
     144              :      * @brief
     145              :      *   This method searches for the timer matching the provided parameters.
     146              :      *   and returns whether it is still "running" and waiting to trigger or not.
     147              :      *
     148              :      *   @note This is used to verify by how long the ExtendTimer method extends the timer, as it may ignore an extension request
     149              :      *        if it is shorter than the current timer's remaining time.
     150              :      *
     151              :      *   @param[in]  onComplete         A pointer to the function called when timer expires.
     152              :      *   @param[in]  appState           A pointer to the application state object used when timer expires.
     153              :      *
     154              :      *   @return True if there is a current timer set to call, at some point in the future, the provided onComplete callback
     155              :      *           with the corresponding appState context. False otherwise.
     156              :      */
     157              :     virtual bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) = 0;
     158              : 
     159              :     /**
     160              :      * @brief
     161              :      *   This method searches for the timer matching the provided parameters
     162              :      *   and returns the remaining time left before it expires.
     163              :      *   @param[in]  onComplete         A pointer to the function called when timer expires.
     164              :      *   @param[in]  appState           A pointer to the application state object used when timer expires.
     165              :      *
     166              :      *  @return The remaining time left before the timer expires.
     167              :      */
     168              :     virtual Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) = 0;
     169              : 
     170              :     /**
     171              :      * @brief This method cancels a one-shot timer, started earlier through @p StartTimer().  This method must
     172              :      *        be called while in the Matter context (from the Matter event loop, or while holding the Matter
     173              :      *        stack lock).
     174              :      *
     175              :      *   @note
     176              :      *       The cancellation could fail silently if the timer specified by the combination of the callback
     177              :      *       function and application state object couldn't be found.
     178              :      *
     179              :      *   @param[in]  aOnComplete   A pointer to the callback function used in calling @p StartTimer().
     180              :      *   @param[in]  aAppState     A pointer to the application state object used in calling @p StartTimer().
     181              :      *
     182              :      */
     183              :     virtual void CancelTimer(TimerCompleteCallback aOnComplete, void * aAppState) = 0;
     184              : 
     185              :     /**
     186              :      * @brief
     187              :      *   Schedules a `TimerCompleteCallback` to be run as soon as possible in the Matter context.
     188              :      *
     189              :      *  WARNING: This must only be called when already in the Matter context (from the Matter event loop, or
     190              :      *           while holding the Matter stack lock). The `PlatformMgr::ScheduleWork()` equivalent method
     191              :      *           is safe to call outside Matter context.
     192              :      *
     193              :      * @param[in] aComplete     A pointer to a callback function to be called when this timer fires.
     194              :      * @param[in] aAppState     A pointer to an application state object to be passed to the callback function as argument.
     195              :      *
     196              :      * @retval CHIP_ERROR_INCORRECT_STATE   If the System::Layer has not been initialized.
     197              :      * @retval CHIP_ERROR_NO_MEMORY         If the SystemLayer cannot allocate a new timer.
     198              :      * @retval CHIP_NO_ERROR                On success.
     199              :      */
     200              :     virtual CriticalFailure ScheduleWork(TimerCompleteCallback aComplete, void * aAppState) = 0;
     201              : 
     202              :     /**
     203              :      * @brief
     204              :      *   Schedules a lambda object to be run as soon as possible in the Matter context.
     205              :      *
     206              :      * This is safe to call from any context and will guarantee execution in Matter context.
     207              :      * Note that the Lambda's capture have to fit within `CHIP_CONFIG_LAMBDA_EVENT_SIZE` bytes.
     208              :      *
     209              :      * @param[in] lambda The Lambda to execute in Matter context.
     210              :      *
     211              :      * @retval CHIP_NO_ERROR On success.
     212              :      * @retval other Platform-specific errors generated indicating the reason for failure.
     213              :      */
     214              :     template <typename Lambda>
     215           61 :     CriticalFailure ScheduleLambda(const Lambda & lambda)
     216              :     {
     217              :         static_assert(std::is_invocable_v<Lambda>, "lambda argument must be an invocable with no arguments");
     218              :         LambdaBridge bridge;
     219           61 :         bridge.Initialize(lambda);
     220           61 :         return ScheduleLambdaBridge(std::move(bridge));
     221              :     }
     222              : 
     223              : private:
     224              :     CriticalFailure ScheduleLambdaBridge(LambdaBridge && bridge);
     225              : 
     226              :     // Not copyable
     227              :     Layer(const Layer &)             = delete;
     228              :     Layer & operator=(const Layer &) = delete;
     229              : };
     230              : 
     231              : #if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
     232              : 
     233              : class LayerFreeRTOS : public Layer
     234              : {
     235              : };
     236              : 
     237              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
     238              : 
     239              : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
     240              : class LayerSockets : public Layer
     241              : {
     242              : public:
     243              :     /**
     244              :      * Initialize watching for events on a file descriptor.
     245              :      *
     246              :      * Returns an opaque token through @a tokenOut that must be passed to subsequent operations for this file descriptor.
     247              :      * Multiple calls to start watching the same file descriptor will return the same token.
     248              :      * StopWatchingSocket() must be called before closing the file descriptor.
     249              :      */
     250              :     virtual CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut) = 0;
     251              : 
     252              :     /**
     253              :      * Register a callback function.
     254              :      *
     255              :      * The callback will be invoked (with the CHIP stack lock held) when requested event(s) are ready.
     256              :      */
     257              :     virtual CHIP_ERROR SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data) = 0;
     258              : 
     259              :     /**
     260              :      * Request a callback when the associated file descriptor is readable.
     261              :      */
     262              :     virtual CHIP_ERROR RequestCallbackOnPendingRead(SocketWatchToken token) = 0;
     263              : 
     264              :     /**
     265              :      * Request a callback when the associated file descriptor is writable.
     266              :      */
     267              :     virtual CHIP_ERROR RequestCallbackOnPendingWrite(SocketWatchToken token) = 0;
     268              : 
     269              :     /**
     270              :      * Cancel a request for a callback when the associated file descriptor is readable.
     271              :      */
     272              :     virtual CHIP_ERROR ClearCallbackOnPendingRead(SocketWatchToken token) = 0;
     273              : 
     274              :     /**
     275              :      * Cancel a request for a callback when the associated file descriptor is writable.
     276              :      */
     277              :     virtual CHIP_ERROR ClearCallbackOnPendingWrite(SocketWatchToken token) = 0;
     278              : 
     279              :     /**
     280              :      * Stop watching for events on the associated file descriptor.
     281              :      *
     282              :      * This MUST be called before the file descriptor is closed.
     283              :      * It is not necessary to clear callback requests before calling this function.
     284              :      */
     285              :     virtual CHIP_ERROR StopWatchingSocket(SocketWatchToken * tokenInOut) = 0;
     286              : 
     287              :     /**
     288              :      * Return a SocketWatchToken that is guaranteed not to be valid. Clients may use this to initialize variables.
     289              :      */
     290              :     virtual SocketWatchToken InvalidSocketWatchToken() = 0;
     291              : };
     292              : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
     293              : 
     294              : class LayerSelectLoop;
     295              : 
     296              : /**
     297              :  * EventLoopHandlers can be registered with a LayerSelectLoop instance to enable
     298              :  * participation of those handlers in the processing cycle of the event loop. This makes
     299              :  * it possible to implement adapters that allow components utilizing a third-party event
     300              :  * loop API to participate in the Matter event loop, instead of having to run an entirely
     301              :  * separate event loop on another thread.
     302              :  *
     303              :  * Specifically, the `PrepareEvents` and `HandleEvents` methods of registered event loop
     304              :  * handlers will be called from the LayerSelectLoop methods of the same names.
     305              :  *
     306              :  * @see LayerSelectLoop::PrepareEvents
     307              :  * @see LayerSelectLoop::HandleEvents
     308              :  */
     309              : class EventLoopHandler : public chip::IntrusiveListNodeBase<>
     310              : {
     311              : public:
     312            2 :     virtual ~EventLoopHandler() {}
     313              : 
     314              :     /**
     315              :      * Prepares events and returns the next requested wake time.
     316              :      */
     317            0 :     virtual Clock::Timestamp PrepareEvents(Clock::Timestamp now) { return Clock::Timestamp::max(); }
     318              : 
     319              :     /**
     320              :      * Handles / dispatches pending events.
     321              :      * Every call to this method will have been preceded by a call to `PrepareEvents`.
     322              :      */
     323              :     virtual void HandleEvents() = 0;
     324              : 
     325              : private:
     326              :     // mState is provided exclusively for use by the LayerSelectLoop implementation
     327              :     // sub-class and can be accessed by it via the LayerSelectLoop::LoopHandlerState() helper.
     328              :     friend class LayerSelectLoop;
     329              :     intptr_t mState = 0;
     330              : };
     331              : 
     332              : class LayerSelectLoop :
     333              : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
     334              :     public LayerSockets
     335              : #else
     336              :     public Layer
     337              : #endif
     338              : {
     339              : public:
     340              :     virtual void Signal()          = 0;
     341              :     virtual void EventLoopBegins() = 0;
     342              :     virtual void PrepareEvents()   = 0;
     343              :     virtual void WaitForEvents()   = 0;
     344              :     virtual void HandleEvents()    = 0;
     345              :     virtual void EventLoopEnds()   = 0;
     346              : 
     347              :     virtual void AddLoopHandler(EventLoopHandler & handler)    = 0;
     348              :     virtual void RemoveLoopHandler(EventLoopHandler & handler) = 0;
     349              : 
     350              : #if CHIP_SYSTEM_CONFIG_USE_LIBEV
     351              :     virtual void SetLibEvLoop(struct ev_loop * aLibEvLoopP) = 0;
     352              :     virtual struct ev_loop * GetLibEvLoop()                 = 0;
     353              : #endif // CHIP_SYSTEM_CONFIG_USE_LIBEV
     354              : 
     355              : protected:
     356              :     // Expose EventLoopHandler.mState as a non-const reference to sub-classes
     357           12 :     decltype(EventLoopHandler::mState) & LoopHandlerState(EventLoopHandler & handler) { return handler.mState; }
     358              : };
     359              : 
     360              : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH
     361              : class LayerDispatch :
     362              : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
     363              :     public LayerSockets
     364              : #else
     365              :     public Layer
     366              : #endif
     367              : {
     368              : public:
     369              :     virtual void SetDispatchQueue(dispatch_queue_t dispatchQueue)  = 0;
     370              :     virtual dispatch_queue_t GetDispatchQueue()                    = 0;
     371              :     virtual void HandleDispatchQueueEvents(Clock::Timeout timeout) = 0;
     372              : 
     373              :     /**
     374              :      * Schedule a block to run asynchronously.
     375              :      *
     376              :      * @param block The block to be executed.
     377              :      *
     378              :      * @note This method is thread-safe and can be called from any dispatch queue.
     379              :      */
     380              :     virtual CriticalFailure ScheduleWorkWithBlock(dispatch_block_t block)                     = 0;
     381              :     virtual CriticalFailure StartTimerWithBlock(dispatch_block_t block, Clock::Timeout delay) = 0;
     382              : };
     383              : #endif
     384              : 
     385              : } // namespace System
     386              : } // namespace chip
        

Generated by: LCOV version 2.0-1