Thread Class Reference

This class is an platform-independent class that creates an internally held thread and executes it. More...

#include <Thread.h>

Inheritance diagram for Thread:

Inheritance graph
[legend]
List of all members.

Public Types

enum  { SOCKET_SET_READ = 0, SOCKET_SET_WRITE, SOCKET_SET_EXCEPTION, NUM_SOCKET_SETS }
 Enumeration of the socket sets that are available for blocking on; used in GetOwnerSocketSet() and GetInternalSocketSet() calls. More...

Public Member Functions

 Thread ()
 Constructor.
virtual ~Thread ()
 Destructor.
virtual status_t StartInternalThread ()
 Start the internal thread running.
bool IsInternalThreadRunning () const
 Returns true iff the thread is considered to be running.
bool IsCallerInternalThread () const
 Returns true iff the calling thread is the internal thread, or false if the caller is any other thread.
virtual void ShutdownInternalThread (bool waitForThread=true)
 Tells the internal thread to quit by sending it a NULL MessageRef, and then optionally waits for it to go away by calling WaitForInternalThreadToExit().
status_t WaitForInternalThreadToExit ()
 Blocks and won't return until after the internal thread exits.
virtual status_t SendMessageToInternalThread (const MessageRef &msg)
 Puts the given message into a message queue for the internal thread to pick up, and then calls SignalInternalThread() (if necessary) to signal the internal thread that a new message is ready.
virtual int32 GetNextReplyFromInternalThread (MessageRef &ref, uint64 wakeupTime=0)
 This method attempts to retrieve the next reply message that has been sent back to the main thread by the internal thread (via SendMessageToOwner()).
Queue< MessageRef > * LockAndReturnMessageQueue ()
 Locks the internal thread's message queue and returns a pointer to it.
status_t UnlockMessageQueue ()
 Unlocks our internal message queue, so that the internal thread can again pop messages off of it.
Queue< MessageRef > * LockAndReturnReplyQueue ()
 Locks this Thread's reply queue and returns a pointer to it.
status_t UnlockReplyQueue ()
 Unlocks the reply message queue, so that the internal thread can again append messages to it.
const SocketRefGetOwnerWakeupSocket ()
 Returns the socket that the main thread may select() for read on for wakeup-notification bytes.
Hashtable< SocketRef, bool > & GetOwnerSocketSet (uint32 socketSet)
 This function returns a reference to one of the three socket-sets that GetNextReplyFromInternalThread() will optionally use to determine whether to return early.
const Hashtable< SocketRef,
bool > & 
GetOwnerSocketSet (uint32 socketSet) const
 As above, but returns a read-only reference.

Protected Member Functions

virtual status_t MessageReceivedFromOwner (const MessageRef &msgRef, uint32 numLeft)
 If you are using the default implementation of InternalThreadEntry(), then this method will be called whenever a new MessageRef is received by the internal thread.
status_t SendMessageToOwner (const MessageRef &replyRef)
 May be called by the internal thread to send a Message back to the owning thread.
virtual void InternalThreadEntry ()
 You may override this method to be your Thread's execution entry point.
virtual int32 WaitForNextMessageFromOwner (MessageRef &ref, uint64 wakeupTime=MUSCLE_TIME_NEVER)
 This method is meant to be called by the internally held thread.
virtual void SignalInternalThread ()
 Called by SendMessageToThread() whenever there is a need to wake up the internal thread so that it will look at its reply queue.
virtual void SignalOwner ()
 Called by SendMessageToOwner() whenever there is a need to wake up the owning thread so that it will look at its reply queue.
const SocketRefGetInternalThreadWakeupSocket ()
 Returns the socket that the internal thread may select() for read on for wakeup-notification bytes.
status_t LockSignalling ()
 Locks the lock we use to serialize calls to SignalInternalThread() and SignalOwner().
status_t UnlockSignalling ()
 Unlocks the lock we use to serialize calls to SignalInternalThread() and SignalOwner().
void CloseSockets ()
 Closes all of our threading sockets, if they are open.
Hashtable< SocketRef, bool > & GetInternalSocketSet (uint32 socketSet)
 This function returns a reference to one of the three socket-sets that WaitForNextMessageFromOwner() will optionally use to determine whether to return early.
const Hashtable< SocketRef,
bool > & 
GetInternalSocketSet (uint32 socketSet) const
 As above, but returns a read-only reference.

Classes

class  ThreadSpecificData
 This class encapsulates data that is used by one of our two threads (internal or owner).

Detailed Description

This class is an platform-independent class that creates an internally held thread and executes it.

You will want to subclass Thread in order to specify the behaviour of the internally held thread... The default thread implementation doesn't do anything very useful. It also includes support for sending Messages to the thread, receiving reply Messages from the thread, and for waiting for the thread to exit.

Definition at line 43 of file Thread.h.


Member Enumeration Documentation

anonymous enum

Enumeration of the socket sets that are available for blocking on; used in GetOwnerSocketSet() and GetInternalSocketSet() calls.

Enumerator:
SOCKET_SET_READ  set of sockets to watch for ready-to-read (i.e.

incoming data available)

SOCKET_SET_WRITE  set of sockets to watch for ready-to-write (i.e.

outgoing buffer space available)

SOCKET_SET_EXCEPTION  set of sockets to watch for exceptional conditions (implementation defined)
NUM_SOCKET_SETS  A guard value.

Definition at line 157 of file Thread.h.


Constructor & Destructor Documentation

Thread::Thread (  ) 

Constructor.

Does very little (in particular, the internal thread is not started here... that happens when you call StartInternalThread())

virtual Thread::~Thread (  )  [virtual]

Destructor.

You must have made sure that the internal thread is no longer running before deleting the Thread object, or an assertion failure will occur. (You should make sure the internal thread is gone by calling WaitForInternalThreadToExit() before deleting this Thread object)


Member Function Documentation

virtual status_t Thread::StartInternalThread (  )  [virtual]

Start the internal thread running.

Returns:
B_NO_ERROR on success, or B_ERROR on failure (out of memory, or thread is already running)

Reimplemented in AcceptSocketsThread, and MessageTransceiverThread.

bool Thread::IsInternalThreadRunning (  )  const [inline]

Returns true iff the thread is considered to be running.

(Note that the thread is considered running from the time StartInternalThread() returns B_NO_ERROR until the time WaitForInternalThreadToExit() is called and returns B_NO_ERROR. Even if the thread terminates itself before then, it is still considered to be 'running' as far as we're concerned)

Definition at line 67 of file Thread.h.

virtual void Thread::ShutdownInternalThread ( bool  waitForThread = true  )  [virtual]

Tells the internal thread to quit by sending it a NULL MessageRef, and then optionally waits for it to go away by calling WaitForInternalThreadToExit().

If the internal thread isn't running, this method is a no-op. You must call this before deleting the MessageTransceiverThread object!

Parameters:
waitForThread if true, this method won't return until the thread is gone. Defaults to true. (if you set this to false, you'll need to also call WaitForThreadToExit() before deleting this object)

status_t Thread::WaitForInternalThreadToExit (  ) 

Blocks and won't return until after the internal thread exits.

If you have called StartInternalThread(), you'll need to call this method (or ShutdownInternalThread()) before deleting this Thread object or calling StartInternalThread() again--even if your thread has already terminated itself! That way consistency is guaranteed and race conditions are avoided.

Returns:
B_NO_ERROR on success, or B_ERROR if the internal thread wasn't running.

virtual status_t Thread::SendMessageToInternalThread ( const MessageRef msg  )  [virtual]

Puts the given message into a message queue for the internal thread to pick up, and then calls SignalInternalThread() (if necessary) to signal the internal thread that a new message is ready.

If the internal thread isn't currently running, then the MessageRef will be queued up and available to the internal thread to process when it is started.

Parameters:
msg Reference to the message that is to be given to the internal thread.
Returns:
B_NO_ERROR on success, or B_ERROR on failure (out of memory)

virtual int32 Thread::GetNextReplyFromInternalThread ( MessageRef ref,
uint64  wakeupTime = 0 
) [virtual]

This method attempts to retrieve the next reply message that has been sent back to the main thread by the internal thread (via SendMessageToOwner()).

Parameters:
ref On success, (ref) will be a reference to the new reply message.
wakeupTime Time at which this method should stop blocking and return, even if there is no new reply message ready. If this value is 0 (the default) or otherwise less than the current time (as returned by GetRunTime64()), then this method does a non-blocking poll of the reply queue. If (wakeuptime) is set to MUSCLE_TIME_NEVER, then this method will block indefinitely, until a new reply is ready.
See also:
GetOwnerSocketSet() for advanced control of this method's behaviour
Returns:
The number of Messages left in the reply queue on success, or -1 on failure (The call timed out without any replies ever showing up)

Queue<MessageRef>* Thread::LockAndReturnMessageQueue (  ) 

Locks the internal thread's message queue and returns a pointer to it.

Since the queue is locked, you may examine or modify the queue safely. Once this method has returned successfully, you are responsible for unlocking the message queue again by calling UnlockMessageQueue(). If you don't, the Thread will remain locked and stuck!

Returns:
a pointer to our internal Message queue, on success, or NULL on failure (couldn't lock)

status_t Thread::UnlockMessageQueue (  ) 

Unlocks our internal message queue, so that the internal thread can again pop messages off of it.

Should be called exactly once after each successful call to LockAndReturnMessageQueue(). After this call returns, it is no longer safe to use the pointer that was previously returned by LockAndReturnMessageQueue().

Returns:
B_NO_ERROR on success, or B_ERROR if the unlock call failed (perhaps it wasn't locked?)

Queue<MessageRef>* Thread::LockAndReturnReplyQueue (  ) 

Locks this Thread's reply queue and returns a pointer to it.

Since the queue is locked, you may examine or modify the queue safely. Once this method has returned successfully, you are responsible for unlocking the message queue again by calling UnlockReplyQueue(). If you don't, the Thread will remain locked and stuck!

Returns:
a pointer to our internal reply queue on success, or NULL on failure (couldn't lock)

status_t Thread::UnlockReplyQueue (  ) 

Unlocks the reply message queue, so that the internal thread can again append messages to it.

Should be called exactly once after each successful call to LockAndReturnReplyQueue(). After this call returns, it is no longer safe to use the pointer that was previously returned by LockAndReturnReplyQueue().

Returns:
B_NO_ERROR on success, or B_ERROR if the unlock call failed (perhaps it wasn't locked?)

const SocketRef& Thread::GetOwnerWakeupSocket (  ) 

Returns the socket that the main thread may select() for read on for wakeup-notification bytes.

This Thread object's thread-signalling sockets will be allocated by this method if they aren't already allocated.

Hashtable<SocketRef, bool>& Thread::GetOwnerSocketSet ( uint32  socketSet  )  [inline]

This function returns a reference to one of the three socket-sets that GetNextReplyFromInternalThread() will optionally use to determine whether to return early.

By default, all of the socket-sets are empty, and GetNextReplyFromInternalThread() will return only when a new Message has arrived from the internal thread, or when the timeout period has elapsed.

However, in some cases it is useful to have GetNextReplyFromInternalThread() return under other conditions as well, such as when a specified socket becomes ready-to-read-from or ready-to-write-to. You can specify that a socket should be watched in this manner, by adding that socket to the appropriate socket set(s). For example, to tell GetNextReplyFromInternalThread() to always return when mySocket is ready to be written to, you would add mySocket to the SOCKET_SET_WRITE set, like this:

_thread.GetOwnerSocketSet(SOCKET_SET_WRITE).Put(mySocket, false);

(This only needs to be done once) After GetNextReplyFromInternalThread() returns, you can determine whether your socket is ready-to-write-to by checking its associated value in the table, like this:

bool canWrite = false; _thread.GetOwnerSocketSet(SOCKET_SET_WRITE).Get(mySocket, canWrite); if (canWrite) printf("Socket is ready to be written to!\n");

Parameters:
socketSet SOCKET_SET_* indicating which socket-set to return a reference to.
Note:
This method should only be called from the main thread!

Definition at line 191 of file Thread.h.

virtual status_t Thread::MessageReceivedFromOwner ( const MessageRef msgRef,
uint32  numLeft 
) [protected, virtual]

If you are using the default implementation of InternalThreadEntry(), then this method will be called whenever a new MessageRef is received by the internal thread.

Default implementation does nothing, and returns B_NO_ERROR if (msgRef) is valid, or B_ERROR if (msgRef) is a NULL reference.

Parameters:
msgRef Reference to the just-received Message object.
numLeft Number of Messages still left in the owner's message queue.
Returns:
B_NO_ERROR if you wish to continue processing, or B_ERROR if you wish to terminate the internal thread and go away.

status_t Thread::SendMessageToOwner ( const MessageRef replyRef  )  [protected]

May be called by the internal thread to send a Message back to the owning thread.

Puts the given MessageRef into the replies queue, and then calls SignalOwner() (if necessary) to notify the main thread that replies are pending.

Parameters:
replyRef MessageRef to send back to the owning thread.
Returns:
B_NO_ERROR on success, or B_ERROR on failure (out of memory?)

virtual void Thread::InternalThreadEntry (  )  [protected, virtual]

You may override this method to be your Thread's execution entry point.

Default implementation runs in a loop calling WaitForNextMessageFromOwner() and then MessageReceivedFromOwner(). In many cases, that is all you need, so you may not need to override this method.

Reimplemented in AcceptSocketsThread, and MessageTransceiverThread.

virtual int32 Thread::WaitForNextMessageFromOwner ( MessageRef ref,
uint64  wakeupTime = MUSCLE_TIME_NEVER 
) [protected, virtual]

This method is meant to be called by the internally held thread.

It will attempt retrieve the next message that has been sent to the thread via SendMessageToThread().

Parameters:
ref On success, (ref) will be set to be a reference to the retrieved Message.
wakeupTime Time at which this method should stop blocking and return, even if there is no new message ready. If this value is 0 or otherwise less than the current time (as returned by GetRunTime64()), then this method does a non-blocking poll of the queue. If (wakeuptime) is set to MUSCLE_TIME_NEVER (the default value), then this method will block indefinitely, until a Message is ready.
Returns:
The number of Messages still remaining in the message queue on success, or -1 on failure (i.e. the call was aborted before any Messages ever showing up, and (ref) was not written to)
See also:
GetInternalSocketSet() for advanced control of this method's behaviour

virtual void Thread::SignalInternalThread (  )  [protected, virtual]

Called by SendMessageToThread() whenever there is a need to wake up the internal thread so that it will look at its reply queue.

Default implementation sends a byte on a socket to implement this, but you can override this method to do it a different way if you need to.

virtual void Thread::SignalOwner (  )  [protected, virtual]

Called by SendMessageToOwner() whenever there is a need to wake up the owning thread so that it will look at its reply queue.

Default implementation sends a byte to the main-thread-listen socket, but you can override this method to do it different way if you need to.

Reimplemented in muscle::QAcceptSocketsThread, muscle::QMessageTransceiverThread, SDLMessageTransceiverThread, and Win32MessageTransceiverThread.

const SocketRef& Thread::GetInternalThreadWakeupSocket (  )  [protected]

Returns the socket that the internal thread may select() for read on for wakeup-notification bytes.

This Thread object's thread-signalling sockets will be allocated by this method if they aren't already allocated.

Returns:
The socket fd that the thread is to listen on, or a NULL reference on error.

status_t Thread::LockSignalling (  )  [inline, protected]

Locks the lock we use to serialize calls to SignalInternalThread() and SignalOwner().

Be sure to call UnlockSignallingLock() when you are done with the lock.

Returns:
B_NO_ERROR on success, or B_ERROR on failure (couldn't lock)

Definition at line 264 of file Thread.h.

References Mutex::Lock().

status_t Thread::UnlockSignalling (  )  [inline, protected]

Unlocks the lock we use to serialize calls to SignalInternalThread() and SignalOwner().

Returns:
B_NO_ERROR on success, or B_ERROR on failure (couldn't unlock)

Definition at line 269 of file Thread.h.

References Mutex::Unlock().

Hashtable<SocketRef, bool>& Thread::GetInternalSocketSet ( uint32  socketSet  )  [inline, protected]

This function returns a reference to one of the three socket-sets that WaitForNextMessageFromOwner() will optionally use to determine whether to return early.

By default, all of the socket-sets are empty, and WaitForNextMessageFromOwner() will return only when a new Message has arrived from the owner thread, or when the timeout period has elapsed.

However, in some cases it is useful to have WaitForNextMessageFromOwner() return under other conditions as well, such as when a specified socket becomes ready-to-read-from or ready-to-write-to. You can specify that a socket should be watched in this manner, by adding that socket to the appropriate socket set(s). For example, to tell WaitForNextMessageFromOwner() to always return when mySocket is ready to be written to, you would add mySocket to the SOCKET_SET_WRITE set, like this:

_thread.GetInternalSocketSet(SOCKET_SET_WRITE).Put(mySocket, false);

(This only needs to be done once) After WaitForNextMessageFromOwner() returns, you can determine whether your socket is ready-to-write-to by checking its associated value in the table, like this:

bool canWrite = false; _thread.GetInternalSocketSet(SOCKET_SET_WRITE).Get(mySocket, canWrite); if (canWrite) printf("Socket is ready to be written to!\n");

Parameters:
socketSet SOCKET_SET_* indicating which socket-set to return a reference to.
Note:
This method should only be called from the internal thread!

Definition at line 301 of file Thread.h.


The documentation for this class was generated from the following file:
Generated on Thu Jun 5 17:48:41 2008 for MUSCLE by  doxygen 1.5.1