Live Cells C++
Reactive Programming for C++
Loading...
Searching...
No Matches
mutable_compute_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_MUTABLE_DEPENDENT_CELL_HPP
19#define LIVE_CELLS_MUTABLE_DEPENDENT_CELL_HPP
20
21#include <memory>
22#include <functional>
23#include <unordered_set>
24
25#include "observable.hpp"
26#include "mutable_cell.hpp"
27#include "exceptions.hpp"
28#include "observer_cell_state.hpp"
29
30namespace live_cells {
31
35 template <typename T>
37 public mutable_cell_state<T>,
38 public observer,
39 public observer_cell_state {
40
43
44 public:
45
54 mutable_compute_cell_state(key_ref key, const std::unordered_set<cell> &arguments) :
55 parent(key),
57
63 T value() {
64 if (stale) {
65 computed = true;
66
67 try {
68 this->silent_set(compute());
69 }
70 catch (const stop_compute_exception &) {
71 // Prevent value from being updated
72 }
73
74 stale = !this->is_active();
75 }
76
77 return parent::value();
78 }
79
85 void value(T value) {
86 reverse = true;
87 this->notify_will_update();
88
89 updating = false;
90 stale = false;
91 computed = false;
92
93 this->silent_set(value);
94
95 try {
96 batch([&, this] () {
98 });
99 }
100 catch (...) {
101 // Prevent exception from being propagated to caller
102 }
103
104 if (parent::is_batch_update()) {
105 this->add_to_batch();
106 }
107 else {
108 this->notify_update();
109 }
110
111 reverse = false;
112 }
113
114 void will_update(const key_ref &k) override {
115 if (!reverse) {
116 handle_will_update([this] {
117 this->notify_will_update();
118 });
119 }
120 }
121
122 void update(const key_ref &k, bool changed) override {
123 handle_update(changed, [this] (bool changed) {
124 this->notify_update(changed);
125 });
126 }
127
132 void init() override {
135
136 try {
137 this->silent_set(this->value());
138 }
139 catch (...) {
140 // Prevent exception from being propagated to caller
141 }
142
143 for (auto arg : arguments) {
144 arg.add_observer(observer_ptr());
145 }
146 }
147
152 void pause() override {
155
156 for (auto arg : arguments) {
157 arg.remove_observer(observer_ptr());
158 }
159 }
160
161 protected:
166 std::unordered_set<cell> arguments;
167
172 bool reverse = false;
173
178 bool computed = true;
179
189 virtual T compute() = 0;
190
203 virtual void reverse_compute(T value) = 0;
204
212 std::shared_ptr<observer> observer_ptr() {
213 return std::dynamic_pointer_cast<observer>(this->shared_from_this());
214 }
215 };
216
217} // live_cells
218
219#endif /* LIVE_CELLS_MUTABLE_DEPENDENT_CELL_HPP */
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
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
A computed cell which determines its argument cells at runtime.
Definition dynamic_compute_cell.hpp:153
Dynamically type key container.
Definition keys.hpp:76
Defines the interface for a key which uniquely identifies a cell.
Definition keys.hpp:33
Maintains the state of a mutable_cell.
Definition mutable_cell.hpp:78
void add_to_batch()
Add this state to the list of mutable cells that were updating during the current batch update.
Definition mutable_cell.hpp:145
void silent_set(T value)
Set the cell's value without notifying observers.
Definition mutable_cell.hpp:128
Maintains the state of a mutable computed cell.
Definition mutable_compute_cell_state.hpp:39
void value(T value)
Set the value of the cell.
Definition mutable_compute_cell_state.hpp:85
std::unordered_set< cell > arguments
Set of argument cells referenced by the value computation function.
Definition mutable_compute_cell_state.hpp:166
std::shared_ptr< observer > observer_ptr()
Get an observer::ref for this, that can be passed to add_observer() and remove_observer() of the Cell...
Definition mutable_compute_cell_state.hpp:212
void will_update(const key_ref &k) override
Notifies this observer that the value of the Cell identified by k is going to change.
Definition mutable_compute_cell_state.hpp:114
bool reverse
Is the value of the cell being set, and hence a reverse computation being performed?
Definition mutable_compute_cell_state.hpp:172
void init() override
Add this state as an observer to the compute function arguments.
Definition mutable_compute_cell_state.hpp:132
virtual T compute()=0
Compute the value of the cell as a function of its argument cells.
virtual void reverse_compute(T value)=0
Perform the reverse computation.
bool computed
Is the cell's value the computed value (true) or a value that was set (false).
Definition mutable_compute_cell_state.hpp:178
void update(const key_ref &k, bool changed) override
Notifies this observer that the value of the Cell identified by k has changed.
Definition mutable_compute_cell_state.hpp:122
void pause() override
Remove this state from the observers of the compute function arguments.
Definition mutable_compute_cell_state.hpp:152
T value()
Get the value of the cell.
Definition mutable_compute_cell_state.hpp:63
mutable_compute_cell_state(key_ref key, const std::unordered_set< cell > &arguments)
Create the state for a mutable computed cell.
Definition mutable_compute_cell_state.hpp:54
Provides functionality for observing a cell from a cell_state.
Definition observer_cell_state.hpp:21
bool updating
Are the argument cells in the process of updating their values?
Definition observer_cell_state.hpp:32
void init_observer_state()
Initialize the cell observation state.
Definition observer_cell_state.hpp:40
void handle_will_update(const std::invocable auto &notify_will_update)
Handle a observer::will_update call.
Definition observer_cell_state.hpp:66
void pause_observer_state()
Pause the cell observation state.
Definition observer_cell_state.hpp:50
bool stale
Does the value have to be recomputed?
Definition observer_cell_state.hpp:26
void handle_update(bool changed, const std::invocable< bool > auto &notify_update)
Handle an observer::update call.
Definition observer_cell_state.hpp:120
Defines the interface for observing changes to the value of a Cell.
Definition types.hpp:32
Definition boolean.hpp:26
void batch(F fn)
Batch changes to the values of mutable cells.
Definition mutable_cell.hpp:307
Exception indicating that the value of a cell should not be computed.
Definition exceptions.hpp:33