1#ifndef SOFT_STATE_MAP_HPP_B0MARRWZ
2#define SOFT_STATE_MAP_HPP_B0MARRWZ
4#include <vanetza/common/clock.hpp>
5#include <vanetza/common/runtime.hpp>
6#include <boost/heap/binomial_heap.hpp>
7#include <boost/range/iterator_range_core.hpp>
8#include <boost/range/adaptor/filtered.hpp>
9#include <boost/range/adaptor/transformed.hpp>
13#include <unordered_map>
20template<
typename VALUE>
23 VALUE operator()() {
return VALUE(); }
27
28
29
30
31
37 using mapped_type = VALUE;
38 using value_type = std::pair<
const key_type&, mapped_type&>;
39 using creator_type = CTOR;
45 ExpiryWithKey() =
default;
46 ExpiryWithKey(
const key_type& key,
Clock::time_point expiry) :
47 Clock::time_point(expiry), m_key(key) {}
49 const key_type& key()
const {
return m_key; }
58 ValueWithHandle(mapped_type&& v) : value(std::move(v)) {}
60 typename heap_type::handle_type handle;
63 mapped_type& operator*() {
return value; }
64 const mapped_type& operator*()
const {
return value; }
69 using data_filter = std::function<
bool(
const typename map_type::value_type&)>;
70 using data_transform = std::function<value_type(
typename map_type::value_type&)>;
74
75
76
77
78 template<
typename T = CTOR>
79 SoftStateMap(
const Runtime& rt,
typename std::enable_if<std::is_default_constructible<T>::value>::type* =
nullptr) :
85
86
87
88
90 m_runtime(rt), m_creator(std::move(ctor))
95
96
97
100 m_lifetime = lifetime;
104
105
106
107
110 return get_data(key).value;
114
115
116
117
120 auto* data = get_data_ptr(key);
121 return data && !is_expired(*data->handle) ? &data->value :
nullptr;
125
126
127
128
131 auto* data = get_data_ptr(key);
132 return data && !is_expired(*data->handle) ? &data->value :
nullptr;
136
137
138
139
142 return get_value_ptr(key) !=
nullptr;
146
147
148
149
152 auto* data = get_data_ptr(key);
156 data = &get_data(key);
157 assert(data !=
nullptr);
163
164
165
168 while (!m_heap.empty() && is_expired(m_heap.top())) {
169 m_map.erase(m_heap.top().key());
177
178
181 data_filter filter_fn = [
this](
const typename map_type::value_type& v) {
182 return !
this->is_expired(*v.second.handle);
184 data_transform transform_fn = [](
typename map_type::value_type& v) {
185 return value_type { v.first, v.second.value };
187 using namespace boost::adaptors;
188 data_range range_all = boost::make_iterator_range(m_map.begin(), m_map.end());
189 return range_all | filtered(filter_fn) | transformed(transform_fn);
192 const map_range map()
const
200 auto* data = get_data_ptr(key);
202 auto insertion = m_map.emplace(std::piecewise_construct,
203 std::forward_as_tuple(key), std::forward_as_tuple(m_creator()));
204 data = &insertion.first->second;
205 data->handle = m_heap.push(ExpiryWithKey {key, m_runtime.now() + m_lifetime});
206 }
else if (is_expired(*data->handle)) {
215 auto it = m_map.find(key);
216 return it != m_map.end() ? &it->second :
nullptr;
221 auto it = m_map.find(key);
222 return it != m_map.end() ? &it->second :
nullptr;
227 return m_runtime
.now() > expiry;
230 void refresh(
typename heap_type::handle_type& handle)
233 static_cast<Clock::time_point&>(expiry) = m_runtime.now() + m_lifetime;
234 m_heap.update(handle);
238 Clock::duration m_lifetime;
239 creator_type m_creator;
virtual Clock::time_point now() const =0
void add(const id_type &) override
void remove(const id_type &) override
void increment(const id_type &) override
void add(const id_type &) override
void remove(const id_type &) override
counter_type counter(const id_type &) const override
counter_type counter(const id_type &) const override
void remove(const id_type &) override
void add(const id_type &) override
void increment(const id_type &) override
virtual void increment(const id_type &id)=0
virtual void add(const id_type &id)=0
virtual void remove(const id_type &id)=0
virtual counter_type counter(const id_type &id) const =0
SoftStateMap(const Runtime &rt, typename std::enable_if< std::is_default_constructible< T >::value >::type *=nullptr)
SoftStateMap(const Runtime &rt, creator_type &&ctor)
bool has_value(const key_type &key) const
mapped_type & refresh(const key_type &key)
const mapped_type * get_value_ptr(const key_type &key) const
void set_lifetime(Clock::duration lifetime)
mapped_type & get_value(const key_type &key)
mapped_type * get_value_ptr(const key_type &key)