3 * Copyright (c) 2020 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <type_traits>
23 #include <core/CHIPError.h>
26 namespace Retransmit {
29 * Handles lifetimes of payloads.
31 * E.g. for buffers, handles reference counting.
33 template <typename PayloadType>
36 static PayloadType Acquire(PayloadType & payload);
37 static void Release(PayloadType & payload);
41 * This class maintains a cache of data that is sufficient to retransmit.
43 * Typical use is to keep track of unacknowledged packets and resend them
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
50 * PayloadType MUST provide a way to reference count, as the data will
51 * preserved until the cache is freed:
53 * PayloadType chip::Retransmit::Aquire(PayloadType&);
54 * chip::Retransmit::Release(PayloadType&);
56 template <typename KeyType, typename PayloadType, size_t N>
61 Cache(const Cache &) = delete;
62 Cache & operator=(const Cache &) = delete;
66 for (size_t i = 0; i < N; i++)
70 Lifetime<PayloadType>::Release(mEntries[i].payload);
76 * Add a payload to the cache.
78 CHIP_ERROR Add(const KeyType & key, PayloadType & payload)
80 if (mInUse.count() >= N)
82 return CHIP_ERROR_NO_MEMORY;
85 for (size_t i = 0; i < N; i++)
90 mEntries[i].key = key;
91 mEntries[i].payload = Lifetime<PayloadType>::Acquire(payload);
100 * Remove a payload from the cache given the key.
102 CHIP_ERROR Remove(const KeyType & key)
104 for (size_t i = 0; i < N; i++)
106 if (mInUse.test(i) && (mEntries[i].key == key))
109 Lifetime<PayloadType>::Release(mEntries[i].payload);
110 return CHIP_NO_ERROR;
114 return CHIP_ERROR_KEY_NOT_FOUND;
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.
121 * @tparam Matcher is a generic matcher object defining a bool Matches method.
123 template <typename Matcher>
124 void RemoveMatching(const Matcher & matcher)
126 for (size_t i = 0; i < N; i++)
128 if (mInUse.test(i) && matcher.Matches(mEntries[i].key))
131 Lifetime<PayloadType>::Release(mEntries[i].payload);
137 * Search for a specific entry within the cache.
139 * @tparam Matcher is a generic macher object defining a bool Maches method.
141 * @param matcher the entry to find
142 * @param key - out set the key if found
143 * @param payload - the payload if found
145 * Key and payload are only valid as long as no remove methods
146 * are called on the class.
148 template <typename Matcher>
149 bool Find(const Matcher & matcher, const KeyType ** key, const PayloadType ** payload)
154 for (size_t i = 0; i < N; i++)
156 if (mInUse.test(i) && matcher.Matches(mEntries[i].key))
158 *key = &mEntries[i].key;
159 *payload = &mEntries[i].payload;
173 Entry mEntries[N]; // payload entries
174 std::bitset<N> mInUse; // compact 'in use' marker for payloads
175 }; // namespace Retransmit
177 } // namespace Retransmit