LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   resume and suspend pthreads (http://www.linuxquestions.org/questions/programming-9/resume-and-suspend-pthreads-184535/)

okhan 05-22-2004 12:57 PM

HELP: resume and suspend pthreads
 
Hello ppl!

How do you implement suspend/resume for pthreads? I read somewhere that you have to use a combination of mutex, condition variables and boolean predicates to implement this feature. This is required because i have to port some Windows code to linux and there is this class CPrcThread which is an abstraction for threads. So there are thread.suspend and thread.resume functions in the windows API so thats ok, but how do i do that with pthreads? I have come up with a solution of my own but it has hit a snag. This is my solution

Code:

void CPrcThread<Worker>::suspend()
{
    ifdef WIN32
    //do windows specific things here...
    #endif

    #ifdef __linux__
    pthread_mutex_lock(&mutex);
    flag--;
    pthread_mutex_unlock(&mutex);
    #endif
}

void CPrcThread<Worker>::resume()
{
        #ifdef WIN32
        //do windows specific things here...
        #endif

        #ifdef __linux__
        pthread_mutex_lock(&mutex);
        flag++;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        #endif
}

void* CPrcThread<Worker>::threadFunc(void* pParameter)
{

while(1)
{

        #ifdef WIN32
        //do windows specific things here...
        //no member variables accessed here so its ok...
        #endif


        #ifdef __linux__
          pthread_mutex_lock(&mutex);
          while(flag <= 0)
          {
                  pthread_cond_wait(&cond, &mutex);
          }
          pthread_mutex_unlock(&mutex);
          #endif


          //actual thread work here
 
}

}

mutex, cond, and flag are member variables of CPrcThread.
First of all, i dont know if this is the correct way to implement suspend/resume? Secondly, the bigger problem is that the threadFunc function is static for reasons i cant control. How do i then access the member variables??

Thanks in advance!

paulsm4 05-23-2004 12:50 AM

Hi -

I've got Richter ("Programming Applications for MS Windows") open to Chap 7 (to refresh my memory on the specifics of Win32 thread scheduling) and Stevens ("Unix Network Programming, Vol 1") open to Chap 23 (to see if there are any alternatives besides what you're already doing).

You haven't given us any specifics on exactly what the Windows code is trying to do (or why it needs to do it that way) ...

... but, frankly, it sounds like you're absolutely on the right track. The approach you're taking seems to be the right way to do it.

Good luck!

okhan 05-23-2004 10:11 AM

thanks for the reply, paulsm4!
in the resume and suspend functions, the windows specific thing just calls the corresponding Windows API resume and suspend functions respectively. while in the threadFunc function, a function is invoked which is the member of an object pointed to by the argument pParameter. Thats all. It doesnt (or at least it shouldnt) change the way what i do for the linux version...no?

cppkid 07-30-2004 08:32 AM

I don't know that you have found the answer to you question or not, coz its too late, but i joined this forum yesterday. Anyway i have witten a few functions for posix threads, including suspend and resume and threadfunction, and are working fine. I am including the cpp and header file with this messege, you can make a (.a) file, i mean library and use these functions, directly. If you need to plz revise the Quit mechanism as it is not that good, due to short time i could not spare more time on it. The thread is created with a Dummy function maped and suspended, then you can resume the thread, and can give the your function (static function), as a parameter to resume function with the refference of class.



________________________________SysThread.h_________________________


#include<pthread.h>

#define SUSPENDED 1
#define EXITED 2
#define RESUMED 3
#define QUITTED 4

class CSysThread
{
private:
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;
int m_nSuspend;
int m_nState;
pthread_t m_ThdID;
void *m_pObjThdFn;
char (*ThreadFunction)(void *);
static char Dummy(void *arg);
static void CallBack(void *arg);
bool IsThdSuspended();

protected:
int m_nErr;

public:
static void *ThdFn(void *pObj);
int Suspend(void);
int Resume(char (*)(void*), void *);
int IsSuspended();
int GetErr();
unsigned long GetThreadID();
int Quit();
int TerminateSysThread();

// Constructer / Destructer
CSysThread();
virtual ~CSysThread();
};





__________________SysThread.cpp____________________________________

#include "SysThread.h"
#include<iostream.h>
#include<unistd.h>
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________CONSTRUCTER_________________________________________________
//_____________________________________________________________________________________________
CSysThread::CSysThread()
{
int nRet;

ThreadFunction = (char (*)(void*))Dummy;
m_pObjThdFn = NULL;
m_nState = QUITTED;
m_nSuspend = 0;
m_ThdID = 0;
m_nErr = 0;

nRet = pthread_mutex_init(&m_SuspendMutex,NULL); // Return Check
if(nRet != 0)
{
m_nErr = 1;
return;
}

nRet = pthread_cond_init(&m_ResumeCond,NULL); // Return Check
if(nRet != 0)
{
m_nErr = 1;
return;
}


nRet = pthread_create(&m_ThdID, NULL, ThdFn,this);
if(nRet != 0)
{
m_nErr = 1;
return;
}
m_nState = RESUMED;
nRet = pthread_mutex_lock(&m_SuspendMutex); // Return Check
if(nRet != 0)
{
m_nErr = 1;
return;
}

Suspend();
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________DESTRUCTER__________________________________________________
//_____________________________________________________________________________________________
CSysThread::~CSysThread()
{
if(m_ThdID == 0) return;
pthread_exit(0);
m_nState = EXITED;
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________SUSPEND_________________________________________________
//_____________________________________________________________________________________________
int CSysThread::Suspend()
{
cout<<"Suspending........\n";

if(IsThdSuspended()) return 0; // Alredy Suspended

m_nSuspend = 1;
return 1;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//______________________________________RESUME_________________________________________________
//_____________________________________________________________________________________________
int CSysThread::Resume(char (*func)(void*), void *pObj)
{
int nCondRet;

if(IsThdSuspended() == false) return -1;

m_pObjThdFn = pObj;
ThreadFunction = (char (*)(void*))func;
nCondRet = pthread_cond_signal(&m_ResumeCond);
if(nCondRet != 0) return -1;
return 1;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//______________________________________IsSuspended____________________________________________
//_____________________________________________________________________________________________

int CSysThread::IsSuspended()
{
return m_nState;
}

bool CSysThread::IsThdSuspended()
{
int nRet;

nRet = pthread_mutex_trylock(&m_SuspendMutex);
if(nRet == 0) // Thread was suspended
{
nRet = pthread_mutex_unlock(&m_SuspendMutex);
return true;
}
return false;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________GetErr______________________________________________
//_____________________________________________________________________________________________
int CSysThread::GetErr()
{
return m_nErr;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________GetThreadID______________________________________________
//_____________________________________________________________________________________________
unsigned long CSysThread::GetThreadID()
{
return m_ThdID;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________TerminateSysThread__________________________________
//_____________________________________________________________________________________________
int CSysThread::TerminateSysThread()
{
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
pthread_cancel(m_ThdID);
m_nState = EXITED;
return 1;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________Quit________________________________________________
//_____________________________________________________________________________________________
int CSysThread::Quit()
{
int nRet;

if(m_ThdID == 0) return -1;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
nRet = pthread_cancel(m_ThdID);
m_nState = EXITED;
return nRet;
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________________ThdFn___________________________________________
//_____________________________________________________________________________________________

void* CSysThread::ThdFn(void *ptr)
{
char ch;
int nSuspRet;
CSysThread *pCthd = (CSysThread*)ptr;

pthread_cleanup_push(&CallBack,pCthd);}

while(1)
{

if(pCthd->m_nSuspend==1)
{
pCthd->m_nSuspend = 0;
pCthd->m_nState = SUSPENDED;
pthread_cond_wait(&pCthd->m_ResumeCond,&pCthd->m_SuspendMutex);
}
pCthd->m_nState = RESUMED;
usleep(2000);
// check if the funtion is exited, Call the thread cancelation
ch = (*(pCthd->ThreadFunction))(pCthd->m_pObjThdFn);
if(ch < 0)
{
nSuspRet = pCthd->Suspend();
if(nSuspRet < 0)
{
pthread_exit(0);
pCthd->m_nState = EXITED;
}
}
}
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________________CallBack___________________________________________
//_____________________________________________________________________________________________

void CSysThread::CallBack(void *ptr)
{
CSysThread *pCthd = (CSysThread*)ptr;

pCthd->m_nState = QUITTED;
pCthd->m_ThdID = 0;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________________CallBack___________________________________________
//_____________________________________________________________________________________________
char CSysThread::Dummy(void *arg)
{
sleep(1);
return 1;
}




Regards:
Tayyab


All times are GMT -5. The time now is 11:11 AM.