Matter SDK Coverage Report
Current view: top level - app - AttributeAccessInterfaceCache.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 100.0 % 33 33
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2024 Project CHIP Authors
       4              :  *    All rights reserved.
       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              : #pragma once
      19              : 
      20              : #include <stddef.h>
      21              : 
      22              : #include <app/AttributeAccessInterface.h>
      23              : #include <lib/core/DataModelTypes.h>
      24              : 
      25              : namespace chip {
      26              : namespace app {
      27              : 
      28              : /**
      29              :  * @brief Cache to make look-up of AttributeAccessInterface (AAI) instances faster.
      30              :  *
      31              :  * This cache makes use of the fact that looking-up AttributeAccessInterface
      32              :  * instances is usually done in loops, during read/subscription wildcard
      33              :  * expansion, and there is a significant amount of locality.
      34              :  *
      35              :  * This cache records both "used" (i.e. uses AAI) and the single last
      36              :  * "unused" (i.e. does NOT use AAI) entries. Combining positive/negative
      37              :  * lookup led to factor of ~10 reduction of AAI lookups in total for wildcard
      38              :  * reads on chip-all-clusters-app, with a cache size of 1. Increasing the size did not
      39              :  * significantly improve the performance.
      40              :  */
      41              : class AttributeAccessInterfaceCache
      42              : {
      43              : public:
      44              :     enum class CacheResult
      45              :     {
      46              :         kCacheMiss,
      47              :         kDefinitelyUnused,
      48              :         kDefinitelyUsed
      49              :     };
      50              : 
      51            9 :     AttributeAccessInterfaceCache() { Invalidate(); }
      52              : 
      53              :     /**
      54              :      * @brief Invalidate the whole cache. Must be called every time list of AAI registrations changes.
      55              :      */
      56           55 :     void Invalidate()
      57              :     {
      58          110 :         for (auto & entry : mCacheSlots)
      59              :         {
      60           55 :             entry.Invalidate();
      61              :         }
      62           55 :         mLastUnusedEntry.Invalidate();
      63           55 :     }
      64              : 
      65              :     /**
      66              :      * @brief Mark that we know a given <`endpointId`, `clusterId`> uses AAI, with instance `attrInterface`
      67              :      */
      68           25 :     void MarkUsed(EndpointId endpointId, ClusterId clusterId, AttributeAccessInterface * attrInterface)
      69              :     {
      70           25 :         GetCacheSlot(endpointId, clusterId)->Set(endpointId, clusterId, attrInterface);
      71           25 :     }
      72              : 
      73              :     /**
      74              :      * @brief Mark that we know a given <`endpointId`, `clusterId`> does NOT use AAI.
      75              :      */
      76            5 :     void MarkUnused(EndpointId endpointId, ClusterId clusterId) { mLastUnusedEntry.Set(endpointId, clusterId, nullptr); }
      77              : 
      78              :     /**
      79              :      * @brief Get the AttributeAccessInterface instance for a given <`endpointId`, `clusterId`>, if present in cache.
      80              :      *
      81              :      * @param endpointId - Endpoint ID to look-up.
      82              :      * @param clusterId - Cluster ID to look-up.
      83              :      * @param outAttributeAccess - If not null, and Get returns `kDefinitelyUsed`, then this is set to the instance pointer.
      84              :      * @return a for whether the entry is actually used or not.
      85              :      */
      86         5198 :     CacheResult Get(EndpointId endpointId, ClusterId clusterId, AttributeAccessInterface ** outAttributeAccess)
      87              :     {
      88         5198 :         if (mLastUnusedEntry.Matches(endpointId, clusterId))
      89              :         {
      90          179 :             return CacheResult::kDefinitelyUnused;
      91              :         }
      92              : 
      93         5019 :         AttributeAccessCacheEntry * cacheSlot = GetCacheSlot(endpointId, clusterId);
      94         5019 :         if (cacheSlot->Matches(endpointId, clusterId) && (cacheSlot->accessor != nullptr))
      95              :         {
      96         4989 :             if (outAttributeAccess != nullptr)
      97              :             {
      98         4989 :                 *outAttributeAccess = cacheSlot->accessor;
      99              :             }
     100         4989 :             return CacheResult::kDefinitelyUsed;
     101              :         }
     102              : 
     103           30 :         return CacheResult::kCacheMiss;
     104              :     }
     105              : 
     106              : private:
     107              :     struct AttributeAccessCacheEntry
     108              :     {
     109              :         EndpointId endpointId               = kInvalidEndpointId;
     110              :         ClusterId clusterId                 = kInvalidClusterId;
     111              :         AttributeAccessInterface * accessor = nullptr;
     112              : 
     113          110 :         void Invalidate()
     114              :         {
     115          110 :             endpointId = kInvalidEndpointId;
     116          110 :             clusterId  = kInvalidClusterId;
     117          110 :             accessor   = nullptr;
     118          110 :         }
     119              : 
     120           30 :         void Set(EndpointId theEndpointId, ClusterId theClusterId, AttributeAccessInterface * theAccessor)
     121              :         {
     122           30 :             endpointId = theEndpointId;
     123           30 :             clusterId  = theClusterId;
     124           30 :             accessor   = theAccessor;
     125           30 :         }
     126              : 
     127        10217 :         bool Matches(EndpointId theEndpointId, ClusterId theClusterId) const
     128              :         {
     129        10217 :             return (endpointId == theEndpointId) && (clusterId == theClusterId);
     130              :         }
     131              :     };
     132              : 
     133         5044 :     AttributeAccessCacheEntry * GetCacheSlot(EndpointId endpointId, ClusterId clusterId)
     134              :     {
     135              :         (void) endpointId;
     136              :         (void) clusterId;
     137         5044 :         return &mCacheSlots[0];
     138              :     }
     139              : 
     140              :     AttributeAccessCacheEntry mCacheSlots[1];
     141              :     AttributeAccessCacheEntry mLastUnusedEntry;
     142              : };
     143              : 
     144              : } // namespace app
     145              : } // namespace chip
        

Generated by: LCOV version 2.0-1