Skip to content
Browse files

Merge pull request #72 from arturoc/feature-voidevent

add VoidEvent
  • Loading branch information...
2 parents a44758f + f731dbb commit f5c091fd14e621ead5e4916af444d256ea420f0e @aleks-f aleks-f committed Jan 23, 2013
View
38 Foundation/include/Poco/AbstractDelegate.h
@@ -85,6 +85,44 @@ class AbstractDelegate
}
};
+template <>
+class AbstractDelegate<void>
+ /// Base class for Delegate and Expire.
+{
+public:
+ AbstractDelegate()
+ {
+ }
+
+ AbstractDelegate(const AbstractDelegate& del)
+ {
+ }
+
+ virtual ~AbstractDelegate()
+ {
+ }
+
+ virtual bool notify(const void* sender) = 0;
+ /// Invokes the delegate's callback function.
+ /// Returns true if successful, or false if the delegate
+ /// has been disabled or has expired.
+
+ virtual bool equals(const AbstractDelegate& other) const = 0;
+ /// Compares the AbstractDelegate with the other one for equality.
+
+ virtual AbstractDelegate* clone() const = 0;
+ /// Returns a deep copy of the AbstractDelegate.
+
+ virtual void disable() = 0;
+ /// Disables the delegate, which is done prior to removal.
+
+ virtual const AbstractDelegate* unwrap() const
+ /// Returns the unwrapped delegate. Must be overridden by decorators
+ /// like Expire.
+ {
+ return this;
+ }
+};
} // namespace Poco
View
290 Foundation/include/Poco/AbstractEvent.h
@@ -346,6 +346,296 @@ class AbstractEvent
AbstractEvent& operator = (const AbstractEvent& other);
};
+template <class TStrategy, class TDelegate, class TMutex>
+class AbstractEvent<void,TStrategy,TDelegate,TMutex>
+ /// An AbstractEvent is the base class of all events.
+ /// It works similar to the way C# handles notifications (aka events in C#).
+ ///
+ /// Events can be used to send information to a set of delegates
+ /// which are registered with the event. The type of the data is specified with
+ /// the template parameter TArgs. The TStrategy parameter must be a subclass
+ /// of NotificationStrategy. The parameter TDelegate can either be a subclass of AbstractDelegate
+ /// or of AbstractPriorityDelegate.
+ ///
+ /// Note that AbstractEvent should never be used directly. One ought to use
+ /// one of its subclasses which set the TStrategy and TDelegate template parameters
+ /// to fixed values. For most use-cases the BasicEvent template will be sufficient:
+ ///
+ /// #include "Poco/BasicEvent.h"
+ /// #include "Poco/Delegate.h"
+ ///
+ /// Note that as of release 1.4.2, the behavior of BasicEvent equals that of FIFOEvent,
+ /// so the FIFOEvent class is no longer necessary and provided for backwards compatibility
+ /// only.
+ ///
+ /// BasicEvent works with a standard delegate. They allow one object to register
+ /// onr or more delegates with an event. In contrast, a PriorityDelegate comes with an attached priority value
+ /// and allows one object to register for one priority value one or more delegates. Note that PriorityDelegates
+ /// only work with PriorityEvents:
+ ///
+ /// #include "Poco/PriorityEvent.h"
+ /// #include "Poco/PriorityDelegate.h"
+ ///
+ /// Use events by adding them as public members to the object which is throwing notifications:
+ ///
+ /// class MyData
+ /// {
+ /// public:
+ /// Poco::BasicEvent<int> dataChanged;
+ ///
+ /// MyData();
+ /// ...
+ /// void setData(int i);
+ /// ...
+ /// private:
+ /// int _data;
+ /// };
+ ///
+ /// Firing the event is done either by calling the event's notify() or notifyAsync() method:
+ ///
+ /// void MyData::setData(int i)
+ /// {
+ /// this->_data = i;
+ /// dataChanged.notify(this, this->_data);
+ /// }
+ ///
+ /// Alternatively, instead of notify(), operator () can be used.
+ ///
+ /// void MyData::setData(int i)
+ /// {
+ /// this->_data = i;
+ /// dataChanged(this, this->_data);
+ /// }
+ ///
+ /// Note that operator (), notify() and notifyAsync() do not catch exceptions, i.e. in case a
+ /// delegate throws an exception, notifying is immediately aborted and the exception is propagated
+ /// back to the caller.
+ ///
+ /// Delegates can register methods at the event. In the case of a BasicEvent
+ /// the Delegate template is used, in case of an PriorityEvent a PriorityDelegate is used.
+ /// Mixing of delegates, e.g. using a PriorityDelegate with a BasicEvent is not allowed and
+ /// can lead to compile-time and/or run-time errors. The standalone delegate() functions
+ /// can be used to construct Delegate objects.
+ ///
+ /// Events require the observers to have one of the following method signatures:
+ ///
+ /// void onEvent(const void* pSender, TArgs& args);
+ /// void onEvent(TArgs& args);
+ /// static void onEvent(const void* pSender, TArgs& args);
+ /// static void onEvent(void* pSender, TArgs& args);
+ /// static void onEvent(TArgs& args);
+ ///
+ /// For performance reasons arguments are always sent by reference. This also allows observers
+ /// to modify the event argument. To prevent that, use <[const TArg]> as template
+ /// parameter. A non-conformant method signature leads to compile errors.
+ ///
+ /// Assuming that the observer meets the method signature requirement, it can register
+ /// this method with the += operator:
+ ///
+ /// class MyController
+ /// {
+ /// protected:
+ /// MyData _data;
+ ///
+ /// void onDataChanged(void* pSender, int& data);
+ /// ...
+ /// };
+ ///
+ /// MyController::MyController()
+ /// {
+ /// _data.dataChanged += delegate(this, &MyController::onDataChanged);
+ /// }
+ ///
+ /// In some cases it might be desirable to work with automatically expiring registrations. Simply add
+ /// to delegate as 3rd parameter a expireValue (in milliseconds):
+ ///
+ /// _data.dataChanged += delegate(this, &MyController::onDataChanged, 1000);
+ ///
+ /// This will add a delegate to the event which will automatically be removed in 1000 millisecs.
+ ///
+ /// Unregistering happens via the -= operator. Forgetting to unregister a method will lead to
+ /// segmentation faults later, when one tries to send a notify to a no longer existing object.
+ ///
+ /// MyController::~MyController()
+ /// {
+ /// _data.dataChanged -= delegate(this, &MyController::onDataChanged);
+ /// }
+ ///
+ /// Working with PriorityDelegate's as similar to working with BasicEvent.
+ /// Instead of delegate(), the priorityDelegate() function must be used
+ /// to create the PriorityDelegate.
+{
+public:
+ AbstractEvent():
+ _executeAsync(this, &AbstractEvent::executeAsyncImpl),
+ _enabled(true)
+ {
+ }
+
+ AbstractEvent(const TStrategy& strat):
+ _executeAsync(this, &AbstractEvent::executeAsyncImpl),
+ _strategy(strat),
+ _enabled(true)
+ {
+ }
+
+ virtual ~AbstractEvent()
+ {
+ }
+
+ void operator += (const TDelegate& aDelegate)
+ /// Adds a delegate to the event.
+ ///
+ /// Exact behavior is determined by the TStrategy.
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+ _strategy.add(aDelegate);
+ }
+
+ void operator -= (const TDelegate& aDelegate)
+ /// Removes a delegate from the event.
+ ///
+ /// If the delegate is not found, this function does nothing.
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+ _strategy.remove(aDelegate);
+ }
+
+ void operator () (const void* pSender)
+ /// Shortcut for notify(pSender, args);
+ {
+ notify(pSender);
+ }
+
+ void operator () ()
+ /// Shortcut for notify(args).
+ {
+ notify(0);
+ }
+
+ void notify(const void* pSender)
+ /// Sends a notification to all registered delegates. The order is
+ /// determined by the TStrategy. This method is blocking. While executing,
+ /// the list of delegates may be modified. These changes don't
+ /// influence the current active notifications but are activated with
+ /// the next notify. If a delegate is removed during a notify(), the
+ /// delegate will no longer be invoked (unless it has already been
+ /// invoked prior to removal). If one of the delegates throws an exception,
+ /// the notify method is immediately aborted and the exception is propagated
+ /// to the caller.
+ {
+ Poco::ScopedLockWithUnlock<TMutex> lock(_mutex);
+
+ if (!_enabled) return;
+
+ // thread-safeness:
+ // copy should be faster and safer than blocking until
+ // execution ends
+ TStrategy strategy(_strategy);
+ lock.unlock();
+ strategy.notify(pSender);
+ }
+
+ ActiveResult<void> notifyAsync(const void* pSender)
+ /// Sends a notification to all registered delegates. The order is
+ /// determined by the TStrategy. This method is not blocking and will
+ /// immediately return. The delegates are invoked in a seperate thread.
+ /// Call activeResult.wait() to wait until the notification has ended.
+ /// While executing, other objects can change the delegate list. These changes don't
+ /// influence the current active notifications but are activated with
+ /// the next notify. If a delegate is removed during a notify(), the
+ /// delegate will no longer be invoked (unless it has already been
+ /// invoked prior to removal). If one of the delegates throws an exception,
+ /// the execution is aborted and the exception is propagated to the caller.
+ {
+ NotifyAsyncParams params(pSender);
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+
+ // thread-safeness:
+ // copy should be faster and safer than blocking until
+ // execution ends
+ // make a copy of the strategy here to guarantee that
+ // between notifyAsync and the execution of the method no changes can occur
+
+ params.ptrStrat = SharedPtr<TStrategy>(new TStrategy(_strategy));
+ params.enabled = _enabled;
+ }
+ ActiveResult<void> result = _executeAsync(params);
+ return result;
+ }
+
+ void enable()
+ /// Enables the event.
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+ _enabled = true;
+ }
+
+ void disable()
+ /// Disables the event. notify and notifyAsnyc will be ignored,
+ /// but adding/removing delegates is still allowed.
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+ _enabled = false;
+ }
+
+ bool isEnabled() const
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+ return _enabled;
+ }
+
+ void clear()
+ /// Removes all delegates.
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+ _strategy.clear();
+ }
+
+ bool empty() const
+ /// Checks if any delegates are registered at the delegate.
+ {
+ typename TMutex::ScopedLock lock(_mutex);
+ return _strategy.empty();
+ }
+
+protected:
+ struct NotifyAsyncParams
+ {
+ SharedPtr<TStrategy> ptrStrat;
+ const void* pSender;
+ bool enabled;
+
+ NotifyAsyncParams(const void* pSend):ptrStrat(), pSender(pSend), enabled(true)
+ /// Default constructor reduces the need for TArgs to have an empty constructor, only copy constructor is needed.
+ {
+ }
+ };
+
+ ActiveMethod<void, NotifyAsyncParams, AbstractEvent> _executeAsync;
+
+ void executeAsyncImpl(const NotifyAsyncParams& par)
+ {
+ if (!par.enabled)
+ {
+ return;
+ }
+
+ NotifyAsyncParams params = par;
+ params.ptrStrat->notify(params.pSender);
+ return;
+ }
+
+ TStrategy _strategy; /// The strategy used to notify observers.
+ bool _enabled; /// Stores if an event is enabled. Notfies on disabled events have no effect
+ /// but it is possible to change the observers.
+ mutable TMutex _mutex;
+
+private:
+ AbstractEvent(const AbstractEvent& other);
+ AbstractEvent& operator = (const AbstractEvent& other);
+};
} // namespace Poco
View
79 Foundation/include/Poco/DefaultStrategy.h
@@ -128,6 +128,85 @@ class DefaultStrategy: public NotificationStrategy<TArgs, TDelegate>
Delegates _delegates;
};
+template <class TDelegate>
+class DefaultStrategy<void,TDelegate>: public NotificationStrategy<void, TDelegate>
+ /// Default notification strategy.
+ ///
+ /// Internally, a std::vector<> is used to store
+ /// delegate objects. Delegates are invoked in the
+ /// order in which they have been registered.
+{
+public:
+ typedef SharedPtr<TDelegate> DelegatePtr;
+ typedef std::vector<DelegatePtr> Delegates;
+ typedef typename Delegates::iterator Iterator;
+
+public:
+ DefaultStrategy()
+ {
+ }
+
+ DefaultStrategy(const DefaultStrategy& s):
+ _delegates(s._delegates)
+ {
+ }
+
+ ~DefaultStrategy()
+ {
+ }
+
+ void notify(const void* sender)
+ {
+ for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+ {
+ (*it)->notify(sender);
+ }
+ }
+
+ void add(const TDelegate& delegate)
+ {
+ _delegates.push_back(DelegatePtr(static_cast<TDelegate*>(delegate.clone())));
+ }
+
+ void remove(const TDelegate& delegate)
+ {
+ for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+ {
+ if (delegate.equals(**it))
+ {
+ (*it)->disable();
+ _delegates.erase(it);
+ return;
+ }
+ }
+ }
+
+ DefaultStrategy& operator = (const DefaultStrategy& s)
+ {
+ if (this != &s)
+ {
+ _delegates = s._delegates;
+ }
+ return *this;
+ }
+
+ void clear()
+ {
+ for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+ {
+ (*it)->disable();
+ }
+ _delegates.clear();
+ }
+
+ bool empty() const
+ {
+ return _delegates.empty();
+ }
+
+protected:
+ Delegates _delegates;
+};
} // namespace Poco
View
209 Foundation/include/Poco/Delegate.h
@@ -263,6 +263,215 @@ static FunctionDelegate<TArgs, false> delegate(void (*NotifyMethod)(TArgs&))
}
+
+
+
+template <class TObj>
+class Delegate<TObj,void,true>: public AbstractDelegate<void>
+{
+public:
+ typedef void (TObj::*NotifyMethod)(const void*);
+
+ Delegate(TObj* obj, NotifyMethod method):
+ _receiverObject(obj),
+ _receiverMethod(method)
+ {
+ }
+
+ Delegate(const Delegate& delegate):
+ AbstractDelegate<void>(delegate),
+ _receiverObject(delegate._receiverObject),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ ~Delegate()
+ {
+ }
+
+ Delegate& operator = (const Delegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ this->_receiverObject = delegate._receiverObject;
+ this->_receiverMethod = delegate._receiverMethod;
+ }
+ return *this;
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverObject)
+ {
+ (_receiverObject->*_receiverMethod)(sender);
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const Delegate* pOtherDelegate = reinterpret_cast<const Delegate*>(other.unwrap());
+ return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new Delegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverObject = 0;
+ }
+
+protected:
+ TObj* _receiverObject;
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ Delegate();
+};
+
+
+template <class TObj>
+class Delegate<TObj, void, false>: public AbstractDelegate<void>
+{
+public:
+ typedef void (TObj::*NotifyMethod)();
+
+ Delegate(TObj* obj, NotifyMethod method):
+ _receiverObject(obj),
+ _receiverMethod(method)
+ {
+ }
+
+ Delegate(const Delegate& delegate):
+ AbstractDelegate<void>(delegate),
+ _receiverObject(delegate._receiverObject),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ ~Delegate()
+ {
+ }
+
+ Delegate& operator = (const Delegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ this->_pTarget = delegate._pTarget;
+ this->_receiverObject = delegate._receiverObject;
+ this->_receiverMethod = delegate._receiverMethod;
+ }
+ return *this;
+ }
+
+ bool notify(const void*)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverObject)
+ {
+ (_receiverObject->*_receiverMethod)();
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const Delegate* pOtherDelegate = reinterpret_cast<const Delegate*>(other.unwrap());
+ return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new Delegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverObject = 0;
+ }
+
+protected:
+ TObj* _receiverObject;
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ Delegate();
+};
+
+
+template <class TObj>
+static Delegate<TObj, void, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*))
+{
+ return Delegate<TObj, void, true>(pObj, NotifyMethod);
+}
+
+
+template <class TObj>
+static Delegate<TObj, void, false> delegate(TObj* pObj, void (TObj::*NotifyMethod)())
+{
+ return Delegate<TObj, void, false>(pObj, NotifyMethod);
+}
+
+
+template <class TObj>
+static Expire<void> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), Timestamp::TimeDiff expireMillisecs)
+{
+ return Expire<void>(Delegate<TObj, void, true>(pObj, NotifyMethod), expireMillisecs);
+}
+
+
+template <class TObj>
+static Expire<void> delegate(TObj* pObj, void (TObj::*NotifyMethod)(), Timestamp::TimeDiff expireMillisecs)
+{
+ return Expire<void>(Delegate<TObj, void, false>(pObj, NotifyMethod), expireMillisecs);
+}
+
+
+inline Expire<void> delegate(void (*NotifyMethod)(const void*), Timestamp::TimeDiff expireMillisecs)
+{
+ return Expire<void>(FunctionDelegate<void, true, true>(NotifyMethod), expireMillisecs);
+}
+
+
+inline Expire<void> delegate(void (*NotifyMethod)(void*), Timestamp::TimeDiff expireMillisecs)
+{
+ return Expire<void>(FunctionDelegate<void, true, false>(NotifyMethod), expireMillisecs);
+}
+
+
+inline Expire<void> delegate(void (*NotifyMethod)(), Timestamp::TimeDiff expireMillisecs)
+{
+ return Expire<void>(FunctionDelegate<void, false>(NotifyMethod), expireMillisecs);
+}
+
+
+inline FunctionDelegate<void, true, true> delegate(void (*NotifyMethod)(const void*))
+{
+ return FunctionDelegate<void, true, true>(NotifyMethod);
+}
+
+
+inline FunctionDelegate<void, true, false> delegate(void (*NotifyMethod)(void*))
+{
+ return FunctionDelegate<void, true, false>(NotifyMethod);
+}
+
+
+inline FunctionDelegate<void, false> delegate(void (*NotifyMethod)())
+{
+ return FunctionDelegate<void, false>(NotifyMethod);
+}
+
} // namespace Poco
View
81 Foundation/include/Poco/Expire.h
@@ -128,6 +128,87 @@ class Expire: public AbstractDelegate<TArgs>
Expire();
};
+template <>
+class Expire<void>: public AbstractDelegate<void>
+ /// Decorator for AbstractDelegate adding automatic
+ /// expiration of registrations to AbstractDelegate's.
+{
+public:
+ Expire(const AbstractDelegate<void>& p, Timestamp::TimeDiff expireMillisecs):
+ _pDelegate(p.clone()),
+ _expire(expireMillisecs*1000)
+ {
+ }
+
+ Expire(const Expire& expire):
+ AbstractDelegate<void>(expire),
+ _pDelegate(expire._pDelegate->clone()),
+ _expire(expire._expire),
+ _creationTime(expire._creationTime)
+ {
+ }
+
+ ~Expire()
+ {
+ delete _pDelegate;
+ }
+
+ Expire& operator = (const Expire& expire)
+ {
+ if (&expire != this)
+ {
+ delete this->_pDelegate;
+ this->_pDelegate = expire._pDelegate->clone();
+ this->_expire = expire._expire;
+ this->_creationTime = expire._creationTime;
+ //this->_pTarget = expire._pTarget;
+ }
+ return *this;
+ }
+
+ bool notify(const void* sender)
+ {
+ if (!expired())
+ return this->_pDelegate->notify(sender);
+ else
+ return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ return other.equals(*_pDelegate);
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new Expire(*this);
+ }
+
+ void disable()
+ {
+ _pDelegate->disable();
+ }
+
+ const AbstractDelegate<void>* unwrap() const
+ {
+ return this->_pDelegate;
+ }
+
+protected:
+ bool expired() const
+ {
+ return _creationTime.isElapsed(_expire);
+ }
+
+ AbstractDelegate<void>* _pDelegate;
+ Timestamp::TimeDiff _expire;
+ Timestamp _creationTime;
+
+private:
+ Expire();
+};
+
+
} // namespace Poco
View
210 Foundation/include/Poco/FunctionDelegate.h
@@ -254,6 +254,216 @@ class FunctionDelegate<TArgs, false, senderIsConst>: public AbstractDelegate<TAr
};
+
+
+
+
+template <>
+class FunctionDelegate<void,true,true>: public AbstractDelegate<void>
+ /// Wraps a freestanding function or static member function
+ /// for use as a Delegate.
+{
+public:
+ typedef void (*NotifyMethod)(const void*);
+
+ FunctionDelegate(NotifyMethod method):
+ _receiverMethod(method)
+ {
+ }
+
+ FunctionDelegate(const FunctionDelegate& delegate):
+ AbstractDelegate<void>(delegate),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ ~FunctionDelegate()
+ {
+ }
+
+ FunctionDelegate& operator = (const FunctionDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ //this->_pTarget = delegate._pTarget;
+ this->_receiverMethod = delegate._receiverMethod;
+ }
+ return *this;
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverMethod)
+ {
+ (*_receiverMethod)(sender);
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+ return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new FunctionDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverMethod = 0;
+ }
+
+protected:
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ FunctionDelegate();
+};
+
+
+template <>
+class FunctionDelegate<void, true, false>: public AbstractDelegate<void>
+{
+public:
+ typedef void (*NotifyMethod)(void*);
+
+ FunctionDelegate(NotifyMethod method):
+ _receiverMethod(method)
+ {
+ }
+
+ FunctionDelegate(const FunctionDelegate& delegate):
+ AbstractDelegate<void>(delegate),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ ~FunctionDelegate()
+ {
+ }
+
+ FunctionDelegate& operator = (const FunctionDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ //this->_pTarget = delegate._pTarget;
+ this->_receiverMethod = delegate._receiverMethod;
+ }
+ return *this;
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverMethod)
+ {
+ (*_receiverMethod)(const_cast<void*>(sender));
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+ return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new FunctionDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverMethod = 0;
+ }
+
+protected:
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ FunctionDelegate();
+};
+
+
+template <bool senderIsConst>
+class FunctionDelegate<void, false, senderIsConst>: public AbstractDelegate<void>
+{
+public:
+ typedef void (*NotifyMethod)();
+
+ FunctionDelegate(NotifyMethod method):
+ _receiverMethod(method)
+ {
+ }
+
+ FunctionDelegate(const FunctionDelegate& delegate):
+ AbstractDelegate<void>(delegate),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ ~FunctionDelegate()
+ {
+ }
+
+ FunctionDelegate& operator = (const FunctionDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ //this->_pTarget = delegate._pTarget;
+ this->_receiverMethod = delegate._receiverMethod;
+ }
+ return *this;
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverMethod)
+ {
+ (*_receiverMethod)();
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+ return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new FunctionDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverMethod = 0;
+ }
+
+protected:
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ FunctionDelegate();
+};
+
+
} // namespace Poco
View
208 Foundation/include/Poco/FunctionPriorityDelegate.h
@@ -260,6 +260,214 @@ class FunctionPriorityDelegate<TArgs, false>: public AbstractPriorityDelegate<TA
};
+template <>
+class FunctionPriorityDelegate<void,true,true>: public AbstractPriorityDelegate<void>
+ /// Wraps a freestanding function or static member function
+ /// for use as a PriorityDelegate.
+{
+public:
+ typedef void (*NotifyMethod)(const void*);
+
+ FunctionPriorityDelegate(NotifyMethod method, int prio):
+ AbstractPriorityDelegate<void>(prio),
+ _receiverMethod(method)
+ {
+ }
+
+ FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+ AbstractPriorityDelegate<void>(delegate),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ this->_receiverMethod = delegate._receiverMethod;
+ this->_priority = delegate._priority;
+ }
+ return *this;
+ }
+
+ ~FunctionPriorityDelegate()
+ {
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverMethod)
+ {
+ (*_receiverMethod)(sender);
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+ return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new FunctionPriorityDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverMethod = 0;
+ }
+
+protected:
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ FunctionPriorityDelegate();
+};
+
+
+template <>
+class FunctionPriorityDelegate<void, true, false>: public AbstractPriorityDelegate<void>
+{
+public:
+ typedef void (*NotifyMethod)(void*);
+
+ FunctionPriorityDelegate(NotifyMethod method, int prio):
+ AbstractPriorityDelegate<void>(prio),
+ _receiverMethod(method)
+ {
+ }
+
+ FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+ AbstractPriorityDelegate<void>(delegate),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ this->_receiverMethod = delegate._receiverMethod;
+ this->_priority = delegate._priority;
+ }
+ return *this;
+ }
+
+ ~FunctionPriorityDelegate()
+ {
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverMethod)
+ {
+ (*_receiverMethod)(const_cast<void*>(sender));
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+ return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new FunctionPriorityDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverMethod = 0;
+ }
+
+protected:
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ FunctionPriorityDelegate();
+};
+
+
+template <>
+class FunctionPriorityDelegate<void, false>: public AbstractPriorityDelegate<void>
+{
+public:
+ typedef void (*NotifyMethod)();
+
+ FunctionPriorityDelegate(NotifyMethod method, int prio):
+ AbstractPriorityDelegate<void>(prio),
+ _receiverMethod(method)
+ {
+ }
+
+ FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+ AbstractPriorityDelegate<void>(delegate),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ this->_receiverMethod = delegate._receiverMethod;
+ this->_priority = delegate._priority;
+ }
+ return *this;
+ }
+
+ ~FunctionPriorityDelegate()
+ {
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverMethod)
+ {
+ (*_receiverMethod)();
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+ return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new FunctionPriorityDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverMethod = 0;
+ }
+
+protected:
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ FunctionPriorityDelegate();
+};
+
} // namespace Poco
View
34 Foundation/include/Poco/NotificationStrategy.h
@@ -80,6 +80,40 @@ class NotificationStrategy
/// Returns false if the strategy contains at least one delegate.
};
+template <class TDelegate>
+class NotificationStrategy<void,TDelegate>
+ /// The interface that all notification strategies must implement.
+ ///
+ /// Note: Event is based on policy-driven design, so every strategy implementation
+ /// must provide all the methods from this interface (otherwise: compile errors)
+ /// but does not need to inherit from NotificationStrategy.
+{
+public:
+ NotificationStrategy()
+ {
+ }
+
+ virtual ~NotificationStrategy()
+ {
+ }
+
+ virtual void notify(const void* sender) = 0;
+ /// Sends a notification to all registered delegates.
+
+ virtual void add(const TDelegate& delegate) = 0;
+ /// Adds a delegate to the strategy.
+
+ virtual void remove(const TDelegate& delegate) = 0;
+ /// Removes a delegate from the strategy, if found.
+ /// Does nothing if the delegate has not been added.
+
+ virtual void clear() = 0;
+ /// Removes all delegates from the strategy.
+
+ virtual bool empty() const = 0;
+ /// Returns false if the strategy contains at least one delegate.
+};
+
} // namespace Poco
View
214 Foundation/include/Poco/PriorityDelegate.h
@@ -198,6 +198,152 @@ class PriorityDelegate<TObj, TArgs, false>: public AbstractPriorityDelegate<TArg
};
+template <class TObj>
+class PriorityDelegate<TObj, void, true>: public AbstractPriorityDelegate<void>
+{
+public:
+ typedef void (TObj::*NotifyMethod)(const void*);
+
+ PriorityDelegate(TObj* obj, NotifyMethod method, int prio):
+ AbstractPriorityDelegate<void>(prio),
+ _receiverObject(obj),
+ _receiverMethod(method)
+ {
+ }
+
+ PriorityDelegate(const PriorityDelegate& delegate):
+ AbstractPriorityDelegate<void>(delegate),
+ _receiverObject(delegate._receiverObject),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ PriorityDelegate& operator = (const PriorityDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ this->_pTarget = delegate._pTarget;
+ this->_receiverObject = delegate._receiverObject;
+ this->_receiverMethod = delegate._receiverMethod;
+ this->_priority = delegate._priority;
+ }
+ return *this;
+ }
+
+ ~PriorityDelegate()
+ {
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverObject)
+ {
+ (_receiverObject->*_receiverMethod)(sender);
+ return true;
+ }
+ else return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const PriorityDelegate* pOtherDelegate = dynamic_cast<const PriorityDelegate*>(other.unwrap());
+ return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new PriorityDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverObject = 0;
+ }
+
+protected:
+ TObj* _receiverObject;
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ PriorityDelegate();
+};
+
+template <class TObj>
+class PriorityDelegate<TObj, void, false>: public AbstractPriorityDelegate<void>
+{
+public:
+ typedef void (TObj::*NotifyMethod)();
+
+ PriorityDelegate(TObj* obj, NotifyMethod method, int prio):
+ AbstractPriorityDelegate<void>(prio),
+ _receiverObject(obj),
+ _receiverMethod(method)
+ {
+ }
+
+ PriorityDelegate(const PriorityDelegate& delegate):
+ AbstractPriorityDelegate<void>(delegate),
+ _receiverObject(delegate._receiverObject),
+ _receiverMethod(delegate._receiverMethod)
+ {
+ }
+
+ PriorityDelegate& operator = (const PriorityDelegate& delegate)
+ {
+ if (&delegate != this)
+ {
+ this->_pTarget = delegate._pTarget;
+ this->_receiverObject = delegate._receiverObject;
+ this->_receiverMethod = delegate._receiverMethod;
+ this->_priority = delegate._priority;
+ }
+ return *this;
+ }
+
+ ~PriorityDelegate()
+ {
+ }
+
+ bool notify(const void* sender)
+ {
+ Mutex::ScopedLock lock(_mutex);
+ if (_receiverObject)
+ {
+ (_receiverObject->*_receiverMethod)();
+ return true;
+ }
+ return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ const PriorityDelegate* pOtherDelegate = dynamic_cast<const PriorityDelegate*>(other.unwrap());
+ return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+ }
+
+ AbstractDelegate<void>* clone() const
+ {
+ return new PriorityDelegate(*this);
+ }
+
+ void disable()
+ {
+ Mutex::ScopedLock lock(_mutex);
+ _receiverObject = 0;
+ }
+
+protected:
+ TObj* _receiverObject;
+ NotifyMethod _receiverMethod;
+ Mutex _mutex;
+
+private:
+ PriorityDelegate();
+};
+
template <class TObj, class TArgs>
static PriorityDelegate<TObj, TArgs, true> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), int prio)
{
@@ -268,7 +414,73 @@ static FunctionPriorityDelegate<TArgs, false> priorityDelegate(void (*NotifyMeth
}
-} // namespace Poco
+
+template <class TObj>
+static PriorityDelegate<TObj, void, true> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), int prio)
+{
+ return PriorityDelegate<TObj, void, true>(pObj, NotifyMethod, prio);
+}
+
+
+template <class TObj>
+static PriorityDelegate<TObj, void, false> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(), int prio)
+{
+ return PriorityDelegate<TObj, void, false>(pObj, NotifyMethod, prio);
+}
+
+
+template <class TObj>
+static PriorityExpire<void> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+ return PriorityExpire<void>(PriorityDelegate<TObj, void, true>(pObj, NotifyMethod, prio), expireMilliSec);
+}
+
+
+template <class TObj>
+static PriorityExpire<void> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+ return PriorityExpire<void>(PriorityDelegate<TObj, void, false>(pObj, NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline PriorityExpire<void> priorityDelegate(void (*NotifyMethod)(const void*), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+ return PriorityExpire<void>(FunctionPriorityDelegate<void, true, true>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline PriorityExpire<void> priorityDelegate(void (*NotifyMethod)(void*), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+ return PriorityExpire<void>(FunctionPriorityDelegate<void, true, false>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline PriorityExpire<void> priorityDelegate(void (*NotifyMethod)(), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+ return PriorityExpire<void>(FunctionPriorityDelegate<void, false>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline FunctionPriorityDelegate<void, true, true> priorityDelegate(void (*NotifyMethod)(const void*), int prio)
+{
+ return FunctionPriorityDelegate<void, true, true>(NotifyMethod, prio);
+}
+
+
+inline FunctionPriorityDelegate<void, true, false> priorityDelegate(void (*NotifyMethod)(void*), int prio)
+{
+ return FunctionPriorityDelegate<void, true, false>(NotifyMethod, prio);
+}
+
+
+inline FunctionPriorityDelegate<void, false> priorityDelegate(void (*NotifyMethod)(), int prio)
+{
+ return FunctionPriorityDelegate<void, false>(NotifyMethod, prio);
+}
+
+
+} // namespace Poco
+
#endif // Foundation_PriorityDelegate_INCLUDED
View
78 Foundation/include/Poco/PriorityExpire.h
@@ -129,7 +129,85 @@ class PriorityExpire: public AbstractPriorityDelegate<TArgs>
PriorityExpire();
};
+template <>
+class PriorityExpire<void>: public AbstractPriorityDelegate<void>
+ /// Decorator for AbstractPriorityDelegate adding automatic
+ /// expiring of registrations to AbstractPriorityDelegate.
+{
+public:
+ PriorityExpire(const AbstractPriorityDelegate<void>& p, Timestamp::TimeDiff expireMilliSec):
+ AbstractPriorityDelegate<void>(p),
+ _pDelegate(static_cast<AbstractPriorityDelegate<void>*>(p.clone())),
+ _expire(expireMilliSec*1000)
+ {
+ }
+
+ PriorityExpire(const PriorityExpire& expire):
+ AbstractPriorityDelegate<void>(expire),
+ _pDelegate(static_cast<AbstractPriorityDelegate<void>*>(expire._pDelegate->clone())),
+ _expire(expire._expire),
+ _creationTime(expire._creationTime)
+ {
+ }
+
+ ~PriorityExpire()
+ {
+ delete _pDelegate;
+ }
+
+ PriorityExpire& operator = (const PriorityExpire& expire)
+ {
+ if (&expire != this)
+ {
+ delete this->_pDelegate;
+ this->_pDelegate = static_cast<AbstractPriorityDelegate<void>*>(expire._pDelegate->clone());
+ this->_expire = expire._expire;
+ this->_creationTime = expire._creationTime;
+ }
+ return *this;
+ }
+
+ bool notify(const void* sender)
+ {
+ if (!expired())
+ return this->_pDelegate->notify(sender);
+ else
+ return false;
+ }
+
+ bool equals(const AbstractDelegate<void>& other) const
+ {
+ return other.equals(*_pDelegate);
+ }
+
+ AbstractPriorityDelegate<void>* clone() const
+ {
+ return new PriorityExpire(*this);
+ }
+
+ void disable()
+ {
+ _pDelegate->disable();
+ }
+ const AbstractPriorityDelegate<void>* unwrap() const
+ {
+ return this->_pDelegate;
+ }
+
+protected:
+ bool expired() const
+ {
+ return _creationTime.isElapsed(_expire);
+ }
+
+ AbstractPriorityDelegate<void>* _pDelegate;
+ Timestamp::TimeDiff _expire;
+ Timestamp _creationTime;
+
+private:
+ PriorityExpire();
+};
} // namespace Poco
View
73 Foundation/include/Poco/PriorityStrategy.h
@@ -135,7 +135,80 @@ class PriorityStrategy: public NotificationStrategy<TArgs, TDelegate>
Delegates _delegates;
};
+template <class TDelegate>
+class PriorityStrategy<void, TDelegate>
+ /// NotificationStrategy for PriorityEvent.
+ ///
+ /// Delegates are kept in a std::vector<>, ordered
+ /// by their priority.
+{
+public:
+ typedef SharedPtr<TDelegate> DelegatePtr;
+ typedef std::vector<DelegatePtr> Delegates;
+ typedef typename Delegates::iterator Iterator;
+public:
+
+ void notify(const void* sender)
+ {
+ for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+ {
+ (*it)->notify(sender);
+ }
+ }
+
+ void add(const TDelegate& delegate)
+ {
+ for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+ {
+ if ((*it)->priority() > delegate.priority())
+ {
+ _delegates.insert(it, DelegatePtr(static_cast<TDelegate*>(delegate.clone())));
+ return;
+ }
+ }
+ _delegates.push_back(DelegatePtr(static_cast<TDelegate*>(delegate.clone())));
+ }
+
+ void remove(const TDelegate& delegate)
+ {
+ for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+ {
+ if (delegate.equals(**it))
+ {
+ (*it)->disable();
+ _delegates.erase(it);
+ return;
+ }
+ }
+ }
+
+ PriorityStrategy& operator = (const PriorityStrategy& s)
+ {
+ if (this != &s)
+ {
+ _delegates = s._delegates;
+ }
+ return *this;
+ }
+
+ void clear()
+ {
+ for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+ {
+ (*it)->disable();
+ }
+ _delegates.clear();
+ }
+
+ bool empty() const
+ {
+ return _delegates.empty();
+ }
+
+protected:
+ Delegates _delegates;
+};
} // namespace Poco
View
47 Foundation/testsuite/src/BasicEventTest.cpp
@@ -62,6 +62,17 @@ void BasicEventTest::testNoDelegate()
EventArgs args;
assert (_count == 0);
+ assert (Void.empty());
+ Void.notify(this);
+ assert (_count == 0);
+
+ Void += delegate(this, &BasicEventTest::onVoid);
+ assert (!Void.empty());
+ Void -= delegate(this, &BasicEventTest::onVoid);
+ assert (Void.empty());
+ Void.notify(this);
+
+ assert (_count == 0);
assert (Simple.empty());
Simple.notify(this, tmp);
assert (_count == 0);
@@ -114,6 +125,13 @@ void BasicEventTest::testNoDelegate()
Simple.notify(this, tmp);
assert (_count == 3);
Simple -= delegate(BasicEventTest::onStaticSimple);
+
+ Void += delegate(&BasicEventTest::onStaticVoid);
+ Void += delegate(&BasicEventTest::onStaticVoid);
+
+ Void.notify(this);
+ assert (_count == 5);
+ Void -= delegate(BasicEventTest::onStaticVoid);
}
void BasicEventTest::testSingleDelegate()
@@ -123,34 +141,38 @@ void BasicEventTest::testSingleDelegate()
assert (_count == 0);
+ Void += delegate(this, &BasicEventTest::onVoid);
+ Void.notify(this);
+ assert (_count == 1);
+
Simple += delegate(this, &BasicEventTest::onSimple);
Simple.notify(this, tmp);
- assert (_count == 1);
+ assert (_count == 2);
ConstSimple += delegate(this, &BasicEventTest::onConstSimple);
ConstSimple.notify(this, tmp);
- assert (_count == 2);
+ assert (_count == 3);
EventArgs* pArgs = &args;
Complex += delegate(this, &BasicEventTest::onComplex);
Complex.notify(this, pArgs);
- assert (_count == 3);
+ assert (_count == 4);
Complex2 += delegate(this, &BasicEventTest::onComplex2);
Complex2.notify(this, args);
- assert (_count == 4);
+ assert (_count == 5);
const EventArgs* pCArgs = &args;
ConstComplex += delegate(this, &BasicEventTest::onConstComplex);
ConstComplex.notify(this, pCArgs);
- assert (_count == 5);
+ assert (_count == 6);
Const2Complex += delegate(this, &BasicEventTest::onConst2Complex);
Const2Complex.notify(this, pArgs);
- assert (_count == 6);
+ assert (_count == 7);
// check if 2nd notify also works
Const2Complex.notify(this, pArgs);
- assert (_count == 7);
+ assert (_count == 8);
}
@@ -315,6 +337,16 @@ void BasicEventTest::testAsyncNotify()
assert (_count == LARGEINC);
}
+void BasicEventTest::onStaticVoid(const void* pSender)
+{
+ BasicEventTest* p = const_cast<BasicEventTest*>(reinterpret_cast<const BasicEventTest*>(pSender));
+ p->_count++;
+}
+
+void BasicEventTest::onVoid(const void* pSender)
+{
+ _count++;
+}
void BasicEventTest::onSimpleNoSender(int& i)
{
@@ -394,6 +426,7 @@ void BasicEventTest::setUp()
// must clear events, otherwise repeating test executions will fail
// because tests are only created once, only setup is called before
// each test run
+ Void.clear();
Simple.clear();
ConstSimple.clear();
Complex.clear();
View
6 Foundation/testsuite/src/BasicEventTest.h
@@ -44,6 +44,7 @@
class BasicEventTest: public CppUnit::TestCase
{
+ Poco::BasicEvent<void> Void;
Poco::BasicEvent<int> Simple;
Poco::BasicEvent<const int> ConstSimple;
Poco::BasicEvent<Poco::EventArgs*> Complex;
@@ -72,9 +73,14 @@ class BasicEventTest: public CppUnit::TestCase
protected:
+ static void onStaticVoid(const void* pSender);
+
+ void onVoid(const void* pSender);
+
static void onStaticSimple(const void* pSender, int& i);
static void onStaticSimple2(void* pSender, int& i);
static void onStaticSimple3(int& i);
+
void onSimpleNoSender(int& i);
void onSimple(const void* pSender, int& i);
void onSimpleOther(const void* pSender, int& i);
View
32 Foundation/testsuite/src/FIFOEventTest.cpp
@@ -61,6 +61,14 @@ void FIFOEventTest::testNoDelegate()
EventArgs args;
assert (_count == 0);
+ Void.notify(this);
+ assert (_count == 0);
+
+ Void += delegate(this, &FIFOEventTest::onVoid);
+ Void -= delegate(this, &FIFOEventTest::onVoid);
+ Void.notify(this);
+ assert (_count == 0);
+
Simple.notify(this, tmp);
assert (_count == 0);
@@ -105,34 +113,38 @@ void FIFOEventTest::testSingleDelegate()
assert (_count == 0);
+ Void += delegate(this, &FIFOEventTest::onVoid);
+ Void.notify(this);
+ assert (_count == 1);
+
Simple += delegate(this, &FIFOEventTest::onSimple);
Simple.notify(this, tmp);
- assert (_count == 1);
+ assert (_count == 2);
ConstSimple += delegate(this, &FIFOEventTest::onConstSimple);
ConstSimple.notify(this, tmp);
- assert (_count == 2);
+ assert (_count == 3);
EventArgs* pArgs = &args;
Complex += delegate(this, &FIFOEventTest::onComplex);
Complex.notify(this, pArgs);
- assert (_count == 3);
+ assert (_count == 4);
Complex2 += delegate(this, &FIFOEventTest::onComplex2);
Complex2.notify(this, args);
- assert (_count == 4);
+ assert (_count == 5);
const EventArgs* pCArgs = &args;
ConstComplex += delegate(this, &FIFOEventTest::onConstComplex);
ConstComplex.notify(this, pCArgs);
- assert (_count == 5);
+ assert (_count == 6);
Const2Complex += delegate(this, &FIFOEventTest::onConst2Complex);
Const2Complex.notify(this, pArgs);
- assert (_count == 6);
+ assert (_count == 7);
// check if 2nd notify also works
Const2Complex.notify(this, pArgs);
- assert (_count == 7);
+ assert (_count == 8);
}
@@ -353,6 +365,11 @@ void FIFOEventTest::testAsyncNotify()
assert (_count == LARGEINC);
}
+void FIFOEventTest::onVoid(const void* pSender)
+{
+ _count++;
+}
+
void FIFOEventTest::onSimple(const void* pSender, int& i)
{
_count++;
@@ -405,6 +422,7 @@ void FIFOEventTest::setUp()
// must clear events, otherwise repeating test executions will fail
// because tests are only created once, only setup is called before
// each test run
+ Void.clear();
Simple.clear();
ConstSimple.clear();
Complex.clear();
View
3 Foundation/testsuite/src/FIFOEventTest.h
@@ -44,6 +44,7 @@
class FIFOEventTest: public CppUnit::TestCase
{
+ Poco::FIFOEvent<void> Void;
Poco::FIFOEvent<int> Simple;
Poco::FIFOEvent<const int> ConstSimple;
Poco::FIFOEvent<Poco::EventArgs*> Complex;
@@ -72,7 +73,7 @@ class FIFOEventTest: public CppUnit::TestCase
static CppUnit::Test* suite();
protected:
-
+ void onVoid(const void* pSender);
void onSimple(const void* pSender, int& i);
void onSimpleOther(const void* pSender, int& i);
void onConstSimple(const void* pSender, const int& i);
View
47 Foundation/testsuite/src/PriorityEventTest.cpp
@@ -61,6 +61,14 @@ void PriorityEventTest::testNoDelegate()
EventArgs args;
assert (_count == 0);
+ Void.notify(this);
+ assert (_count == 0);
+
+ Void += priorityDelegate(this, &PriorityEventTest::onVoid, 0);
+ Void -= priorityDelegate(this, &PriorityEventTest::onVoid, 0);
+ Void.notify(this);
+ assert (_count == 0);
+
Simple.notify(this, tmp);
assert (_count == 0);
@@ -111,6 +119,15 @@ void PriorityEventTest::testNoDelegate()
Simple.notify(this, tmp);
assert (_count == 4);
Simple -= priorityDelegate(PriorityEventTest::onStaticSimple, 0);
+
+
+ Void += priorityDelegate(&PriorityEventTest::onStaticVoid, 0);
+ Void += priorityDelegate(&PriorityEventTest::onStaticVoid, 0);
+ Void += priorityDelegate(&PriorityEventTest::onStaticVoid, 1);
+
+ Void.notify(this);
+ assert (_count == 7);
+ Void -= priorityDelegate(PriorityEventTest::onStaticVoid, 0);
}
void PriorityEventTest::testSingleDelegate()
@@ -120,41 +137,47 @@ void PriorityEventTest::testSingleDelegate()
assert (_count == 0);
+ Void += priorityDelegate(this, &PriorityEventTest::onVoid, 0);
+ // unregistering with a different priority --> different observer, is ignored
+ Void -= priorityDelegate(this, &PriorityEventTest::onVoid, 3);
+ Void.notify(this);
+ assert (_count == 1);
+
Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
// unregistering with a different priority --> different observer, is ignored
Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 3);
Simple.notify(this, tmp);
- assert (_count == 1);
+ assert (_count == 2);
ConstSimple += priorityDelegate(this, &PriorityEventTest::onConstSimple, 0);
ConstSimple -= priorityDelegate(this, &PriorityEventTest::onConstSimple, 3);
ConstSimple.notify(this, tmp);
- assert (_count == 2);
+ assert (_count == 3);
EventArgs* pArgs = &args;
Complex += priorityDelegate(this, &PriorityEventTest::onComplex, 0);
Complex -= priorityDelegate(this, &PriorityEventTest::onComplex, 3);
Complex.notify(this, pArgs);
- assert (_count == 3);
+ assert (_count == 4);
Complex2 += priorityDelegate(this, &PriorityEventTest::onComplex2, 0);
Complex2 -= priorityDelegate(this, &PriorityEventTest::onComplex2, 3);
Complex2.notify(this, args);
- assert (_count == 4);
+ assert (_count == 5);
const EventArgs* pCArgs = &args;
ConstComplex += priorityDelegate(this, &PriorityEventTest::onConstComplex, 0);
ConstComplex -= priorityDelegate(this, &PriorityEventTest::onConstComplex, 3);
ConstComplex.notify(this, pCArgs);
- assert (_count == 5);
+ assert (_count == 6);
Const2Complex += priorityDelegate(this, &PriorityEventTest::onConst2Complex, 0);
Const2Complex -= priorityDelegate(this, &PriorityEventTest::onConst2Complex, 3);
Const2Complex.notify(this, pArgs);
- assert (_count == 6);
+ assert (_count == 7);
// check if 2nd notify also works
Const2Complex.notify(this, pArgs);
- assert (_count == 7);
+ assert (_count == 8);
}
@@ -400,6 +423,15 @@ void PriorityEventTest::testAsyncNotify()
}
+void PriorityEventTest::onStaticVoid(const void* pSender)
+{
+ PriorityEventTest* p = const_cast<PriorityEventTest*>(reinterpret_cast<const PriorityEventTest*>(pSender));
+ p->_count++;
+}
+
+void PriorityEventTest::onVoid(const void* pSender){
+ _count++;
+}
void PriorityEventTest::onStaticSimple(const void* pSender, int& i)
{
@@ -478,6 +510,7 @@ void PriorityEventTest::setUp()
// must clear events, otherwise repeating test executions will fail
// because tests are only created once, only setup is called before
// each test run
+ Void.clear();
Simple.clear();
ConstSimple.clear();
Complex.clear();
View
5 Foundation/testsuite/src/PriorityEventTest.h
@@ -44,6 +44,7 @@
class PriorityEventTest: public CppUnit::TestCase
{
+ Poco::PriorityEvent<void> Void;
Poco::PriorityEvent<int> Simple;
Poco::PriorityEvent<const int> ConstSimple;
Poco::PriorityEvent<Poco::EventArgs*> Complex;
@@ -72,6 +73,10 @@ class PriorityEventTest: public CppUnit::TestCase
static CppUnit::Test* suite();
protected:
+ static void onStaticVoid(const void* pSender);
+
+ void onVoid(const void* pSender);
+
static void onStaticSimple(const void* pSender, int& i);
static void onStaticSimple2(void* pSender, int& i);
static void onStaticSimple3(int& i);

0 comments on commit f5c091f

Please sign in to comment.
Something went wrong with that request. Please try again.