Live Cells C++
Reactive Programming for C++
Loading...
Searching...
No Matches
cell_state.hpp
1/*
2 * live_cells_cpp
3 * Copyright (C) 2024 Alexander Gutev <alex.gutev@gmail.com>
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you
6 * may not use this file except in compliance with the License. You
7 * 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
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 */
17
18#ifndef LIVE_CELLS_CELL_STATE_HPP
19#define LIVE_CELLS_CELL_STATE_HPP
20
21#include <unordered_map>
22#include <memory>
23
24#include "keys.hpp"
25#include "observable.hpp"
26
27namespace live_cells {
43 class cell_state : public std::enable_shared_from_this<cell_state> {
44 public:
46 typedef std::shared_ptr<cell_state> ref;
47
54
55 virtual ~cell_state() noexcept;
56
57 cell_state& operator=(const cell_state &other) = delete;
58
68 virtual void init() {}
69
79 virtual void pause() {}
86 virtual void add_observer(observer::ref o);
87
98 virtual void remove_observer(observer::ref o);
99
105 virtual void notify_will_update();
106
116 virtual void notify_update(bool did_change = true);
117
118 protected:
124
129 std::unordered_map<observer::ref, std::size_t> observers;
130
136 bool is_active() const {
137 return !observers.empty();
138 }
139
140 private:
141
142#ifndef NDEBUG
157 int notify_count = 0;
158#endif
159 };
160
165 public:
170 return instance_;
171 }
172
192 template <typename S, typename... Args>
193 std::shared_ptr<S> get(key_ref k, Args... args) {
194 if (k->is_unique()) {
195 return std::make_shared<S>(k, args...);
196 }
197
198 // TODO: Ensure that dynamic_pointer_cast succeeds.
199
200 auto it = states.find(k);
201
202 if (it != states.end()) {
203 if (auto state = it->second.lock()) {
204 return std::dynamic_pointer_cast<S>(state);
205 }
206 else {
207 states.erase(it);
208 }
209 }
210
211 auto state = states.emplace(k, std::weak_ptr<S>(std::make_shared<S>(k, args...))).first->second.lock();
212 return std::dynamic_pointer_cast<S>(state);
213 }
214
220 void remove(key_ref k) {
221 if (!k->is_unique()) {
222 states.erase(k);
223 }
224 }
225
226 private:
228 static state_manager instance_;
229
233 std::unordered_map<key_ref, std::weak_ptr<cell_state>> states;
234
235 state_manager() = default;
236 state_manager(const state_manager &) = delete;
237
238 state_manager &operator=(const state_manager &) = delete;
239 };
240
241} // live_cells
242
243#endif /* LIVE_CELLS_CELL_STATE_HPP */
Maintains the state of a stateful cell.
Definition cell_state.hpp:43
virtual void remove_observer(observer::ref o)
Remove an observer from the cell's set of observers.
Definition live_cells.cpp:62
virtual void notify_will_update()
Notify the observers that the cell's value will change.
Definition live_cells.cpp:76
virtual void notify_update(bool did_change=true)
Notify the observers that the cell's value has changed.
Definition live_cells.cpp:92
virtual void init()
Called before the first observer is added.
Definition cell_state.hpp:68
key_ref key_
Key identifying the cell corresponding to this state.
Definition cell_state.hpp:123
std::shared_ptr< cell_state > ref
Shared pointer to a cell_state.
Definition cell_state.hpp:46
cell_state(key_ref k)
Create a cell state with a given key.
Definition cell_state.hpp:53
virtual void pause()
Called after the last observer is removed.
Definition cell_state.hpp:79
bool is_active() const
Does the cell have at least one observer?
Definition cell_state.hpp:136
virtual void add_observer(observer::ref o)
Add an observer to the cell's set of observers.
Definition live_cells.cpp:47
std::unordered_map< observer::ref, std::size_t > observers
The set of observers observing changes to the values in the cell corresponding to this state.
Definition cell_state.hpp:129
Dynamically type key container.
Definition keys.hpp:76
virtual bool is_unique() const noexcept
Is this a unique key?
Definition keys.hpp:61
std::shared_ptr< observer > ref
Shared pointer to an observer.
Definition types.hpp:37
Maintains the association between keys and cell states.
Definition cell_state.hpp:164
void remove(key_ref k)
Definition cell_state.hpp:220
std::shared_ptr< S > get(key_ref k, Args... args)
Definition cell_state.hpp:193
static state_manager & global()
Definition cell_state.hpp:169
Definition boolean.hpp:26