Author: tabish Date: Tue Sep 8 23:52:58 2009 New Revision: 812733 URL: http://svn.apache.org/viewvc?rev=812733&view=rev Log: Updated Thread class with more functionality and better APR isolation. Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.h Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.cpp?rev=812733&r1=812732&r2=812733&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.cpp Tue Sep 8 23:52:58 2009 @@ -57,15 +57,9 @@ apr_thread_t* threadHandle; /** - * Started state of this thread. + * Current state of this thread. */ - bool started; - - /** - * Indicates whether the thread has already been - * joined. - */ - bool joined; + Thread::State state; /** * The Assigned name of this thread. @@ -108,22 +102,26 @@ if( properties->exHandler != NULL ) { properties->exHandler->uncaughtException( properties->parent, error ); } + } catch( std::exception& stdEx ) { - error.printStackTrace(); + RuntimeException error( __FILE__, __LINE__, stdEx.what() ); + if( properties->exHandler != NULL ) { + properties->exHandler->uncaughtException( properties->parent, error ); + } } catch( ... ) { + RuntimeException error( __FILE__, __LINE__, - "unhandled exception bubbled up to Thread::run"); + "Uncaught exception bubbled up to Thread::run, Thread Terminating."); if( properties->exHandler != NULL ) { properties->exHandler->uncaughtException( properties->parent, error ); } - - error.printStackTrace(); } // Indicate we are done. + properties->state = Thread::TERMINATED; apr_thread_exit( self, APR_SUCCESS ); return NULL; } @@ -166,8 +164,7 @@ this->properties->name = name; } - this->properties->joined = false; - this->properties->started = false; + this->properties->state = Thread::NEW; this->properties->priority = Thread::NORM_PRIORITY; this->properties->task = task; this->properties->threadHandle = NULL; @@ -180,9 +177,14 @@ } //////////////////////////////////////////////////////////////////////////////// +void Thread::run() { + // No work to do as yet. +} + +//////////////////////////////////////////////////////////////////////////////// void Thread::start() throw ( Exception ) { - if( this->properties->started ) { + if( this->properties->state > Thread::NEW ) { throw Exception( __FILE__, __LINE__, "Thread::start - Thread already started"); @@ -203,27 +205,55 @@ "Thread::start - Could not start thread"); } - // Mark the thread as started. - this->properties->started = true; + this->properties->state = Thread::RUNNABLE; } //////////////////////////////////////////////////////////////////////////////// -void Thread::join() throw( Exception ) +void Thread::join() throw( decaf::lang::exceptions::InterruptedException ) { - if( !this->properties->started ) { + if( this->properties->state < Thread::RUNNABLE ) { throw Exception( __FILE__, __LINE__, "Thread::join() called without having called Thread::start()"); } - if( !this->properties->joined ) { + if( this->properties->state != Thread::TERMINATED ) { apr_status_t threadReturn; - if( apr_thread_join( &threadReturn, this->properties->threadHandle ) != APR_SUCCESS ) { - throw Exception( __FILE__, __LINE__, - "Thread::join() - Failed to Join the Thread"); - } + apr_thread_join( &threadReturn, this->properties->threadHandle ); + } +} + +//////////////////////////////////////////////////////////////////////////////// +void Thread::join( long long millisecs ) + throw ( decaf::lang::exceptions::IllegalArgumentException, + decaf::lang::exceptions::InterruptedException ) { + + if( millisecs < 0 ) { + throw IllegalArgumentException( + __FILE__, __LINE__, + "Thread::join( millisecs ) - Value given {%d} is less than 0", millisecs ); + } + + this->join(); +} + +//////////////////////////////////////////////////////////////////////////////// +void Thread::join( long long millisecs DECAF_UNUSED, unsigned int nanos DECAF_UNUSED ) + throw ( decaf::lang::exceptions::IllegalArgumentException, + decaf::lang::exceptions::InterruptedException ) { + + if( millisecs < 0 ) { + throw IllegalArgumentException( + __FILE__, __LINE__, + "Thread::join( millisecs, nanos ) - Value given {%d} is less than 0", millisecs ); } - this->properties->joined = true; + if( nanos > 999999 ) { + throw IllegalArgumentException( + __FILE__, __LINE__, + "Thread::join( millisecs, nanos ) - Nanoseconds must be in range [0...999999]" ); + } + + this->join(); } //////////////////////////////////////////////////////////////////////////////// @@ -231,6 +261,12 @@ throw( lang::exceptions::InterruptedException, lang::exceptions::IllegalArgumentException ) { + if( millisecs < 0 ) { + throw IllegalArgumentException( + __FILE__, __LINE__, + "Thread::sleep( millisecs ) - Value given {%d} is less than 0", millisecs ); + } + Thread::sleep( millisecs, 0 ); } @@ -239,6 +275,20 @@ throw( lang::exceptions::InterruptedException, lang::exceptions::IllegalArgumentException ) { + if( millisecs < 0 ) { + throw IllegalArgumentException( + __FILE__, __LINE__, + "Thread::sleep( millisecs, nanos ) - Value given {%d} is less than 0", millisecs ); + } + + if( nanos > 999999 ) { + throw IllegalArgumentException( + __FILE__, __LINE__, + "Thread::sleep( millisecs, nanos ) - Nanoseconds must be in range [0...999999]" ); + } + + // TODO -- Add in nanos + apr_sleep( (apr_interval_time_t)(millisecs * 1000) ); } @@ -298,3 +348,14 @@ Integer::toString( this->properties->priority ) + ", ThreadID=" + Long::toString( Thread::getId() ); } + +//////////////////////////////////////////////////////////////////////////////// +bool Thread::isAlive() const { + return this->properties->state != Thread::NEW && + this->properties->state != Thread::TERMINATED; +} + +//////////////////////////////////////////////////////////////////////////////// +Thread::State Thread::getState() const { + return this->properties->state; +} Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.h URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.h?rev=812733&r1=812732&r2=812733&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.h (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/lang/Thread.h Tue Sep 8 23:52:58 2009 @@ -75,6 +75,35 @@ /** The maximum priority that a thread can have. */ static const int MAX_PRIORITY = 10; + /** Represents the various states that the Thread can be in during its lifetime. */ + enum State{ + + /** Before a Thread is started it exists in this State. */ + NEW = 0, + + /** While a Thread is running and is not blocked it is in this State. */ + RUNNABLE = 1, + + /** A Thread that is waiting to acquire a lock is in this state. */ + BLOCKED = 2, + + /** A Thread that is waiting for another Thread to perform an action is in this state */ + WAITING = 3, + + /** + * A Thread that is waiting for another Thread to perform an action up to a specified + * time interval is in this state. + */ + TIMED_WAITING = 4, + + /** A Thread that is blocked in a Sleep call is in this state. */ + SLEEPING = 5, + + /** A Thread whose run method has exited is in this state. */ + TERMINATED = 6 + + }; + public: /** @@ -150,15 +179,48 @@ virtual void start() throw ( Exception ); /** - * Wait til the thread exits. This is when the run() - * method has returned or has thrown an exception. + * Forces the Current Thread to wait until the thread exits. + * + * @throws InterruptedException if any thread has interrupted the current thread. + * The interrupted status of the current thread is cleared when this + * exception is thrown. + */ + virtual void join() throw ( decaf::lang::exceptions::InterruptedException ); + + /** + * Forces the Current Thread to wait until the thread exits. + * + * @param millisecs the time in Milliseconds before the thread resumes + * + * @throws IllegalArgumentException if the milliseconds parameter is negative. + * @throws InterruptedException if any thread has interrupted the current thread. + * The interrupted status of the current thread is cleared when this + * exception is thrown. */ - virtual void join() throw ( Exception ); + virtual void join( long long millisecs ) + throw ( decaf::lang::exceptions::IllegalArgumentException, + decaf::lang::exceptions::InterruptedException ); + + /** + * Forces the Current Thread to wait until the thread exits. + * + * @param millisecs the time in Milliseconds before the thread resumes + * @param nanos 0-999999 extra nanoseconds to sleep. + * + * @throws IllegalArgumentException if the nanoseconds parameter is out of range + * or the milliseconds paramter is negative. + * @throws InterruptedException if any thread has interrupted the current thread. + * The interrupted status of the current thread is cleared when this + * exception is thrown. + */ + virtual void join( long long millisecs, unsigned int nanos ) + throw ( decaf::lang::exceptions::IllegalArgumentException, + decaf::lang::exceptions::InterruptedException ); /** * Default implementation of the run method - does nothing. */ - virtual void run(){}; + virtual void run(); /** * Returns the Thread's assigned name. @@ -212,6 +274,21 @@ */ std::string toString() const; + /** + * Returns true if the Thread is alive, meaning it has been started and has not yet + * died. + * + * @return true if the thread is alive. + */ + bool isAlive() const; + + /** + * Returns the currently set State of this Thread. + * + * @return the Thread's current state. + */ + Thread::State getState() const; + public: /**