OpenSdkThread.cc

Go to the documentation of this file.
00001 /*
00002  * This file is part of openSDK.
00003  *
00004  * Copyright (C) 2006-2007 openSDK team
00005  *
00006  * openSDK is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; version 2.
00009  *
00010  * openSDK is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with openSDK; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  *
00019  *     $Id: OpenSdkThread.cc,v 1.7 2007/03/24 11:32:23 nuno-lopes Exp $
00020  */
00021 
00022 #include <iostream>
00023 #include <OpenSdkThread.h>
00024 #include <Platform.h>
00025 
00026 using namespace std;
00027 
00028 static void* threadFunc(void*arg);
00029 
00030 //static var initialization
00031 std::vector<OpenSdkThread*> *OpenSdkThread::threadVector;
00032 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00033 
00034 #define LOCK() pthread_mutex_lock(&mutex);
00035 #define UNLOCK() pthread_mutex_unlock(&mutex);
00036 
00037 
00038 int OpenSdkThread::runFunction(FuncPointer func, void *arg)
00039 {
00040         std::vector<OpenSdkThread*>::iterator it = threadVector->begin();
00041 
00042         do {
00043                 OpenSdkThread *ost = *it;
00044 
00045                 pthread_mutex_lock(&ost->stateMutex);
00046 
00047                 if (ost->state == Idle) {
00048                         ost->state = Running;
00049                         pthread_mutex_unlock(&ost->stateMutex);
00050 
00051                         ost->func = func;
00052                         ost->arg = arg;
00053                         pthread_mutex_unlock(&ost->runMutex);
00054                         return 0;
00055                 }
00056 
00057                 pthread_mutex_unlock(&ost->stateMutex);
00058 
00059                 if(++it == threadVector->end()) {
00060 //                      it = threadPool->begin(); // uncomment to enable continuous thread search
00061                         cerr << "****************** OpenSdkThread::runFunction: no thread available ******************" << endl;
00062                         return -1;
00063                 }
00064 
00065         } while (true);
00066 }
00067 
00068 
00069 void OpenSdkThread::initThreadPool()
00070 {
00071         cout << "Initializing thread pool ..." << endl;
00072 
00073         threadVector = new std::vector<OpenSdkThread*>;
00074 
00075         for(int i = 0; i<THREAD_POOL_SIZE; i++) {
00076                 OpenSdkThread *ost = new OpenSdkThread();
00077                 threadVector->push_back(ost);
00078         }
00079 
00080         cout << "thread pool created with " << THREAD_POOL_SIZE << " threads." << endl;
00081 }
00082 
00083 void OpenSdkThread::cleanThreadPool()
00084 {
00085         LOCK();
00086         for (std::vector<OpenSdkThread*>::iterator it = OpenSdkThread::threadVector->begin();
00087                 it != OpenSdkThread::threadVector->end(); ++it) {
00088                 (*it)->state = Dead;
00089                 pthread_mutex_unlock(&((*it)->runMutex));
00090         }
00091         UNLOCK();
00092 
00093         int guard = 42;
00094         while (--guard) {
00095                 opensdk_yield();
00096 
00097                 LOCK();
00098                 if (threadVector->empty()) {
00099                         UNLOCK();
00100                         delete threadVector;
00101                         return;
00102                 }
00103                 UNLOCK();
00104         }
00105 }
00106 
00107 
00108 OpenSdkThread::OpenSdkThread()
00109 {
00110         pthread_mutex_init(&(this->runMutex), NULL);
00111         pthread_mutex_init(&(this->stateMutex), NULL);
00112 
00113         pthread_mutex_lock(&(this->runMutex));
00114 
00115         pthread_t threadId;
00116         int threadRet = pthread_create(&threadId, NULL, threadFunc, this);
00117 
00118         if (threadRet == 0) {
00119                 // thread created
00120                 this->state = Idle;
00121                 pthread_detach(threadId);
00122         } else {
00123                 // thread NOT created
00124                 cerr << "ERROR: failed to create thread" << endl;
00125                 exit(0xdead);
00126         }
00127 }
00128 
00129 
00130 OpenSdkThread::~OpenSdkThread()
00131 {
00132         pthread_mutex_destroy(&(this->runMutex));
00133         pthread_mutex_destroy(&(this->stateMutex));
00134 }
00135 
00136 
00137 void OpenSdkThread::deleteThread(void)
00138 {
00139         LOCK();
00140 
00141         for (std::vector<OpenSdkThread*>::iterator it = OpenSdkThread::threadVector->begin();
00142                 it != OpenSdkThread::threadVector->end(); ++it) {
00143                 if (*it == this) {
00144                         threadVector->erase(it);
00145                         UNLOCK();
00146                         return;
00147                 }
00148         }
00149 
00150         UNLOCK();
00151         cerr << "[OpenSdkThread::deleteThread] the impossible happened: thread not found in the list" << endl;
00152 }
00153 
00154 
00155 static void* threadFunc(void *arg)
00156 {
00157         OpenSdkThread *ost = (OpenSdkThread*)arg;
00158 
00159         while (true) {
00160                 pthread_mutex_lock(&(ost->runMutex)); // unlocks are made elsewhere, to control when this thread runs or not
00161 
00162                 if (ost->state == Dead) {
00163                         ost->deleteThread();
00164 
00165                         // at this point it is safe to unlock this mutex because it isn't listed in the thread pool
00166                         // we need to unlock the mutex because mutexes should be unlocked before being destroy
00167                         pthread_mutex_unlock(&(ost->runMutex));
00168                         delete ost;
00169                         return NULL;
00170                 }
00171 
00172                 ost->func(ost->arg);
00173 
00174                 pthread_mutex_lock(&(ost->stateMutex));
00175                 ost->state = Idle;
00176                 pthread_mutex_unlock(&(ost->stateMutex));
00177         }
00178 }

Generated on Sun Dec 2 23:04:30 2007 for openSDK by  doxygen 1.3.9.1