OpenCPN Partial API docs
Loading...
Searching...
No Matches
observable.cpp
Go to the documentation of this file.
1/*************************************************************************
2 *
3 *
4 * Copyright (C) 2022 - 2025 Alec Leamas
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the
18 * Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 **************************************************************************/
21
29#include <algorithm>
30#include <mutex>
31#include <sstream>
32#include <unordered_map>
33
34#include <wx/log.h>
35
36#include "observable.h"
37
38std::string ptr_key(const void* ptr) {
39 std::ostringstream oss;
40 oss << ptr;
41 return oss.str();
42}
43
44/* ListenersByKey implementation. */
45
46ListenersByKey& ListenersByKey::GetInstance(const std::string& key) {
47 static std::unordered_map<std::string, ListenersByKey> instances;
48 static std::mutex s_mutex;
49
50 std::lock_guard<std::mutex> lock(s_mutex);
51 if (instances.find(key) == instances.end()) {
52 instances[key] = ListenersByKey();
53 }
54 return instances[key];
55}
56
57/* Observable implementation. */
58
59using ev_pair = std::pair<wxEvtHandler*, wxEventType>;
60
61void Observable::Listen(wxEvtHandler* listener, wxEventType ev_type) {
62 std::lock_guard<std::mutex> lock(m_mutex);
63 const auto& listeners = m_list.listeners;
64
65 ev_pair key_pair(listener, ev_type);
66 auto found = std::find(listeners.begin(), listeners.end(), key_pair);
67 assert((found == listeners.end()) && "Duplicate listener");
68 m_list.listeners.push_back(key_pair);
69}
70
71bool Observable::Unlisten(wxEvtHandler* listener, wxEventType ev_type) {
72 std::lock_guard<std::mutex> lock(m_mutex);
73 auto& listeners = m_list.listeners;
74
75 ev_pair key_pair(listener, ev_type);
76 auto found = std::find(listeners.begin(), listeners.end(), key_pair);
77 if (found == listeners.end()) return false;
78 listeners.erase(found);
79 return true;
80}
81
82void Observable::Notify(const std::shared_ptr<const void>& ptr,
83 const std::string& s, int num,
84 void* client_data) {
85 std::lock_guard<std::mutex> lock(m_mutex);
86 auto& listeners = m_list.listeners;
87
88 for (const auto& l : listeners) {
89 auto evt = new ObservedEvt(l.second);
90 evt->SetSharedPtr(ptr);
91 evt->SetClientData(client_data);
92 evt->SetString(s.c_str()); // Better safe than sorry: force a deep copy
93 evt->SetInt(num);
94 wxQueueEvent(l.first, evt);
95 }
96}
97
98void Observable::Notify() { Notify("", nullptr); }
99
100/* ObservableListener implementation. */
101
102void ObservableListener::Listen(const std::string& k, wxEvtHandler* l,
103 wxEventType e) {
104 if (!key.empty()) Unlisten();
105 key = k;
106 listener = l;
107 ev_type = e;
108 Listen();
109}
110
111void ObservableListener::Listen() {
112 if (!key.empty()) {
113 assert(listener);
114 Observable(key).Listen(listener, ev_type);
115 }
116}
117
118void ObservableListener::Unlisten() {
119 if (!key.empty()) {
120 assert(listener);
121 Observable(key).Unlisten(listener, ev_type);
122 key = "";
123 }
124}
Private helper class.
Definition observable.h:83
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
The observable notify/listen basic nuts and bolts.
Definition observable.h:100
virtual void Notify()
Notify all listeners about variable change.
bool Unlisten(wxEvtHandler *listener, wxEventType ev)
Remove window listening to ev from list of listeners.
Custom event class for OpenCPN's notification system.
std::string ptr_key(const void *ptr)
Return address as printable string.
General observable implementation with several specializations.