From 9ae4244b4b28f71e2386dc9a60e433d3fe83509e Mon Sep 17 00:00:00 2001 From: maroy Date: Wed, 24 Nov 2004 13:05:27 +0000 Subject: [PATCH] addded Thread::yield() replaced usleep() call to nanosleep() in TimeCoversion::sleep() --- .../core/include/LiveSupport/Core/Thread.h | 14 ++++++-- livesupport/modules/core/src/TestRunnable.cxx | 12 +++---- livesupport/modules/core/src/TestRunnable.h | 23 +++++++++++-- livesupport/modules/core/src/Thread.cxx | 17 +++++++--- livesupport/modules/core/src/ThreadTest.cxx | 34 ++++++++++++++++--- livesupport/modules/core/src/ThreadTest.h | 14 ++++++-- .../modules/core/src/TimeConversion.cxx | 17 ++++++++-- 7 files changed, 108 insertions(+), 23 deletions(-) diff --git a/livesupport/modules/core/include/LiveSupport/Core/Thread.h b/livesupport/modules/core/include/LiveSupport/Core/Thread.h index 15c94b872..44ae231df 100644 --- a/livesupport/modules/core/include/LiveSupport/Core/Thread.h +++ b/livesupport/modules/core/include/LiveSupport/Core/Thread.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Thread.h,v $ ------------------------------------------------------------------------------*/ @@ -62,7 +62,7 @@ namespace Core { * A generic thread executor class. * * @author $Author: maroy $ - * @version $Revision: 1.2 $ + * @version $Revision: 1.3 $ * @see RunnableInterface */ class Thread @@ -136,6 +136,16 @@ class Thread runnable->stop(); } + /** + * Force the current thread to relinquish use of its processor. + * So that other threads get a chance to run. + */ + static void + yield(void) throw () + { + pthread_yield(); + } + /** * Join the thread. * Wait for the thread to terminate and free up all its resources. diff --git a/livesupport/modules/core/src/TestRunnable.cxx b/livesupport/modules/core/src/TestRunnable.cxx index 402268884..29ffa0ee0 100644 --- a/livesupport/modules/core/src/TestRunnable.cxx +++ b/livesupport/modules/core/src/TestRunnable.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TestRunnable.cxx,v $ ------------------------------------------------------------------------------*/ @@ -54,10 +54,12 @@ using namespace LiveSupport::Core; /*------------------------------------------------------------------------------ * Constructor. *----------------------------------------------------------------------------*/ -TestRunnable :: TestRunnable(void) throw () +TestRunnable :: TestRunnable(Ptr::Ref loopTime) + throw () { - shouldRun = true; - state = created; + shouldRun = true; + state = created; + this->loopTime = loopTime; } @@ -69,8 +71,6 @@ TestRunnable :: run(void) throw () { state = running; - Ptr::Ref loopTime(new time_duration(seconds(1))); - while (shouldRun) { // don't do anything in the main loop TimeConversion::sleep(loopTime); diff --git a/livesupport/modules/core/src/TestRunnable.h b/livesupport/modules/core/src/TestRunnable.h index 196e9a8c4..9c4774f34 100644 --- a/livesupport/modules/core/src/TestRunnable.h +++ b/livesupport/modules/core/src/TestRunnable.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TestRunnable.h,v $ ------------------------------------------------------------------------------*/ @@ -59,7 +59,7 @@ namespace Core { * A sample Runnable object, for testing purposes. * * @author $Author: maroy $ - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ class TestRunnable : public virtual RunnableInterface { @@ -70,6 +70,12 @@ class TestRunnable : public virtual RunnableInterface typedef enum { created, running, stopped } State; private: + /** + * The time interval the run() method will check if stop() + * has been called meanwhile. + */ + Ptr::Ref loopTime; + /** * Flag that marks if the main execution body should be * running. @@ -81,11 +87,22 @@ class TestRunnable : public virtual RunnableInterface */ State state; + /** + * Default constructor. + */ + TestRunnable(void) throw () + { + } + + public: /** * Constructor. + * + * @param loopTime the time at which the run() method checks + * if it still should run. */ - TestRunnable(void) throw (); + TestRunnable(Ptr::Ref loopTime) throw (); /** * A virtual destructor, as this class has virtual functions. diff --git a/livesupport/modules/core/src/Thread.cxx b/livesupport/modules/core/src/Thread.cxx index 082d3270b..a0d682c47 100644 --- a/livesupport/modules/core/src/Thread.cxx +++ b/livesupport/modules/core/src/Thread.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Thread.cxx,v $ ------------------------------------------------------------------------------*/ @@ -75,7 +75,7 @@ Thread :: posixThreadFunction(void * thread) throw () pThread->runnable->run(); - return 0; + pthread_exit(0); } @@ -85,8 +85,17 @@ Thread :: posixThreadFunction(void * thread) throw () void Thread :: start(void) throw (std::exception) { - int ret; - if ((ret = pthread_create(&thread, 0, posixThreadFunction, this))) { + int ret; + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + ret = pthread_create(&thread, &attr, posixThreadFunction, this); + pthread_attr_destroy(&attr); + + yield(); + + if (ret) { // TODO: signal return code throw std::exception(); } diff --git a/livesupport/modules/core/src/ThreadTest.cxx b/livesupport/modules/core/src/ThreadTest.cxx index 933042cd3..3ed040624 100644 --- a/livesupport/modules/core/src/ThreadTest.cxx +++ b/livesupport/modules/core/src/ThreadTest.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/ThreadTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -82,14 +82,14 @@ void ThreadTest :: simpleTest(void) throw (CPPUNIT_NS::Exception) { - Ptr::Ref runnable(new TestRunnable()); + Ptr::Ref cycle(new time_duration(seconds(1))); + Ptr::Ref runnable(new TestRunnable(cycle)); Ptr::Ref thread(new Thread(runnable)); Ptr::Ref sleepTime(new time_duration(seconds(1))); CPPUNIT_ASSERT(runnable->getState() == TestRunnable::created); thread->start(); - // sleep to yield the thread some time to actually start - TimeConversion::sleep(sleepTime); + Thread::yield(); CPPUNIT_ASSERT(runnable->getState() == TestRunnable::running); TimeConversion::sleep(sleepTime); CPPUNIT_ASSERT(runnable->getState() == TestRunnable::running); @@ -99,3 +99,29 @@ ThreadTest :: simpleTest(void) thread->join(); } + +/*------------------------------------------------------------------------------ + * A test to see if a thread respoding slowly for a stop() + * call is joined correctly. + *----------------------------------------------------------------------------*/ +void +ThreadTest :: slowThreadTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref cycle(new time_duration(seconds(10))); + Ptr::Ref runnable(new TestRunnable(cycle)); + Ptr::Ref thread(new Thread(runnable)); + Ptr::Ref sleepTime(new time_duration(seconds(1))); + + CPPUNIT_ASSERT(runnable->getState() == TestRunnable::created); + thread->start(); + Thread::yield(); + CPPUNIT_ASSERT(runnable->getState() == TestRunnable::running); + TimeConversion::sleep(sleepTime); + CPPUNIT_ASSERT(runnable->getState() == TestRunnable::running); + thread->stop(); + TimeConversion::sleep(sleepTime); + thread->join(); + CPPUNIT_ASSERT(runnable->getState() == TestRunnable::stopped); +} + diff --git a/livesupport/modules/core/src/ThreadTest.h b/livesupport/modules/core/src/ThreadTest.h index 256dc2d24..32042efe1 100644 --- a/livesupport/modules/core/src/ThreadTest.h +++ b/livesupport/modules/core/src/ThreadTest.h @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/ThreadTest.h,v $ ------------------------------------------------------------------------------*/ @@ -58,13 +58,14 @@ namespace Core { * Unit test for the Thread class. * * @author $Author: maroy $ - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * @see Thread */ class ThreadTest : public CPPUNIT_NS::TestFixture { CPPUNIT_TEST_SUITE(ThreadTest); CPPUNIT_TEST(simpleTest); + CPPUNIT_TEST(slowThreadTest); CPPUNIT_TEST_SUITE_END(); protected: @@ -77,6 +78,15 @@ class ThreadTest : public CPPUNIT_NS::TestFixture void simpleTest(void) throw (CPPUNIT_NS::Exception); + /** + * A test to see if a thread respoding slowly for a stop() + * call is joined correctly. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + slowThreadTest(void) throw (CPPUNIT_NS::Exception); + public: /** diff --git a/livesupport/modules/core/src/TimeConversion.cxx b/livesupport/modules/core/src/TimeConversion.cxx index 7ac005a3b..e7e40f6bd 100644 --- a/livesupport/modules/core/src/TimeConversion.cxx +++ b/livesupport/modules/core/src/TimeConversion.cxx @@ -22,7 +22,7 @@ Author : $Author: maroy $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TimeConversion.cxx,v $ ------------------------------------------------------------------------------*/ @@ -97,6 +97,19 @@ void TimeConversion :: sleep(Ptr::Ref duration) throw () { - usleep(duration->total_microseconds()); + int ret; + struct timespec tv; + + tv.tv_sec = duration->total_seconds(); + tv.tv_nsec = duration->fractional_seconds(); + + // if fractional digits is in microseconds, convert it to nanoseconds + if (time_duration::num_fractional_digits() == 6) { + tv.tv_nsec *= 1000L; + } + + if ((ret = nanosleep(&tv, 0))) { + // TODO: signal error + } }