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>
77 struct InternalKey : std::pair<int, int>
81 : std::pair<Priority, int>(std::numeric_limits<Priority>::lowest(), -1)
84 InternalKey(
int i,
int j)
85 : std::pair<int, int>(i, j)
88 ~InternalKey() =
default;
90 bool assigned()
const {
return this->second != -1; }
92 bool operator<(
const InternalKey& rhs)
const
94 return this->first == rhs.first ? this->second < rhs.second : rhs.first < this->first;
99 class Key final : InternalKey
106 , m_observers(nullptr)
111 Key& operator=(
const Key&) =
delete;
114 : InternalKey(std::move(key))
116 m_observers = key.m_observers;
119 std::unique_lock<std::mutex> lock(m_observers->m_mutex);
120 m_observers->m_keys[*
this] =
this;
121 key.m_observers =
nullptr;
125 Key& operator=(Key&& key) noexcept
129 m_observers->
erase(*
this);
132 static_cast<InternalKey&
>(*this) = std::move(
static_cast<InternalKey&
>(key));
133 m_observers = key.m_observers;
137 std::unique_lock<std::mutex> lock(m_observers->m_mutex);
138 m_observers->m_keys[*
this] =
this;
139 key.m_observers =
nullptr;
148 m_observers->
erase(*
this);
149 m_observers =
nullptr;
153 bool operator==(
const Key& rhs)
155 return this->first == rhs.first && this->second == rhs.second;
157 bool operator!=(
const Key& rhs) {
return !((*this) == rhs); }
159 bool assigned()
const {
return this->InternalKey::assigned(); }
165 std::unique_lock<std::mutex> lock(m_observers->m_mutex);
166 m_observers->m_keys.erase(*
this);
168 m_observers =
nullptr;
172 Key(
const InternalKey& key,
Observers* observers)
174 , m_observers(observers)
178 m_observers->m_keys[key] =
this;
194 : m_initializer(initializer)
200 std::unique_lock<std::mutex> lock(m_mutex);
201 for (
auto& keypair : m_keys)
203 keypair.second->m_observers =
nullptr;
209 template<
class... Types>
210 auto operator()(Types&&... args) -> decltype(std::declval<Observer>()(args...))
212 return m_override ? m_override.operator()(std::forward<Types>(args)...)
218 template<
class... Types>
220 std::is_integral<decltype(std::declval<Observer>()(args...))>::value,
221 decltype(std::declval<Observer>()(args...))>::type
223 decltype(std::declval<Observer>()(args...)) result = 0;
227 for (
auto& entry : m_observers)
233 if (m_toErase.find(entry.first) == m_toErase.end())
237 std::cerr <<
"Calling observer (" << entry.first.first <<
", " << entry.first.second
238 <<
"): " << m_descriptions[entry.first] << std::endl;
240 if (entry.first.assigned())
242 result |= entry.second(std::forward<Types>(args)...);
245 else if (DebugObservers)
247 std::cerr <<
"Skipping erased observer (" << entry.first.first <<
", " << entry.first.second
248 <<
"): " << m_descriptions[entry.first] << std::endl;
256 for (
auto& toErase : m_toErase)
260 std::cerr <<
"Erasing observer (" << toErase.first <<
", " << toErase.second
261 <<
"): " << m_descriptions[toErase] << std::endl;
272 template<
class... Types>
274 !std::is_integral<decltype(std::declval<Observer>()(args...))>::value,
275 decltype(std::declval<Observer>()(args...))>::type
279 for (
auto& entry : m_observers)
285 if (m_toErase.find(entry.first) == m_toErase.end())
289 std::cerr <<
"Calling observer (" << entry.first.first <<
", " << entry.first.second
290 <<
"): " << m_descriptions[entry.first] << std::endl;
292 if (entry.first.assigned())
294 entry.second(std::forward<Types>(args)...);
297 else if (DebugObservers)
299 std::cerr <<
"Skipping erased observer (" << entry.first.first <<
", " << entry.first.second
300 <<
"): " << m_descriptions[entry.first] << std::endl;
308 for (
auto& toErase : m_toErase)
312 std::cerr <<
"Erasing observer (" << toErase.first <<
", " << toErase.second
313 <<
"): " << m_descriptions[toErase] << std::endl;
329 Key
insert(Observer fn,
Priority priority,
bool initialize, std::string description =
"")
335 if (m_observers.empty())
347 typename std::map<InternalKey, Observer>::iterator upper;
348 if (priority != std::numeric_limits<Priority>::lowest())
350 auto key = InternalKey(priority - 1, -1);
351 upper = m_observers.upper_bound(key);
357 if (upper != m_observers.begin())
366 upper = --m_observers.end();
372 handleId = (upper->first.first == priority ? upper->first.second + 1 : 0);
374 InternalKey handle = InternalKey(priority, handleId);
375 if (initialize && m_initializer)
380 m_descriptions.insert(std::make_pair(handle, description));
383 std::cerr <<
"Inserting observer (" << handle.first <<
", " << handle.second
384 <<
"): " << description << std::endl;
386 return m_observers.insert(std::make_pair(handle, fn)).second ? Key(handle,
this) : Key();
389 Key
insert(Observer fn, std::string description =
"")
391 return insert(fn, std::numeric_limits<Priority>::lowest(),
true, description);
404 std::cerr <<
"Queueing observer erasure (" << handle.first <<
", " << handle.second
405 <<
"): " << m_descriptions[handle] << std::endl;
407 m_toErase.insert(handle);
408 return m_observers.size() - m_toErase.size();
412 std::cerr <<
"Immediate observer erasure (" << handle.first <<
", " << handle.second
413 <<
"): " << m_descriptions[handle] << std::endl;
415 return erase(
static_cast<InternalKey&
>(handle));
419 Observer
find(
const Key& handle)
const
421 auto entry = m_observers.find(handle);
422 return entry == m_observers.end() ? nullptr : entry->second;
426 std::size_t
size()
const {
return m_observers.size(); }
436 const Initializer& initializer()
const {
return m_initializer; }
438 void setInitializer(
Initializer fn) { m_initializer = fn; }
440 std::string description(Key handle)
const {
return m_descriptions[handle]; }
446 std::map<InternalKey, Observer> m_observers;
451 std::map<InternalKey, std::string> m_descriptions;
460 std::size_t
erase(
const InternalKey& key)
462 std::unique_lock<std::mutex> lock(m_mutex);
464 return m_observers.erase(key);
467 bool m_observing{
false };
468 std::set<InternalKey> m_toErase;
471 std::map<InternalKey, Key*> m_keys;
476 #endif // smtk_common_Observers_h