Merge pull request #601 from martin-osborne/issue_532-3

Issue #532 -  Changes to address `FastMutex` being non-recursive on Win32 platforms
This commit is contained in:
Aleksandar Fabijanic
2015-02-09 21:08:12 -06:00
52 changed files with 695 additions and 95 deletions

View File

@@ -43,7 +43,7 @@ public:
ActiveResultHolder(): ActiveResultHolder():
_pData(0), _pData(0),
_pExc(0), _pExc(0),
_event(false) _event(Event::EVENT_MANUALRESET)
/// Creates an ActiveResultHolder. /// Creates an ActiveResultHolder.
{ {
} }
@@ -149,7 +149,7 @@ class ActiveResultHolder<void>: public RefCountedObject
public: public:
ActiveResultHolder(): ActiveResultHolder():
_pExc(0), _pExc(0),
_event(false) _event(Event::EVENT_MANUALRESET)
/// Creates an ActiveResultHolder. /// Creates an ActiveResultHolder.
{ {
} }

View File

@@ -84,7 +84,7 @@ public:
_runnable(*pOwner, method), _runnable(*pOwner, method),
_stopped(true), _stopped(true),
_running(false), _running(false),
_done(false) _done(Event::EVENT_MANUALRESET)
/// Creates the activity. Call start() to /// Creates the activity. Call start() to
/// start it. /// start it.
{ {

View File

@@ -46,11 +46,21 @@ class Foundation_API Event: private EventImpl
/// for an event to become signalled. /// for an event to become signalled.
{ {
public: public:
Event(bool autoReset = true); enum EventType
/// Creates the event. If autoReset is true, {
EVENT_MANUALRESET = EVENT_MANUALRESET_IMPL, /// Manual reset event
EVENT_AUTORESET = EVENT_AUTORESET_IMPL, /// Auto-reset event
};
explicit Event(EventType type = EVENT_AUTORESET);
/// Creates the event. If type is EVENT_AUTORESET,
/// the event is automatically reset after /// the event is automatically reset after
/// a wait() successfully returns. /// a wait() successfully returns.
//@ deprecated
explicit Event(bool autoReset);
/// Please use Event::Event(EventType) instead.
~Event(); ~Event();
/// Destroys the event. /// Destroys the event.

View File

@@ -31,8 +31,15 @@ namespace Poco {
class Foundation_API EventImpl class Foundation_API EventImpl
{ {
public:
enum EventTypeImpl
{
EVENT_MANUALRESET_IMPL,
EVENT_AUTORESET_IMPL,
};
protected: protected:
EventImpl(bool autoReset); EventImpl(EventTypeImpl type);
~EventImpl(); ~EventImpl();
void setImpl(); void setImpl();
void waitImpl(); void waitImpl();

View File

@@ -30,8 +30,15 @@ namespace Poco {
class Foundation_API EventImpl class Foundation_API EventImpl
{ {
public:
enum EventTypeImpl
{
EVENT_MANUALRESET_IMPL,
EVENT_AUTORESET_IMPL,
};
protected: protected:
EventImpl(bool autoReset); EventImpl(EventTypeImpl type);
~EventImpl(); ~EventImpl();
void setImpl(); void setImpl();
void waitImpl(); void waitImpl();

View File

@@ -30,8 +30,15 @@ namespace Poco {
class Foundation_API EventImpl class Foundation_API EventImpl
{ {
public:
enum EventTypeImpl
{
EVENT_MANUALRESET_IMPL,
EVENT_AUTORESET_IMPL,
};
protected: protected:
EventImpl(bool autoReset); EventImpl(EventTypeImpl type);
~EventImpl(); ~EventImpl();
void setImpl(); void setImpl();
void waitImpl(); void waitImpl();

View File

@@ -45,20 +45,24 @@ class Foundation_API Mutex: private MutexImpl
/// A Mutex (mutual exclusion) is a synchronization /// A Mutex (mutual exclusion) is a synchronization
/// mechanism used to control access to a shared resource /// mechanism used to control access to a shared resource
/// in a concurrent (multithreaded) scenario. /// in a concurrent (multithreaded) scenario.
/// Mutexes are recursive, that is, the same mutex can be
/// locked multiple times by the same thread (but, of course,
/// not by other threads).
/// Using the ScopedLock class is the preferred way to automatically /// Using the ScopedLock class is the preferred way to automatically
/// lock and unlock a mutex. /// lock and unlock a mutex.
{ {
public: public:
enum MutexType
/// The type of a mutex.
{
MUTEX_RECURSIVE = MUTEX_RECURSIVE_IMPL, /// A recursive mutex
MUTEX_NONRECURSIVE = MUTEX_NONRECURSIVE_IMPL, /// A non-recursive mutex
};
typedef Poco::ScopedLock<Mutex> ScopedLock; typedef Poco::ScopedLock<Mutex> ScopedLock;
Mutex(); explicit Mutex(MutexType type = MUTEX_RECURSIVE);
/// creates the Mutex. /// Creates the Mutex.
~Mutex(); ~Mutex();
/// destroys the Mutex. /// Destroys the Mutex.
void lock(); void lock();
/// Locks the mutex. Blocks if the mutex /// Locks the mutex. Blocks if the mutex
@@ -99,10 +103,11 @@ private:
class Foundation_API FastMutex: private FastMutexImpl class Foundation_API FastMutex: private FastMutexImpl
/// A FastMutex (mutual exclusion) is similar to a Mutex. /// A FastMutex (mutual exclusion) is similar to a Mutex.
/// Unlike a Mutex, however, a FastMutex is not recursive, /// Locking a FastMutex is guaranteed to be at least as
/// which means that a deadlock will occur if the same /// fast as locking a Mutex. However, a FastMutex is not
/// thread tries to lock a mutex it has already locked again. /// guaranteed to be either recursive or non-recursive.
/// Locking a FastMutex is faster than locking a recursive Mutex. /// It is best suited to thread safe components like pools,
/// caches and queues where locking is internal to the component.
/// Using the ScopedLock class is the preferred way to automatically /// Using the ScopedLock class is the preferred way to automatically
/// lock and unlock a mutex. /// lock and unlock a mutex.
{ {

View File

@@ -31,9 +31,15 @@ namespace Poco {
class Foundation_API MutexImpl class Foundation_API MutexImpl
{ {
public:
enum MutexTypeImpl
{
MUTEX_RECURSIVE_IMPL,
MUTEX_NONRECURSIVE_IMPL,
};
protected: protected:
MutexImpl(); explicit MutexImpl(MutexTypeImpl type);
MutexImpl(bool fast);
~MutexImpl(); ~MutexImpl();
void lockImpl(); void lockImpl();
bool tryLockImpl(); bool tryLockImpl();

View File

@@ -31,9 +31,15 @@ namespace Poco {
class Foundation_API MutexImpl class Foundation_API MutexImpl
{ {
public:
enum MutexTypeImpl
{
MUTEX_RECURSIVE_IMPL,
MUTEX_NONRECURSIVE_IMPL,
};
protected: protected:
MutexImpl(); explicit MutexImpl(MutexTypeImpl type);
MutexImpl(bool fast);
~MutexImpl(); ~MutexImpl();
void lockImpl(); void lockImpl();
bool tryLockImpl(); bool tryLockImpl();

View File

@@ -30,26 +30,58 @@ namespace Poco {
class Foundation_API MutexImpl class Foundation_API MutexImpl
{ {
public:
enum MutexTypeImpl
{
MUTEX_RECURSIVE_IMPL,
MUTEX_NONRECURSIVE_IMPL,
};
protected: protected:
MutexImpl(); explicit MutexImpl(MutexTypeImpl type);
~MutexImpl(); ~MutexImpl();
void lockImpl(); void lockImpl();
bool tryLockImpl(); bool tryLockImpl();
bool tryLockImpl(long milliseconds); bool tryLockImpl(long milliseconds);
void unlockImpl(); void unlockImpl();
private:
CRITICAL_SECTION _cs;
int _lockCount;
const bool _recursive;
private:
MutexImpl(const MutexImpl&);
MutexImpl& operator = (const MutexImpl&);
};
class Foundation_API FastMutexImpl
{
protected:
FastMutexImpl();
~FastMutexImpl();
void lockImpl();
bool tryLockImpl();
bool tryLockImpl(long milliseconds);
void unlockImpl();
private: private:
CRITICAL_SECTION _cs; CRITICAL_SECTION _cs;
}; };
typedef MutexImpl FastMutexImpl;
// //
// inlines // inlines
// //
inline void MutexImpl::lockImpl() inline void MutexImpl::unlockImpl()
{
--_lockCount;
LeaveCriticalSection(&_cs);
}
inline void FastMutexImpl::lockImpl()
{ {
try try
{ {
@@ -62,7 +94,7 @@ inline void MutexImpl::lockImpl()
} }
inline bool MutexImpl::tryLockImpl() inline bool FastMutexImpl::tryLockImpl()
{ {
try try
{ {
@@ -75,7 +107,7 @@ inline bool MutexImpl::tryLockImpl()
} }
inline void MutexImpl::unlockImpl() inline void FastMutexImpl::unlockImpl()
{ {
LeaveCriticalSection(&_cs); LeaveCriticalSection(&_cs);
} }

View File

@@ -30,22 +30,47 @@ namespace Poco {
class Foundation_API MutexImpl class Foundation_API MutexImpl
{ {
public:
enum MutexTypeImpl
{
MUTEX_RECURSIVE_IMPL,
MUTEX_NONRECURSIVE_IMPL,
};
protected: protected:
MutexImpl(); explicit MutexImpl(MutexTypeImpl type);
~MutexImpl(); ~MutexImpl();
void lockImpl(); void lockImpl();
bool tryLockImpl(); bool tryLockImpl();
bool tryLockImpl(long milliseconds); bool tryLockImpl(long milliseconds);
void unlockImpl(); void unlockImpl();
private:
HANDLE _mutex;
int _lockCount;
const bool _recursive;
private:
MutexImpl(const MutexImpl&);
MutexImpl& operator = (const MutexImpl&);
};
class Foundation_API FastMutexImpl
{
protected:
FastMutexImpl();
~FastMutexImpl();
void lockImpl();
bool tryLockImpl();
bool tryLockImpl(long milliseconds);
void unlockImpl();
private: private:
HANDLE _mutex; HANDLE _mutex;
}; };
typedef MutexImpl FastMutexImpl;
} // namespace Poco } // namespace Poco

View File

@@ -120,7 +120,7 @@ private:
thread(0), thread(0),
prio(PRIO_NORMAL_IMPL), prio(PRIO_NORMAL_IMPL),
policy(SCHED_OTHER), policy(SCHED_OTHER),
done(false), done(Event::EVENT_MANUALRESET),
stackSize(POCO_THREAD_STACK_SIZE), stackSize(POCO_THREAD_STACK_SIZE),
started(false), started(false),
joined(false) joined(false)

View File

@@ -0,0 +1,7 @@
set(SAMPLE_NAME "MutexBenchmark")
set(LOCAL_SRCS "")
aux_source_directory(src LOCAL_SRCS)
add_executable( ${SAMPLE_NAME} ${LOCAL_SRCS} )
target_link_libraries( ${SAMPLE_NAME} PocoFoundation )

View File

@@ -0,0 +1,67 @@
//
// Benchmark.cpp
//
// $Id$
//
// This sample shows a benchmark of various mutex implementations.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Mutex.h"
#include "Poco/Stopwatch.h"
#include <iostream>
#include <iomanip>
template<typename Mtx>
void Benchmark(Mtx& mtx, std::string const& label)
{
Poco::Stopwatch sw;
sw.start();
const int LOOP_COUNT = 1000000000;
mtx.lock();
for (int i = 0 ; i < LOOP_COUNT ; ++i)
{
mtx.unlock();
mtx.lock();
}
mtx.unlock();
sw.stop();
std::cout << label << ' ' << sw.elapsed() << " [us]" << std::endl;
}
int main(int argc, char** argv)
{
{
Poco::NullMutex mtx;
Benchmark(mtx, "NullMutex");
}
{
Poco::Mutex mtx(Poco::Mutex::MUTEX_RECURSIVE);
Benchmark(mtx, "Mutex(MUTEX_RECURSIVE)");
}
{
Poco::Mutex mtx(Poco::Mutex::MUTEX_NONRECURSIVE);
Benchmark(mtx, "Mutex(MUTEX_NONRECURSIVE)");
}
{
Poco::FastMutex mtx;
Benchmark(mtx, "FastMutex");
}
return 0;
}

View File

@@ -1,5 +1,6 @@
add_subdirectory(ActiveMethod) add_subdirectory(ActiveMethod)
add_subdirectory(Activity) add_subdirectory(Activity)
add_subdirectory(Benchmark)
add_subdirectory(BinaryReaderWriter) add_subdirectory(BinaryReaderWriter)
add_subdirectory(DateTime) add_subdirectory(DateTime)
add_subdirectory(LogRotation) add_subdirectory(LogRotation)

View File

@@ -29,7 +29,12 @@
namespace Poco { namespace Poco {
Event::Event(bool autoReset): EventImpl(autoReset) Event::Event(EventType type): EventImpl((EventTypeImpl) type)
{
}
Event::Event(bool autoReset): EventImpl(autoReset ? EVENT_AUTORESET_IMPL : EVENT_MANUALRESET_IMPL)
{ {
} }

View File

@@ -26,7 +26,7 @@
namespace Poco { namespace Poco {
EventImpl::EventImpl(bool autoReset): _auto(autoReset), _state(false) EventImpl::EventImpl(EventTypeImpl type): _auto(type == EVENT_AUTORESET_IMPL), _state(false)
{ {
#if defined(POCO_VXWORKS) #if defined(POCO_VXWORKS)
// This workaround is for VxWorks 5.x where // This workaround is for VxWorks 5.x where

View File

@@ -21,7 +21,7 @@
namespace Poco { namespace Poco {
EventImpl::EventImpl(bool autoReset): _auto(autoReset), _state(false) EventImpl::EventImpl(EventTypeImpl type): _auto(type == EVENT_AUTORESET_IMPL), _state(false)
{ {
_sem = semCCreate(SEM_Q_PRIORITY, 0); _sem = semCCreate(SEM_Q_PRIORITY, 0);
if (_sem == 0) if (_sem == 0)

View File

@@ -20,9 +20,9 @@
namespace Poco { namespace Poco {
EventImpl::EventImpl(bool autoReset) EventImpl::EventImpl(EventTypeImpl type)
{ {
_event = CreateEventW(NULL, autoReset ? FALSE : TRUE, FALSE, NULL); _event = CreateEventW(NULL, type == EVENT_AUTORESET_IMPL ? FALSE : TRUE, FALSE, NULL);
if (!_event) if (!_event)
throw SystemException("cannot create event"); throw SystemException("cannot create event");
} }

View File

@@ -33,7 +33,8 @@
namespace Poco { namespace Poco {
Mutex::Mutex() Mutex::Mutex(MutexType type)
: MutexImpl((MutexTypeImpl) type)
{ {
} }

View File

@@ -38,7 +38,7 @@
namespace Poco { namespace Poco {
MutexImpl::MutexImpl() MutexImpl::MutexImpl(MutexTypeImpl type)
{ {
#if defined(POCO_VXWORKS) #if defined(POCO_VXWORKS)
// This workaround is for VxWorks 5.x where // This workaround is for VxWorks 5.x where
@@ -50,34 +50,9 @@ MutexImpl::MutexImpl()
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
#if defined(PTHREAD_MUTEX_RECURSIVE_NP) #if defined(PTHREAD_MUTEX_RECURSIVE_NP)
pthread_mutexattr_settype_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutexattr_settype_np(&attr, type == MUTEX_RECURSIVE_IMPL ? PTHREAD_MUTEX_RECURSIVE_NP : PTHREAD_MUTEX_NORMAL_NP);
#elif !defined(POCO_VXWORKS)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
#endif
if (pthread_mutex_init(&_mutex, &attr))
{
pthread_mutexattr_destroy(&attr);
throw SystemException("cannot create mutex");
}
pthread_mutexattr_destroy(&attr);
}
MutexImpl::MutexImpl(bool fast)
{
#if defined(POCO_VXWORKS)
// This workaround is for VxWorks 5.x where
// pthread_mutex_init() won't properly initialize the mutex
// resulting in a subsequent freeze in pthread_mutex_destroy()
// if the mutex has never been used.
std::memset(&_mutex, 0, sizeof(_mutex));
#endif
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if defined(PTHREAD_MUTEX_RECURSIVE_NP)
pthread_mutexattr_settype_np(&attr, fast ? PTHREAD_MUTEX_NORMAL_NP : PTHREAD_MUTEX_RECURSIVE_NP);
#elif !defined(POCO_VXWORKS) #elif !defined(POCO_VXWORKS)
pthread_mutexattr_settype(&attr, fast ? PTHREAD_MUTEX_NORMAL : PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_settype(&attr, type == MUTEX_RECURSIVE_IMPL ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL);
#endif #endif
if (pthread_mutex_init(&_mutex, &attr)) if (pthread_mutex_init(&_mutex, &attr))
{ {
@@ -144,7 +119,7 @@ bool MutexImpl::tryLockImpl(long milliseconds)
} }
FastMutexImpl::FastMutexImpl(): MutexImpl(true) FastMutexImpl::FastMutexImpl(): MutexImpl(MUTEX_NONRECURSIVE_IMPL)
{ {
} }

View File

@@ -21,23 +21,16 @@
namespace Poco { namespace Poco {
MutexImpl::MutexImpl() MutexImpl::MutexImpl(MutexTypeImpl type)
{ {
_sem = semMCreate(SEM_INVERSION_SAFE | SEM_Q_PRIORITY); switch (type)
if (_sem == 0)
throw Poco::SystemException("cannot create mutex");
}
MutexImpl::MutexImpl(bool fast)
{
if (fast)
{
_sem = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
}
else
{ {
case MUTEX_RECURSIVE_IMPL:
_sem = semMCreate(SEM_INVERSION_SAFE | SEM_Q_PRIORITY); _sem = semMCreate(SEM_INVERSION_SAFE | SEM_Q_PRIORITY);
break;
case MUTEX_NONRECURSIVE_IMPL:
_sem = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
break;
} }
if (_sem == 0) if (_sem == 0)
throw Poco::SystemException("cannot create mutex"); throw Poco::SystemException("cannot create mutex");
@@ -57,7 +50,7 @@ bool MutexImpl::tryLockImpl(long milliseconds)
} }
FastMutexImpl::FastMutexImpl(): MutexImpl(true) FastMutexImpl::FastMutexImpl(): MutexImpl(MUTEX_NONRECURSIVE_IMPL)
{ {
} }

View File

@@ -15,13 +15,16 @@
#include "Poco/Mutex_WIN32.h" #include "Poco/Mutex_WIN32.h"
#include "Poco/Thread.h"
#include "Poco/Timestamp.h" #include "Poco/Timestamp.h"
namespace Poco { namespace Poco {
MutexImpl::MutexImpl() MutexImpl::MutexImpl(MutexTypeImpl type)
: _lockCount(0)
, _recursive(type == MUTEX_RECURSIVE_IMPL)
{ {
// the fct has a boolean return value under WInnNt/2000/XP but not on Win98 // the fct has a boolean return value under WInnNt/2000/XP but not on Win98
// the return only checks if the input address of &_cs was valid, so it is safe to omit it // the return only checks if the input address of &_cs was valid, so it is safe to omit it
@@ -35,7 +38,87 @@ MutexImpl::~MutexImpl()
} }
void MutexImpl::lockImpl()
{
try
{
EnterCriticalSection(&_cs);
++_lockCount;
if (!_recursive && _lockCount > 1)
{
// We're trying to go recursive so self-deadlock
Thread::current()->join();
}
}
catch (...)
{
throw SystemException("cannot lock mutex");
}
}
bool MutexImpl::tryLockImpl()
{
try
{
if (TryEnterCriticalSection(&_cs) == 0)
return false;
if (!_recursive && _lockCount > 0)
{
LeaveCriticalSection(&_cs);
return false;
}
++_lockCount;
return true;
}
catch (...)
{
}
throw SystemException("cannot lock mutex");
}
bool MutexImpl::tryLockImpl(long milliseconds) bool MutexImpl::tryLockImpl(long milliseconds)
{
const int sleepMillis = 5;
Timestamp now;
Timestamp::TimeDiff diff(Timestamp::TimeDiff(milliseconds)*1000);
do
{
try
{
if (tryLockImpl())
return true;
}
catch (...)
{
throw SystemException("cannot lock mutex");
}
Sleep(sleepMillis);
} while (!now.isElapsed(diff));
return false;
}
FastMutexImpl::FastMutexImpl()
{
// the fct has a boolean return value under WInnNt/2000/XP but not on Win98
// the return only checks if the input address of &_cs was valid, so it is safe to omit it
InitializeCriticalSectionAndSpinCount(&_cs, 4000);
}
FastMutexImpl::~FastMutexImpl()
{
DeleteCriticalSection(&_cs);
}
bool FastMutexImpl::tryLockImpl(long milliseconds)
{ {
const int sleepMillis = 5; const int sleepMillis = 5;
Timestamp now; Timestamp now;

View File

@@ -15,12 +15,16 @@
#include "Poco/Mutex_WINCE.h" #include "Poco/Mutex_WINCE.h"
#include "Poco/Thread.h"
#include "Poco/Timestamp.h"
namespace Poco { namespace Poco {
MutexImpl::MutexImpl() MutexImpl::MutexImpl(MutexTypeImpl type)
: _lockCount(0)
, _recursive(type == MUTEX_RECURSIVE_IMPL)
{ {
_mutex = CreateMutexW(NULL, FALSE, NULL); _mutex = CreateMutexW(NULL, FALSE, NULL);
if (!_mutex) throw SystemException("cannot create mutex"); if (!_mutex) throw SystemException("cannot create mutex");
@@ -38,6 +42,12 @@ void MutexImpl::lockImpl()
switch (WaitForSingleObject(_mutex, INFINITE)) switch (WaitForSingleObject(_mutex, INFINITE))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
++_lockCount;
if (!_recursive && _lockCount > 1)
{
// We're trying to go recursive so self-deadlock
Thread::current()->join();
}
return; return;
default: default:
throw SystemException("cannot lock mutex"); throw SystemException("cannot lock mutex");
@@ -46,6 +56,80 @@ void MutexImpl::lockImpl()
bool MutexImpl::tryLockImpl() bool MutexImpl::tryLockImpl()
{
switch (WaitForSingleObject(_mutex, 0))
{
case WAIT_TIMEOUT:
return false;
case WAIT_OBJECT_0:
if (!_recursive && _lockCount > 0)
{
ReleaseMutex(_mutex);
return false;
}
++_lockCount;
return true;
default:
throw SystemException("cannot lock mutex");
}
}
bool MutexImpl::tryLockImpl(long milliseconds)
{
const int sleepMillis = 5;
Timestamp now;
Timestamp::TimeDiff diff(Timestamp::TimeDiff(milliseconds)*1000);
do
{
try
{
if (tryLockImpl())
return true;
}
catch (...)
{
throw SystemException("cannot lock mutex");
}
Sleep(sleepMillis);
} while (!now.isElapsed(diff));
return false;
}
void MutexImpl::unlockImpl()
{
ReleaseMutex(_mutex);
}
FastMutexImpl::FastMutexImpl()
{
_mutex = CreateMutexW(NULL, FALSE, NULL);
if (!_mutex) throw SystemException("cannot create mutex");
}
FastMutexImpl::~FastMutexImpl()
{
CloseHandle(_mutex);
}
void FastMutexImpl::lockImpl()
{
switch (WaitForSingleObject(_mutex, INFINITE))
{
case WAIT_OBJECT_0:
return;
default:
throw SystemException("cannot lock mutex");
}
}
bool FastMutexImpl::tryLockImpl()
{ {
switch (WaitForSingleObject(_mutex, 0)) switch (WaitForSingleObject(_mutex, 0))
{ {
@@ -59,7 +143,7 @@ bool MutexImpl::tryLockImpl()
} }
bool MutexImpl::tryLockImpl(long milliseconds) bool FastMutexImpl::tryLockImpl(long milliseconds)
{ {
switch (WaitForSingleObject(_mutex, milliseconds + 1)) switch (WaitForSingleObject(_mutex, milliseconds + 1))
{ {
@@ -73,7 +157,7 @@ bool MutexImpl::tryLockImpl(long milliseconds)
} }
void MutexImpl::unlockImpl() void FastMutexImpl::unlockImpl()
{ {
ReleaseMutex(_mutex); ReleaseMutex(_mutex);
} }

View File

@@ -27,7 +27,7 @@ Task::Task(const std::string& name):
_pOwner(0), _pOwner(0),
_progress(0), _progress(0),
_state(TASK_IDLE), _state(TASK_IDLE),
_cancelEvent(false) _cancelEvent(Event::EVENT_MANUALRESET)
{ {
} }

View File

@@ -93,7 +93,7 @@ Thread::Thread():
_id(uniqueId()), _id(uniqueId()),
_name(makeName()), _name(makeName()),
_pTLS(0), _pTLS(0),
_event(true) _event()
{ {
} }
@@ -102,7 +102,7 @@ Thread::Thread(const std::string& name):
_id(uniqueId()), _id(uniqueId()),
_name(name), _name(name),
_pTLS(0), _pTLS(0),
_event(true) _event()
{ {
} }

View File

@@ -65,7 +65,10 @@ PooledThread::PooledThread(const std::string& name, int stackSize):
_pTarget(0), _pTarget(0),
_name(name), _name(name),
_thread(name), _thread(name),
_targetCompleted(false) _targetReady(),
_targetCompleted(Event::EVENT_MANUALRESET),
_started(),
_mutex()
{ {
poco_assert_dbg (stackSize >= 0); poco_assert_dbg (stackSize >= 0);
_thread.setStackSize(stackSize); _thread.setStackSize(stackSize);

View File

@@ -24,7 +24,7 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
NotificationsTestSuite NullStreamTest NumberFormatterTest \ NotificationsTestSuite NullStreamTest NumberFormatterTest \
NumberParserTest PathTest PatternFormatterTest PBKDF2EngineTest RWLockTest \ NumberParserTest PathTest PatternFormatterTest PBKDF2EngineTest RWLockTest \
RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest \ RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest \
SemaphoreTest ConditionTest SharedLibraryTest SharedLibraryTestSuite \ SemaphoreTest MutexTest ConditionTest SharedLibraryTest SharedLibraryTestSuite \
SimpleFileChannelTest StopwatchTest \ SimpleFileChannelTest StopwatchTest \
StreamConverterTest StreamCopierTest StreamTokenizerTest \ StreamConverterTest StreamCopierTest StreamTokenizerTest \
StreamsTestSuite StringTest StringTokenizerTest TaskTestSuite TaskTest \ StreamsTestSuite StringTest StringTokenizerTest TaskTestSuite TaskTest \

View File

@@ -66,6 +66,7 @@ SOURCES="
ManifestTest.cpp ManifestTest.cpp
MemoryPoolTest.cpp MemoryPoolTest.cpp
MemoryStreamTest.cpp MemoryStreamTest.cpp
MutexTest.cpp
NDCTest.cpp NDCTest.cpp
NotificationCenterTest.cpp NotificationCenterTest.cpp
NotificationQueueTest.cpp NotificationQueueTest.cpp

View File

@@ -1074,6 +1074,10 @@
RelativePath=".\src\ConditionTest.cpp" RelativePath=".\src\ConditionTest.cpp"
> >
</File> </File>
<File
RelativePath=".\src\MutexTest.cpp"
>
</File>
<File <File
RelativePath=".\src\RWLockTest.cpp" RelativePath=".\src\RWLockTest.cpp"
> >
@@ -1122,6 +1126,10 @@
RelativePath=".\src\ConditionTest.h" RelativePath=".\src\ConditionTest.h"
> >
</File> </File>
<File
RelativePath=".\src\MutexTest.h"
>
</File>
<File <File
RelativePath=".\src\RWLockTest.h" RelativePath=".\src\RWLockTest.h"
> >

View File

@@ -340,6 +340,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -477,6 +478,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -336,6 +336,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -746,6 +749,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -343,6 +343,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -480,6 +481,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -336,6 +336,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -746,6 +749,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -360,6 +360,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -498,6 +499,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -330,6 +330,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -740,6 +743,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -365,6 +365,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -503,6 +504,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -336,6 +336,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -746,6 +749,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -388,6 +388,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -525,6 +526,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -336,6 +336,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -746,6 +749,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -1029,6 +1029,10 @@
RelativePath=".\src\ConditionTest.cpp" RelativePath=".\src\ConditionTest.cpp"
> >
</File> </File>
<File
RelativePath=".\src\MutexTest.cpp"
>
</File>
<File <File
RelativePath=".\src\RWLockTest.cpp" RelativePath=".\src\RWLockTest.cpp"
> >
@@ -1077,6 +1081,10 @@
RelativePath=".\src\ConditionTest.h" RelativePath=".\src\ConditionTest.h"
> >
</File> </File>
<File
RelativePath=".\src\MutexTest.h"
>
</File>
<File <File
RelativePath=".\src\RWLockTest.h" RelativePath=".\src\RWLockTest.h"
> >

View File

@@ -359,6 +359,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -498,6 +499,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -339,6 +339,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -752,6 +755,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -365,6 +365,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -504,6 +505,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -336,6 +336,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -749,6 +752,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -372,6 +372,7 @@
<ClCompile Include="src\ActiveMethodTest.cpp" /> <ClCompile Include="src\ActiveMethodTest.cpp" />
<ClCompile Include="src\ActivityTest.cpp" /> <ClCompile Include="src\ActivityTest.cpp" />
<ClCompile Include="src\ConditionTest.cpp" /> <ClCompile Include="src\ConditionTest.cpp" />
<ClCompile Include="src\MutexTest.cpp" />
<ClCompile Include="src\RWLockTest.cpp" /> <ClCompile Include="src\RWLockTest.cpp" />
<ClCompile Include="src\SemaphoreTest.cpp" /> <ClCompile Include="src\SemaphoreTest.cpp" />
<ClCompile Include="src\ThreadingTestSuite.cpp" /> <ClCompile Include="src\ThreadingTestSuite.cpp" />
@@ -510,6 +511,7 @@
<ClInclude Include="src\ActiveMethodTest.h" /> <ClInclude Include="src\ActiveMethodTest.h" />
<ClInclude Include="src\ActivityTest.h" /> <ClInclude Include="src\ActivityTest.h" />
<ClInclude Include="src\ConditionTest.h" /> <ClInclude Include="src\ConditionTest.h" />
<ClInclude Include="src\MutexTest.h" />
<ClInclude Include="src\RWLockTest.h" /> <ClInclude Include="src\RWLockTest.h" />
<ClInclude Include="src\SemaphoreTest.h" /> <ClInclude Include="src\SemaphoreTest.h" />
<ClInclude Include="src\ThreadingTestSuite.h" /> <ClInclude Include="src\ThreadingTestSuite.h" />

View File

@@ -336,6 +336,9 @@
<ClCompile Include="src\ConditionTest.cpp"> <ClCompile Include="src\ConditionTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\MutexTest.cpp">
<Filter>Threading\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\RWLockTest.cpp"> <ClCompile Include="src\RWLockTest.cpp">
<Filter>Threading\Source Files</Filter> <Filter>Threading\Source Files</Filter>
</ClCompile> </ClCompile>
@@ -749,6 +752,9 @@
<ClInclude Include="src\ConditionTest.h"> <ClInclude Include="src\ConditionTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\MutexTest.h">
<Filter>Threading\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\RWLockTest.h"> <ClInclude Include="src\RWLockTest.h">
<Filter>Threading\Header Files</Filter> <Filter>Threading\Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -1023,6 +1023,10 @@
RelativePath=".\src\ConditionTest.cpp" RelativePath=".\src\ConditionTest.cpp"
> >
</File> </File>
<File
RelativePath=".\src\MutexTest.cpp"
>
</File>
<File <File
RelativePath=".\src\RWLockTest.cpp" RelativePath=".\src\RWLockTest.cpp"
> >
@@ -1071,6 +1075,10 @@
RelativePath=".\src\ConditionTest.h" RelativePath=".\src\ConditionTest.h"
> >
</File> </File>
<File
RelativePath=".\src\MutexTest.h"
>
</File>
<File <File
RelativePath=".\src\RWLockTest.h" RelativePath=".\src\RWLockTest.h"
> >

View File

@@ -0,0 +1,143 @@
//
// MutexTest.cpp
//
// $Id: //poco/1.4/Foundation/testsuite/src/MutexTest.cpp#1 $
//
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "MutexTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/Exception.h"
#include "Poco/Mutex.h"
#include "Poco/Runnable.h"
#include "Poco/Thread.h"
#include "Poco/Timestamp.h"
using Poco::Mutex;
using Poco::Runnable;
using Poco::SystemException;
using Poco::Thread;
using Poco::Timestamp;
namespace
{
class SelfDeadlockRunnable: public Runnable
{
public:
SelfDeadlockRunnable():
_ran(false)
{
}
void run()
{
try
{
Mutex mtx(Mutex::MUTEX_NONRECURSIVE);
mtx.lock();
mtx.lock();
}
catch (...)
{
}
_ran = true;
}
bool ran() const
{
return _ran;
}
private:
bool _ran;
};
}
MutexTest::MutexTest(const std::string& name): CppUnit::TestCase(name)
{
}
MutexTest::~MutexTest()
{
}
void MutexTest::testMutexRecursion()
{
Mutex mtx(Mutex::MUTEX_NONRECURSIVE);
mtx.lock();
bool success = mtx.tryLock();
assert (!success);
Timestamp mark;
success = mtx.tryLock(2000); // Wait 2 seconds
assert (!success);
// Test that we waited approx. 2 sec
Timestamp::TimeDiff elapsed = mark.elapsed();
assert (elapsed > 1000000);
assert (elapsed < 3000000);
success = mtx.tryLock(0);
assert (!success);
SelfDeadlockRunnable r;
Thread t;
t.start(r);
success = t.tryJoin(2000);
assert (!success);
assert (!r.ran());
}
void MutexTest::testRecursiveMutexRecursion()
{
Mutex mtx;
mtx.lock();
bool success = mtx.tryLock();
assert (success);
Timestamp mark;
success = mtx.tryLock(2000); // Wait 2 seconds
assert (success);
// Test that we completed almost immediately
Timestamp::TimeDiff elapsed = mark.elapsed();
assert (elapsed < 100000);
success = mtx.tryLock(0);
assert (success);
}
void MutexTest::setUp()
{
}
void MutexTest::tearDown()
{
}
CppUnit::Test* MutexTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MutexTest");
CppUnit_addTest(pSuite, MutexTest, testMutexRecursion);
CppUnit_addTest(pSuite, MutexTest, testRecursiveMutexRecursion);
return pSuite;
}

View File

@@ -0,0 +1,41 @@
//
// MutexTest.h
//
// $Id: //poco/1.4/Foundation/testsuite/src/MutexTest.h#1 $
//
// Definition of the MutexTest class.
//
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef MutexTest_INCLUDED
#define MutexTest_INCLUDED
#include "Poco/Foundation.h"
#include "CppUnit/TestCase.h"
class MutexTest: public CppUnit::TestCase
{
public:
MutexTest(const std::string& name);
~MutexTest();
void testMutexRecursion();
void testRecursiveMutexRecursion();
void setUp();
void tearDown();
static CppUnit::Test* suite();
private:
};
#endif // MutexTest_INCLUDED

View File

@@ -19,12 +19,13 @@
#include "Poco/Thread.h" #include "Poco/Thread.h"
using Poco::Event;
using Poco::ThreadPool; using Poco::ThreadPool;
using Poco::RunnableAdapter; using Poco::RunnableAdapter;
using Poco::Thread; using Poco::Thread;
ThreadPoolTest::ThreadPoolTest(const std::string& name): CppUnit::TestCase(name), _event(false) ThreadPoolTest::ThreadPoolTest(const std::string& name): CppUnit::TestCase(name), _event(Event::EVENT_MANUALRESET)
{ {
} }

View File

@@ -12,6 +12,7 @@
#include "ThreadingTestSuite.h" #include "ThreadingTestSuite.h"
#include "ThreadTest.h" #include "ThreadTest.h"
#include "MutexTest.h"
#include "SemaphoreTest.h" #include "SemaphoreTest.h"
#include "RWLockTest.h" #include "RWLockTest.h"
#include "ThreadPoolTest.h" #include "ThreadPoolTest.h"
@@ -28,6 +29,7 @@ CppUnit::Test* ThreadingTestSuite::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ThreadingTestSuite"); CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ThreadingTestSuite");
pSuite->addTest(ThreadTest::suite()); pSuite->addTest(ThreadTest::suite());
pSuite->addTest(MutexTest::suite());
pSuite->addTest(SemaphoreTest::suite()); pSuite->addTest(SemaphoreTest::suite());
pSuite->addTest(RWLockTest::suite()); pSuite->addTest(RWLockTest::suite());
pSuite->addTest(ThreadPoolTest::suite()); pSuite->addTest(ThreadPoolTest::suite());