Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / retransmit / Cache.h
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 <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::Aquire(PayloadType&);
54  *    chip::Retransmit::Release(PayloadType&);
55  */
56 template <typename KeyType, typename PayloadType, size_t N>
57 class Cache
58 {
59 public:
60     Cache() {}
61     Cache(const Cache &) = delete;
62     Cache & operator=(const Cache &) = delete;
63
64     ~Cache()
65     {
66         for (size_t i = 0; i < N; i++)
67         {
68             if (mInUse.test(i))
69             {
70                 Lifetime<PayloadType>::Release(mEntries[i].payload);
71             }
72         }
73     }
74
75     /**
76      * Add a payload to the cache.
77      */
78     CHIP_ERROR Add(const KeyType & key, PayloadType & payload)
79     {
80         if (mInUse.count() >= N)
81         {
82             return CHIP_ERROR_NO_MEMORY;
83         }
84
85         for (size_t i = 0; i < N; i++)
86         {
87             if (!mInUse.test(i))
88             {
89                 mInUse.set(i);
90                 mEntries[i].key     = key;
91                 mEntries[i].payload = Lifetime<PayloadType>::Acquire(payload);
92                 break;
93             }
94         }
95
96         return CHIP_NO_ERROR;
97     }
98
99     /**
100      * Remove a payload from the cache given the key.
101      */
102     CHIP_ERROR Remove(const KeyType & key)
103     {
104         for (size_t i = 0; i < N; i++)
105         {
106             if (mInUse.test(i) && (mEntries[i].key == key))
107             {
108                 mInUse.reset(i);
109                 Lifetime<PayloadType>::Release(mEntries[i].payload);
110                 return CHIP_NO_ERROR;
111             }
112         }
113
114         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     void RemoveMatching(const Matcher & matcher)
125     {
126         for (size_t i = 0; i < N; i++)
127         {
128             if (mInUse.test(i) && matcher.Matches(mEntries[i].key))
129             {
130                 mInUse.reset(i);
131                 Lifetime<PayloadType>::Release(mEntries[i].payload);
132             }
133         }
134     }
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     bool Find(const Matcher & matcher, const KeyType ** key, const PayloadType ** payload)
150     {
151         *key     = nullptr;
152         *payload = nullptr;
153
154         for (size_t i = 0; i < N; i++)
155         {
156             if (mInUse.test(i) && matcher.Matches(mEntries[i].key))
157             {
158                 *key     = &mEntries[i].key;
159                 *payload = &mEntries[i].payload;
160                 return true;
161             }
162         }
163         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