1
2 #if !defined(INCLUDED_SIGNAL_H)
3 #define INCLUDED_SIGNAL_H
4
5 #include "isignal.h"
6 #include "memory/allocator.h"
7 #include "debugging/debugging.h"
8 #include <iterator>
9
10 namespace ListDetail {
11 struct ListNodeBase {
12 ListNodeBase* next;
13 ListNodeBase* prev;
14 };
15
list_initialise(ListNodeBase & self)16 inline void list_initialise(ListNodeBase& self) {
17 self.next = self.prev = &self;
18 }
19
list_swap(ListNodeBase & self,ListNodeBase & other)20 inline void list_swap(ListNodeBase& self, ListNodeBase& other) {
21 ListNodeBase tmp(self);
22 if (other.next == &other) {
23 list_initialise(self);
24 } else {
25 self = other;
26 self.next->prev = self.prev->next = &self;
27 }
28 if (tmp.next == &self) {
29 list_initialise(other);
30 } else {
31 other = tmp;
32 other.next->prev = other.prev->next = &other;
33 }
34 }
35
node_link(ListNodeBase * node,ListNodeBase * next)36 inline void node_link(ListNodeBase* node, ListNodeBase* next) {
37 node->next = next;
38 node->prev = next->prev;
39 next->prev = node;
40 node->prev->next = node;
41 }
node_unlink(ListNodeBase * node)42 inline void node_unlink(ListNodeBase* node) {
43 node->prev->next = node->next;
44 node->next->prev = node->prev;
45 }
46
47 template<typename Value>
48 struct ListNode : public ListNodeBase {
49 Value value;
50
ListNodeListNode51 ListNode(const Value& value) : value(value) {
52 }
getNextListNode53 ListNode* getNext() const {
54 return static_cast<ListNode*>(next);
55 }
getPrevListNode56 ListNode* getPrev() const {
57 return static_cast<ListNode*>(prev);
58 }
59 };
60
61 template<typename Type>
62 class NonConstTraits {
63 public:
64 typedef Type value_type;
65 typedef value_type* pointer;
66 typedef value_type& reference;
67
68 template<typename Other>
69 struct rebind {
70 typedef NonConstTraits<Other> other;
71 };
72 };
73
74 template<typename Type>
75 class ConstTraits {
76 public:
77 typedef Type value_type;
78 typedef const value_type* pointer;
79 typedef const value_type& reference;
80
81 template<typename Other>
82 struct rebind {
83 typedef ConstTraits<Other> other;
84 };
85 };
86
87 template<typename Traits>
88 class ListIterator {
89 public:
90 typedef std::bidirectional_iterator_tag iterator_category;
91 typedef std::ptrdiff_t difference_type;
92 typedef difference_type distance_type;
93 typedef typename Traits::value_type value_type;
94 typedef typename Traits::pointer pointer;
95 typedef typename Traits::reference reference;
96
97 private:
98 typedef ListNode<value_type> Node;
99 typedef typename Traits::template rebind<Node>::other NodeTraits;
100 typedef typename NodeTraits::pointer NodePointer;
101 typedef typename Traits::template rebind< Opaque<value_type> >::other OpaqueTraits;
102 typedef typename OpaqueTraits::pointer OpaquePointer;
103 NodePointer m_node;
104
increment()105 void increment() {
106 m_node = m_node->getNext();
107 }
decrement()108 void decrement() {
109 m_node = m_node->getPrev();
110 }
111
112
113 public:
ListIterator(NodePointer node)114 explicit ListIterator(NodePointer node) : m_node(node) {
115 }
ListIterator(OpaquePointer p)116 explicit ListIterator(OpaquePointer p) : m_node(reinterpret_cast<NodePointer>(p)) {
117 }
118
node()119 NodePointer node() {
120 return m_node;
121 }
opaque()122 OpaquePointer opaque() const {
123 return reinterpret_cast<OpaquePointer>(m_node);
124 }
125
126 bool operator==(const ListIterator& other) const {
127 return m_node == other.m_node;
128 }
129 bool operator!=(const ListIterator& other) const {
130 return !operator==(other);
131 }
132 ListIterator& operator++() {
133 increment();
134 return *this;
135 }
136 ListIterator operator++(int) {
137 ListIterator tmp = *this;
138 increment();
139 return tmp;
140 }
141 ListIterator& operator--() {
142 decrement();
143 return *this;
144 }
145 ListIterator operator--(int) {
146 ListIterator tmp = *this;
147 decrement();
148 return tmp;
149 }
150 reference operator*() const {
151 return m_node->value;
152 }
153 pointer operator->() const {
154 return &(operator*());
155 }
156 };
157 }
158
159 template < typename Value, typename Allocator = DefaultAllocator<Value> >
160 class List : private Allocator {
161 typedef ListDetail::ListNode<Value> Node;
162 ListDetail::ListNodeBase list;
163 typedef typename Allocator::template rebind<Node>::other NodeAllocator;
164
newNode(const Value & value)165 Node* newNode(const Value& value) {
166 return new (NodeAllocator(*this).allocate(1)) Node(value);
167 }
deleteNode(Node * node)168 void deleteNode(Node* node) {
169 node->~Node();
170 NodeAllocator(*this).deallocate(node, 1);
171 }
172 public:
173 typedef Value value_type;
174 typedef ListDetail::ListIterator< ListDetail::NonConstTraits<Value> > iterator;
175 typedef ListDetail::ListIterator< ListDetail::ConstTraits<Value> > const_iterator;
176
List()177 List() {
178 list_initialise(list);
179 }
List(const Allocator & allocator)180 explicit List(const Allocator& allocator) : Allocator(allocator) {
181 list_initialise(list);
182 }
~List()183 ~List() {
184 for (; list.next != &list;) {
185 Node* node = static_cast<Node*>(list.next);
186 list.next = list.next->next;
187 deleteNode(node);
188 }
189 }
begin()190 iterator begin() {
191 return iterator(static_cast<Node*>(list.next));
192 }
end()193 iterator end() {
194 return iterator(static_cast<Node*>(&list));
195 }
begin()196 const_iterator begin() const {
197 return const_iterator(static_cast<const Node*>(list.next));
198 }
end()199 const_iterator end() const {
200 return const_iterator(static_cast<const Node*>(&list));
201 }
push_back(const Value & value)202 void push_back(const Value& value) {
203 insert(end(), value);
204 }
pop_back(const Value & value)205 void pop_back(const Value& value) {
206 erase(--end(), value);
207 }
push_front(const Value & value)208 void push_front(const Value& value) {
209 insert(begin(), value);
210 }
pop_front(const Value & value)211 void pop_front(const Value& value) {
212 erase(begin(), value);
213 }
insert(iterator pos,const Value & value)214 iterator insert(iterator pos, const Value& value) {
215 Node* node = newNode(value);
216 node_link(node, pos.node());
217 return iterator(node);
218 }
erase(iterator pos)219 iterator erase(iterator pos) {
220 Node* node = pos.node();
221 Node* next = node->getNext();
222 node_unlink(node);
223 deleteNode(node);
224 return iterator(next);
225 }
226 };
227
228 template<typename Functor>
229 class SignalBase {
230 typedef List<Functor> SignalList;
231 SignalList events;
232
233 public:
234
235 typedef Functor handler_type;
236 typedef Handle< Opaque<Functor> > handler_id_type;
237 typedef typename SignalList::iterator iterator;
238 typedef typename SignalList::const_iterator const_iterator;
begin()239 iterator begin() {
240 return events.begin();
241 }
end()242 iterator end() {
243 return events.end();
244 }
begin()245 const_iterator begin() const {
246 return events.begin();
247 }
end()248 const_iterator end() const {
249 return events.end();
250 }
connectFirst(const Functor & event)251 handler_id_type connectFirst(const Functor& event) {
252 events.push_front(event);
253 return handler_id_type(begin().opaque());
254 }
connectLast(const Functor & event)255 handler_id_type connectLast(const Functor& event) {
256 events.push_back(event);
257 return handler_id_type((--end()).opaque());
258 }
isConnected(handler_id_type id)259 bool isConnected(handler_id_type id) {
260 for (iterator i = begin(); i != end(); ++i) {
261 if (id.get() == i.opaque()) {
262 return true;
263 }
264 }
265 return false;
266 }
connectBefore(handler_id_type id,const Functor & event)267 handler_id_type connectBefore(handler_id_type id, const Functor& event) {
268 ASSERT_MESSAGE(isConnected(id), "SignalBase::connectBefore: invalid id");
269 return events.insert(iterator(id.get()), event).opaque();
270 }
connectAfter(handler_id_type id,const Functor & event)271 handler_id_type connectAfter(handler_id_type id, const Functor& event) {
272 ASSERT_MESSAGE(isConnected(id), "SignalBase::connectAfter: invalid id");
273 return events.insert(++iterator(id.get()), event).opaque();
274 }
disconnect(handler_id_type id)275 void disconnect(handler_id_type id) {
276 ASSERT_MESSAGE(isConnected(id), "SignalBase::disconnect: invalid id");
277 events.erase(iterator(id.get()));
278 }
279 };
280
281 ///\brief
282 // It is safe to disconnect the signal handler currently being invoked.
283 template<typename InputIterator, typename SignalHandlerInvoke>
invokeSignalHandlers(InputIterator first,InputIterator last,SignalHandlerInvoke invoke)284 inline void invokeSignalHandlers(InputIterator first, InputIterator last, SignalHandlerInvoke invoke) {
285 while (first != last && invoke(*first++) != SIGNAL_STOP_EMISSION) {
286 }
287 }
288
289 class Signal0 : public SignalBase<SignalHandler> {
290 public:
operator()291 void operator()() const {
292 invokeSignalHandlers(begin(), end(), FunctorInvoke<handler_type>());
293 }
294 };
295
296 template<typename FirstArgument>
297 class Signal1 : public SignalBase< SignalHandler1<FirstArgument> > {
298 typedef SignalBase< SignalHandler1<FirstArgument> > Base;
299 public:
operator()300 void operator()(FirstArgument a1) const {
301 invokeSignalHandlers(Base::begin(), Base::end(), Functor1Invoke<typename Base::handler_type>(a1));
302 }
303 };
304
305 template<typename FirstArgument, typename SecondArgument>
306 class Signal2 : public SignalBase< SignalHandler2<FirstArgument, SecondArgument> > {
307 typedef SignalBase< SignalHandler2<FirstArgument, SecondArgument> > Base;
308 public:
operator()309 void operator()(FirstArgument a1, SecondArgument a2) const {
310 invokeSignalHandlers(Base::begin(), Base::end(), Functor2Invoke<typename Base::handler_type>(a1, a2));
311 }
312 };
313
314 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument>
315 class Signal3 : public SignalBase< SignalHandler3<FirstArgument, SecondArgument, ThirdArgument> > {
316 typedef SignalBase< SignalHandler3<FirstArgument, SecondArgument, ThirdArgument> > Base;
317 public:
operator()318 void operator()(FirstArgument a1, SecondArgument a2, ThirdArgument a3) const {
319 invokeSignalHandlers(Base::begin(), Base::end(), Functor3Invoke<typename Base::handler_type>(a1, a2, a3));
320 }
321 };
322
323 #endif
324