Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

Thread.cc

Go to the documentation of this file.
00001 /*
00002  * Thread.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Thread wrapper.
00006  *
00007  * Copyright (c) 2003-05 Milan Cermak
00008  */
00009 /*
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 
00027 #include <stlib/os/Thread.h>
00028 #include <stlib/Array.h>
00029 #include <stlib/Iterator.h>
00030 #include <stlib/Set.h>
00031 #include <stlib/String.h>
00032 #include <stlib/NotFoundError.h>
00033 
00034 using namespace OS;
00035 
00036 Set Thread::threads(5);          // Thread container
00037 
00038 Thread::Thread(Callback<void> *receiver)
00039 {
00040     finalizeThreads();
00041     // Nainicializujeme podminku behu vlakna a mutex
00042     pthread_mutex_init(&mutVar, NULL);
00043     pthread_cond_init(&runCond, NULL);
00044     // Nastavime vykonnou funkci
00045     _receiver = receiver;
00046     _arguments = nil;
00047     // Nastavime priznak beziciho vlakna
00048     runningThread = false;
00049 }
00050 
00051 Thread::~Thread(void)
00052 {
00053     terminate();
00054     // Zrusime podminku a mutex
00055     pthread_cond_destroy(&runCond);
00056     pthread_mutex_destroy(&mutVar);
00057     _receiver = nil;
00058 }
00059 
00060 /* Class-accessing protocol */
00061 String *Thread::className(void) const
00062 {
00063     return new String("Thread");
00064 }
00065 
00066 Thread *Thread::fork(Callback<void> *receiver)
00067 {
00068     Thread *thread = new Thread(receiver);
00069     thread->run();
00070     return thread;
00071 }
00072 
00073 Thread *Thread::fork(Callback<void> *receiver, Array *args)
00074 {
00075     Thread *thread = new Thread(receiver);
00076     thread->arguments(args);
00077     thread->run();
00078     return thread;
00079 }
00080 
00081 /* Prevezme hodnoty od ukoncenych vlaken */
00082 void Thread::finalizeThreads(void)
00083 {
00084     Set *temp = (Set *) threads.copy();
00085     for (Iterator* i = temp->iterator(); !i->finished(); i->next()) {
00086         Thread *th = (Thread *) i->value();
00087         if (!th->isRunning())
00088             th->finalize();
00089     }
00090     delete temp;
00091 }
00092 
00093 void Thread::arguments(Array *args)
00094 {
00095     _arguments = args;
00096 }
00097 
00098 // obnovi beh vlakna
00099 void Thread::resume()
00100 {
00101     if (runningThread == false) {  // vlakno dosud nebylo vytvoreno
00102         // zadna akce
00103         return;
00104     }
00105     pthread_cond_signal(&runCond);
00106 }
00107 
00108 // pozastavi beh vlakna
00109 void Thread::suspend()
00110 {
00111     if (runningThread == false) {  // vlakno dosud nebylo vytvoreno
00112         // zadna akce
00113         return;
00114     }
00115     pthread_cond_wait(&runCond, &mutVar);
00116 }
00117 
00118 // Init vytvori pro objekt CThread jeho provadeci tok - vlakno
00119 // tim je staticka metoda ThreadProc, ktere se preda ukazatel this
00120 void Thread::run()
00121 {
00122     runningThread = true;
00123     pthread_create(&hThread, NULL, threadProc, this);
00124     threads.add(this);
00125 }
00126 
00127 void Thread::finalize(void)
00128 {
00129     pthread_join(hThread, NULL);
00130     runningThread = false;
00131     try {
00132         threads.remove(this);
00133     }
00134     catch (NotFoundError *ex) {
00135         /* It doesn't matter if it was there or not. It isn't now for sure. */
00136     }
00137 }
00138 
00139 void Thread::terminate(void)
00140 {
00141     // zruseni vlakna
00142     if (runningThread != false) {
00143         pthread_cancel(hThread);
00144         // Pockame az vlakno dobehne a odchytime navratovou hodnotu
00145         finalize();
00146     }
00147 }
00148 
00149 void Thread::yield(void)
00150 {
00151     sleep(1);
00152 }
00153 
00154 /* Testing protocol */
00155 bool Thread::isRunning(void)
00156 {
00157     return runningThread;
00158 }
00159 
00160 // hlavni procedura vlakna
00161 void *Thread::threadProc(void *x)
00162 {
00163     // pomoci myThread lze pristupovat i k nestatickym clenum tridy
00164     Thread *myThread = (Thread *) x;
00165 
00166     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00167     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00168     myThread->runningThread = true;
00169 
00170     myThread->_receiver->executeWith(myThread->_arguments);
00171 
00172     myThread->runningThread = false;
00173 
00174     return NULL;                 // opustenim ThreadProc zanika
00175                                  // pracovni vlakno objektu Thread
00176 }

Generated on Mon Nov 27 09:47:55 2006 for Smalltalk like C++ Class Library by  doxygen 1.4.2