@@ -39,18 +39,22 @@ class ListenerSet{
3939 return m_count.load (std::memory_order_acquire);
4040 }
4141
42- // Add a new listener. This will never fail unless it throws.
43- // Deadlocking is not possible since there's only one local lock.
42+ // Add a new listener. This is always safe as it will never fail unless it
43+ // throws. Deadlocking is not possible since there's only one local lock.
4444 void add (ListenerType& listener);
4545
46- // Remove a listener. This will deadlock if a listener tries to remove
47- // from inside a callback.
48- void remove (ListenerType& listener);
46+ // Remove a listener. This will block if the listener being removed is
47+ // running a callback from this class.
48+ // Therefore, this will deadlock if a listener tries to remove itself from
49+ // inside its own callback.
50+ void remove (ListenerType& listener) noexcept ;
4951
50- // Same as above, but will return false if it needs to wait.
51- // This can never deadlock.
52- bool try_remove (ListenerType& listener);
52+ // Remove a listener (non-blocking). This will return false if it needs to
53+ // wait. This function is always safe and will never deadlock.
54+ bool try_remove (ListenerType& listener) noexcept ;
5355
56+
57+ public:
5458 template <typename Function, class ... Args>
5559 void run_method (Function function, Args&&... args);
5660
@@ -121,10 +125,10 @@ void ListenerSet<ListenerType>::add(ListenerType& listener){
121125 }
122126 node.next = m_list;
123127 m_list = &node;
124- m_count.store (m_listeners.size (), std::memory_order_relaxed );
128+ m_count.store (m_listeners.size (), std::memory_order_release );
125129}
126130template <typename ListenerType>
127- void ListenerSet<ListenerType>::remove(ListenerType& listener){
131+ void ListenerSet<ListenerType>::remove(ListenerType& listener) noexcept {
128132#ifdef PA_DEBUG_ListenerSet
129133 auto scope = m_sanitizer.check_scope ();
130134#endif
@@ -142,7 +146,9 @@ void ListenerSet<ListenerType>::remove(ListenerType& listener){
142146#endif
143147
144148 if (!node.lock .try_acquire_write ()){
145- std::cout << " ListenerSet::remove(): Retry inner." << std::endl;
149+ try {
150+ std::cout << " ListenerSet::remove(): Retry inner." << std::endl;
151+ }catch (...){}
146152 continue ;
147153 }
148154
@@ -161,15 +167,15 @@ void ListenerSet<ListenerType>::remove(ListenerType& listener){
161167#endif
162168
163169 m_listeners.erase (iter);
164- m_count.store (m_listeners.size (), std::memory_order_relaxed );
170+ m_count.store (m_listeners.size (), std::memory_order_release );
165171 return ;
166172 }
167173}
168174
169175
170176
171177template <typename ListenerType>
172- bool ListenerSet<ListenerType>::try_remove(ListenerType& listener){
178+ bool ListenerSet<ListenerType>::try_remove(ListenerType& listener) noexcept {
173179#ifdef PA_DEBUG_ListenerSet
174180 auto scope = m_sanitizer.check_scope ();
175181#endif
@@ -184,7 +190,9 @@ bool ListenerSet<ListenerType>::try_remove(ListenerType& listener){
184190
185191 Node& node = iter->second ;
186192 if (!node.lock .try_acquire_write ()){
187- std::cout << " ListenerSet::try_remove(): Fail inner." << std::endl;
193+ try {
194+ std::cout << " ListenerSet::try_remove(): Fail inner." << std::endl;
195+ }catch (...){}
188196 return false ;
189197 }
190198
@@ -205,7 +213,7 @@ bool ListenerSet<ListenerType>::try_remove(ListenerType& listener){
205213#endif
206214
207215 m_listeners.erase (iter);
208- m_count.store (m_listeners.size (), std::memory_order_relaxed );
216+ m_count.store (m_listeners.size (), std::memory_order_release );
209217 m_lock.unlock_write ();
210218 return true ;
211219}
0 commit comments