Matter SDK Coverage Report
Current view: top level - lib/core - CHIPCallback.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 20.4 % 49 10
Test Date: 2025-01-17 19:00:11 Functions: 21.4 % 28 6

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : /**
      19              :  *  @file
      20              :  *    This file contains definitions for Callback objects for registering with
      21              :  *     Clusters and the Device
      22              :  */
      23              : 
      24              : #pragma once
      25              : 
      26              : #include <stddef.h>
      27              : #include <stdint.h>
      28              : 
      29              : #include <lib/core/CHIPConfig.h>
      30              : 
      31              : namespace chip {
      32              : 
      33              : namespace Callback {
      34              : 
      35              : /**
      36              :  *  @class Cancelable
      37              :  *
      38              :  *    Private members of a Callback for use by subsystems that accept
      39              :  *     Callbacks for event registration/notification.
      40              :  *
      41              :  */
      42              : class Cancelable
      43              : {
      44              :     typedef void (*CancelFn)(Cancelable *);
      45              : 
      46              : public:
      47              :     /**
      48              :      *  @brief for use by Callback callees, i.e. those that accept callbacks for
      49              :      *   event registration.  The names suggest how to use these members, but
      50              :      *   implementations can choose.
      51              :      */
      52              :     Cancelable * mNext;
      53              :     Cancelable * mPrev;
      54              : 
      55              :     // CHIP_CONFIG_CANCELABLE_HAS_INFO_STRING_FIELD allows consumers that were
      56              :     // using this field to opt into having it (and the resulting memory bloat)
      57              :     // while allowing everyone else to save the memory.
      58              : #if CHIP_CONFIG_CANCELABLE_HAS_INFO_STRING_FIELD
      59              :     alignas(uint64_t) char mInfo[24];
      60              : #endif // CHIP_CONFIG_CANCELABLE_HAS_INFO_STRING_FIELD
      61              : 
      62              :     /**
      63              :      * @brief when non-null, indicates the Callback is registered with
      64              :      *   a subsystem and that Cancelable members belong to
      65              :      *   that subsystem
      66              :      */
      67              :     CancelFn mCancel;
      68              : 
      69         4208 :     Cancelable()
      70         4208 :     {
      71         4208 :         mNext = mPrev = this;
      72         4208 :         mCancel       = nullptr;
      73         4208 :     }
      74              : 
      75              :     /**
      76              :      * @brief run whatever function the callee/registrar has specified in order
      77              :      *  to clean up any resource allocation associated with the registration,
      78              :      *  and surrender ownership of the Cancelable's fields
      79              :      */
      80         4208 :     Cancelable * Cancel()
      81              :     {
      82         4208 :         if (mCancel != nullptr)
      83              :         {
      84            0 :             CancelFn cancel = mCancel;
      85            0 :             mCancel         = nullptr;
      86            0 :             cancel(this);
      87              :         }
      88         4208 :         return this;
      89              :     }
      90         4208 :     ~Cancelable() { Cancel(); }
      91              : 
      92              :     Cancelable(const Cancelable &) = delete;
      93              : };
      94              : 
      95              : typedef void (*CallFn)(void *);
      96              : 
      97              : /**
      98              :  *  @class Callback
      99              :  *
     100              :  *    Base struct used for registration of items of interest, includes
     101              :  *     memory for list management and storing information about the registration's
     102              :  *     meaning.  Callback also defines cancellation.
     103              :  *    Callbacks can be registered with exactly one callee at a time. While
     104              :  *     registered (as indicated by a non-null mCancel function), all fields of
     105              :  *     the Callback save usercontext are "owned" by the callee, and should not
     106              :  *     be touched unless Cancel() has first been called.
     107              :  *    When a callee accepts a Callback for registration, step one is always Cancel(),
     108              :  *     in order to take ownership of Cancelable members next, prev, info_ptr, and info_scalar.
     109              :  *    This template class also defines a default notification function prototype.
     110              :  *
     111              :  *   One-shot semantics can be accomplished by calling Cancel() before calling mCall.
     112              :  *     Persistent registration semantics would skip that.
     113              :  *
     114              :  *   There is no provision for queueing data passed as arguments to a Callback's mCall
     115              :  *     function.  If such a thing is required, the normal pattern is to take an output
     116              :  *     parameter at Callback registration time.
     117              :  *
     118              :  */
     119              : template <class T = CallFn>
     120              : class Callback : private Cancelable
     121              : {
     122              : public:
     123              :     /**
     124              :      * pointer to owner context, normally passed to the run function
     125              :      */
     126              :     void * mContext;
     127              : 
     128              :     /**
     129              :      * where to call when the event of interest has occurred
     130              :      */
     131              :     T mCall;
     132              : 
     133              :     /**
     134              :      * Indication that the Callback is registered with a notifier
     135              :      */
     136            0 :     bool IsRegistered() { return (mCancel != nullptr); }
     137              : 
     138              :     /**
     139              :      * Cancel, i.e. de-register interest in the event,
     140              :      * This is the only way to get access to the Cancelable, to enqueue,
     141              :      *  store any per-registration state.
     142              :      * There are 3 primary use cases for this API:
     143              :      *   1. For the owner of the Callback, Cancel() means "where-ever this Callback
     144              :      *       was put in a list or registered for an event, gimme back, remove interest".
     145              :      *   2. To a new registrar, during a registration call, it means "hey cleanup any
     146              :      *       current registrations, let me use the internal fields of Cancelable
     147              :      *       to keep track of what the owner is interested in.
     148              :      *   3. To any current registrar (i.e. when mCancel is non-null), Cancel() means:
     149              :      *       "remove this Callback from any internal lists and free any resources
     150              :      *        you've allocated to track the interest".
     151              :      *
     152              :      *  For example: a sockets library with an API like Socket::Readable(Callback<> *cb)
     153              :      *    using an underlying persistent registration API with the OS (like epoll())
     154              :      *    might store the file descriptor and interest mask in the scalar, put the
     155              :      *    Callback in a list.  Cancel() would dequeue the callback and remove
     156              :      *    the socket from the interest set
     157              :      *
     158              :      */
     159            0 :     Cancelable * Cancel() { return Cancelable::Cancel(); }
     160              : 
     161              :     /**
     162              :      * public constructor
     163              :      */
     164         2104 :     Callback(T call, void * context) : mContext(context), mCall(call) { Cancelable(); }
     165              : 
     166              :     /**
     167              :      * TODO: type-safety? It'd be nice if Cancelables that aren't Callbacks returned null
     168              :      *    here.  https://github.com/project-chip/connectedhomeip/issues/1350
     169              :      */
     170            0 :     static Callback * FromCancelable(Cancelable * ca) { return static_cast<Callback *>(ca); }
     171              : };
     172              : 
     173              : /**
     174              :  * @brief core of a simple doubly-linked list Callback keeper-tracker-of
     175              :  *
     176              :  */
     177              : class CallbackDeque : public Cancelable
     178              : {
     179              : public:
     180              :     /**
     181              :      * @brief appends with overridden cancel function, in case the
     182              :      *   list change requires some other state update.
     183              :      */
     184            0 :     void Enqueue(Cancelable * ca, void (*cancel)(Cancelable *))
     185              :     {
     186              :         // add to a doubly-linked list, set cancel function
     187            0 :         InsertBefore(ca, this, cancel);
     188            0 :     }
     189              :     /**
     190              :      * @brief appends
     191              :      */
     192            0 :     void Enqueue(Cancelable * ca) { Enqueue(ca, Dequeue); }
     193              : 
     194              :     /**
     195              :      * @brief dequeue, but don't cancel, all cas that match the by()
     196              :      */
     197              :     void DequeueBy(bool (*by)(uint64_t, const Cancelable *), uint64_t p, Cancelable & dequeued)
     198              :     {
     199              :         for (Cancelable * ca = mNext; ca != this;)
     200              :         {
     201              :             Cancelable * next = ca->mNext;
     202              :             if (by(p, ca))
     203              :             {
     204              :                 _Dequeue(ca);
     205              :                 _InsertBefore(ca, &dequeued);
     206              :             }
     207              :             ca = next;
     208              :         }
     209              :     }
     210              : 
     211              :     /**
     212              :      * @brief insert the node in a queue in order, sorted by "sortby(a, b)"
     213              :      *   sortby(a, b) should return 1 if a > b, -1 if a < b and 0 if a == b
     214              :      */
     215              :     void InsertBy(Cancelable * ca, int (*sortby)(void *, const Cancelable *, const Cancelable *), void * p,
     216              :                   void (*cancel)(Cancelable *))
     217              :     {
     218              :         Cancelable * where; // node before which we need to insert
     219              :         for (where = mNext; where != this; where = where->mNext)
     220              :         {
     221              :             if (sortby(p, ca, where) <= 0)
     222              :             {
     223              :                 break;
     224              :             }
     225              :         }
     226              :         InsertBefore(ca, where, cancel);
     227              :     }
     228              : 
     229              :     void InsertBy(Cancelable * ca, int (*sortby)(void *, const Cancelable *, const Cancelable *), void * p)
     230              :     {
     231              :         InsertBy(ca, sortby, p, Dequeue);
     232              :     }
     233              : 
     234              :     /**
     235              :      * @brief insert the node in a the list at a specific point
     236              :      */
     237            0 :     void InsertBefore(Cancelable * ca, Cancelable * where, void (*cancel)(Cancelable *))
     238              :     {
     239            0 :         ca->Cancel(); // make doubly-sure we're not corrupting another list somewhere
     240            0 :         ca->mCancel = cancel;
     241            0 :         _InsertBefore(ca, where);
     242            0 :     }
     243              :     void InsertBefore(Cancelable * ca, Cancelable * where) { InsertBefore(ca, where, Dequeue); }
     244              : 
     245              :     /**
     246              :      * @brief returns first item unless list is empty, otherwise returns NULL
     247              :      */
     248            0 :     Cancelable * First() { return (mNext != this) ? mNext : nullptr; }
     249              : 
     250              :     /**
     251              :      * @brief Dequeue all, return in a stub. does not cancel the cas, as the list
     252              :      *   members are still in use
     253              :      */
     254            0 :     void DequeueAll(Cancelable & ready)
     255              :     {
     256            0 :         if (mNext != this)
     257              :         {
     258            0 :             ready.mNext        = mNext;
     259            0 :             ready.mPrev        = mPrev;
     260            0 :             ready.mPrev->mNext = &ready;
     261            0 :             ready.mNext->mPrev = &ready;
     262              : 
     263            0 :             mNext = mPrev = this;
     264              :         }
     265            0 :     }
     266              : 
     267              :     /**
     268              :      * @brief dequeue but don't cancel, useful if
     269              :      *     immediately putting on another list
     270              :      */
     271            0 :     static void Dequeue(Cancelable * ca)
     272              :     {
     273            0 :         _Dequeue(ca);
     274            0 :         ca->mCancel = nullptr;
     275            0 :     }
     276              : 
     277              :     /**
     278              :      * @brief empty?
     279              :      */
     280              :     bool IsEmpty() { return mNext == this; }
     281              : 
     282              : private:
     283            0 :     static void _Dequeue(Cancelable * ca)
     284              :     {
     285            0 :         ca->mNext->mPrev = ca->mPrev;
     286            0 :         ca->mPrev->mNext = ca->mNext;
     287            0 :         ca->mNext = ca->mPrev = ca;
     288            0 :     }
     289            0 :     void _InsertBefore(Cancelable * ca, Cancelable * where)
     290              :     {
     291            0 :         ca->mPrev           = where->mPrev;
     292            0 :         where->mPrev->mNext = ca;
     293            0 :         where->mPrev        = ca;
     294            0 :         ca->mNext           = where;
     295            0 :     }
     296              : };
     297              : 
     298              : } // namespace Callback
     299              : } // namespace chip
        

Generated by: LCOV version 2.0-1