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