Poco::BasicEvent improvements and preparations for future support of lambdas/std::function

This commit is contained in:
Guenter Obiltschnig 2014-11-24 11:17:27 +01:00
parent 77bbc7e9ba
commit d5d048e689
12 changed files with 351 additions and 343 deletions

View File

@ -65,6 +65,7 @@ public:
}
};
template <>
class AbstractDelegate<void>
/// Base class for Delegate and Expire.
@ -104,6 +105,7 @@ public:
}
};
} // namespace Poco

View File

@ -151,6 +151,7 @@ class AbstractEvent
/// to create the PriorityDelegate.
{
public:
typedef TDelegate* DelegateHandle;
typedef TArgs Args;
AbstractEvent():
@ -188,6 +189,28 @@ public:
_strategy.remove(aDelegate);
}
DelegateHandle add(const TDelegate& aDelegate)
/// Adds a delegate to the event.
///
/// Exact behavior is determined by the TStrategy.
///
/// Returns a DelegateHandle which can be used in call to
/// remove() to remove the delegate.
{
typename TMutex::ScopedLock lock(_mutex);
return _strategy.add(aDelegate);
}
void remove(DelegateHandle delegateHandle)
/// Removes a delegate from the event using a DelegateHandle
/// returned by add().
///
/// If the delegate is not found, this function does nothing.
{
typename TMutex::ScopedLock lock(_mutex);
_strategy.remove(delegateHandle);
}
void operator () (const void* pSender, TArgs& args)
/// Shortcut for notify(pSender, args);
{
@ -330,126 +353,13 @@ private:
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.
class AbstractEvent<void, TStrategy, TDelegate, TMutex>
{
public:
typedef TDelegate* DelegateHandle;
AbstractEvent():
_executeAsync(this, &AbstractEvent::executeAsyncImpl),
_enabled(true)
@ -484,6 +394,28 @@ public:
typename TMutex::ScopedLock lock(_mutex);
_strategy.remove(aDelegate);
}
DelegateHandle add(const TDelegate& aDelegate)
/// Adds a delegate to the event.
///
/// Exact behavior is determined by the TStrategy.
///
/// Returns a DelegateHandle which can be used in call to
/// remove() to remove the delegate.
{
typename TMutex::ScopedLock lock(_mutex);
return _strategy.add(aDelegate);
}
void remove(DelegateHandle delegateHandle)
/// Removes a delegate from the event using a DelegateHandle
/// returned by add().
///
/// If the delegate is not found, this function does nothing.
{
typename TMutex::ScopedLock lock(_mutex);
_strategy.remove(delegateHandle);
}
void operator () (const void* pSender)
/// Shortcut for notify(pSender, args);
@ -621,6 +553,7 @@ private:
AbstractEvent& operator = (const AbstractEvent& other);
};
} // namespace Poco

View File

@ -37,6 +37,7 @@ class DefaultStrategy: public NotificationStrategy<TArgs, TDelegate>
/// order in which they have been registered.
{
public:
typedef TDelegate* DelegateHandle;
typedef SharedPtr<TDelegate> DelegatePtr;
typedef std::vector<DelegatePtr> Delegates;
typedef typename Delegates::iterator Iterator;
@ -63,9 +64,11 @@ public:
}
}
void add(const TDelegate& delegate)
DelegateHandle add(const TDelegate& delegate)
{
_delegates.push_back(DelegatePtr(static_cast<TDelegate*>(delegate.clone())));
DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
_delegates.push_back(pDelegate);
return pDelegate.get();
}
void remove(const TDelegate& delegate)
@ -80,6 +83,19 @@ public:
}
}
}
void remove(DelegateHandle delegateHandle)
{
for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
{
if (*it == delegateHandle)
{
(*it)->disable();
_delegates.erase(it);
return;
}
}
}
DefaultStrategy& operator = (const DefaultStrategy& s)
{
@ -108,6 +124,7 @@ protected:
Delegates _delegates;
};
template <class TDelegate>
class DefaultStrategy<void,TDelegate>: public NotificationStrategy<void, TDelegate>
/// Default notification strategy.
@ -117,6 +134,7 @@ class DefaultStrategy<void,TDelegate>: public NotificationStrategy<void, TDelega
/// order in which they have been registered.
{
public:
typedef TDelegate* DelegateHandle;
typedef SharedPtr<TDelegate> DelegatePtr;
typedef std::vector<DelegatePtr> Delegates;
typedef typename Delegates::iterator Iterator;
@ -143,9 +161,11 @@ public:
}
}
void add(const TDelegate& delegate)
DelegateHandle add(const TDelegate& delegate)
{
_delegates.push_back(DelegatePtr(static_cast<TDelegate*>(delegate.clone())));
DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
_delegates.push_back(pDelegate);
return pDelegate.get();
}
void remove(const TDelegate& delegate)
@ -161,6 +181,19 @@ public:
}
}
void remove(DelegateHandle delegateHandle)
{
for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
{
if (*it == delegateHandle)
{
(*it)->disable();
_delegates.erase(it);
return;
}
}
}
DefaultStrategy& operator = (const DefaultStrategy& s)
{
if (this != &s)
@ -188,6 +221,7 @@ protected:
Delegates _delegates;
};
} // namespace Poco

View File

@ -174,78 +174,75 @@ private:
template <class TObj, class TArgs>
static Delegate<TObj, TArgs, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&))
inline Delegate<TObj, TArgs, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&))
{
return Delegate<TObj, TArgs, true>(pObj, NotifyMethod);
}
template <class TObj, class TArgs>
static Delegate<TObj, TArgs, false> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&))
inline Delegate<TObj, TArgs, false> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&))
{
return Delegate<TObj, TArgs, false>(pObj, NotifyMethod);
}
template <class TObj, class TArgs>
static Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
inline Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
{
return Expire<TArgs>(Delegate<TObj, TArgs, true>(pObj, NotifyMethod), expireMillisecs);
}
template <class TObj, class TArgs>
static Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs)
inline Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs)
{
return Expire<TArgs>(Delegate<TObj, TArgs, false>(pObj, NotifyMethod), expireMillisecs);
}
template <class TArgs>
static Expire<TArgs> delegate(void (*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
inline Expire<TArgs> delegate(void (*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
{
return Expire<TArgs>(FunctionDelegate<TArgs, true, true>(NotifyMethod), expireMillisecs);
}
template <class TArgs>
static Expire<TArgs> delegate(void (*NotifyMethod)(void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
inline Expire<TArgs> delegate(void (*NotifyMethod)(void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
{
return Expire<TArgs>(FunctionDelegate<TArgs, true, false>(NotifyMethod), expireMillisecs);
}
template <class TArgs>
static Expire<TArgs> delegate(void (*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs)
inline Expire<TArgs> delegate(void (*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs)
{
return Expire<TArgs>(FunctionDelegate<TArgs, false>(NotifyMethod), expireMillisecs);
}
template <class TArgs>
static FunctionDelegate<TArgs, true, true> delegate(void (*NotifyMethod)(const void*, TArgs&))
inline FunctionDelegate<TArgs, true, true> delegate(void (*NotifyMethod)(const void*, TArgs&))
{
return FunctionDelegate<TArgs, true, true>(NotifyMethod);
}
template <class TArgs>
static FunctionDelegate<TArgs, true, false> delegate(void (*NotifyMethod)(void*, TArgs&))
inline FunctionDelegate<TArgs, true, false> delegate(void (*NotifyMethod)(void*, TArgs&))
{
return FunctionDelegate<TArgs, true, false>(NotifyMethod);
}
template <class TArgs>
static FunctionDelegate<TArgs, false> delegate(void (*NotifyMethod)(TArgs&))
inline FunctionDelegate<TArgs, false> delegate(void (*NotifyMethod)(TArgs&))
{
return FunctionDelegate<TArgs, false>(NotifyMethod);
}
template <class TObj>
class Delegate<TObj,void,true>: public AbstractDelegate<void>
{
@ -390,28 +387,28 @@ private:
template <class TObj>
static Delegate<TObj, void, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*))
inline 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)())
inline 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)
inline 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)
inline Expire<void> delegate(TObj* pObj, void (TObj::*NotifyMethod)(), Timestamp::TimeDiff expireMillisecs)
{
return Expire<void>(Delegate<TObj, void, false>(pObj, NotifyMethod), expireMillisecs);
}
@ -452,6 +449,7 @@ inline FunctionDelegate<void, false> delegate(void (*NotifyMethod)())
return FunctionDelegate<void, false>(NotifyMethod);
}
} // namespace Poco

View File

@ -108,6 +108,7 @@ private:
Expire();
};
template <>
class Expire<void>: public AbstractDelegate<void>
/// Decorator for AbstractDelegate adding automatic
@ -189,7 +190,6 @@ private:
};
} // namespace Poco

View File

@ -34,16 +34,16 @@ class FunctionDelegate: public AbstractDelegate<TArgs>
/// for use as a Delegate.
{
public:
typedef void (*NotifyMethod)(const void*, TArgs&);
typedef void (*NotifyFunction)(const void*, TArgs&);
FunctionDelegate(NotifyMethod method):
_receiverMethod(method)
FunctionDelegate(NotifyFunction function):
_function(function)
{
}
FunctionDelegate(const FunctionDelegate& delegate):
AbstractDelegate<TArgs>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -55,8 +55,7 @@ public:
{
if (&delegate != this)
{
this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_function = delegate._function;
}
return *this;
}
@ -64,9 +63,9 @@ public:
bool notify(const void* sender, TArgs& arguments)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(sender, arguments);
(*_function)(sender, arguments);
return true;
}
else return false;
@ -75,7 +74,7 @@ public:
bool equals(const AbstractDelegate<TArgs>& other) const
{
const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && _function == pOtherDelegate->_function;
}
AbstractDelegate<TArgs>* clone() const
@ -86,11 +85,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -102,16 +101,16 @@ template <class TArgs>
class FunctionDelegate<TArgs, true, false>: public AbstractDelegate<TArgs>
{
public:
typedef void (*NotifyMethod)(void*, TArgs&);
typedef void (*NotifyFunction)(void*, TArgs&);
FunctionDelegate(NotifyMethod method):
_receiverMethod(method)
FunctionDelegate(NotifyFunction function):
_function(function)
{
}
FunctionDelegate(const FunctionDelegate& delegate):
AbstractDelegate<TArgs>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -123,8 +122,7 @@ public:
{
if (&delegate != this)
{
this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_function = delegate._function;
}
return *this;
}
@ -132,9 +130,9 @@ public:
bool notify(const void* sender, TArgs& arguments)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(const_cast<void*>(sender), arguments);
(*_function)(const_cast<void*>(sender), arguments);
return true;
}
else return false;
@ -143,7 +141,7 @@ public:
bool equals(const AbstractDelegate<TArgs>& other) const
{
const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && _function == pOtherDelegate->_function;
}
AbstractDelegate<TArgs>* clone() const
@ -154,11 +152,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -170,16 +168,16 @@ template <class TArgs, bool senderIsConst>
class FunctionDelegate<TArgs, false, senderIsConst>: public AbstractDelegate<TArgs>
{
public:
typedef void (*NotifyMethod)(TArgs&);
typedef void (*NotifyFunction)(TArgs&);
FunctionDelegate(NotifyMethod method):
_receiverMethod(method)
FunctionDelegate(NotifyFunction function):
_function(function)
{
}
FunctionDelegate(const FunctionDelegate& delegate):
AbstractDelegate<TArgs>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -191,8 +189,7 @@ public:
{
if (&delegate != this)
{
this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_function = delegate._function;
}
return *this;
}
@ -200,9 +197,9 @@ public:
bool notify(const void* /*sender*/, TArgs& arguments)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(arguments);
(*_function)(arguments);
return true;
}
else return false;
@ -211,7 +208,7 @@ public:
bool equals(const AbstractDelegate<TArgs>& other) const
{
const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && _function == pOtherDelegate->_function;
}
AbstractDelegate<TArgs>* clone() const
@ -222,11 +219,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -234,26 +231,22 @@ private:
};
template <>
class FunctionDelegate<void,true,true>: public AbstractDelegate<void>
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*);
typedef void (*NotifyFunction)(const void*);
FunctionDelegate(NotifyMethod method):
_receiverMethod(method)
FunctionDelegate(NotifyFunction function):
_function(function)
{
}
FunctionDelegate(const FunctionDelegate& delegate):
AbstractDelegate<void>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -265,8 +258,7 @@ public:
{
if (&delegate != this)
{
//this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_function = delegate._function;
}
return *this;
}
@ -274,9 +266,9 @@ public:
bool notify(const void* sender)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(sender);
(*_function)(sender);
return true;
}
else return false;
@ -285,7 +277,7 @@ public:
bool equals(const AbstractDelegate<void>& other) const
{
const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && _function == pOtherDelegate->_function;
}
AbstractDelegate<void>* clone() const
@ -296,11 +288,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -312,16 +304,16 @@ template <>
class FunctionDelegate<void, true, false>: public AbstractDelegate<void>
{
public:
typedef void (*NotifyMethod)(void*);
typedef void (*NotifyFunction)(void*);
FunctionDelegate(NotifyMethod method):
_receiverMethod(method)
FunctionDelegate(NotifyFunction function):
_function(function)
{
}
FunctionDelegate(const FunctionDelegate& delegate):
AbstractDelegate<void>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -333,8 +325,7 @@ public:
{
if (&delegate != this)
{
//this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_function = delegate._function;
}
return *this;
}
@ -342,9 +333,9 @@ public:
bool notify(const void* sender)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(const_cast<void*>(sender));
(*_function)(const_cast<void*>(sender));
return true;
}
else return false;
@ -353,7 +344,7 @@ public:
bool equals(const AbstractDelegate<void>& other) const
{
const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && _function == pOtherDelegate->_function;
}
AbstractDelegate<void>* clone() const
@ -364,11 +355,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -380,16 +371,16 @@ template <bool senderIsConst>
class FunctionDelegate<void, false, senderIsConst>: public AbstractDelegate<void>
{
public:
typedef void (*NotifyMethod)();
typedef void (*NotifyFunction)();
FunctionDelegate(NotifyMethod method):
_receiverMethod(method)
FunctionDelegate(NotifyFunction function):
_function(function)
{
}
FunctionDelegate(const FunctionDelegate& delegate):
AbstractDelegate<void>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -401,8 +392,7 @@ public:
{
if (&delegate != this)
{
//this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_function = delegate._function;
}
return *this;
}
@ -410,9 +400,9 @@ public:
bool notify(const void* /*sender*/)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)();
(*_function)();
return true;
}
else return false;
@ -421,7 +411,7 @@ public:
bool equals(const AbstractDelegate<void>& other) const
{
const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
return pOtherDelegate && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && _function == pOtherDelegate->_function;
}
AbstractDelegate<void>* clone() const
@ -432,11 +422,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:

View File

@ -34,17 +34,17 @@ class FunctionPriorityDelegate: public AbstractPriorityDelegate<TArgs>
/// for use as a PriorityDelegate.
{
public:
typedef void (*NotifyMethod)(const void*, TArgs&);
typedef void (*NotifyFunction)(const void*, TArgs&);
FunctionPriorityDelegate(NotifyMethod method, int prio):
FunctionPriorityDelegate(NotifyFunction function, int prio):
AbstractPriorityDelegate<TArgs>(prio),
_receiverMethod(method)
_function(function)
{
}
FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
AbstractPriorityDelegate<TArgs>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -52,9 +52,8 @@ public:
{
if (&delegate != this)
{
this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_priority = delegate._priority;
this->_function = delegate._function;
this->_priority = delegate._priority;
}
return *this;
}
@ -66,9 +65,9 @@ public:
bool notify(const void* sender, TArgs& arguments)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(sender, arguments);
(*_function)(sender, arguments);
return true;
}
else return false;
@ -77,7 +76,7 @@ public:
bool equals(const AbstractDelegate<TArgs>& other) const
{
const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
}
AbstractDelegate<TArgs>* clone() const
@ -88,11 +87,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -104,17 +103,17 @@ template <class TArgs>
class FunctionPriorityDelegate<TArgs, true, false>: public AbstractPriorityDelegate<TArgs>
{
public:
typedef void (*NotifyMethod)(void*, TArgs&);
typedef void (*NotifyFunction)(void*, TArgs&);
FunctionPriorityDelegate(NotifyMethod method, int prio):
FunctionPriorityDelegate(NotifyFunction function, int prio):
AbstractPriorityDelegate<TArgs>(prio),
_receiverMethod(method)
_function(function)
{
}
FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
AbstractPriorityDelegate<TArgs>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -122,9 +121,8 @@ public:
{
if (&delegate != this)
{
this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_priority = delegate._priority;
this->_function = delegate._function;
this->_priority = delegate._priority;
}
return *this;
}
@ -136,9 +134,9 @@ public:
bool notify(const void* sender, TArgs& arguments)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(const_cast<void*>(sender), arguments);
(*_function)(const_cast<void*>(sender), arguments);
return true;
}
else return false;
@ -147,7 +145,7 @@ public:
bool equals(const AbstractDelegate<TArgs>& other) const
{
const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
}
AbstractDelegate<TArgs>* clone() const
@ -158,11 +156,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -174,17 +172,17 @@ template <class TArgs>
class FunctionPriorityDelegate<TArgs, false>: public AbstractPriorityDelegate<TArgs>
{
public:
typedef void (*NotifyMethod)(TArgs&);
typedef void (*NotifyFunction)(TArgs&);
FunctionPriorityDelegate(NotifyMethod method, int prio):
FunctionPriorityDelegate(NotifyFunction function, int prio):
AbstractPriorityDelegate<TArgs>(prio),
_receiverMethod(method)
_function(function)
{
}
FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
AbstractPriorityDelegate<TArgs>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -192,9 +190,8 @@ public:
{
if (&delegate != this)
{
this->_pTarget = delegate._pTarget;
this->_receiverMethod = delegate._receiverMethod;
this->_priority = delegate._priority;
this->_function = delegate._function;
this->_priority = delegate._priority;
}
return *this;
}
@ -206,9 +203,9 @@ public:
bool notify(const void* sender, TArgs& arguments)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(arguments);
(*_function)(arguments);
return true;
}
else return false;
@ -217,7 +214,7 @@ public:
bool equals(const AbstractDelegate<TArgs>& other) const
{
const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverMethod == pOtherDelegate->_receiverMethod;
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
}
AbstractDelegate<TArgs>* clone() const
@ -228,11 +225,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -241,22 +238,22 @@ private:
template <>
class FunctionPriorityDelegate<void,true,true>: public AbstractPriorityDelegate<void>
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*);
typedef void (*NotifyFunction)(const void*);
FunctionPriorityDelegate(NotifyMethod method, int prio):
FunctionPriorityDelegate(NotifyFunction function, int prio):
AbstractPriorityDelegate<void>(prio),
_receiverMethod(method)
_function(function)
{
}
FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
AbstractPriorityDelegate<void>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -264,8 +261,8 @@ public:
{
if (&delegate != this)
{
this->_receiverMethod = delegate._receiverMethod;
this->_priority = delegate._priority;
this->_function = delegate._function;
this->_priority = delegate._priority;
}
return *this;
}
@ -277,9 +274,9 @@ public:
bool notify(const void* sender)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(sender);
(*_function)(sender);
return true;
}
else return false;
@ -288,7 +285,7 @@ public:
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;
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
}
AbstractDelegate<void>* clone() const
@ -299,11 +296,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -315,17 +312,17 @@ template <>
class FunctionPriorityDelegate<void, true, false>: public AbstractPriorityDelegate<void>
{
public:
typedef void (*NotifyMethod)(void*);
typedef void (*NotifyFunction)(void*);
FunctionPriorityDelegate(NotifyMethod method, int prio):
FunctionPriorityDelegate(NotifyFunction function, int prio):
AbstractPriorityDelegate<void>(prio),
_receiverMethod(method)
_function(function)
{
}
FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
AbstractPriorityDelegate<void>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -333,8 +330,8 @@ public:
{
if (&delegate != this)
{
this->_receiverMethod = delegate._receiverMethod;
this->_priority = delegate._priority;
this->_function = delegate._function;
this->_priority = delegate._priority;
}
return *this;
}
@ -346,9 +343,9 @@ public:
bool notify(const void* sender)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)(const_cast<void*>(sender));
(*_function)(const_cast<void*>(sender));
return true;
}
else return false;
@ -357,7 +354,7 @@ public:
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;
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
}
AbstractDelegate<void>* clone() const
@ -368,11 +365,11 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
@ -384,17 +381,17 @@ template <>
class FunctionPriorityDelegate<void, false>: public AbstractPriorityDelegate<void>
{
public:
typedef void (*NotifyMethod)();
typedef void (*NotifyFunction)();
FunctionPriorityDelegate(NotifyMethod method, int prio):
FunctionPriorityDelegate(NotifyFunction function, int prio):
AbstractPriorityDelegate<void>(prio),
_receiverMethod(method)
_function(function)
{
}
FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
AbstractPriorityDelegate<void>(delegate),
_receiverMethod(delegate._receiverMethod)
_function(delegate._function)
{
}
@ -402,8 +399,8 @@ public:
{
if (&delegate != this)
{
this->_receiverMethod = delegate._receiverMethod;
this->_priority = delegate._priority;
this->_function = delegate._function;
this->_priority = delegate._priority;
}
return *this;
}
@ -415,9 +412,9 @@ public:
bool notify(const void* sender)
{
Mutex::ScopedLock lock(_mutex);
if (_receiverMethod)
if (_function)
{
(*_receiverMethod)();
(*_function)();
return true;
}
else return false;
@ -426,7 +423,7 @@ public:
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;
return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
}
AbstractDelegate<void>* clone() const
@ -437,17 +434,18 @@ public:
void disable()
{
Mutex::ScopedLock lock(_mutex);
_receiverMethod = 0;
_function = 0;
}
protected:
NotifyMethod _receiverMethod;
NotifyFunction _function;
Mutex _mutex;
private:
FunctionPriorityDelegate();
};
} // namespace Poco

View File

@ -35,6 +35,8 @@ class NotificationStrategy
/// but does not need to inherit from NotificationStrategy.
{
public:
typedef TDelegate* DelegateHandle;
NotificationStrategy()
{
}
@ -46,13 +48,17 @@ public:
virtual void notify(const void* sender, TArgs& arguments) = 0;
/// Sends a notification to all registered delegates.
virtual void add(const TDelegate& delegate) = 0;
virtual DelegateHandle 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 remove(DelegateHandle delegateHandle) = 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.
@ -60,8 +66,9 @@ public:
/// Returns false if the strategy contains at least one delegate.
};
template <class TDelegate>
class NotificationStrategy<void,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
@ -69,6 +76,8 @@ class NotificationStrategy<void,TDelegate>
/// but does not need to inherit from NotificationStrategy.
{
public:
typedef TDelegate* DelegateHandle;
NotificationStrategy()
{
}
@ -80,13 +89,17 @@ public:
virtual void notify(const void* sender) = 0;
/// Sends a notification to all registered delegates.
virtual void add(const TDelegate& delegate) = 0;
virtual DelegateHandle 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 remove(DelegateHandle delegateHandle) = 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.

View File

@ -251,6 +251,7 @@ private:
PriorityDelegate();
};
template <class TObj>
class PriorityDelegate<TObj, void, false>: public AbstractPriorityDelegate<void>
{
@ -324,6 +325,7 @@ private:
PriorityDelegate();
};
template <class TObj, class TArgs>
static PriorityDelegate<TObj, TArgs, true> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), int prio)
{
@ -394,9 +396,6 @@ static FunctionPriorityDelegate<TArgs, false> priorityDelegate(void (*NotifyMeth
}
template <class TObj>
static PriorityDelegate<TObj, void, true> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), int prio)
{
@ -463,4 +462,5 @@ inline FunctionPriorityDelegate<void, false> priorityDelegate(void (*NotifyMetho
} // namespace Poco
#endif // Foundation_PriorityDelegate_INCLUDED

View File

@ -109,6 +109,7 @@ private:
PriorityExpire();
};
template <>
class PriorityExpire<void>: public AbstractPriorityDelegate<void>
/// Decorator for AbstractPriorityDelegate adding automatic
@ -188,6 +189,8 @@ protected:
private:
PriorityExpire();
};
} // namespace Poco

View File

@ -36,6 +36,7 @@ class PriorityStrategy: public NotificationStrategy<TArgs, TDelegate>
/// by their priority.
{
public:
typedef TDelegate* DelegateHandle;
typedef SharedPtr<TDelegate> DelegatePtr;
typedef std::vector<DelegatePtr> Delegates;
typedef typename Delegates::iterator Iterator;
@ -62,17 +63,20 @@ public:
}
}
void add(const TDelegate& delegate)
DelegateHandle 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;
DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
_delegates.insert(it, pDelegate);
return pDelegate.get();
}
}
_delegates.push_back(DelegatePtr(static_cast<TDelegate*>(delegate.clone())));
DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
_delegates.push_back(pDelegate);
return pDelegate.get();
}
void remove(const TDelegate& delegate)
@ -88,6 +92,19 @@ public:
}
}
void remove(DelegateHandle delegateHandle)
{
for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
{
if (*it == delegateHandle)
{
(*it)->disable();
_delegates.erase(it);
return;
}
}
}
PriorityStrategy& operator = (const PriorityStrategy& s)
{
if (this != &s)
@ -115,6 +132,7 @@ protected:
Delegates _delegates;
};
template <class TDelegate>
class PriorityStrategy<void, TDelegate>
/// NotificationStrategy for PriorityEvent.
@ -123,6 +141,7 @@ class PriorityStrategy<void, TDelegate>
/// by their priority.
{
public:
typedef TDelegate* DelegateHandle;
typedef SharedPtr<TDelegate> DelegatePtr;
typedef std::vector<DelegatePtr> Delegates;
typedef typename Delegates::iterator Iterator;
@ -137,17 +156,20 @@ public:
}
}
void add(const TDelegate& delegate)
DelegateHandle 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;
DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
_delegates.insert(it, pDelegate);
return pDelegate.get();
}
}
_delegates.push_back(DelegatePtr(static_cast<TDelegate*>(delegate.clone())));
DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
_delegates.push_back(pDelegate);
return pDelegate.get();
}
void remove(const TDelegate& delegate)
@ -163,6 +185,19 @@ public:
}
}
void remove(DelegateHandle delegateHandle)
{
for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
{
if (*it == delegateHandle)
{
(*it)->disable();
_delegates.erase(it);
return;
}
}
}
PriorityStrategy& operator = (const PriorityStrategy& s)
{
if (this != &s)
@ -189,6 +224,8 @@ public:
protected:
Delegates _delegates;
};
} // namespace Poco

View File

@ -1,49 +1,49 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae arcu
ac arcu semper mollis. Donec lobortis mi at dui. Integer placerat,
sapien at suscipit faucibus, mi quam sodales sapien, non accumsan enim
justo sit amet sem. Proin fermentum dui vitae metus. Donec a velit et
lectus fermentum bibendum. Donec risus magna, fermentum tempor, tempor
cursus, elementum ac, turpis. Suspendisse ultricies tincidunt quam. Nam
quis risus. Suspendisse in lacus. Vivamus et est ac nisi sollicitudin
ullamcorper. Sed vitae ligula non sem suscipit tempus. Donec tincidunt,
justo nec tristique euismod, sapien velit consequat ante, in vestibulum
dolor justo nec orci. Sed placerat eros. Suspendisse potenti. Vestibulum
eu sem at ante aliquet varius. In quis diam nec libero pretium
vestibulum. Morbi ipsum. Vivamus eros.
Nam pellentesque ante. Donec sit amet nisl. Vestibulum blandit risus sit
amet quam facilisis mollis. Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Nulla mattis orci a diam. Duis ultricies massa rhoncus
neque. Morbi hendrerit arcu vel mi. Suspendisse lorem. Pellentesque non
nunc molestie metus pretium tristique. Maecenas ante. Nunc sagittis.
Proin ornare. Donec mi tellus, venenatis nec, ultrices ac, hendrerit in,
quam. Mauris nunc. Vivamus cursus rhoncus felis. Nunc at justo. In hac
habitasse platea dictumst. Nulla metus sapien, cursus nec, luctus eget,
malesuada sed, odio. Sed augue orci, sollicitudin id, auctor eu,
porttitor id, eros. Proin arcu dolor, iaculis quis, ullamcorper sit
amet, ullamcorper nec, ante. Sed dictum luctus est. Phasellus nibh.
Morbi fringilla magna et mi. In eleifend sem non dui luctus suscipit.
Duis dapibus. Proin molestie. Cras vel dui.
In et orci vel erat euismod sodales. Integer porta. Vivamus congue
turpis eu eros tincidunt fermentum. Curabitur consequat ultrices mi.
Praesent sit amet ante. Proin ante. Phasellus vitae nibh. Aliquam ipsum
massa, pretium quis, mattis sed, sagittis sit amet, justo. Integer quam.
Aenean leo erat, commodo quis, elementum sit amet, placerat sed, lacus.
Nam a nunc in sapien scelerisque sodales. Phasellus luctus arcu at
nulla. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Donec facilisis.
Nam scelerisque lacus a eros. Praesent ac arcu et nisl eleifend commodo.
Aenean vestibulum, augue vel posuere mattis, sem massa varius mauris,
non porttitor diam felis eu libero. Suspendisse vulputate, urna quis
dictum scelerisque, risus est pharetra orci, a iaculis dui sem quis
quam. Nam imperdiet quam eget velit. Mauris dui lacus, posuere in,
cursus eget, ultrices ut, eros. Etiam eget purus. Curabitur accumsan
lacinia urna. Donec aliquet dictum erat. Nulla ac magna. Quisque
ultrices vehicula lacus. Fusce eu quam quis est mollis adipiscing.
Pellentesque non libero at eros vulputate iaculis. Praesent vitae orci
ac sapien laoreet scelerisque. Ut ut libero. Vivamus massa urna,
convallis at, laoreet a, adipiscing et, eros. Suspendisse feugiat
malesuada felis. Suspendisse a odio eget tortor tempus pretium.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae arcu
ac arcu semper mollis. Donec lobortis mi at dui. Integer placerat,
sapien at suscipit faucibus, mi quam sodales sapien, non accumsan enim
justo sit amet sem. Proin fermentum dui vitae metus. Donec a velit et
lectus fermentum bibendum. Donec risus magna, fermentum tempor, tempor
cursus, elementum ac, turpis. Suspendisse ultricies tincidunt quam. Nam
quis risus. Suspendisse in lacus. Vivamus et est ac nisi sollicitudin
ullamcorper. Sed vitae ligula non sem suscipit tempus. Donec tincidunt,
justo nec tristique euismod, sapien velit consequat ante, in vestibulum
dolor justo nec orci. Sed placerat eros. Suspendisse potenti. Vestibulum
eu sem at ante aliquet varius. In quis diam nec libero pretium
vestibulum. Morbi ipsum. Vivamus eros.
Nam pellentesque ante. Donec sit amet nisl. Vestibulum blandit risus sit
amet quam facilisis mollis. Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Nulla mattis orci a diam. Duis ultricies massa rhoncus
neque. Morbi hendrerit arcu vel mi. Suspendisse lorem. Pellentesque non
nunc molestie metus pretium tristique. Maecenas ante. Nunc sagittis.
Proin ornare. Donec mi tellus, venenatis nec, ultrices ac, hendrerit in,
quam. Mauris nunc. Vivamus cursus rhoncus felis. Nunc at justo. In hac
habitasse platea dictumst. Nulla metus sapien, cursus nec, luctus eget,
malesuada sed, odio. Sed augue orci, sollicitudin id, auctor eu,
porttitor id, eros. Proin arcu dolor, iaculis quis, ullamcorper sit
amet, ullamcorper nec, ante. Sed dictum luctus est. Phasellus nibh.
Morbi fringilla magna et mi. In eleifend sem non dui luctus suscipit.
Duis dapibus. Proin molestie. Cras vel dui.
In et orci vel erat euismod sodales. Integer porta. Vivamus congue
turpis eu eros tincidunt fermentum. Curabitur consequat ultrices mi.
Praesent sit amet ante. Proin ante. Phasellus vitae nibh. Aliquam ipsum
massa, pretium quis, mattis sed, sagittis sit amet, justo. Integer quam.
Aenean leo erat, commodo quis, elementum sit amet, placerat sed, lacus.
Nam a nunc in sapien scelerisque sodales. Phasellus luctus arcu at
nulla. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Donec facilisis.
Nam scelerisque lacus a eros. Praesent ac arcu et nisl eleifend commodo.
Aenean vestibulum, augue vel posuere mattis, sem massa varius mauris,
non porttitor diam felis eu libero. Suspendisse vulputate, urna quis
dictum scelerisque, risus est pharetra orci, a iaculis dui sem quis
quam. Nam imperdiet quam eget velit. Mauris dui lacus, posuere in,
cursus eget, ultrices ut, eros. Etiam eget purus. Curabitur accumsan
lacinia urna. Donec aliquet dictum erat. Nulla ac magna. Quisque
ultrices vehicula lacus. Fusce eu quam quis est mollis adipiscing.
Pellentesque non libero at eros vulputate iaculis. Praesent vitae orci
ac sapien laoreet scelerisque. Ut ut libero. Vivamus massa urna,
convallis at, laoreet a, adipiscing et, eros. Suspendisse feugiat
malesuada felis. Suspendisse a odio eget tortor tempus pretium.