mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-02 09:49:48 +02:00
added NullMutex, extended Events so that mutex is a template param, minor performance optimzation for strategies
This commit is contained in:
parent
ce17ae2c66
commit
358797c89e
@ -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"
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
//
|
//
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user