|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "threading.hpp" |
|
|
#include "threading.hpp" |
|
|
|
|
|
|
|
|
using namespace std; // Introduce std namespace. |
|
|
|
|
|
|
|
|
namespace cd = codedweller; |
|
|
|
|
|
|
|
|
ThreadManager Threads; // Master thread manager. |
|
|
ThreadManager Threads; // Master thread manager. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; // return true; |
|
|
return true; // return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const RuntimeCheck ThreadingCheck1("ThreadManager::unlockExistingThread():ThreadingCheck1(0 != LockedThread)"); |
|
|
|
|
|
const RuntimeCheck ThreadingCheck2("ThreadManager::unlockExistingThread():ThreadingCheck2(T == LockedThread)"); |
|
|
|
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck1("ThreadManager::unlockExistingThread():ThreadingCheck1(0 != LockedThread)"); |
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck2("ThreadManager::unlockExistingThread():ThreadingCheck2(T == LockedThread)"); |
|
|
|
|
|
|
|
|
void ThreadManager::unlockExistingThread(Thread* T) { // Unlocks ThreadManager if T locked. |
|
|
void ThreadManager::unlockExistingThread(Thread* T) { // Unlocks ThreadManager if T locked. |
|
|
ThreadingCheck1(0 != LockedThread); // We had better have a locked thread. |
|
|
ThreadingCheck1(0 != LockedThread); // We had better have a locked thread. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// POSIX Mutex Implementation ////////////////////////////////////////////////// |
|
|
// POSIX Mutex Implementation ////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
const RuntimeCheck ThreadingCheck7("Mutex::Mutex():ThreadingCheck7(0 == pthread_mutex_init(&MyMutex,NULL))"); |
|
|
|
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck7("Mutex::Mutex():ThreadingCheck7(0 == pthread_mutex_init(&MyMutex,NULL))"); |
|
|
|
|
|
|
|
|
Mutex::Mutex() : // Constructing a POSIX mutex means |
|
|
Mutex::Mutex() : // Constructing a POSIX mutex means |
|
|
IAmLocked(false) { // setting the IAmLocked flag to false and |
|
|
IAmLocked(false) { // setting the IAmLocked flag to false and |
|
|
ThreadingCheck7(0 == pthread_mutex_init(&MyMutex,NULL)); // initializing the mutex_t object. |
|
|
ThreadingCheck7(0 == pthread_mutex_init(&MyMutex,NULL)); // initializing the mutex_t object. |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const ExitCheck ThreadingCheck8("Mutex::~Mutex():ThreadingCheck8(false == IAmLocked)"); |
|
|
|
|
|
const ExitCheck ThreadingCheck9("Mutex::~Mutex():ThreadingCheck9(0 == pthread_mutex_destroy(&MyMutex))"); |
|
|
|
|
|
|
|
|
const cd::ExitCheck ThreadingCheck8("Mutex::~Mutex():ThreadingCheck8(false == IAmLocked)"); |
|
|
|
|
|
const cd::ExitCheck ThreadingCheck9("Mutex::~Mutex():ThreadingCheck9(0 == pthread_mutex_destroy(&MyMutex))"); |
|
|
|
|
|
|
|
|
Mutex::~Mutex() { // Before we destroy our mutex we check |
|
|
Mutex::~Mutex() { // Before we destroy our mutex we check |
|
|
ThreadingCheck8(false == IAmLocked); // to see that it is not locked and |
|
|
ThreadingCheck8(false == IAmLocked); // to see that it is not locked and |
|
|
ThreadingCheck9(0 == pthread_mutex_destroy(&MyMutex)); // destroy the primative. |
|
|
ThreadingCheck9(0 == pthread_mutex_destroy(&MyMutex)); // destroy the primative. |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const RuntimeCheck ThreadingCheck10("Mutex::lock():ThreadingCheck10(0 == pthread_mutex_lock(&MyMutex));"); |
|
|
|
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck10("Mutex::lock():ThreadingCheck10(0 == pthread_mutex_lock(&MyMutex));"); |
|
|
|
|
|
|
|
|
void Mutex::lock() { // Locking a POSIX mutex means |
|
|
void Mutex::lock() { // Locking a POSIX mutex means |
|
|
ThreadingCheck10(0 == pthread_mutex_lock(&MyMutex)); // asserting our lock was successful and |
|
|
ThreadingCheck10(0 == pthread_mutex_lock(&MyMutex)); // asserting our lock was successful and |
|
|
IAmLocked = true; // setting the IAmLocked flag. |
|
|
IAmLocked = true; // setting the IAmLocked flag. |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const LogicCheck ThreadingCheck11("Mutex::unlock():ThreadingCheck11(true == IAmLocked)"); |
|
|
|
|
|
const RuntimeCheck ThreadingCheck12("Mutex::unlock():ThreadingCheck12(0 == pthread_mutex_unlock(&MyMutex))"); |
|
|
|
|
|
|
|
|
const cd::LogicCheck ThreadingCheck11("Mutex::unlock():ThreadingCheck11(true == IAmLocked)"); |
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck12("Mutex::unlock():ThreadingCheck12(0 == pthread_mutex_unlock(&MyMutex))"); |
|
|
|
|
|
|
|
|
void Mutex::unlock() { // Unlocking a POSIX mutex means |
|
|
void Mutex::unlock() { // Unlocking a POSIX mutex means |
|
|
ThreadingCheck11(true == IAmLocked); // asserting that we are locked, |
|
|
ThreadingCheck11(true == IAmLocked); // asserting that we are locked, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// POSIX Implementation //////////////////////////////////////////////////////// |
|
|
// POSIX Implementation //////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
const RuntimeCheck ThreadingCheck14("ProductionGateway::ProductionGateway():ThreadingCheck14(0 == pthread_mutex_init(&MyMutex, NULL));"); |
|
|
|
|
|
const RuntimeCheck ThreadingCheck15("ProductionGateway::ProductionGateway():ThreadingCheck15(0 == pthread_cond_init(&MyConditionVariable, NULL))"); |
|
|
|
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck14("ProductionGateway::ProductionGateway():ThreadingCheck14(0 == pthread_mutex_init(&MyMutex, NULL));"); |
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck15("ProductionGateway::ProductionGateway():ThreadingCheck15(0 == pthread_cond_init(&MyConditionVariable, NULL))"); |
|
|
|
|
|
|
|
|
ProductionGateway::ProductionGateway() : // Construct in POSIX like this: |
|
|
ProductionGateway::ProductionGateway() : // Construct in POSIX like this: |
|
|
Product(0), // All of our counts start at zero. |
|
|
Product(0), // All of our counts start at zero. |
|
|
|
|
|
|
|
|
ThreadingCheck15(0 == pthread_cond_init(&MyConditionVariable, NULL)); // Initialize our condition variable. |
|
|
ThreadingCheck15(0 == pthread_cond_init(&MyConditionVariable, NULL)); // Initialize our condition variable. |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const ExitCheck ThreadingCheck16("ProductionGateway::~ProductionGateway():ThreadingCheck16(0 == pthread_mutex_destroy(&MyMutex))"); |
|
|
|
|
|
const ExitCheck ThreadingCheck17("ProductionGateway::~ProductionGateway():ThreadingCheck17(0 == pthread_cond_destroy(&MyConditionVariable))"); |
|
|
|
|
|
|
|
|
const cd::ExitCheck ThreadingCheck16("ProductionGateway::~ProductionGateway():ThreadingCheck16(0 == pthread_mutex_destroy(&MyMutex))"); |
|
|
|
|
|
const cd::ExitCheck ThreadingCheck17("ProductionGateway::~ProductionGateway():ThreadingCheck17(0 == pthread_cond_destroy(&MyConditionVariable))"); |
|
|
|
|
|
|
|
|
ProductionGateway::~ProductionGateway() { // When we're done we must destroy |
|
|
ProductionGateway::~ProductionGateway() { // When we're done we must destroy |
|
|
ThreadingCheck16(0 == pthread_mutex_destroy(&MyMutex)); // our local mutex and |
|
|
ThreadingCheck16(0 == pthread_mutex_destroy(&MyMutex)); // our local mutex and |
|
|
ThreadingCheck17(0 == pthread_cond_destroy(&MyConditionVariable)); // our condition variable. |
|
|
ThreadingCheck17(0 == pthread_cond_destroy(&MyConditionVariable)); // our condition variable. |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const RuntimeCheck ThreadingCheck18("ProductionGateway::produce():ThreadingCheck18(0 == pthread_mutex_lock(&MyMutex))"); |
|
|
|
|
|
const RuntimeCheck ThreadingCheck19("ProductionGateway::produce():ThreadingCheck19(0 == pthread_cond_signal(&MyConditionVariable))"); |
|
|
|
|
|
const RuntimeCheck ThreadingCheck20("ProductionGateway::produce():ThreadingCheck20(0 == pthread_mutex_unlock(&MyMutex))"); |
|
|
|
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck18("ProductionGateway::produce():ThreadingCheck18(0 == pthread_mutex_lock(&MyMutex))"); |
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck19("ProductionGateway::produce():ThreadingCheck19(0 == pthread_cond_signal(&MyConditionVariable))"); |
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck20("ProductionGateway::produce():ThreadingCheck20(0 == pthread_mutex_unlock(&MyMutex))"); |
|
|
|
|
|
|
|
|
void ProductionGateway::produce() { // To produce in POSIX |
|
|
void ProductionGateway::produce() { // To produce in POSIX |
|
|
ThreadingCheck18(0 == pthread_mutex_lock(&MyMutex)); // Lock our mutex. |
|
|
ThreadingCheck18(0 == pthread_mutex_lock(&MyMutex)); // Lock our mutex. |
|
|
|
|
|
|
|
|
ThreadingCheck20(0 == pthread_mutex_unlock(&MyMutex)); // At the end unlock our mutex so |
|
|
ThreadingCheck20(0 == pthread_mutex_unlock(&MyMutex)); // At the end unlock our mutex so |
|
|
} // waiting threads can fly free :-) |
|
|
} // waiting threads can fly free :-) |
|
|
|
|
|
|
|
|
const RuntimeCheck ThreadingCheck21("ProductionGateway::consume():ThreadingCheck21(0 == pthread_mutex_lock(&MyMutex))"); |
|
|
|
|
|
const RuntimeCheck ThreadingCheck22("ProductionGateway::consume():ThreadingCheck22(0 == pthread_cond_wait(&MyConditionVariable, &MyMutex))"); |
|
|
|
|
|
const RuntimeCheck ThreadingCheck23("ProductionGateway::consume():ThreadingCheck23(0 == pthread_mutex_unlock(&MyMutex))"); |
|
|
|
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck21("ProductionGateway::consume():ThreadingCheck21(0 == pthread_mutex_lock(&MyMutex))"); |
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck22("ProductionGateway::consume():ThreadingCheck22(0 == pthread_cond_wait(&MyConditionVariable, &MyMutex))"); |
|
|
|
|
|
const cd::RuntimeCheck ThreadingCheck23("ProductionGateway::consume():ThreadingCheck23(0 == pthread_mutex_unlock(&MyMutex))"); |
|
|
|
|
|
|
|
|
void ProductionGateway::consume() { // To consume in POSIX |
|
|
void ProductionGateway::consume() { // To consume in POSIX |
|
|
ThreadingCheck21(0 == pthread_mutex_lock(&MyMutex)); // Lock our mutex. |
|
|
ThreadingCheck21(0 == pthread_mutex_lock(&MyMutex)); // Lock our mutex. |