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"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="Foundation"
ProjectGUID="{8164D41D-B053-405B-826C-CF37AC0EF176}"
RootNamespace="Foundation"

View File

@ -51,7 +51,7 @@
namespace Poco {
template <class TArgs, class TStrategy, class TDelegate>
template <class TArgs, class TStrategy, class TDelegate, class TMutex = FastMutex>
class AbstractEvent
/// An AbstractEvent is the super-class of all events.
/// 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
/// can deviate.
{
FastMutex::ScopedLock lock(_mutex);
typename TMutex::ScopedLock lock(_mutex);
_strategy.add(aDelegate);
}
@ -192,7 +192,7 @@ public:
/// already existing one is determined by the < operator.
/// If the observer is not found, the unregister will be ignored
{
FastMutex::ScopedLock lock(_mutex);
typename TMutex::ScopedLock lock(_mutex);
_strategy.remove(aDelegate);
}
@ -213,7 +213,7 @@ public:
bool enabled = false;
{
FastMutex::ScopedLock lock(_mutex);
typename TMutex::ScopedLock lock(_mutex);
enabled = _enabled;
if (_enabled)
{
@ -243,7 +243,7 @@ public:
NotifyAsyncParams params(pSender, args);
{
FastMutex::ScopedLock lock(_mutex);
typename TMutex::ScopedLock lock(_mutex);
// thread-safeness:
// copy should be faster and safer than blocking until
@ -262,7 +262,7 @@ public:
void enable()
/// Enables the event
{
FastMutex::ScopedLock lock(_mutex);
typename TMutex::ScopedLock lock(_mutex);
_enabled = true;
}
@ -270,22 +270,29 @@ public:
/// Disables the event. notify and notifyAsnyc will be ignored,
/// but adding/removing delegates is still allowed.
{
FastMutex::ScopedLock lock(_mutex);
typename TMutex::ScopedLock lock(_mutex);
_enabled = false;
}
bool isEnabled() const
{
FastMutex::ScopedLock lock(_mutex);
typename TMutex::ScopedLock lock(_mutex);
return _enabled;
}
void clear()
/// Removes all delegates.
{
FastMutex::ScopedLock lock(_mutex);
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
@ -319,7 +326,7 @@ protected:
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 FastMutex _mutex;
mutable TMutex _mutex;
private:
AbstractEvent(const AbstractEvent& other);

View File

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

View File

@ -50,7 +50,7 @@ namespace Poco {
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
/// to register exactly once. The observer must provide an
/// < (less-than) operator.

View File

@ -49,11 +49,12 @@
namespace Poco {
template <class TArgs>
template <class TArgs, class TMutex = FastMutex>
class FIFOEvent: public AbstractEvent <
TArgs,
FIFOStrategy<TArgs, AbstractDelegate<TArgs>, p_less<AbstractDelegate< TArgs> > >,
AbstractDelegate<TArgs>
AbstractDelegate<TArgs>,
TMutex
>
/// A FIFOEvent uses internally a FIFOStrategy which guarantees
/// 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>
class FIFOStrategy: public NotificationStrategy<TArgs, TDelegate>
class FIFOStrategy//: public NotificationStrategy<TArgs, TDelegate>
{
public:
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
//

View File

@ -49,6 +49,9 @@ namespace Poco {
template <class TArgs, class TDelegate>
class NotificationStrategy
/// 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:
NotificationStrategy()

View File

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

View File

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

View File

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