Matter SDK Coverage Report
Current view: top level - transport/retransmit - Cache.h (source / functions) Coverage Total Hit
Test: SHA:4d2388ac7eed75b2fe5e05e20de377999c632502 Lines: 100.0 % 38 38
Test Date: 2025-07-27 07:17:09 Functions: 100.0 % 13 13

            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              : #pragma once
      18              : 
      19              : #include <bitset>
      20              : #include <cstddef>
      21              : #include <type_traits>
      22              : 
      23              : #include <lib/core/CHIPError.h>
      24              : 
      25              : namespace chip {
      26              : namespace Retransmit {
      27              : 
      28              : /**
      29              :  * Handles lifetimes of payloads.
      30              :  *
      31              :  * E.g. for buffers, handles reference counting.
      32              :  */
      33              : template <typename PayloadType>
      34              : struct Lifetime
      35              : {
      36              :     static PayloadType Acquire(PayloadType & payload);
      37              :     static void Release(PayloadType & payload);
      38              : };
      39              : 
      40              : /**
      41              :  * This class maintains a cache of data that is sufficient to retransmit.
      42              :  *
      43              :  * Typical use is to keep track of unacknowledged packets and resend them
      44              :  * as needed.
      45              :  *
      46              :  * @tparam KeyType the key to identify a single message
      47              :  * @tparam PayloadType the type of payload to cache for the given peer address
      48              :  * @tparam N size of the available cache
      49              :  *
      50              :  * PayloadType MUST provide a way to reference count, as the data will
      51              :  * preserved until the cache is freed:
      52              :  *
      53              :  *    PayloadType chip::Retransmit::Acquire(PayloadType&);
      54              :  *    chip::Retransmit::Release(PayloadType&);
      55              :  */
      56              : template <typename KeyType, typename PayloadType, size_t N>
      57              : class Cache
      58              : {
      59              : public:
      60            6 :     Cache() {}
      61              :     Cache(const Cache &)             = delete;
      62              :     Cache & operator=(const Cache &) = delete;
      63              : 
      64            6 :     ~Cache()
      65              :     {
      66           61 :         for (size_t i = 0; i < N; i++)
      67              :         {
      68           55 :             if (mInUse.test(i))
      69              :             {
      70            9 :                 Lifetime<PayloadType>::Release(mEntries[i].payload);
      71              :             }
      72              :         }
      73            6 :     }
      74              : 
      75              :     /**
      76              :      * Add a payload to the cache.
      77              :      */
      78           21 :     CHIP_ERROR Add(const KeyType & key, PayloadType & payload)
      79              :     {
      80           21 :         if (mInUse.count() >= N)
      81              :         {
      82            3 :             return CHIP_ERROR_NO_MEMORY;
      83              :         }
      84              : 
      85           41 :         for (size_t i = 0; i < N; i++)
      86              :         {
      87           41 :             if (!mInUse.test(i))
      88              :             {
      89           18 :                 mInUse.set(i);
      90           18 :                 mEntries[i].key     = key;
      91           18 :                 mEntries[i].payload = Lifetime<PayloadType>::Acquire(payload);
      92           18 :                 break;
      93              :             }
      94              :         }
      95              : 
      96           18 :         return CHIP_NO_ERROR;
      97              :     }
      98              : 
      99              :     /**
     100              :      * Remove a payload from the cache given the key.
     101              :      */
     102           10 :     CHIP_ERROR Remove(const KeyType & key)
     103              :     {
     104           29 :         for (size_t i = 0; i < N; i++)
     105              :         {
     106           26 :             if (mInUse.test(i) && (mEntries[i].key == key))
     107              :             {
     108            7 :                 mInUse.reset(i);
     109            7 :                 Lifetime<PayloadType>::Release(mEntries[i].payload);
     110            7 :                 return CHIP_NO_ERROR;
     111              :             }
     112              :         }
     113              : 
     114            3 :         return CHIP_ERROR_KEY_NOT_FOUND;
     115              :     }
     116              : 
     117              :     /**
     118              :      * Remove any matching payloads. Used for mass removal, e.g. when a connection
     119              :      * is closed, relevant payloads need/can be cleared for the entire connection.
     120              :      *
     121              :      * @tparam Matcher is a generic matcher object defining a bool Matches method.
     122              :      */
     123              :     template <typename Matcher>
     124            1 :     void RemoveMatching(const Matcher & matcher)
     125              :     {
     126            5 :         for (size_t i = 0; i < N; i++)
     127              :         {
     128            4 :             if (mInUse.test(i) && matcher.Matches(mEntries[i].key))
     129              :             {
     130            2 :                 mInUse.reset(i);
     131            2 :                 Lifetime<PayloadType>::Release(mEntries[i].payload);
     132              :             }
     133              :         }
     134            1 :     }
     135              : 
     136              :     /**
     137              :      * Search for a specific entry within the cache.
     138              :      *
     139              :      * @tparam Matcher is a generic macher object defining a bool Maches method.
     140              :      *
     141              :      * @param matcher the entry to find
     142              :      * @param key - out set the key if found
     143              :      * @param payload - the payload if found
     144              :      *
     145              :      * Key and payload are only valid as long as no remove methods
     146              :      * are called on the class.
     147              :      */
     148              :     template <typename Matcher>
     149            4 :     bool Find(const Matcher & matcher, const KeyType ** key, const PayloadType ** payload)
     150              :     {
     151            4 :         *key     = nullptr;
     152            4 :         *payload = nullptr;
     153              : 
     154           16 :         for (size_t i = 0; i < N; i++)
     155              :         {
     156           14 :             if (mInUse.test(i) && matcher.Matches(mEntries[i].key))
     157              :             {
     158            2 :                 *key     = &mEntries[i].key;
     159            2 :                 *payload = &mEntries[i].payload;
     160            2 :                 return true;
     161              :             }
     162              :         }
     163            2 :         return false;
     164              :     }
     165              : 
     166              : private:
     167              :     struct Entry
     168              :     {
     169              :         KeyType key;
     170              :         PayloadType payload;
     171              :     };
     172              : 
     173              :     Entry mEntries[N];     // payload entries
     174              :     std::bitset<N> mInUse; // compact 'in use' marker for payloads
     175              : };                         // namespace Retransmit
     176              : 
     177              : } // namespace Retransmit
     178              : } // namespace chip
        

Generated by: LCOV version 2.0-1