# thread_os2.cpp

Go to the documentation of this file.

    00001 /* $Id: thread_os2.cpp 26353 2014-02-18 17:58:46Z frosch $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "../stdafx.h"
    00013 #include "thread.h"
    00014
    00015 #define INCL_DOS
    00016 #include <os2.h>
    00017 #include <process.h>
    00018
    00022 class ThreadObject_OS2 : public ThreadObject {
    00023 private:
    00024   TID thread;
    00025   OTTDThreadFunc proc;
    00026   void *param;
    00027   bool self_destruct;
    00028
    00029 public:
    00033   ThreadObject_OS2(OTTDThreadFunc proc, void *param, bool self_destruct) :
    00034     thread(0),
    00035     proc(proc),
    00036     param(param),
    00037     self_destruct(self_destruct)
    00038   {
    00039     thread = _beginthread(stThreadProc, NULL, 32768, this);
    00040   }
    00041
    00042   /* virtual */ bool Exit()
    00043   {
    00044     _endthread();
    00045     return true;
    00046   }
    00047
    00048   /* virtual */ void Join()
    00049   {
    00050     DosWaitThread(&this->thread, DCWW_WAIT);
    00051     this->thread = 0;
    00052   }
    00053 private:
    00058   static void stThreadProc(void *thr)
    00059   {
    00060     ((ThreadObject_OS2 *)thr)->ThreadProc();
    00061   }
    00062
    00067   void ThreadProc()
    00068   {
    00069     /* Call the proc of the creator to continue this thread */
    00070     try {
    00071       this->proc(this->param);
    00072     } catch (OTTDThreadExitSignal e) {
    00073     } catch (...) {
    00074       NOT_REACHED();
    00075     }
    00076
    00077     if (self_destruct) {
    00078       this->Exit();
    00079       delete this;
    00080     }
    00081   }
    00082 };
    00083
    00084 /* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
    00085 {
    00086   ThreadObject *to = new ThreadObject_OS2(proc, param, thread == NULL);
    00087   if (thread != NULL) *thread = to;
    00088   return true;
    00089 }
    00090
    00094 class ThreadMutex_OS2 : public ThreadMutex {
    00095 private:
    00096   HMTX mutex;
    00097   HEV event;
    00098   uint recursive_count;
    00099
    00100 public:
    00101   ThreadMutex_OS2() : recursive_count(0)
    00102   {
    00103     DosCreateMutexSem(NULL, &mutex, 0, FALSE);
    00104     DosCreateEventSem(NULL, &event, 0, FALSE);
    00105   }
    00106
    00107   /* virtual */ ~ThreadMutex_OS2()
    00108   {
    00109     DosCloseMutexSem(mutex);
    00110     DosCloseEventSem(event);
    00111   }
    00112
    00113   /* virtual */ void BeginCritical(bool allow_recursive = false)
    00114   {
    00115     /* os2 mutex is recursive by itself */
    00116     DosRequestMutexSem(mutex, (unsigned long) SEM_INDEFINITE_WAIT);
    00117     this->recursive_count++;
    00118     if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
    00119   }
    00120
    00121   /* virtual */ void EndCritical(bool allow_recursive = false)
    00122   {
    00123     if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
    00124     this->recursive_count--;
    00125     DosReleaseMutexSem(mutex);
    00126   }
    00127
    00128   /* virtual */ void WaitForSignal()
    00129   {
    00130     assert(this->recursive_count == 1); // Do we need to call Begin/EndCritical multiple times otherwise?
    00131     this->EndCritical();
    00132     DosWaitEventSem(event, SEM_INDEFINITE_WAIT);
    00133     this->BeginCritical();
    00134   }
    00135
    00136   /* virtual */ void SendSignal()
    00137   {
    00138     DosPostEventSem(event);
    00139   }
    00140 };
    00141
    00142 /* static */ ThreadMutex *ThreadMutex::New()
    00143 {
    00144   return new ThreadMutex_OS2();
    00145 }