ROSE 0.11.145.147
Callbacks.h
1// WARNING: Changes to this file must be contributed back to Sawyer or else they will
2// be clobbered by the next update from Sawyer. The Sawyer repository is at
3// https://gitlab.com/charger7534/sawyer.git.
4
5
6
7
8#ifndef Sawyer_Callbacks_H
9#define Sawyer_Callbacks_H
10
11#include <Sawyer/Sawyer.h>
12#include <Sawyer/SharedPointer.h>
13#include <list>
14
15namespace Sawyer {
16
17// FIXME[Robb Matzke 2014-08-13]: documentation
18template<class Callback>
19class Callbacks {
20private:
21 typedef std::list<Callback> CbList;
22 CbList callbacks_;
23
24public:
25 bool isEmpty() const {
26 return callbacks_.empty();
27 }
28
29 bool operator==(const Callbacks &other) {
30 return callbacks_.size() == other.callbacks_.size() &&
31 std::equal(callbacks_.begin(), callbacks_.end(), other.callbacks_.begin());
32 }
33
34 Callbacks& append(const Callback &callback) {
35 callbacks_.push_back(callback);
36 return *this;
37 }
38
39 Callbacks& append(const Callbacks &other) {
40 callbacks_.insert(callbacks_.end(), other.callbacks_.begin(), other.callbacks_.end());
41 return *this;
42 }
43
44 Callbacks& prepend(const Callback &callback) {
45 callbacks_.push_front(callback);
46 return *this;
47 }
48
49 Callback& prepend(const Callbacks &other) {
50 callbacks_.insert(callbacks_.begin(), other.callbacks_.begin(), other.callbacks_.end());
51 return *this;
52 }
53
54 Callbacks& eraseFirst(const Callback &callback) {
55 for (typename CbList::iterator iter=callbacks_.begin(); iter!=callbacks_.end(); ++iter) {
56 if (*iter == callback) {
57 callbacks_.erase(iter);
58 break;
59 }
60 }
61 return *this;
62 }
63
64 Callbacks& eraseLast(const Callback &callback) {
65 for (typename CbList::reverse_iterator reverseIter=callbacks_.rbegin(); reverseIter!=callbacks_.rend(); ++reverseIter) {
66 if (*reverseIter == callback) {
67 typename CbList::iterator forwardIter = (++reverseIter).base();
68 callbacks_.erase(forwardIter);
69 break;
70 }
71 }
72 return *this;
73 }
74
75 Callbacks& eraseMatching(const Callback &callback) {
76 typename CbList::iterator iter = callbacks_.begin();
77 while (iter!=callbacks_.end()) {
78 if (*iter == callback) {
79 typename CbList::iterator toErase = iter++;
80 callbacks_.erase(toErase); // std::list iterators are stable over erasure
81 } else {
82 ++iter;
83 }
84 }
85 }
86
87 template<class CB, class Args>
88 bool applyCallback(CB *callback, bool chained, Args &args) const {
89 return (*callback)(chained, args);
90 }
91
92 template<class CB, class Args>
93 bool applyCallback(const SharedPointer<CB> &callback, bool chained, Args &args) const {
94 return (*callback)(chained, args);
95 }
96
97#if __cplusplus >= 201103ul
98 template<class CB, class Args>
99 bool applyCallback(const std::shared_ptr<CB> &callback, bool chained, Args &args) const {
100 return (*callback)(chained, args);
101 }
102#endif
103
104 template<class CB, class Args>
105 bool applyCallback(CB &callback, bool chained, Args &args) const {
106 return callback(chained, args);
107 }
108
109 template<class Arguments>
110 bool apply(bool chained, const Arguments &arguments) const {
111 for (typename CbList::const_iterator iter=callbacks_.begin(); iter!=callbacks_.end(); ++iter)
112 chained = applyCallback(*iter, chained, arguments);
113 return chained;
114 }
115
116 template<class Arguments>
117 bool apply(bool chained, Arguments &arguments) const {
118 for (typename CbList::const_iterator iter=callbacks_.begin(); iter!=callbacks_.end(); ++iter)
119 chained = applyCallback(*iter, chained, arguments);
120 return chained;
121 }
122};
123
124template<class Callback>
126 Callbacks<Callback> &callbacks_;
127 Callback callback_;
128public:
129 TemporaryCallback(Callbacks<Callback> &callbacks, const Callback &callback)
130 : callbacks_(callbacks), callback_(callback) {
131 callbacks_.append(callback);
132 }
133
135 callbacks_.eraseLast(callback_);
136 }
137};
138
139} // namespace
140
141#endif
Reference-counting intrusive smart pointer.
Sawyer support library.