Hymn to Beauty
C++ 3D Engine
LockBox.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <functional>
4#include <memory>
5
6namespace Utility {
7template <typename T> class LockBox;
8template <typename T> void swap(LockBox<T>& first, LockBox<T>& second);
9
16template <typename T> class LockBox {
17 public:
20 class Key {};
21
22 friend void swap<T>(LockBox<T>& first, LockBox<T>& second);
23
25 LockBox() = default;
26
28
35 LockBox(std::shared_ptr<Key> key, T* data);
36
38
41 LockBox(const LockBox<T>& other);
42
45
48 LockBox(LockBox<T>&& other);
49
51
56
60 ~LockBox();
61
63
69 bool Open(std::shared_ptr<Key> key, const std::function<void(T&)>& forValidKey);
70
72
75 uint32_t RefCount() const;
76
77 private:
78 struct Shared {
79 uint32_t refs = 0;
80 std::shared_ptr<Key> key = std::shared_ptr<Key>(nullptr);
81 T* data = nullptr;
82 };
83
84 Shared* shared = nullptr;
85};
86
88
92template <typename T> void swap(LockBox<T>& first, LockBox<T>& second) {
93 using std::swap;
94 swap(first.shared, second.shared);
95}
96
97template <typename T> LockBox<T>::LockBox(std::shared_ptr<Key> key, T* data) {
98 shared = new Shared;
99 shared->refs = 1;
100 shared->key = key;
101 shared->data = data;
102}
103
104template <typename T> LockBox<T>::LockBox(const LockBox<T>& other) {
105 shared = other.shared;
106 shared->refs++;
107}
108
109template <typename T> LockBox<T>::LockBox(LockBox<T>&& other) : LockBox() {
110 swap(*this, other);
111}
112
113// Why not placement new: https://stackoverflow.com/a/7178022
114// Copy-and-swap idiom: https://stackoverflow.com/a/3279550
115template <typename T> LockBox<T>& LockBox<T>::operator=(LockBox<T> rhs) {
116 swap(*this, rhs);
117 return *this;
118}
119
120template <typename T> LockBox<T>::~LockBox() {
121 if (shared && --shared->refs == 0) {
122 delete shared;
123 }
124}
125
126template <typename T> bool LockBox<T>::Open(std::shared_ptr<Key> key, const std::function<void(T&)>& forValidKey) {
127 if (shared && key.get() == shared->key.get()) {
128 forValidKey(*shared->data);
129 return true;
130 }
131 return false;
132}
133
134template <typename T> uint32_t LockBox<T>::RefCount() const {
135 return shared ? shared->refs : 0;
136}
137} // namespace Utility
Definition: LockBox.hpp:20
Definition: LockBox.hpp:16
uint32_t RefCount() const
Number of lockboxes with the same reference.
Definition: LockBox.hpp:134
LockBox()=default
Constructor that defaults to referencing no data.
LockBox< T > & operator=(LockBox< T > rhs)
Replace the currently held reference with a new one.
Definition: LockBox.hpp:115
~LockBox()
Definition: LockBox.hpp:120
friend void swap(LockBox< T > &first, LockBox< T > &second)
Swap two lockboxes with each other.
Definition: LockBox.hpp:92
bool Open(std::shared_ptr< Key > key, const std::function< void(T &)> &forValidKey)
Open a box to access underlying contents.
Definition: LockBox.hpp:126
Definition: ResourceView.hpp:12
void swap(LockBox< T > &first, LockBox< T > &second)
Swap two lockboxes with each other.
Definition: LockBox.hpp:92