]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
6 | #include <list> | |
7 | #include <mutex> | |
8 | ||
9 | /* | |
10 | ||
11 | Keep a history of item values so that readers can dereference the pointer to | |
12 | the latest value and continue using it as long as they want. This container | |
13 | is only appropriate for values that are updated a handful of times over their | |
14 | total lifetime. | |
15 | ||
11fdf7f2 TL |
16 | */ |
17 | ||
11fdf7f2 TL |
18 | template<class T> |
19 | class safe_item_history { | |
20 | private: | |
21 | std::mutex lock; | |
22 | std::list<T> history; | |
23 | T *current = nullptr; | |
24 | ||
25 | public: | |
26 | safe_item_history() { | |
27 | history.emplace_back(T()); | |
28 | current = &history.back(); | |
29 | } | |
30 | ||
31 | // readers are lock-free | |
32 | const T& operator*() const { | |
33 | return *current; | |
34 | } | |
35 | const T *operator->() const { | |
36 | return current; | |
37 | } | |
38 | ||
39 | // writes are serialized | |
40 | const T& operator=(const T& other) { | |
41 | std::lock_guard l(lock); | |
42 | history.push_back(other); | |
43 | current = &history.back(); | |
44 | return *current; | |
45 | } | |
46 | ||
11fdf7f2 | 47 | }; |