vpr::ThreadPosix Class Reference

Threads implementation using POSIX threads (both Draft 4 and the "final" draft of the standard are supported). More...

#include <vpr/Thread/Thread.h>

Inheritance diagram for vpr::ThreadPosix:

Inheritance graph
[legend]
Collaboration diagram for vpr::ThreadPosix:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 ThreadPosix (VPRThreadPriority priority=VPR_PRIORITY_NORMAL, VPRThreadScope scope=VPR_GLOBAL_THREAD, VPRThreadState state=VPR_JOINABLE_THREAD, size_t stack_size=0)
 Non-spawning constructor.
 ThreadPosix (thread_func_t func, void *arg=NULL, VPRThreadPriority priority=VPR_PRIORITY_NORMAL, VPRThreadScope scope=VPR_GLOBAL_THREAD, VPRThreadState state=VPR_JOINABLE_THREAD, size_t stack_size=0)
 Spawning constructor with argument.
 ThreadPosix (BaseThreadFunctor *functorPtr, VPRThreadPriority priority=VPR_PRIORITY_NORMAL, VPRThreadScope scope=VPR_GLOBAL_THREAD, VPRThreadState state=VPR_JOINABLE_THREAD, size_t stack_size=0)
 Spawning constructor (functor version).
virtual ~ThreadPosix ()
 Destructor.
virtual void setFunctor (BaseThreadFunctor *functorPtr)
 Sets the functor that this thread will execute.
virtual vpr::ReturnStatus start ()
 Starts this thread's execution.
virtual int join (void **status=0)
 Makes the calling thread wait for the termination of this thread.
virtual int resume ()
 Resumes the execution of a thread that was previously suspended using suspend().
virtual int suspend (void)
 Suspends the execution of this thread.
virtual int getPrio (VPRThreadPriority *prio)
 Gets this thread's priority.
virtual int setPrio (VPRThreadPriority prio)
 Sets this thread's priority.
virtual int setRunOn (int cpu)
 Sets the CPU affinity for this thread (the CPU on which this thread will exclusively run).
virtual int getRunOn (int *cur_cpu)
 Gets the CPU affinity for this thread (the CPU on which this thread exclusively runs).
virtual int kill (int signum)
 Sends the specified signal to this thread (not necessarily SIGKILL).
virtual void kill ()
 Kills (cancels) this thread.
std::ostream & outStream (std::ostream &out)
 Provides a way of printing the process ID neatly.

Static Public Member Functions

static void yield ()
 Yields execution of the calling thread to allow a different blocked thread to execute.
static Threadself ()
 Get a pointer to the thread we are in.

Protected Member Functions

vpr::ReturnStatus spawn (BaseThreadFunctor *functorPtr)
 Creates a new thread that will execute functorPtr.
void startThread (void *nullParam)
 Called by the spawn routine to start the user thread function.

Classes

struct  staticWrapper

Detailed Description

Threads implementation using POSIX threads (both Draft 4 and the "final" draft of the standard are supported).

This works by recieving a function in the constructor that is the function to call when the new thread is created. The function is stored internally to the class, then the class is "boot-strapped" by spawning a call to the startThread() function with in turn will call the previously set thread function.

This is typedef'd to vpr::Thread.

Definition at line 83 of file ThreadPosix.h.


Constructor & Destructor Documentation

vpr::ThreadPosix::ThreadPosix ( VPRThreadPriority  priority = VPR_PRIORITY_NORMAL,
VPRThreadScope  scope = VPR_GLOBAL_THREAD,
VPRThreadState  state = VPR_JOINABLE_THREAD,
size_t  stack_size = 0 
)

Non-spawning constructor.

This will not start a thread.

Definition at line 76 of file ThreadPosix.cpp.

00078    : mUserThreadFunctor(NULL)
00079    , mDeleteThreadFunctor(false)
00080    , mRunning(false)
00081    , mPriority(priority)
00082    , mScope(scope)
00083    , mState(state)
00084    , mStackSize(stackSize)
00085    , mThreadStartCompleted(false)
00086    , mStartFunctor(NULL)
00087 {
00088    /* Do nothing. */ ;
00089 }

vpr::ThreadPosix::ThreadPosix ( thread_func_t  func,
void *  arg = NULL,
VPRThreadPriority  priority = VPR_PRIORITY_NORMAL,
VPRThreadScope  scope = VPR_GLOBAL_THREAD,
VPRThreadState  state = VPR_JOINABLE_THREAD,
size_t  stack_size = 0 
)

Spawning constructor with argument.

This will start a new thread that will execute the specified function.

Definition at line 93 of file ThreadPosix.cpp.

References setFunctor(), and start().

00096    : mUserThreadFunctor(NULL)
00097    , mDeleteThreadFunctor(false)
00098    , mRunning(false)
00099    , mPriority(priority)
00100    , mScope(scope)
00101    , mState(state)
00102    , mStackSize(stackSize)
00103    , mThreadStartCompleted(false)
00104    , mStartFunctor(NULL)
00105 {
00106    // Create the thread functor to start.  This will be deleted in the
00107    // destructor.
00108    setFunctor(new ThreadNonMemberFunctor(func, arg));
00109    mDeleteThreadFunctor = true;
00110    start();
00111 }

vpr::ThreadPosix::ThreadPosix ( BaseThreadFunctor functorPtr,
VPRThreadPriority  priority = VPR_PRIORITY_NORMAL,
VPRThreadScope  scope = VPR_GLOBAL_THREAD,
VPRThreadState  state = VPR_JOINABLE_THREAD,
size_t  stack_size = 0 
)

Spawning constructor (functor version).

This will start a new thread that will execute the function encapsulated by the functor.

Definition at line 115 of file ThreadPosix.cpp.

References setFunctor(), and start().

00118    : mUserThreadFunctor(NULL)
00119    , mDeleteThreadFunctor(false)
00120    , mRunning(false)
00121    , mPriority(priority)
00122    , mScope(scope)
00123    , mState(state)
00124    , mStackSize(stackSize)
00125    , mThreadStartCompleted(false)
00126    , mStartFunctor(NULL)
00127 {
00128    setFunctor(functorPtr);
00129    start();
00130 }

vpr::ThreadPosix::~ThreadPosix (  )  [virtual]

Destructor.

Postcondition:
This thread is removed from the thread table and from the local thread hash.

Definition at line 133 of file ThreadPosix.cpp.

References vpr::BaseThread::unregisterThread().

00134 {
00135    if ( mDeleteThreadFunctor )
00136    {
00137       delete mUserThreadFunctor;
00138       mUserThreadFunctor = NULL;
00139    }
00140 
00141    if ( NULL != mStartFunctor )
00142    {
00143       delete mStartFunctor;
00144       mStartFunctor = NULL;
00145    }
00146 
00147    // TELL EVERYONE THAT WE'RE DEAD!!!!
00148    ThreadManager::instance()->lock();      // Lock manager
00149    {
00150       unregisterThread();                  // Finish thread deallocation
00151    }
00152    ThreadManager::instance()->unlock();
00153 }


Member Function Documentation

void vpr::ThreadPosix::setFunctor ( BaseThreadFunctor functorPtr  )  [virtual]

Sets the functor that this thread will execute.

Precondition:
The thread is not already running. The functor is valid.

Implements vpr::BaseThread.

Definition at line 155 of file ThreadPosix.cpp.

References vpr::BaseThreadFunctor::isValid(), and vprASSERT.

Referenced by ThreadPosix().

00156 {
00157    vprASSERT(! mRunning && "Thread already running.");
00158    vprASSERT(functorPtr->isValid() && "Invalid functor.");
00159 
00160    mUserThreadFunctor = functorPtr;
00161 }

vpr::ReturnStatus vpr::ThreadPosix::start (  )  [virtual]

Starts this thread's execution.

Precondition:
The functor to execute has been set. The thread is not already running.
Postcondition:
A thread (with any specified attributes) is created that begins executing our functor. Depending on the scheduler, it may begin execution immediately, or it may block for a short time before beginning execution.

Implements vpr::BaseThread.

Definition at line 163 of file ThreadPosix.cpp.

References vpr::CondVarPosix::acquire(), vpr::ReturnStatus::Fail, vpr::BaseThread::registerThread(), vpr::CondVarPosix::release(), vpr::ReturnStatus::setCode(), spawn(), startThread(), vpr::ReturnStatus::success(), vprASSERT, and vpr::CondVarPosix::wait().

Referenced by ThreadPosix().

00164 {
00165    vpr::ReturnStatus status;
00166 
00167    if ( mRunning )
00168    {
00169       vprASSERT(false && "Thread already started");
00170       status.setCode(vpr::ReturnStatus::Fail);
00171    }
00172    else if ( NULL == mUserThreadFunctor )
00173    {
00174       vprASSERT(false && "No functor set");
00175       status.setCode(vpr::ReturnStatus::Fail);
00176    }
00177    else
00178    {
00179       mStartFunctor =
00180          new ThreadMemberFunctor<ThreadPosix>(this, &ThreadPosix::startThread,
00181                                               NULL);
00182 
00183       // Spawn the thread.  If the thread is spawned successfully, the method
00184       // startThread() will register the actual thread info.
00185       mThreadStartCompleted = false;  // Make sure this is set correctly
00186       status = spawn(mStartFunctor);
00187 
00188       // Thread spawned successfully.
00189       if ( status.success() )
00190       {
00191          // startThread() will register the thread, so we wait for
00192          // registration to complete here.
00193          mThreadStartCondVar.acquire();
00194          {
00195             while ( ! mThreadStartCompleted )
00196             {
00197                mThreadStartCondVar.wait();
00198             }
00199          }
00200          mThreadStartCondVar.release();
00201 
00202          mRunning = true;
00203       }
00204       // Thread spawning failed.  Yikes!
00205       else
00206       {
00207          ThreadManager::instance()->lock();
00208          {
00209             registerThread(false);
00210          }
00211          ThreadManager::instance()->unlock();
00212       }
00213    }
00214 
00215    return status;
00216 }

vpr::ReturnStatus vpr::ThreadPosix::spawn ( BaseThreadFunctor functorPtr  )  [protected]

Creates a new thread that will execute functorPtr.

Postcondition:
A thread (with any specified attributes) is created that begins executing func(). Depending on the scheduler, it may begin execution immediately, or it may block for a short time before beginning execution.
Parameters:
functorPtr Function to be executed by the thread.
Returns:
A vpr::ReturnStatus obj is returned to indicate the result of the thread creation.
Note:
The pthreads implementation on HP-UX 10.20 does not allow the stack address to be changed.

Definition at line 219 of file ThreadPosix.cpp.

References vpr::ReturnStatus::Fail, vpr::ReturnStatus::setCode(), and vpr::vprThreadFunctorFunction().

Referenced by start().

00220 {
00221    vpr::ReturnStatus status;
00222    int ret_val;
00223    pthread_attr_t thread_attrs;
00224 
00225    int pthread_prio = vprThreadPriorityToPOSIX(mPriority);
00226 
00227    // Initialize thread_attrs and set the priority of the thread if it is
00228    // supported.
00229    sched_param_t prio_param;
00230 
00231    pthread_attr_init(&thread_attrs);
00232    pthread_attr_setdetachstate(&thread_attrs, vprThreadStateToPOSIX(mState));
00233 
00234    // If thread priority scheduling is available, set the thread's priority
00235    // if it is set to be higher than 0.
00236 #  ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00237    int thread_scope = vprThreadScopeToPOSIX(mScope);
00238 
00239 #  if defined(HAVE_SYS_CAPABILITY_H) && ! defined(VPR_OS_FreeBSD) && \
00240       ! defined(VPR_OS_Linux)
00241    cap_t capabilities = cap_get_proc();
00242 
00243    // If we have the capability to do so, set the scope of the threads
00244    // to system scope.
00245    if ( capabilities->cap_effective & CAP_SCHED_MGT )
00246    {
00247       thread_scope = PTHREAD_SCOPE_SYSTEM;
00248    }
00249 #  endif   /* HAVE_SYS_CAPABILITY_H */
00250 
00251    pthread_attr_setscope(&thread_attrs, thread_scope);
00252 
00253    if ( pthread_prio > 0 )
00254    {
00255       prio_param.sched_priority = pthread_prio;
00256       pthread_attr_setschedparam(&thread_attrs, &prio_param);
00257    }
00258 #  endif   /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00259 
00260    // Set the stack size if a value greater than 0 is specified and this
00261    // pthreads implementation supports it.  Ensure that
00262    // _POSIX_THREAD_ATTR_STACKSIZE is defined before trying to test its
00263    // value.
00264 #ifdef _POSIX_THREAD_ATTR_STACKSIZE
00265    if ( mStackSize > 0 )
00266    {
00267       // XXX: ** STACK SIZE CHECK NEEDED **
00268 
00269       pthread_attr_setstacksize(&thread_attrs, mStackSize);
00270    }
00271 #endif
00272 
00273    // Finally create the thread.
00274    ret_val = pthread_create(&(mThread), &thread_attrs,
00275                             vprThreadFunctorFunction, (void *) functorPtr);
00276 
00277    // Inform the caller if the thread was not created successfully.
00278    if ( ret_val != 0 )
00279    {
00280       status.setCode(vpr::ReturnStatus::Fail);
00281       std::cerr << "vpr::ThreadPosix::spawn() - Cannot create thread:"
00282                 << strerror(ret_val) << std::endl;
00283    }
00284 
00285    return status;
00286 }

void vpr::ThreadPosix::startThread ( void *  nullParam  )  [protected]

Called by the spawn routine to start the user thread function.

Precondition:
Called ONLY by a new thread.
Postcondition:
The new thread will have started the user thread function. Any necessary thread registration is performed. The user thread functor is called.
Parameters:
nullParam Unused.

Definition at line 289 of file ThreadPosix.cpp.

References vpr::CondVarPosix::acquire(), vpr::BaseThread::registerThread(), vpr::CondVarPosix::release(), vpr::ThreadKeyPosix::setspecific(), and vpr::CondVarPosix::signal().

Referenced by start().

00290 {
00291    boost::ignore_unused_variable_warning(nullParam);
00292 
00293    // WE are a new thread... yeah!!!!
00294    // TELL EVERYONE THAT WE LIVE!!!!
00295    ThreadManager::instance()->lock();      // Lock manager
00296    {
00297       threadIdKey().setspecific((void*)this);  // Store the pointer to me
00298       registerThread(true);                    // Finish thread initialization
00299    }
00300    ThreadManager::instance()->unlock();
00301 
00302    // Signal that thread registration is complete.
00303    mThreadStartCondVar.acquire();
00304    {
00305       mThreadStartCompleted = true;
00306       mThreadStartCondVar.signal();
00307    }
00308    mThreadStartCondVar.release();
00309 
00310    // --- CALL USER FUNCTOR --- //
00311    (*mUserThreadFunctor)();
00312 }

virtual int vpr::ThreadPosix::join ( void **  status = 0  )  [inline, virtual]

Makes the calling thread wait for the termination of this thread.

Postcondition:
The caller blocks until this thread finishes its execution (i.e., calls the exit() method). This routine may return immediately if this thread has already exited.
Parameters:
status Current state of the terminating thread when that thread calls the exit routine (optional).
Returns:
0 is returned if this thread is "joined" successfully.
-1 is returned on an error condition.

Reimplemented from vpr::BaseThread.

Definition at line 192 of file ThreadPosix.h.

00193    {
00194       return pthread_join(mThread, status);
00195    }

virtual int vpr::ThreadPosix::resume (  )  [inline, virtual]

Resumes the execution of a thread that was previously suspended using suspend().

Precondition:
This thread was previously suspended using the suspend() member function.
Postcondition:
This thread is sent the SIGCONT signal and is allowed to begin executing again.
Returns:
0 is returned if this thread resumes execuation successfully.

-1 is returned otherwise.

Note:
This is not currently supported on HP-UX 10.20.

Reimplemented from vpr::BaseThread.

Definition at line 211 of file ThreadPosix.h.

References kill().

00212    {
00213       return kill(SIGCONT);
00214    }

virtual int vpr::ThreadPosix::suspend ( void   )  [inline, virtual]

Suspends the execution of this thread.

Postcondition:
This thread is sent the SIGSTOP signal and is thus suspended from execution until the member function resume() is called.
Returns:
0 is returned if this thread is suspended successfully.

-1 is returned otherwise.

Note:
This is not currently supported on HP-UX 10.20.

Reimplemented from vpr::BaseThread.

Definition at line 227 of file ThreadPosix.h.

References kill().

00228    {
00229       return kill(SIGSTOP);
00230    }

int vpr::ThreadPosix::getPrio ( VPRThreadPriority prio  )  [virtual]

Gets this thread's priority.

Postcondition:
The priority of this thread is returned in the integer pointer variable.
Parameters:
prio Pointer to an int variable that will have the thread's priority stored in it.
Returns:
0 is returned if the priority was retrieved successfully.

-1 is returned if the priority could not be read.

Note:
This is only supported on systems that support thread priority scheduling in their pthreads implementation.

Definition at line 315 of file ThreadPosix.cpp.

00316 {
00317 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00318    int policy, ret_val;
00319    sched_param_t fifo_sched_param;
00320 
00321    ret_val = pthread_getschedparam(mThread, &policy, &fifo_sched_param);
00322    *prio = posixThreadPriorityToVPR(fifo_sched_param.sched_priority);
00323 
00324    return ret_val;
00325 #else
00326    std::cerr << "vpr::ThreadPosix::getPrio(): Not supported\n";
00327 
00328    return -1;
00329 #endif
00330 }

int vpr::ThreadPosix::setPrio ( VPRThreadPriority  prio  )  [virtual]

Sets this thread's priority.

Postcondition:
This thread has its priority set to the specified value.
Parameters:
prio The new priority for this thread.
Returns:
0 is returned if this thread's priority was set successfully.

-1 is returned otherwise.

Note:
This is only supported on systems that support thread priority scheduling in their pthreads implementation.

Definition at line 333 of file ThreadPosix.cpp.

00334 {
00335 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00336    sched_param_t sched_param;
00337    sched_param.sched_priority = prio;
00338 
00339    return pthread_setschedparam(mThread, SCHED_RR, &sched_param);
00340 #else
00341    boost::ignore_unused_variable_warning(prio);
00342    std::cerr << "vpr::ThreadPosix::setPrio(): Not supported\n";
00343 
00344    return -1;
00345 #endif
00346 }

int vpr::ThreadPosix::setRunOn ( int  cpu  )  [virtual]

Sets the CPU affinity for this thread (the CPU on which this thread will exclusively run).

Precondition:
The thread must have been set to be a system-scope thread.
Postcondition:
The CPU affinity is set or an error status is returned.
Parameters:
cpu The CPU on which this thread will run exclusively.
Returns:
0 is returned if the affinity is set successfully.

-1 is returned otherwise.

Note:
This is currently only available on IRIX 6.5 and is non-portable.

Definition at line 348 of file ThreadPosix.cpp.

00349 {
00350 #ifdef VPR_OS_IRIX
00351    int ret_val;
00352 
00353    if ( mScope == PTHREAD_SCOPE_SYSTEM )
00354    {
00355       ret_val = pthread_setrunon_np(cpu);
00356    }
00357    else
00358    {
00359       std::cerr << "This thread is not a system-scope thread!\n";
00360       ret_val = -1;
00361    }
00362 
00363    return ret_val;
00364 #else
00365    boost::ignore_unused_variable_warning(cpu);
00366    std::cerr << "vpr::ThreadPosix::setRunOn(): Not available on this system.\n";
00367 
00368    return -1;
00369 #endif
00370 }

int vpr::ThreadPosix::getRunOn ( int *  cur_cpu  )  [virtual]

Gets the CPU affinity for this thread (the CPU on which this thread exclusively runs).

Precondition:
The thread must have been set to be a system-scope thread, and a previous affinity must have been set using setRunOn().
Postcondition:
The CPU affinity for this thread is stored in the cur_cpu pointer.
Parameters:
cur_cpu The CPU affinity for this thread (set by a previous call to setRunOn().
Returns:
0 is returned if the affinity is retrieved successfully.

-1 is returned otherwise.

Note:
This is currently only available on IRIX 6.5 and is non-portable.

Definition at line 372 of file ThreadPosix.cpp.

00373 {
00374 #ifdef VPR_OS_IRIX
00375    int ret_val;
00376 
00377    if ( mScope == PTHREAD_SCOPE_SYSTEM )
00378    {
00379       ret_val = pthread_getrunon_np(cur_cpu);
00380    }
00381    else
00382    {
00383       std::cerr << "This thread is not a system-scope thread!\n";
00384       ret_val = -1;
00385    }
00386 
00387    return ret_val;
00388 #else
00389    boost::ignore_unused_variable_warning(cur_cpu);
00390    std::cerr << "vpr::ThreadPosix::getRunOn(): Not available on this system.\n";
00391 
00392    return -1;
00393 #endif
00394 }

static void vpr::ThreadPosix::yield (  )  [inline, static]

Yields execution of the calling thread to allow a different blocked thread to execute.

Postcondition:
The caller yields its execution control to another thread or process.

Definition at line 306 of file ThreadPosix.h.

00307    {
00308       sched_yield();
00309    }

int vpr::ThreadPosix::kill ( int  signum  )  [virtual]

Sends the specified signal to this thread (not necessarily SIGKILL).

Postcondition:
This thread receives the specified signal.
Parameters:
signum The signal to send to the specified thread.
Returns:
0 is returned if the signal was sent successfully.

-1 is returned otherwise.

Note:
This is not currently supported with Pthreads Draft 4.

Reimplemented from vpr::BaseThread.

Definition at line 396 of file ThreadPosix.cpp.

00397 {
00398    return pthread_kill(mThread, signum);
00399 }

virtual void vpr::ThreadPosix::kill (  )  [inline, virtual]

Kills (cancels) this thread.

Postcondition:
This thread is cancelled. Depending on the cancellation attributes of the specified thread, it may terminate immediately, it may wait until a pre-defined cancel point to stop or it may ignore the cancel altogether. Thus, immediate cancellation is not guaranteed.
Note:
For the sake of clarity, it is probably better to use the cancel() routine instead of kill() because a two-argument version of kill() is also used for sending signals to threads. This kill() and cancel() do exactly the same thing.

Reimplemented from vpr::BaseThread.

Definition at line 339 of file ThreadPosix.h.

Referenced by resume(), and suspend().

00340    {
00341       pthread_cancel(mThread);
00342    }

Thread * vpr::ThreadPosix::self (  )  [static]

Get a pointer to the thread we are in.

Returns:
NULL is returned if this thread is not in the global table.

A non-NULL pointer is returned that points to the thread in which we are currently running.

Definition at line 401 of file ThreadPosix.cpp.

References vpr::ThreadKeyPosix::getspecific(), and vprASSERT.

Referenced by vpr::ThreadPool::addThread(), vpr::ProfileManager::getRootNode(), vpr::Debug::getStream(), and vpr::ThreadPool::threadLoop().

00402 {
00403    vprASSERT((statics.mStaticsInitialized==1221) && "Trying to call vpr::ThreadPosix::self before statics are initialized. Don't do that");
00404 
00405    Thread* my_thread;
00406    threadIdKey().getspecific((void**)&my_thread);
00407 
00408    return my_thread;
00409 }

std::ostream & vpr::ThreadPosix::outStream ( std::ostream &  out  )  [virtual]

Provides a way of printing the process ID neatly.

Reimplemented from vpr::BaseThread.

Definition at line 234 of file ThreadNSPR.cpp.

References vpr::BaseThread::outStream().

Referenced by vpr::operator<<().

00235 {
00236    out.setf(std::ios::right);
00237    out << std::setw(7) << std::setfill('0')
00238 #ifdef VPR_OS_Windows
00239        << _getpid()
00240 #else
00241        << getpid()
00242 #endif
00243        << "/";
00244    out.unsetf(std::ios::right);
00245    BaseThread::outStream(out);
00246    out << std::setfill(' ');
00247    return out;
00248 }


The documentation for this class was generated from the following files:
Generated on Thu Jan 4 10:55:38 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1