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