added NullMutex, extended Events so that mutex is a template param, minor performance optimzation for strategies

This commit is contained in:
Peter Schojer 2008-09-30 06:26:47 +00:00
parent ce17ae2c66
commit 358797c89e
11 changed files with 104 additions and 19 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="8.00" Version="8,00"
Name="Foundation" Name="Foundation"
ProjectGUID="{8164D41D-B053-405B-826C-CF37AC0EF176}" ProjectGUID="{8164D41D-B053-405B-826C-CF37AC0EF176}"
RootNamespace="Foundation" RootNamespace="Foundation"

View File

@ -51,7 +51,7 @@
namespace Poco { namespace Poco {
template <class TArgs, class TStrategy, class TDelegate> template <class TArgs, class TStrategy, class TDelegate, class TMutex = FastMutex>
class AbstractEvent class AbstractEvent
/// An AbstractEvent is the super-class of all events. /// An AbstractEvent is the super-class of all events.
/// It works similar to the way C# handles notifications (aka events in C#). /// It works similar to the way C# handles notifications (aka events in C#).
@ -183,7 +183,7 @@ public:
/// (DefaultStrategy, FIFOStrategy) follow that guideline but future ones /// (DefaultStrategy, FIFOStrategy) follow that guideline but future ones
/// can deviate. /// can deviate.
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
_strategy.add(aDelegate); _strategy.add(aDelegate);
} }
@ -192,7 +192,7 @@ public:
/// already existing one is determined by the < operator. /// already existing one is determined by the < operator.
/// If the observer is not found, the unregister will be ignored /// If the observer is not found, the unregister will be ignored
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
_strategy.remove(aDelegate); _strategy.remove(aDelegate);
} }
@ -213,7 +213,7 @@ public:
bool enabled = false; bool enabled = false;
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
enabled = _enabled; enabled = _enabled;
if (_enabled) if (_enabled)
{ {
@ -243,7 +243,7 @@ public:
NotifyAsyncParams params(pSender, args); NotifyAsyncParams params(pSender, args);
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
// thread-safeness: // thread-safeness:
// copy should be faster and safer than blocking until // copy should be faster and safer than blocking until
@ -262,7 +262,7 @@ public:
void enable() void enable()
/// Enables the event /// Enables the event
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
_enabled = true; _enabled = true;
} }
@ -270,22 +270,29 @@ public:
/// Disables the event. notify and notifyAsnyc will be ignored, /// Disables the event. notify and notifyAsnyc will be ignored,
/// but adding/removing delegates is still allowed. /// but adding/removing delegates is still allowed.
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
_enabled = false; _enabled = false;
} }
bool isEnabled() const bool isEnabled() const
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
return _enabled; return _enabled;
} }
void clear() void clear()
/// Removes all delegates. /// Removes all delegates.
{ {
FastMutex::ScopedLock lock(_mutex); typename TMutex::ScopedLock lock(_mutex);
_strategy.clear(); _strategy.clear();
} }
bool empty() const
/// Checks if any delegates are registered at the delegate
{
typename TMutex::ScopedLock lock(_mutex);
return _strategy.empty();
}
protected: protected:
struct NotifyAsyncParams struct NotifyAsyncParams
@ -319,7 +326,7 @@ protected:
TStrategy _strategy; /// The strategy used to notify observers. TStrategy _strategy; /// The strategy used to notify observers.
bool _enabled; /// Stores if an event is enabled. Notfies on disabled events have no effect bool _enabled; /// Stores if an event is enabled. Notfies on disabled events have no effect
/// but it is possible to change the observers. /// but it is possible to change the observers.
mutable FastMutex _mutex; mutable TMutex _mutex;
private: private:
AbstractEvent(const AbstractEvent& other); AbstractEvent(const AbstractEvent& other);

View File

@ -49,10 +49,11 @@
namespace Poco { namespace Poco {
template <class TArgs> template <class TArgs, class TMutex = FastMutex>
class BasicEvent: public AbstractEvent < class BasicEvent: public AbstractEvent <
TArgs, DefaultStrategy<TArgs, AbstractDelegate<TArgs>, p_less<AbstractDelegate<TArgs> > >, TArgs, DefaultStrategy<TArgs, AbstractDelegate<TArgs>, p_less<AbstractDelegate<TArgs> > >,
AbstractDelegate<TArgs> AbstractDelegate<TArgs>,
TMutex
> >
/// A BasicEvent uses internally a DefaultStrategy which /// A BasicEvent uses internally a DefaultStrategy which
/// invokes delegates in an arbitrary manner. /// invokes delegates in an arbitrary manner.

View File

@ -50,7 +50,7 @@ namespace Poco {
template <class TArgs, class TDelegate, class TCompare> template <class TArgs, class TDelegate, class TCompare>
class DefaultStrategy: public NotificationStrategy<TArgs, TDelegate> class DefaultStrategy//: public NotificationStrategy<TArgs, TDelegate>
/// Default notification strategy. Allows one observer /// Default notification strategy. Allows one observer
/// to register exactly once. The observer must provide an /// to register exactly once. The observer must provide an
/// < (less-than) operator. /// < (less-than) operator.

View File

@ -49,11 +49,12 @@
namespace Poco { namespace Poco {
template <class TArgs> template <class TArgs, class TMutex = FastMutex>
class FIFOEvent: public AbstractEvent < class FIFOEvent: public AbstractEvent <
TArgs, TArgs,
FIFOStrategy<TArgs, AbstractDelegate<TArgs>, p_less<AbstractDelegate< TArgs> > >, FIFOStrategy<TArgs, AbstractDelegate<TArgs>, p_less<AbstractDelegate< TArgs> > >,
AbstractDelegate<TArgs> AbstractDelegate<TArgs>,
TMutex
> >
/// A FIFOEvent uses internally a FIFOStrategy which guarantees /// A FIFOEvent uses internally a FIFOStrategy which guarantees
/// that delegates are invoked in the order they were added to /// that delegates are invoked in the order they were added to

View File

@ -49,7 +49,7 @@ namespace Poco {
template <class TArgs, class TDelegate, class TCompare> template <class TArgs, class TDelegate, class TCompare>
class FIFOStrategy: public NotificationStrategy<TArgs, TDelegate> class FIFOStrategy//: public NotificationStrategy<TArgs, TDelegate>
{ {
public: public:
typedef std::list<TDelegate*> Delegates; typedef std::list<TDelegate*> Delegates;

View File

@ -166,6 +166,55 @@ private:
}; };
class Foundation_API NullMutex
/// A NullMutex is an empty mutex implementation
/// which performs no locking at all. Useful in policy driven design
/// where the type of mutex used can be now a template parameter allowing the user to switch
/// between thread-safe and not thread-safe depending on his need
/// Works with the ScopedLock class
{
public:
typedef Poco::ScopedLock<NullMutex> ScopedLock;
NullMutex()
/// creates the NullMutex.
{
}
~NullMutex()
/// destroys the NullMutex.
{
}
void lock()
/// Always succeeds
{
}
void lock(long milliseconds)
/// Always succeeds
{
}
bool tryLock()
/// Always returns true
{
return true;
}
bool tryLock(long)
/// Always returns true
{
return true;
}
void unlock()
/// Always succeeds
{
}
};
// //
// inlines // inlines
// //

View File

@ -49,6 +49,9 @@ namespace Poco {
template <class TArgs, class TDelegate> template <class TArgs, class TDelegate>
class NotificationStrategy class NotificationStrategy
/// The interface that all notification strategies must implement. /// The interface that all notification strategies must implement.
/// Note: Event is based on policy-driven design, so your strategy implementation
/// must offer all the methods from this interface (otherwise: compile errors)
/// but you don't need to extend from NotificationStrategy!
{ {
public: public:
NotificationStrategy() NotificationStrategy()

View File

@ -49,11 +49,12 @@
namespace Poco { namespace Poco {
template <class TArgs> template <class TArgs, class TMutex = FastMutex>
class PriorityEvent: public AbstractEvent < class PriorityEvent: public AbstractEvent <
TArgs, TArgs,
DefaultStrategy<TArgs, AbstractPriorityDelegate< TArgs>, p_less<AbstractPriorityDelegate<TArgs> > >, DefaultStrategy<TArgs, AbstractPriorityDelegate< TArgs>, p_less<AbstractPriorityDelegate<TArgs> > >,
AbstractPriorityDelegate<TArgs> AbstractPriorityDelegate<TArgs>,
TMutex
> >
/// A PriorityEvent uses internally a DefaultStrategy which /// A PriorityEvent uses internally a DefaultStrategy which
/// invokes delegates in a manner determined by the priority field /// invokes delegates in a manner determined by the priority field

View File

@ -62,11 +62,14 @@ void BasicEventTest::testNoDelegate()
EventArgs args; EventArgs args;
assert (_count == 0); assert (_count == 0);
assert (Simple.empty());
Simple.notify(this, tmp); Simple.notify(this, tmp);
assert (_count == 0); assert (_count == 0);
Simple += delegate(this, &BasicEventTest::onSimple); Simple += delegate(this, &BasicEventTest::onSimple);
assert (!Simple.empty());
Simple -= delegate(this, &BasicEventTest::onSimple); Simple -= delegate(this, &BasicEventTest::onSimple);
assert (Simple.empty());
Simple.notify(this, tmp); Simple.notify(this, tmp);
assert (_count == 0); assert (_count == 0);
@ -166,6 +169,24 @@ void BasicEventTest::testDuplicateRegister()
assert (_count == 1); assert (_count == 1);
} }
void BasicEventTest::testNullMutex()
{
Poco::BasicEvent<int, NullMutex> ev;
int tmp = 0;
assert (_count == 0);
ev += delegate(this, &BasicEventTest::onSimple);
ev += delegate(this, &BasicEventTest::onSimple);
ev.notify(this, tmp);
assert (_count == 1);
ev -= delegate(this, &BasicEventTest::onSimple);
ev.notify(this, tmp);
assert (_count == 1);
}
void BasicEventTest::testDuplicateUnregister() void BasicEventTest::testDuplicateUnregister()
{ {
// duplicate unregister shouldn't give an error, // duplicate unregister shouldn't give an error,
@ -406,5 +427,6 @@ CppUnit::Test* BasicEventTest::suite()
CppUnit_addTest(pSuite, BasicEventTest, testExpireReRegister); CppUnit_addTest(pSuite, BasicEventTest, testExpireReRegister);
CppUnit_addTest(pSuite, BasicEventTest, testOverwriteDelegate); CppUnit_addTest(pSuite, BasicEventTest, testOverwriteDelegate);
CppUnit_addTest(pSuite, BasicEventTest, testAsyncNotify); CppUnit_addTest(pSuite, BasicEventTest, testAsyncNotify);
CppUnit_addTest(pSuite, BasicEventTest, testNullMutex);
return pSuite; return pSuite;
} }

View File

@ -64,6 +64,7 @@ public:
void testReturnParams(); void testReturnParams();
void testOverwriteDelegate(); void testOverwriteDelegate();
void testAsyncNotify(); void testAsyncNotify();
void testNullMutex();
void setUp(); void setUp();
void tearDown(); void tearDown();