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