#if !defined(INCLUDED_SIGNAL_H) #define INCLUDED_SIGNAL_H #include "isignal.h" #include "memory/allocator.h" #include "debugging/debugging.h" #include namespace ListDetail { struct ListNodeBase { ListNodeBase* next; ListNodeBase* prev; }; inline void list_initialise(ListNodeBase& self) { self.next = self.prev = &self; } inline void list_swap(ListNodeBase& self, ListNodeBase& other) { ListNodeBase tmp(self); if(other.next == &other) { list_initialise(self); } else { self = other; self.next->prev = self.prev->next = &self; } if(tmp.next == &self) { list_initialise(other); } else { other = tmp; other.next->prev = other.prev->next = &other; } } inline void node_link(ListNodeBase* node, ListNodeBase* next) { node->next = next; node->prev = next->prev; next->prev = node; node->prev->next = node; } inline void node_unlink(ListNodeBase* node) { node->prev->next = node->next; node->next->prev = node->prev; } template struct ListNode : public ListNodeBase { Value value; ListNode(const Value& value) : value(value) { } ListNode* getNext() const { return static_cast(next); } ListNode* getPrev() const { return static_cast(prev); } }; template class NonConstTraits { public: typedef Type value_type; typedef value_type* pointer; typedef value_type& reference; template struct rebind { typedef NonConstTraits other; }; }; template class ConstTraits { public: typedef Type value_type; typedef const value_type* pointer; typedef const value_type& reference; template struct rebind { typedef ConstTraits other; }; }; template class ListIterator { public: typedef std::bidirectional_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; typedef difference_type distance_type; typedef typename Traits::value_type value_type; typedef typename Traits::pointer pointer; typedef typename Traits::reference reference; private: typedef ListNode Node; typedef typename Traits::template rebind::other NodeTraits; typedef typename NodeTraits::pointer NodePointer; typedef typename Traits::template rebind< Opaque >::other OpaqueTraits; typedef typename OpaqueTraits::pointer OpaquePointer; NodePointer m_node; void increment() { m_node = m_node->getNext(); } void decrement() { m_node = m_node->getPrev(); } public: explicit ListIterator(NodePointer node) : m_node(node) { } explicit ListIterator(OpaquePointer p) : m_node(reinterpret_cast(p)) { } NodePointer node() { return m_node; } OpaquePointer opaque() const { return reinterpret_cast(m_node); } bool operator==(const ListIterator& other) const { return m_node == other.m_node; } bool operator!=(const ListIterator& other) const { return !operator==(other); } ListIterator& operator++() { increment(); return *this; } ListIterator operator++(int) { ListIterator tmp = *this; increment(); return tmp; } ListIterator& operator--() { decrement(); return *this; } ListIterator operator--(int) { ListIterator tmp = *this; decrement(); return tmp; } reference operator*() const { return m_node->value; } pointer operator->() const { return &(operator*()); } }; } template > class List : private Allocator { typedef ListDetail::ListNode Node; ListDetail::ListNodeBase list; typedef typename Allocator::template rebind::other NodeAllocator; Node* newNode(const Value& value) { return new (NodeAllocator(*this).allocate(1)) Node(value); } void deleteNode(Node* node) { node->~Node(); NodeAllocator(*this).deallocate(node, 1); } public: typedef Value value_type; typedef ListDetail::ListIterator< ListDetail::NonConstTraits > iterator; typedef ListDetail::ListIterator< ListDetail::ConstTraits > const_iterator; List() { list_initialise(list); } explicit List(const Allocator& allocator) : Allocator(allocator) { list_initialise(list); } ~List() { for(; list.next != &list;) { Node* node = static_cast(list.next); list.next = list.next->next; deleteNode(node); } } iterator begin() { return iterator(static_cast(list.next)); } iterator end() { return iterator(static_cast(&list)); } const_iterator begin() const { return const_iterator(static_cast(list.next)); } const_iterator end() const { return const_iterator(static_cast(&list)); } void push_back(const Value& value) { insert(end(), value); } void pop_back(const Value& value) { erase(--end(), value); } void push_front(const Value& value) { insert(begin(), value); } void pop_front(const Value& value) { erase(begin(), value); } iterator insert(iterator pos, const Value& value) { Node* node = newNode(value); node_link(node, pos.node()); return iterator(node); } iterator erase(iterator pos) { Node* node = pos.node(); Node* next = node->getNext(); node_unlink(node); deleteNode(node); return iterator(next); } }; template class SignalBase { typedef List SignalList; SignalList events; public: typedef Functor handler_type; typedef Handle< Opaque > handler_id_type; typedef typename SignalList::iterator iterator; typedef typename SignalList::const_iterator const_iterator; iterator begin() { return events.begin(); } iterator end() { return events.end(); } const_iterator begin() const { return events.begin(); } const_iterator end() const { return events.end(); } handler_id_type connectFirst(const Functor& event) { events.push_front(event); return handler_id_type(begin().opaque()); } handler_id_type connectLast(const Functor& event) { events.push_back(event); return handler_id_type((--end()).opaque()); } bool isConnected(handler_id_type id) { for(iterator i = begin(); i != end(); ++i) { if(id.get() == i.opaque()) { return true; } } return false; } handler_id_type connectBefore(handler_id_type id, const Functor& event) { ASSERT_MESSAGE(isConnected(id), "SignalBase::connectBefore: invalid id"); return events.insert(iterator(id.get()), event).opaque(); } handler_id_type connectAfter(handler_id_type id, const Functor& event) { ASSERT_MESSAGE(isConnected(id), "SignalBase::connectAfter: invalid id"); return events.insert(++iterator(id.get()), event).opaque(); } void disconnect(handler_id_type id) { ASSERT_MESSAGE(isConnected(id), "SignalBase::disconnect: invalid id"); events.erase(iterator(id.get())); } }; ///\brief // It is safe to disconnect the signal handler currently being invoked. template inline void invokeSignalHandlers(InputIterator first, InputIterator last, SignalHandlerInvoke invoke) { while(first != last && invoke(*first++) != SIGNAL_STOP_EMISSION); } class Signal0 : public SignalBase { public: void operator()() const { invokeSignalHandlers(begin(), end(), FunctorInvoke()); } }; template class Signal1 : public SignalBase< SignalHandler1 > { typedef SignalBase< SignalHandler1 > Base; public: void operator()(FirstArgument a1) const { invokeSignalHandlers(Base::begin(), Base::end(), Functor1Invoke(a1)); } }; template class Signal2 : public SignalBase< SignalHandler2 > { typedef SignalBase< SignalHandler2 > Base; public: void operator()(FirstArgument a1, SecondArgument a2) const { invokeSignalHandlers(Base::begin(), Base::end(), Functor2Invoke(a1, a2)); } }; template class Signal3 : public SignalBase< SignalHandler3 > { typedef SignalBase< SignalHandler3 > Base; public: void operator()(FirstArgument a1, SecondArgument a2, ThirdArgument a3) const { invokeSignalHandlers(Base::begin(), Base::end(), Functor3Invoke(a1, a2, a3)); } }; #endif