I created a MutexCondition class like this
#ifndef MUTEXCONDITION_H_ #define MUTEXCONDITION_H_ #include <pthread.h> #include <stdio.h> class MutexCondition { private: bool init(); bool destroy(); protected: pthread_mutex_t m_mut; pthread_cond_t m_con; public: MutexCondition(){ init(); } virtual ~MutexCondition(){ destroy(); } bool lock(); bool unLock(); bool wait(); bool signal(); }; #endif /* MUTEXCONDITION_H_ */
MutexCondtion.cpp File
#include "MutexCondition.h" bool MutexCondition::init(){ printf("MutexCondition::init called\n"); pthread_mutex_init(&m_mut, NULL); pthread_cond_init(&m_con, NULL); return true; } bool MutexCondition::destroy(){ pthread_mutex_destroy(&m_mut); pthread_cond_destroy(&m_con); return true; } bool MutexCondition::lock(){ pthread_mutex_lock(&m_mut); return true; } bool MutexCondition::unLock(){ pthread_mutex_unlock(&m_mut); return true; } bool MutexCondition::wait(){ pthread_cond_wait(&m_con, &m_mut); return true; } bool MutexCondition::signal(){ pthread_cond_signal(&m_con); return true; }
And I created a WorkHandler that extends MutexCondition
#ifndef WORKHANDLER_H_ #define WORKHANDLER_H_ #include <stdio.h> #include <stdlib.h> #include <queue> #include <pthread.h> #include <stdio.h> #include <list> #include "MutexCondition.h" #include "Work.h" using namespace::std; class WorkHandler: MutexCondition { private: int m_maxThreads; queue<Work*> m_workQueue; list<pthread_t*> m_workThreadList; //Just thread IDs pthread_t **m_workThreads; void workLoop(); bool initThreads(); void insertWork(Work *work); Work* getWork(); protected: static void* runWorkThread(void* delegate); public: WorkHandler(int maxThreads); virtual ~WorkHandler(); }; #endif /* WORKHANDLER_H_ */
WorkHandler.cpp File
#include "WorkHandler.h" WorkHandler::WorkHandler(int maxThreads) { // TODO Auto-generated constructor stub m_maxThreads = maxThreads; initThreads(); } WorkHandler::~WorkHandler() { // TODO Auto-generated destructor stub } void* WorkHandler::runWorkThread(void *delegate){ printf("WorkHandler::runWorkThread called\n"); WorkHandler *ptr = reinterpret_cast<WorkHandler*>(delegate); ptr->workLoop(); return NULL; } void WorkHandler::workLoop(){ printf("WorkHandler::workLoop called\n"); //WorkHandler *ptr = reinterpret_cast<WorkHandler*>(delegate); while(1){ Work *work = getWork(); } } bool WorkHandler::initThreads(){ for(int i=0; i < m_maxThreads; i++){ pthread_t *thread(new pthread_t); m_workThreadList.push_back(thread); if(pthread_create(thread, NULL, runWorkThread, reinterpret_cast<void *>(this))!=0){ perror("InitThreads, pthread_create error \n"); return false; } pthread_detach(*thread); } return true; } void WorkHandler::insertWork(Work* w){ printf("WorkHandler::Thread %d insertWork locking\n", pthread_self()); lock(); printf("WorkHandler::insertWork Locked and inserting int queue \n"); m_workQueue.push(w); signal(); unLock(); } Work* WorkHandler::getWork(){ printf("WorkHandler::getWork locking\n"); lock(); printf("WorkHandler::getWork locked\n"); while(m_workQueue.empty()){//Need while instead of If printf("WorkHandler::getWork waiting...\n"); wait(); } Work *work = m_workQueue.front(); printf("WorkHandler::getWork got a job\n"); m_workQueue.pop(); unLock(); return work; }
The problem is that I locked the mutex variable in getWork () function like this
printf("WorkHandler::getWork locking\n"); lock(); printf("WorkHandler::getWork locked\n");
However, if I see the log instructions, then all the threads printed these two log statements, and I think this is the problem. I do not put anything in the queue, so the first thread should wait for the condition variable, which should be signaled, and it works fine. But why another thread can enter the area behind the lock, although the first thread is blocked and did not call the unlock () function.
I was wondering if this worked correctly. Please let me know if you guys can see everything I need to fix. Thanks in advance.