@@ -12,6 +12,9 @@ namespace linspire
1212 class solver
1313 {
1414 friend class constraint ;
15+ #ifdef LINSPIRE_ENABLE_LISTENERS
16+ friend class listener ;
17+ #endif
1518
1619 public:
1720 /* *
@@ -210,27 +213,6 @@ namespace linspire
210213 */
211214 [[nodiscard]] bool match (const utils::lin &l0, const utils::lin &l1) const noexcept ;
212215
213- #ifdef LINSPIRE_ENABLE_LISTENERS
214- /* *
215- * @brief Adds a listener to the solver.
216- *
217- * This function registers a listener that will be notified of changes to variable values
218- * within the solver. The listener must implement the `listener` interface.
219- *
220- * @param l A reference to the listener to be added.
221- */
222- void add_listener (listener &l) noexcept ;
223- /* *
224- * @brief Removes a listener from the solver.
225- *
226- * This function unregisters a previously added listener from the solver. The listener will
227- * no longer receive notifications of variable value changes.
228- *
229- * @param l A reference to the listener to be removed.
230- */
231- void remove_listener (listener &l) noexcept ;
232- #endif
233-
234216 friend std::string to_string (const solver &s) noexcept ;
235217 friend json::json to_json (const solver &s) noexcept ;
236218
@@ -271,7 +253,30 @@ namespace linspire
271253 class listener
272254 {
273255 public:
256+ explicit listener (solver &slv) noexcept : slv(slv) { slv.listeners .insert (this ); }
257+ virtual ~listener () noexcept
258+ {
259+ for (const auto &v : listened_vars)
260+ {
261+ slv.listening [v].erase (this );
262+ if (slv.listening [v].empty ())
263+ slv.listening .erase (v);
264+ }
265+ slv.listeners .erase (this );
266+ }
267+
274268 virtual void on_value_changed (const utils::var v) noexcept = 0;
269+
270+ protected:
271+ void listen (const utils::var v) noexcept
272+ {
273+ if (listened_vars.insert (v).second )
274+ slv.listening [v].insert (this );
275+ }
276+
277+ private:
278+ solver &slv;
279+ std::set<utils::var> listened_vars;
275280 };
276281#endif
277282
0 commit comments