Audacity 3.2.0
Observer.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file Observer.cpp
6 @brief Publisher-subscriber pattern, also known as Observer
7
8 Paul Licameli
9
10**********************************************************************/
11#include "Observer.h"
12
13namespace Observer {
14
15namespace detail {
16
17void RecordBase::Unlink() noexcept
18{
19 auto pPrev = prev.lock();
20 assert(pPrev); // See RecordList constructor and PushFront
21 // Do not move from next, see Visit
22 if (auto &pNext = (pPrev->next = next))
23 pNext->prev = move(prev);
24}
25
27 : m_pPolicy{ pPolicy }
28 , m_visitor{ visitor }
29{
30 assert(m_visitor); // precondition
31}
32
34{
36 auto pRecord = move(next);
37 while (pRecord)
38 pRecord = move(pRecord->next);
39}
40
41Subscription RecordList::Subscribe(std::shared_ptr<RecordBase> pRecord)
42{
43 assert(pRecord); // precondition
44 auto result = Subscription{ pRecord };
45 if (auto &pNext = (pRecord->next = move(next)))
46 pNext->prev = pRecord;
47 pRecord->prev = weak_from_this();
48 next = move(pRecord);
49 return result;
50}
51
52bool RecordList::Visit(const void *arg)
53{
54 assert(m_visitor); // See constructor
55 if (m_pPolicy)
57 bool result = false;
58 for (auto pRecord = next; pRecord; pRecord = pRecord->next) {
59 try {
60 if (m_visitor(*pRecord, arg)) {
61 result = true;
62 break;
63 }
64 // pRecord might have been removed from the list by the callback,
65 // but pRecord->next is unchanged. We won't see callbacks added by
66 // the callback, because they are earlier in the list.
67 }
68 catch (...) {
70 result = true;
71 break;
72 }
73 }
74 }
75 // Intentionally not in a finally():
76 if (m_pPolicy)
78 return result;
79}
80
81}
82
83ExceptionPolicy::~ExceptionPolicy() noexcept = default;
84
85Subscription::Subscription() = default;
86Subscription::Subscription(std::weak_ptr<detail::RecordBase> pRecord)
87 : m_wRecord{ move(pRecord) } {}
88Subscription::Subscription(Subscription &&) = default;
90{
91 const bool inequivalent =
92 m_wRecord.owner_before(other.m_wRecord) ||
93 other.m_wRecord.owner_before(m_wRecord);
94 if (inequivalent) {
95 Reset();
96 m_wRecord = move(other.m_wRecord);
97 }
98 return *this;
99}
100
101void Subscription::Reset() noexcept
102{
103 if (auto pRecord = m_wRecord.lock())
104 pRecord->Unlink();
105 m_wRecord.reset();
106}
107
108}
A move-only handle representing a connection to a Publisher.
Definition: Observer.h:70
void Reset() noexcept
Breaks the connection (constant time)
Definition: Observer.cpp:101
std::weak_ptr< detail::RecordBase > m_wRecord
Definition: Observer.h:95
Subscription & operator=(Subscription &&)
Definition: Observer.cpp:89
STL namespace.
May be supplied to constructor of Publisher to customize exception handling.
Definition: Observer.h:29
virtual void OnEndPublish() noexcept(false)=0
Called at the end of each publication, if exiting normally; may throw.
virtual bool OnEachFailedCallback() noexcept(false)=0
virtual ~ExceptionPolicy() noexcept
virtual void OnBeginPublish()=0
Called at the start of each publication.
void Unlink() noexcept
Definition: Observer.cpp:17
std::weak_ptr< RecordLink > prev
Definition: Observer.h:50
const Visitor m_visitor
Definition: Observer.h:65
Subscription Subscribe(std::shared_ptr< RecordBase > pRecord)
Definition: Observer.cpp:41
bool(*)(const RecordBase &record, const void *arg) Visitor
Type of function visiting the list; stop visit on true return.
Definition: Observer.h:56
ExceptionPolicy *const m_pPolicy
Definition: Observer.h:64
bool Visit(const void *arg)
Definition: Observer.cpp:52
RecordList(ExceptionPolicy *pPolicy, Visitor visitor)
Definition: Observer.cpp:26