/*
File: thread.cpp
Copyright 2009 Chris Tonkinson (cmtonkinson@gmail.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see .
*/
/**
* @file thread.cpp
* @author Chris Tonkinson (cmtonkinson@gmail.com)
* @date April 2009
* @brief Implementation file for the Thread class (and associated classes).
*/
#include
#include
#include
#include
#include "thread.h"
/********************************************************* EXCEPTION *********************************************************/
ThreadException::ThreadException( void ) {
return;
}
ThreadException::ThreadException( const ThreadException& ref ) {
message( ref.message() );
return;
}
ThreadException::ThreadException( const char* format, ... ) {
char buffer[THREAD_MAX_BUFFER];
std::string foo( "ThreadException: " );
va_list args;
// Print our variable string to the buffer...
va_start( args, format );
vsprintf( buffer, format, args );
va_end( args );
// Finalize the message...
message( foo.append( buffer ) );
return;
}
ThreadException::~ThreadException( void ) {
return;
}
/********************************************************* MUTEX *********************************************************/
Mutex::Mutex( void ) {
pthread_mutexattr_init( &_attr );
pthread_mutexattr_settype( &_attr, PTHREAD_MUTEX_NORMAL );
pthread_mutex_init( &_mutex, &_attr );
return;
}
Mutex::~Mutex( void ) {
if ( locked() ) {
unlock();
}
pthread_mutexattr_destroy( &_attr );
pthread_mutex_destroy( &_mutex );
return;
}
void Mutex::lock( void ) { // public
pthread_mutex_lock( &_mutex );
locked( true );
return;
}
void Mutex::unlock( void ) { // public
pthread_mutex_unlock( &_mutex );
locked( false );
return;
}
/********************************************************* READ/WRITE MUTEX *********************************************************/
RWMutex::RWMutex( void ) {
pthread_rwlockattr_init( &_attr );
pthread_rwlock_init( &_mutex, &_attr );
return;
}
RWMutex::~RWMutex( void ) {
if ( locked() ) {
unlock();
}
pthread_rwlockattr_destroy( &_attr );
pthread_rwlock_destroy( &_mutex );
return;
}
void RWMutex::readLock( void ) { // public
pthread_rwlock_rdlock( &_mutex );
locked( true );
return;
}
void RWMutex::writeLock( void ) { // public
pthread_rwlock_wrlock( &_mutex );
locked( true );
return;
}
void RWMutex::unlock( void ) { // public
pthread_rwlock_unlock( &_mutex );
locked( false );
return;
}
/********************************************************* THREAD *********************************************************/
Thread::Thread( void ) {
init();
return;
}
Thread::Thread( void* (*thread_start)(void* ptr), void* arg_ptr ) {
init();
start( thread_start, arg_ptr );
return;
}
Thread::~Thread( void ) {
if ( active() ) {
join();
}
return;
}
void Thread::init( void ) { // private
ID( 0 );
argument( NULL );
returnValue( NULL );
active( false );
complete( false );
return;
}
void Thread::start( void* (*thread_start)(void* ptr), void* arg_ptr ) { // private
argument( arg_ptr );
if ( pthread_create( &_ID, NULL, thread_start, (void*)this ) == 0 ) {
// Thread created successfully...
active( true );
} else {
// For whatever reason, the thread creation failed...
throw ThreadException( "Thread creation failed." );
}
return;
}
bool Thread::join( void ) { // public
// Protect against code attempting to join the same thread twice...
if ( active() ) {
if ( pthread_join( ID(), NULL ) == 0 ) {
// Thread joined properly...
active( false );
return true;
} else {
// Thread didn't join properly...
throw ThreadException( "Thread %lu failed to join.", ID() );
}
}
return false;
}
bool Thread::create( void* (*thread_start)(void* ptr), void* arg_ptr ) { // public
// Protect against code attempting to start two pthreads with one Thread object...
if ( !active() ) {
start( thread_start, arg_ptr );
return true;
}
return false;
}