Cross-Platform C++

ot
class Thread

#include "ot/base/Thread.h"

ot::Runnable ot::Monitor ot::ManagedObject ot::SynchronizedObject ot::ManagedObject Class to start and control threads of execution. OpenTop creates a simple abstraction for the concept of threads, providing wrapper classes to provide common functionality on disparate operating environments.

An application may contain many threads, each one executing concurrently to perform a certain task. Every thread has a priority. Where the underlying threading system supports it, threads with a higher priority are executed in preference to threads with a lower priority. The priority of a thread is initially set equal to the thread that created it.

Not all threads will have a Thread object associated with them; only those created using an instance of the Thread class. For example, the thread that executes the main() function when an application starts is created by the operating system and does not have a Thread object. Calls to CurrentThread() will therefore yield a null reference for this thread.

When an application terminates by returning from main(), the operating system terminates any threads that are still executing. The Thread class creates two types of thread: daemon threads and user threads. The only distinction between the two is that user threads are required to terminate before the application terminates whereas daemon threads may be terminated automatically by the operating system.

Applications should include an instance of SystemMonitor in their main() function to ensure System::Terminate() is called at exit. In addition to its other tasks, System::Terminate() checks that all user threads have terminated before proceeding.

There are two ways to create a new thread of execution. One is to declare a class derived from Thread and override the virtual run() method. An instance of this class can then be created and the start() method called. For example, here is a function that uses a specialized thread to simply print "Hello World!" to the console:

    class HelloThread : public Thread {
    public:
        virtual void run() {
            Console::cout() << OT_T("Hello World!");
        }
    };

    void hello() {
        RefPtr<Thread> rpThread = new HelloThread;
        rpThread->start();
        rpThread->join(); // wait for thread termination
    }

The other way is to declare a class derived from Runnable which has a single virtual run() method that should be overridden to perform the required task. An instance of this class can then be passed to a Thread's constructor and the thread will call the run() method for that class. See Runnable for an example of this method.

Due to its nature, a Thread instance is likely to be accessed from more than one thread. For this reason, all access to member state information is synchronized so that it may safely be accessed by multiple concurrent threads.


Reference Counting and Thread objects

When a Thread is started, a RefPtr<Thread> for the Thread is added to a list of active threads. On termination this entry is removed from the list, with the result that the Thread's reference count will be decremented. One effect of this is that a Thread instance is guaranteed to remain valid for as long as the OS thread is active - which you must agree makes perfect sense. Another effect will be that the Thread instance will be destroyed automatically when the Thread terminates unless the application has incremented its reference count (for example by storing the Thread's address in a RefPtr<Thread> when the instance was created).

A Thread object should never be allocated on the stack as stack-based objects are not consistent with the semantics of reference-counting.




Constructor/Destructor Summary
Thread()
         Constructs a Thread using this as the Runnable object and with an automatically generated name.
Thread(Runnable* pTarget)
         Constructs a thread with pTarget as the Runnable object and with an automatically generated name.
Thread(const String& name)
         Constructs a Thread with the specified name, using this as the Runnable object.
Thread(Runnable* pTarget, const String& name)
         Constructs a Thread with the specified name and Runnable object.
~Thread()
         Releases resources associated with the Thread.

Method Summary
static RefPtr< Thread > CurrentThread()
         Returns a reference to the Thread object for the currently executing thread.
static ThreadId CurrentThreadId()
         Returns a ThreadId representing the currently executing thread.
static size_t GetActiveCount()
         Returns the number of active Threads.
static ThreadList GetActiveThreads()
         Returns a list containing references to all the active Thread objects in the system.
 ThreadId getId() const
         Returns the ThreadId for this Thread.
static int GetInterruptSignal()
         Returns the signal number that OpenTop will use for thread interruption.
 String getName() const
         Returns the name of this Thread.
 unsigned getPriority() const
         Returns this Thread's priority.
 void interrupt()
         Interrupts this thread.
 bool interruptSupported() const
         Tests whether the interrupt() method is supported on the current platform.
 bool isActive() const
         Tests to see if this Thread is active.
 bool isDaemon() const
         Tests whether this Thread is a daemon thread.
 void join()
         Waits for this Thread to terminate.
 void join(long millis)
         Waits up to millis milliseconds for this Thread to terminate.
 bool operator!=(const Thread& rhs) const
         Inequality operator.
 bool operator==(const Thread& rhs) const
         Equality operator.
 virtual void run()
         If this thread was constructed using a separate Runnable object, then that Runnable object's run() method is called; otherwise, this method does nothing and returns.
 void setDaemon(bool bDaemon)
         Marks this thread as either a daemon thread or a user thread.
static void SetInterruptSignal(int signo)
         Specifies the signal number to use for interrupt processing in the UNIX environment.
 void setName(const String& name)
         Sets the name of this Thread.
 void setPriority(unsigned priority)
         Sets the Thread's execution priority.
static void Sleep(long millis)
         Suspends execution of the currently executing thread for millis milliseconds or until the current thread is interrupted.
static void Sleep(long millis, long nanos)
         Suspends execution of the currently executing thread for a specified duration.
 void start()
         Causes the Thread to begin execution.
static void Yield()
         Yields any remaining execution time-slice to another thread.

Methods inherited from class ot::ManagedObject
addRef, getRefCount, onFinalRelease, operator=, release

Methods inherited from class ot::Monitor
notify, notifyAll, wait, wait

Methods inherited from class ot::SynchronizedObject
lock, unlock

Typedefs

ThreadList

typedef std::list< RefPtr< Thread > > ThreadList

Enumerations

enum { MinPriority =1,   
  NormPriority =5,   
  MaxPriority =10}   


Constructor/Destructor Detail

Thread

protected  Thread()
Constructs a Thread using this as the Runnable object and with an automatically generated name. This constructor is intended to be used from derived classes which have overridden the run() method to do something useful.

Automatically generated names are of the form "Thread-"+n, where n is an integer.

See also:
run()

Thread

 Thread(Runnable* pTarget)
Constructs a thread with pTarget as the Runnable object and with an automatically generated name.

Parameters:
pTarget - the Runnable object whose run() method will be called in the context of the new thread, when the Thread is started.
See also:
start() , Runnable::run()

Thread

protected  Thread(const String& name)
Constructs a Thread with the specified name, using this as the Runnable object. This constructor is intended to be used from derived classes which have overridden the run() method to do something useful.

Parameters:
name - the name to be given to the thread
See also:
run()

Thread

 Thread(Runnable* pTarget,
        const String& name)
Constructs a Thread with the specified name and Runnable object.

Parameters:
pTarget - the Runnable object whose run() method will be called in the context of the new thread, when the Thread is started.
name - the name for the new Thread
See also:
start() , Runnable::run()

~Thread

 ~Thread()
Releases resources associated with the Thread.


Method Detail

CurrentThread

static RefPtr< Thread > CurrentThread()
Returns a reference to the Thread object for the currently executing thread. If the currently executing thread was not created using a Thread object (such as the thread executing the application's main() function), then a null reference is returned.

Returns:
a reference to the currently executing Thread object, or a null reference if the executing thread was not created using a Thread object.

CurrentThreadId

static ThreadId CurrentThreadId()
Returns a ThreadId representing the currently executing thread.


GetActiveCount

static size_t GetActiveCount()
Returns the number of active Threads. This method simply returns the number of references in the active thread list returned by GetActiveThreads(). The return value may not equate with the number of threads running within the current process.

A Thread becomes active during the call to start() and ceases to be active after the run() method has completed and shortly before it is terminated by the operating system.

See also:
GetActiveThreads()

GetActiveThreads

static ThreadList GetActiveThreads()
Returns a list containing references to all the active Thread objects in the system. A Thread becomes active during the call to start() and ceases to be active after the run() method has completed and shortly before it is terminated.

See also:
GetActiveCount()

getId

ThreadId getId() const
Returns the ThreadId for this Thread.


GetInterruptSignal

static int GetInterruptSignal()
Returns the signal number that OpenTop will use for thread interruption.

See also:
SetInterruptSignal() , interrupt()

getName

String getName() const
Returns the name of this Thread.

Returns:
the name of this Thread.

getPriority

unsigned getPriority() const
Returns this Thread's priority.

See also:
setPriority()

interrupt

void interrupt()
Interrupts this thread. If this thread is waiting in Sleep() or waiting on a ConditionVariable or Monitor, then it will be woken and receive an InterruptedException.

On most UNIX platforms, blocking i/o calls can be interrupted, but this is not portable behaviour.

Interruption is implemented differently on the various supported platforms.

Another complication with interrupting a UNIX thread is that certain i/o operations may be interrupted, with the result that they may throw some form of IOException. These exceptions are rarely recoverable, so interrupt() may only be useful when asking a thread to terminate.

If your application is going to call interrupt() in the UNIX environment, you must choose which signal number to assign and call SetInterruptSignal() during initialization.

Exceptions:
UnsupportedOperationException - when running Windows NT 3.x or a UNIX-like operating system which does not support pthread_kill()
RuntimeException - when running under UNIX and SetInterruptSignal() has not been called to assign an interrupt signal number
Note:
interrupt() is not supported on Windows NT 3.x or Mac OS X
See also:
interruptSupported() , SetInterruptSignal()

interruptSupported

bool interruptSupported() const
Tests whether the interrupt() method is supported on the current platform.

Returns:
true if the interrupt() is supported; false otherwise
See also:
interrupt()
Since:
1.1

isActive

bool isActive() const
Tests to see if this Thread is active. A Thread is active from the point in time that start() is called until after the run() method returns.

Returns:
true if the Thread is active; false otherwise

isDaemon

bool isDaemon() const
Tests whether this Thread is a daemon thread.

Returns:
true if this Thread is a daemon thread; false otherwise
See also:
setDaemon()

join

void join()
Waits for this Thread to terminate.

Exceptions:
InterruptedException - if the waiting thread is interrupted

join

void join(long millis)
Waits up to millis milliseconds for this Thread to terminate.

Parameters:
millis - the number of milliseconds to wait. A value of zero means wait forever
Exceptions:
InterruptedException - if the waiting thread is interrupted

operator!=

bool operator!=(const Thread& rhs) const
Inequality operator. Returns true if rhs represents a different thread to this; false otherwise


operator==

bool operator==(const Thread& rhs) const
Equality operator. Returns true if rhs represents the same thread as this; false otherwise


run

virtual void run()
If this thread was constructed using a separate Runnable object, then that Runnable object's run() method is called; otherwise, this method does nothing and returns. Derived classes of Thread should override this method to do something useful.

This method runs in the context of a newly created thread of execution. The thread of execution is terminated when this method returns.


setDaemon

void setDaemon(bool bDaemon)
Marks this thread as either a daemon thread or a user thread. This method must be called before the thread is started.

An application exits when the only threads left executing are daemon threads. This policy is enforced by the System::Terminate() function, which is called by SystemMonitor's destructor.

Some care should be taken when deciding whether or not to employ daemon threads. The advantage of using a daemon thread is that the application doesn't need to worry about terminating it, but the flip-side is that the thread could be terminated at any point - even when it is doing important work. Another draw-back with using daemon threads is that memory resources used by the thread may not be freed prior to system termination - which could result in memory diagnostic tools indicating a memory leak in the application.

Exceptions:
IllegalThreadStateException - if this method is called after the Thread has been started.
See also:
isDaemon() , System::Terminate()

SetInterruptSignal

static void SetInterruptSignal(int signo)
Specifies the signal number to use for interrupt processing in the UNIX environment. On UNIX/Linux platforms, OpenTop uses signalling to implement thread interruption. This method installs a dummy signal handler for the specified signal.

UNIX signal handling is process-wide and non-modular. If one thread sets a signal handler, all threads get to use the same one. For this reason signal handling is normally dealt with at the application level rather than by individual libraries. This method gives applications the choice of which signal number to assign to OpenTop for thread interruption.

If your application does not use the alarm() function then SIGALRM is a good choice. Note, though, that SIGALRM is not defined in the Windows version of <signal.h>, so conditional code is required. For example:-

   #include "ot/base/SystemMonitor.h"
   #include "ot/base/Thread.h"
   #include <signal.h>
   using namespace ot;

   int main(int argc, char* argv[])
   {
        SystemMonitor monitor; // ensure correct termination
        // Assign an unused signal for UNIX thread interruption handling
        #ifdef SIGALRM
            Thread::SetInterruptSignal(SIGALRM);
        #endif
        ...
   }

Parameters:
signo - the signal number to be assigned to interrupt processing
See also:
interrupt()

setName

void setName(const String& name)
Sets the name of this Thread.

See also:
getName()

setPriority

void setPriority(unsigned priority)
Sets the Thread's execution priority. The priority is specified using an unsigned integer in the range Thread::MinPriority to Thread::MaxPriority.

A thread's execution priority may be altered both before and during its execution.

Not all operating systems support the setting of a thread's execution priority. In this case calling this function does nothing.

Exceptions:
IllegalArgumentException - if priority is less than Thread::MinPriority or greater than Thread::MaxPriority.

Sleep

static void Sleep(long millis)
Suspends execution of the currently executing thread for millis milliseconds or until the current thread is interrupted. This is a static function that can be called from any thread, even from those threads that are not created and controlled by a Thread object (such as the application's main thread).

This function is also available in single-threaded versions of OpenTop.

Parameters:
millis - the number of milliseconds to sleep for
Exceptions:
InterruptedException - if another thread interrupted the current thread
See also:
interrupt()

Sleep

static void Sleep(long millis,
                  long nanos)
Suspends execution of the currently executing thread for a specified duration. There is no guarantee that the current thread will sleep for exactly the specified duration. The Sleep() function may return earlier or later than the specified duration.

This is a static function that can be called from any thread, even from those threads that are not created and controlled by a Thread object (such as the application's main thread).

This function is also available in single-threaded versions of OpenTop.

Parameters:
millis - the number of milliseconds to sleep for
nanos - the number of nanoseconds to sleep for. If the operating system does not support a nanosecond resolution, the number of milliseconds is rounded up when appropriate.
Exceptions:
InterruptedException - if another thread interrupted the current thread
See also:
interrupt()

start

void start()
Causes the Thread to begin execution. A native thread is created using the underlying threading mechanism (e.g. Win32 threads or POSIX threads), which is then directed to execute this Thread's run() method.

Exceptions:
IllegalThreadStateException - if the Thread has been started previously.

Yield

static void Yield()
Yields any remaining execution time-slice to another thread. This is a static function that can be called from any thread, even from those threads that are not created and controlled by a Thread object (such as the application's main thread).

Note:
For historical reasons, Microsoft have created a macro in <winbase.h> called Yield. If you are writing programs for the Microsoft Windows platform you will have to #undef Yield in order to call this function.


Cross-Platform C++

Found a bug or missing feature? Please email us at support@elcel.com

Copyright © 2000-2003 ElCel Technology   Trademark Acknowledgements