10 #ifndef smtk_common_Observers_h
11 #define smtk_common_Observers_h
20 #include <type_traits>
23 #define ADD_OBSERVER(key, observers, observer, priority, initialize) \
24 key = (observers)->insert( \
28 std::string(__FILE__) + std::string(": ") + std::to_string(__LINE__))
65 template<
typename Observer,
bool DebugObservers = false,
int DefaultPriority = 0>
84 struct InternalKey : std::pair<int, int>
91 InternalKey(
int i,
int j)
92 : std::pair<int, int>(i, j)
95 ~InternalKey() =
default;
97 bool assigned()
const {
return this->second != -1; }
99 bool operator<(
const InternalKey& rhs)
const
101 return this->first == rhs.first ? this->second < rhs.second : rhs.first < this->first;
106 class Key final : InternalKey
113 , m_observers(nullptr)
118 Key& operator=(
const Key&) =
delete;
121 : InternalKey(std::move(key))
122 , m_observers(std::move(key.m_observers))
126 std::unique_lock<std::mutex> lock(m_observers->m_mutex);
127 m_observers->m_keys[*
this] =
this;
129 key.m_observers =
nullptr;
133 Key& operator=(Key&& key) noexcept
137 m_observers->
erase(*
this);
140 static_cast<InternalKey&
>(*this) = std::move(
static_cast<InternalKey&
>(key));
141 m_observers = key.m_observers;
145 std::unique_lock<std::mutex> lock(m_observers->m_mutex);
146 m_observers->m_keys[*
this] =
this;
147 key.m_observers =
nullptr;
156 m_observers->
erase(*
this);
157 m_observers =
nullptr;
161 bool operator==(
const Key& rhs)
163 return this->first == rhs.first && this->second == rhs.second;
165 bool operator!=(
const Key& rhs) {
return !((*this) == rhs); }
167 bool assigned()
const {
return this->InternalKey::assigned(); }
173 std::unique_lock<std::mutex> lock(m_observers->m_mutex);
174 m_observers->m_keys.erase(*
this);
176 m_observers =
nullptr;
180 Key(
const InternalKey& key,
Observers* observers)
182 , m_observers(observers)
186 m_observers->m_keys[key] =
this;
202 : m_initializer(initializer)
208 std::unique_lock<std::mutex> lock(m_mutex);
209 for (
auto& keypair : m_keys)
211 keypair.second->m_observers =
nullptr;
217 template<
class... Types>
218 auto operator()(Types&&... args) -> decltype(std::declval<Observer>()(args...))
220 return m_override ? m_override.operator()(std::forward<Types>(args)...)
226 template<
class... Types>
228 std::is_integral<decltype(std::declval<Observer>()(args...))>::value,
229 decltype(std::declval<Observer>()(args...))>::type
231 decltype(std::declval<Observer>()(args...)) result = 0;
235 for (
auto& entry : m_observers)
241 if (m_toErase.find(entry.first) == m_toErase.end())
245 std::cerr <<
"Calling observer (" << entry.first.first <<
", " << entry.first.second
246 <<
"): " << m_descriptions[entry.first] << std::endl;
248 if (entry.first.assigned())
250 result |= entry.second(std::forward<Types>(args)...);
253 else if (DebugObservers)
255 std::cerr <<
"Skipping erased observer (" << entry.first.first <<
", " << entry.first.second
256 <<
"): " << m_descriptions[entry.first] << std::endl;
264 for (
auto& toErase : m_toErase)
268 std::cerr <<
"Erasing observer (" << toErase.first <<
", " << toErase.second
269 <<
"): " << m_descriptions[toErase] << std::endl;
280 template<
class... Types>
282 !std::is_integral<decltype(std::declval<Observer>()(args...))>::value,
283 decltype(std::declval<Observer>()(args...))>::type
287 for (
auto& entry : m_observers)
293 if (m_toErase.find(entry.first) == m_toErase.end())
297 std::cerr <<
"Calling observer (" << entry.first.first <<
", " << entry.first.second
298 <<
"): " << m_descriptions[entry.first] << std::endl;
300 if (entry.first.assigned())
302 entry.second(std::forward<Types>(args)...);
305 else if (DebugObservers)
307 std::cerr <<
"Skipping erased observer (" << entry.first.first <<
", " << entry.first.second
308 <<
"): " << m_descriptions[entry.first] << std::endl;
316 for (
auto& toErase : m_toErase)
320 std::cerr <<
"Erasing observer (" << toErase.first <<
", " << toErase.second
321 <<
"): " << m_descriptions[toErase] << std::endl;
337 Key
insert(Observer fn,
Priority priority,
bool initialize, std::string description =
"")
343 if (m_observers.empty())
355 typename std::map<InternalKey, Observer>::iterator upper;
356 if (priority != std::numeric_limits<Priority>::lowest())
358 auto key = InternalKey(priority - 1, -1);
359 upper = m_observers.upper_bound(key);
365 if (upper != m_observers.begin())
374 upper = --m_observers.end();
380 handleId = (upper->first.first == priority ? upper->first.second + 1 : 0);
382 InternalKey handle = InternalKey(priority, handleId);
383 if (initialize && m_initializer)
388 m_descriptions.insert(std::make_pair(handle, description));
391 std::cerr <<
"Inserting observer (" << handle.first <<
", " << handle.second
392 <<
"): " << description << std::endl;
394 return m_observers.insert(std::make_pair(handle, fn)).second ? Key(handle,
this) : Key();
397 Key
insert(Observer fn, std::string description =
"")
399 return insert(fn, DefaultPriority,
true, description);
412 std::cerr <<
"Queueing observer erasure (" << handle.first <<
", " << handle.second
413 <<
"): " << m_descriptions[handle] << std::endl;
415 m_toErase.insert(handle);
416 return m_observers.size() - m_toErase.size();
420 std::cerr <<
"Immediate observer erasure (" << handle.first <<
", " << handle.second
421 <<
"): " << m_descriptions[handle] << std::endl;
423 return erase(
static_cast<InternalKey&
>(handle));
427 Observer
find(
const Key& handle)
const
429 auto entry = m_observers.find(handle);
430 return entry == m_observers.end() ? nullptr : entry->second;
434 std::size_t
size()
const {
return m_observers.size(); }
444 const Initializer& initializer()
const {
return m_initializer; }
446 void setInitializer(
Initializer fn) { m_initializer = fn; }
448 std::string description(Key handle)
const {
return m_descriptions[handle]; }
454 std::map<InternalKey, Observer> m_observers;
459 std::map<InternalKey, std::string> m_descriptions;
468 std::size_t
erase(
const InternalKey& key)
470 std::unique_lock<std::mutex> lock(m_mutex);
472 return m_observers.erase(key);
475 bool m_observing{
false };
476 std::set<InternalKey> m_toErase;
479 std::map<InternalKey, Key*> m_keys;
484 #endif // smtk_common_Observers_h