diff --git a/Foundation/Foundation_vs80.vcproj b/Foundation/Foundation_vs80.vcproj
index dd00102bb..fcd3fc15d 100644
--- a/Foundation/Foundation_vs80.vcproj
+++ b/Foundation/Foundation_vs80.vcproj
@@ -1699,6 +1699,10 @@
RelativePath=".\src\ThreadPool.cpp"
>
+
+
@@ -1831,6 +1835,10 @@
RelativePath=".\include\Poco\ThreadPool.h"
>
+
+
diff --git a/Foundation/Foundation_vs90.vcproj b/Foundation/Foundation_vs90.vcproj
index 99ec7ffff..3481c9340 100644
--- a/Foundation/Foundation_vs90.vcproj
+++ b/Foundation/Foundation_vs90.vcproj
@@ -1682,6 +1682,10 @@
/>
+
+
@@ -1814,6 +1818,10 @@
RelativePath=".\include\Poco\Thread_WIN32.h"
>
+
+
diff --git a/Foundation/Makefile b/Foundation/Makefile
index cce3f6c9c..14d79ede5 100644
--- a/Foundation/Makefile
+++ b/Foundation/Makefile
@@ -27,7 +27,7 @@ objects = ArchiveStrategy ASCIIEncoding AsyncChannel Base64Decoder Base64Encoder
StreamTokenizer String StringTokenizer SynchronizedObject \
Task TaskManager TaskNotification TeeStream Hash HashStatistic \
TemporaryFile TextConverter TextEncoding TextIterator Thread ThreadLocal \
- ThreadPool ActiveDispatcher Timer Timespan Timestamp Timezone Token URI \
+ ThreadPool ThreadTarget ActiveDispatcher Timer Timespan Timestamp Timezone Token URI \
FileStreamFactory URIStreamFactory URIStreamOpener UTF16Encoding Windows1252Encoding \
UTF8Encoding UnicodeConverter UUID UUIDGenerator Void Format \
Pipe PipeImpl PipeStream SharedMemory FileStream Unicode UTF8String \
diff --git a/Foundation/include/Poco/RunnableAdapter.h b/Foundation/include/Poco/RunnableAdapter.h
index c1b1f7028..68944ef22 100644
--- a/Foundation/include/Poco/RunnableAdapter.h
+++ b/Foundation/include/Poco/RunnableAdapter.h
@@ -5,7 +5,7 @@
//
// Library: Foundation
// Package: Threading
-// Module: Thread
+// Module: RunnableAdapter
//
// Definition of the RunnableAdapter template class.
//
@@ -59,11 +59,15 @@ class RunnableAdapter: public Runnable
public:
typedef void (C::*Callback)();
- RunnableAdapter(C& object, Callback method): _pObject(&object), _method(method)
+ RunnableAdapter(C& object, Callback method):
+ _pObject(&object),
+ _method(method)
{
}
- RunnableAdapter(const RunnableAdapter& ra): _pObject(ra._pObject), _method(ra._method)
+ RunnableAdapter(const RunnableAdapter& ra):
+ _pObject(ra._pObject),
+ _method(ra._method)
{
}
diff --git a/Foundation/include/Poco/Thread.h b/Foundation/include/Poco/Thread.h
index 5cda15e21..606efd826 100644
--- a/Foundation/include/Poco/Thread.h
+++ b/Foundation/include/Poco/Thread.h
@@ -68,6 +68,8 @@ class Foundation_API Thread: private ThreadImpl
/// The name of a thread can be changed at any time.
{
public:
+ using ThreadImpl::Callback;
+
enum Priority
/// Thread priorities.
{
@@ -108,9 +110,22 @@ public:
Priority getPriority() const;
/// Returns the thread's priority.
+ void setStackSize(std::size_t size);
+ /// Sets the thread's stack size in bytes.
+ /// Setting the stack size to 0 will use the default stack size.
+ /// Typically, the real stack size is rounded up to the nearest
+ /// page size multiple.
+
+ std::size_t getStackSize() const;
+ /// Returns the thread's stack size in bytes.
+ /// If the default stack size is used, 0 is returned.
+
void start(Runnable& target);
/// Starts the thread with the given target.
+ void start(Callback target, void* pData = 0);
+ /// Starts the thread with the given target and parameter.
+
void join();
/// Waits until the thread completes execution.
/// If multiple threads try to join the same
@@ -216,6 +231,18 @@ inline Thread* Thread::current()
}
+inline void Thread::setStackSize(std::size_t size)
+{
+ setStackSizeImpl(size);
+}
+
+
+inline std::size_t Thread::getStackSize() const
+{
+ return getStackSizeImpl();
+}
+
+
} // namespace Poco
diff --git a/Foundation/include/Poco/ThreadTarget.h b/Foundation/include/Poco/ThreadTarget.h
new file mode 100644
index 000000000..125643cf9
--- /dev/null
+++ b/Foundation/include/Poco/ThreadTarget.h
@@ -0,0 +1,104 @@
+//
+// ThreadTarget.h
+//
+// $Id: //poco/svn/Foundation/include/Poco/ThreadTarget.h#2 $
+//
+// Library: Foundation
+// Package: Threading
+// Module: ThreadTarget
+//
+// Definition of the ThreadTarget class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Foundation_ThreadTarget_INCLUDED
+#define Foundation_ThreadTarget_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+
+
+namespace Poco {
+
+
+class Foundation_API ThreadTarget: public Runnable
+ /// This adapter simplifies using static member functions as well as
+ /// standalone functions as targets for threads.
+ /// Note that it is possible to pass those entities directly to Thread::start().
+ /// This adapter is provided as a convenience for higher abstraction level
+ /// scenarios where Runnable abstract class is used.
+ ///
+ /// Usage:
+ /// class MyObject
+ /// {
+ /// static void doSomething() {}
+ /// };
+ /// ThreadTarget ra(&MyObject::doSomething));
+ /// Thread thr;
+ /// thr.start(ra);
+ ///
+ /// or:
+ ///
+ /// void doSomething() {}
+ ///
+ /// ThreadTarget ra(doSomething));
+ /// Thread thr;
+ /// thr.start(ra);
+
+{
+public:
+ typedef void (*Callback)();
+
+ ThreadTarget(Callback method);
+
+ ThreadTarget(const ThreadTarget& te);
+
+ ~ThreadTarget();
+
+ ThreadTarget& operator = (const ThreadTarget& te);
+
+ void run();
+
+private:
+ ThreadTarget();
+
+ Callback _method;
+};
+
+
+inline void ThreadTarget::run()
+{
+ _method();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ThreadTarget_INCLUDED
diff --git a/Foundation/include/Poco/Thread_POSIX.h b/Foundation/include/Poco/Thread_POSIX.h
index da5c9a391..41a257c3f 100644
--- a/Foundation/include/Poco/Thread_POSIX.h
+++ b/Foundation/include/Poco/Thread_POSIX.h
@@ -59,6 +59,8 @@ namespace Poco {
class Foundation_API ThreadImpl
{
public:
+ typedef void (*Callback)(void*);
+
enum Priority
{
PRIO_LOWEST_IMPL,
@@ -68,13 +70,25 @@ public:
PRIO_HIGHEST_IMPL
};
+ struct CallbackData: public RefCountedObject
+ {
+ CallbackData(): callback(0), pData(0)
+ {
+ }
+
+ Callback callback;
+ void* pData;
+ };
+
ThreadImpl();
~ThreadImpl();
- Runnable& targetImpl() const;
void setPriorityImpl(int prio);
int getPriorityImpl() const;
+ void setStackSizeImpl(std::size_t size);
+ std::size_t getStackSizeImpl() const;
void startImpl(Runnable& target);
+ void startImpl(Callback target, void* pData = 0);
void joinImpl();
bool joinImpl(long milliseconds);
@@ -91,19 +105,23 @@ private:
struct ThreadData: public RefCountedObject
{
ThreadData():
- pTarget(0),
+ pRunnableTarget(0),
+ pCallbackTarget(0),
thread(0),
prio(PRIO_NORMAL_IMPL),
- done(false)
+ done(false),
+ stackSize(0)
{
}
- Runnable* pTarget;
- pthread_t thread;
- int prio;
- Event done;
+ Runnable* pRunnableTarget;
+ AutoPtr pCallbackTarget;
+ pthread_t thread;
+ int prio;
+ Event done;
+ std::size_t stackSize;
};
-
+
AutoPtr _pData;
static pthread_key_t _currentKey;
@@ -142,12 +160,31 @@ inline void ThreadImpl::sleepImpl(long milliseconds)
}
+inline bool ThreadImpl::isRunningImpl() const
+{
+ return _pData->pRunnableTarget != 0 ||
+ (_pData->pCallbackTarget.get() != 0 && _pData->pCallbackTarget->callback != 0);
+}
+
+
inline void ThreadImpl::yieldImpl()
{
sched_yield();
}
+inline void ThreadImpl::setStackSizeImpl(std::size_t size)
+{
+ _pData->stackSize = size;
+}
+
+
+inline std::size_t ThreadImpl::getStackSizeImpl() const
+{
+ return _pData->stackSize;
+}
+
+
} // namespace Poco
diff --git a/Foundation/include/Poco/Thread_WIN32.h b/Foundation/include/Poco/Thread_WIN32.h
index b594646fd..ec9e43746 100644
--- a/Foundation/include/Poco/Thread_WIN32.h
+++ b/Foundation/include/Poco/Thread_WIN32.h
@@ -51,6 +51,24 @@ namespace Poco {
class Foundation_API ThreadImpl
{
public:
+ typedef void (*Callback)(void*);
+
+#if defined(_DLL)
+ typedef DWORD (WINAPI *Entry)(LPVOID);
+#else
+ typedef unsigned (__stdcall *Entry)(void*);
+#endif
+
+ struct CallbackData
+ {
+ CallbackData(): callback(0), pData(0)
+ {
+ }
+
+ Callback callback;
+ void* pData;
+ };
+
enum Priority
{
PRIO_LOWEST_IMPL = THREAD_PRIORITY_LOWEST,
@@ -65,7 +83,10 @@ public:
void setPriorityImpl(int prio);
int getPriorityImpl() const;
+ void setStackSizeImpl(std::size_t size);
+ std::size_t getStackSizeImpl() const;
void startImpl(Runnable& target);
+ void startImpl(Callback target, void* pData = 0);
void joinImpl();
bool joinImpl(long milliseconds);
@@ -76,15 +97,26 @@ public:
protected:
#if defined(_DLL)
- static DWORD WINAPI entry(LPVOID pThread);
+ static DWORD WINAPI runnableEntry(LPVOID pThread);
#else
- static unsigned __stdcall entry(void* pThread);
+ static unsigned __stdcall runnableEntry(void* pThread);
#endif
+#if defined(_DLL)
+ static DWORD WINAPI functionEntry(LPVOID pThread);
+#else
+ static unsigned __stdcall functionEntry(void* pThread);
+#endif
+
+ void createImpl(Entry ent, void* pData);
+ void threadCleanup();
+
private:
- Runnable* _pTarget;
- HANDLE _thread;
- int _prio;
+ Runnable* _pRunnableTarget;
+ CallbackData _callbackTarget;
+ HANDLE _thread;
+ int _prio;
+ std::size_t _stackSize;
static DWORD _currentKey;
};
@@ -111,6 +143,18 @@ inline void ThreadImpl::yieldImpl()
}
+inline void ThreadImpl::setStackSizeImpl(std::size_t size)
+{
+ _stackSize = size;
+}
+
+
+inline std::size_t ThreadImpl::getStackSizeImpl() const
+{
+ return _stackSize;
+}
+
+
} // namespace Poco
diff --git a/Foundation/src/Thread.cpp b/Foundation/src/Thread.cpp
index b7db7b85c..acc16f52f 100644
--- a/Foundation/src/Thread.cpp
+++ b/Foundation/src/Thread.cpp
@@ -91,6 +91,12 @@ void Thread::start(Runnable& target)
}
+void Thread::start(Callback target, void* pData)
+{
+ startImpl(target, pData);
+}
+
+
void Thread::join()
{
joinImpl();
diff --git a/Foundation/src/ThreadTarget.cpp b/Foundation/src/ThreadTarget.cpp
new file mode 100644
index 000000000..7b1751219
--- /dev/null
+++ b/Foundation/src/ThreadTarget.cpp
@@ -0,0 +1,66 @@
+//
+// ThreadTarget.cpp
+//
+// $Id: //poco/svn/Foundation/src/ThreadTarget.cpp#2 $
+//
+// Library: Foundation
+// Package: Threading
+// Module: ThreadTarget
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/ThreadTarget.h"
+
+
+
+namespace Poco {
+
+
+ThreadTarget::ThreadTarget(Callback method): _method(method)
+{
+}
+
+
+ThreadTarget::ThreadTarget(const ThreadTarget& te): _method(te._method)
+{
+}
+
+
+ThreadTarget& ThreadTarget::operator = (const ThreadTarget& te)
+{
+ _method = te._method;
+ return *this;
+}
+
+
+ThreadTarget::~ThreadTarget()
+{
+}
+
+
+} // namespace Poco
diff --git a/Foundation/src/Thread_POSIX.cpp b/Foundation/src/Thread_POSIX.cpp
index ef3996488..93d639918 100644
--- a/Foundation/src/Thread_POSIX.cpp
+++ b/Foundation/src/Thread_POSIX.cpp
@@ -39,7 +39,6 @@
#include "Poco/ErrorHandler.h"
#include
-
//
// Block SIGPIPE in main thread.
//
@@ -87,7 +86,7 @@ ThreadImpl::ThreadImpl():
ThreadImpl::~ThreadImpl()
{
- if (_pData->pTarget)
+ if (isRunningImpl())
pthread_detach(_pData->thread);
}
@@ -97,7 +96,7 @@ void ThreadImpl::setPriorityImpl(int prio)
if (prio != _pData->prio)
{
_pData->prio = prio;
- if (_pData->pTarget)
+ if (isRunningImpl())
{
struct sched_param par;
par.sched_priority = mapPrio(_pData->prio);
@@ -110,12 +109,52 @@ void ThreadImpl::setPriorityImpl(int prio)
void ThreadImpl::startImpl(Runnable& target)
{
- if (_pData->pTarget) throw SystemException("thread already running");
+ if (_pData->pRunnableTarget) throw SystemException("thread already running");
- _pData->pTarget = ⌖
- if (pthread_create(&_pData->thread, NULL, entry, this))
+ pthread_attr_t attributes;
+ pthread_attr_init(&attributes);
+
+ if (_pData->stackSize != 0)
+ pthread_attr_setstacksize(&attributes, _pData->stackSize);
+
+ _pData->pRunnableTarget = ⌖
+ if (pthread_create(&_pData->thread, &attributes, entry, this))
{
- _pData->pTarget = 0;
+ _pData->pRunnableTarget = 0;
+ throw SystemException("cannot start thread");
+ }
+
+ if (_pData->prio != PRIO_NORMAL_IMPL)
+ {
+ struct sched_param par;
+ par.sched_priority = mapPrio(_pData->prio);
+ if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par))
+ throw SystemException("cannot set thread priority");
+ }
+}
+
+
+void ThreadImpl::startImpl(Callback target, void* pData)
+{
+ if (_pData->pCallbackTarget && _pData->pCallbackTarget->callback)
+ throw SystemException("thread already running");
+
+ pthread_attr_t attributes;
+ pthread_attr_init(&attributes);
+
+ if (_pData->stackSize != 0)
+ pthread_attr_setstacksize(&attributes, _pData->stackSize);
+
+ if (0 == _pData->pCallbackTarget.get())
+ _pData->pCallbackTarget = new CallbackData;
+
+ _pData->pCallbackTarget->callback = target;
+ _pData->pCallbackTarget->pData = pData;
+
+ if (pthread_create(&_pData->thread, &attributes, entry, this))
+ {
+ _pData->pCallbackTarget->callback = 0;
+ _pData->pCallbackTarget->pData = 0;
throw SystemException("cannot start thread");
}
@@ -151,12 +190,6 @@ bool ThreadImpl::joinImpl(long milliseconds)
}
-bool ThreadImpl::isRunningImpl() const
-{
- return _pData->pTarget != 0;
-}
-
-
ThreadImpl* ThreadImpl::currentImpl()
{
if (_haveCurrentKey)
@@ -183,7 +216,10 @@ void* ThreadImpl::entry(void* pThread)
AutoPtr pData = pThreadImpl->_pData;
try
{
- pData->pTarget->run();
+ if (pData->pRunnableTarget)
+ pData->pRunnableTarget->run();
+ else
+ pData->pCallbackTarget->callback(pData->pCallbackTarget->pData);
}
catch (Exception& exc)
{
@@ -197,7 +233,14 @@ void* ThreadImpl::entry(void* pThread)
{
ErrorHandler::handle();
}
- pData->pTarget = 0;
+ if (pData->pRunnableTarget)
+ pData->pRunnableTarget = 0;
+ else
+ {
+ pData->pCallbackTarget->callback = 0;
+ pData->pCallbackTarget->pData = 0;
+ }
+
pData->done.set();
return 0;
}
diff --git a/Foundation/src/Thread_WIN32.cpp b/Foundation/src/Thread_WIN32.cpp
index 73ff8098f..39452bc6c 100644
--- a/Foundation/src/Thread_WIN32.cpp
+++ b/Foundation/src/Thread_WIN32.cpp
@@ -46,7 +46,11 @@ namespace Poco {
DWORD ThreadImpl::_currentKey = TLS_OUT_OF_INDEXES;
-ThreadImpl::ThreadImpl(): _pTarget(0), _thread(0), _prio(PRIO_NORMAL_IMPL)
+ThreadImpl::ThreadImpl():
+ _pRunnableTarget(0),
+ _thread(0),
+ _prio(PRIO_NORMAL_IMPL),
+ _stackSize(0)
{
if (_currentKey == TLS_OUT_OF_INDEXES)
{
@@ -79,15 +83,35 @@ void ThreadImpl::setPriorityImpl(int prio)
void ThreadImpl::startImpl(Runnable& target)
{
- if (_thread) throw SystemException("thread already running");
+ if (isRunningImpl())
+ throw SystemException("thread already running");
- _pTarget = ⌖
+ _pRunnableTarget = ⌖
+
+ createImpl(runnableEntry, this);
+}
+
+
+void ThreadImpl::startImpl(Callback target, void* pData)
+{
+ if (isRunningImpl())
+ throw SystemException("thread already running");
+
+ _callbackTarget.callback = target;
+ _callbackTarget.pData = pData;
+
+ createImpl(functionEntry, this);
+}
+
+
+void ThreadImpl::createImpl(Entry ent, void* pData)
+{
#if defined(_DLL)
DWORD threadId;
- _thread = CreateThread(NULL, 0, entry, this, 0, &threadId);
+ _thread = CreateThread(NULL, _stackSize, ent, pData, 0, &threadId);
#else
unsigned threadId;
- _thread = (HANDLE) _beginthreadex(NULL, 0, entry, this, 0, &threadId);
+ _thread = (HANDLE) _beginthreadex(NULL, _stackSize, runnableEntry, this, 0, &threadId);
#endif
if (!_thread)
throw SystemException("cannot create thread");
@@ -103,6 +127,7 @@ void ThreadImpl::joinImpl()
switch (WaitForSingleObject(_thread, INFINITE))
{
case WAIT_OBJECT_0:
+ threadCleanup();
return;
default:
throw SystemException("cannot join thread");
@@ -119,6 +144,7 @@ bool ThreadImpl::joinImpl(long milliseconds)
case WAIT_TIMEOUT:
return false;
case WAIT_OBJECT_0:
+ threadCleanup();
return true;
default:
throw SystemException("cannot join thread");
@@ -137,6 +163,13 @@ bool ThreadImpl::isRunningImpl() const
}
+void ThreadImpl::threadCleanup()
+{
+ if (!_thread) return;
+ if (CloseHandle(_thread)) _thread = 0;
+}
+
+
ThreadImpl* ThreadImpl::currentImpl()
{
if (_currentKey == TLS_OUT_OF_INDEXES)
@@ -147,15 +180,43 @@ ThreadImpl* ThreadImpl::currentImpl()
#if defined(_DLL)
-DWORD WINAPI ThreadImpl::entry(LPVOID pThread)
+DWORD WINAPI ThreadImpl::runnableEntry(LPVOID pThread)
#else
-unsigned __stdcall ThreadImpl::entry(void* pThread)
+unsigned __stdcall ThreadImpl::runnableEntry(void* pThread)
#endif
{
TlsSetValue(_currentKey, pThread);
try
{
- reinterpret_cast(pThread)->_pTarget->run();
+ reinterpret_cast(pThread)->_pRunnableTarget->run();
+ }
+ catch (Exception& exc)
+ {
+ ErrorHandler::handle(exc);
+ }
+ catch (std::exception& exc)
+ {
+ ErrorHandler::handle(exc);
+ }
+ catch (...)
+ {
+ ErrorHandler::handle();
+ }
+ return 0;
+}
+
+
+#if defined(_DLL)
+DWORD WINAPI ThreadImpl::functionEntry(LPVOID pThread)
+#else
+unsigned __stdcall ThreadImpl::functionEntry(void* pThread)
+#endif
+{
+ TlsSetValue(_currentKey, pThread);
+ try
+ {
+ ThreadImpl* pTI = reinterpret_cast(pThread);
+ pTI->_callbackTarget.callback(pTI->_callbackTarget.pData);
}
catch (Exception& exc)
{
diff --git a/Foundation/testsuite/src/ThreadTest.cpp b/Foundation/testsuite/src/ThreadTest.cpp
index 146fae819..b25a041e0 100644
--- a/Foundation/testsuite/src/ThreadTest.cpp
+++ b/Foundation/testsuite/src/ThreadTest.cpp
@@ -35,11 +35,13 @@
#include "CppUnit/TestSuite.h"
#include "Poco/Thread.h"
#include "Poco/Runnable.h"
+#include "Poco/ThreadTarget.h"
#include "Poco/Event.h"
-
+#include
using Poco::Thread;
using Poco::Runnable;
+using Poco::ThreadTarget;
using Poco::Event;
@@ -74,6 +76,13 @@ public:
_event.set();
}
+ static void staticFunc()
+ {
+ ++_staticVar;
+ }
+
+ static int _staticVar;
+
private:
bool _ran;
std::string _threadName;
@@ -81,6 +90,21 @@ private:
};
+int MyRunnable::_staticVar = 0;
+
+
+void freeFunc()
+{
+ ++MyRunnable::_staticVar;
+}
+
+
+void freeFunc(void* pData)
+{
+ MyRunnable::_staticVar += *reinterpret_cast(pData);
+}
+
+
ThreadTest::ThreadTest(const std::string& name): CppUnit::TestCase(name)
{
}
@@ -195,6 +219,75 @@ void ThreadTest::testJoin()
}
+void ThreadTest::testThreadTarget()
+{
+ ThreadTarget te(&MyRunnable::staticFunc);
+ Thread thread;
+
+ assert (!thread.isRunning());
+
+ int tmp = MyRunnable::_staticVar;
+ thread.start(te);
+ thread.join();
+ assert (tmp + 1 == MyRunnable::_staticVar);
+
+ ThreadTarget te1(freeFunc);
+ assert (!thread.isRunning());
+
+ tmp = MyRunnable::_staticVar;
+ thread.start(te1);
+ thread.join();
+ assert (tmp + 1 == MyRunnable::_staticVar);
+}
+
+
+void ThreadTest::testThreadFunction()
+{
+ Thread thread;
+
+ assert (!thread.isRunning());
+
+ int tmp = MyRunnable::_staticVar;
+ thread.start(freeFunc, &tmp);
+ thread.join();
+ assert (tmp * 2 == MyRunnable::_staticVar);
+
+ assert (!thread.isRunning());
+
+ tmp = MyRunnable::_staticVar = 0;
+ thread.start(freeFunc, &tmp);
+ thread.join();
+ assert (0 == MyRunnable::_staticVar);
+}
+
+
+void ThreadTest::testThreadStackSize()
+{
+ Thread thread;
+ assert (0 == thread.getStackSize());
+ thread.setStackSize(50000000);
+ assert (50000000 == thread.getStackSize());
+ int tmp = MyRunnable::_staticVar;
+ thread.start(freeFunc, &tmp);
+ thread.join();
+ assert (tmp * 2 == MyRunnable::_staticVar);
+
+ thread.setStackSize(1);
+ assert (1 == thread.getStackSize());
+ tmp = MyRunnable::_staticVar;
+ thread.start(freeFunc, &tmp);
+ thread.join();
+ assert (tmp * 2 == MyRunnable::_staticVar);
+
+ thread.setStackSize(0);
+ assert (0 == thread.getStackSize());
+ tmp = MyRunnable::_staticVar;
+ thread.start(freeFunc, &tmp);
+ thread.join();
+ assert (tmp * 2 == MyRunnable::_staticVar);
+}
+
+
void ThreadTest::setUp()
{
}
@@ -214,6 +307,9 @@ CppUnit::Test* ThreadTest::suite()
CppUnit_addTest(pSuite, ThreadTest, testCurrent);
CppUnit_addTest(pSuite, ThreadTest, testThreads);
CppUnit_addTest(pSuite, ThreadTest, testJoin);
+ CppUnit_addTest(pSuite, ThreadTest, testThreadTarget);
+ CppUnit_addTest(pSuite, ThreadTest, testThreadFunction);
+ CppUnit_addTest(pSuite, ThreadTest, testThreadStackSize);
return pSuite;
}
diff --git a/Foundation/testsuite/src/ThreadTest.h b/Foundation/testsuite/src/ThreadTest.h
index b2b67b276..d90b4fc87 100644
--- a/Foundation/testsuite/src/ThreadTest.h
+++ b/Foundation/testsuite/src/ThreadTest.h
@@ -51,6 +51,9 @@ public:
void testCurrent();
void testThreads();
void testJoin();
+ void testThreadTarget();
+ void testThreadFunction();
+ void testThreadStackSize();
void setUp();
void tearDown();