OpenTTD
thread_os2.cpp
Go to the documentation of this file.
1 /* $Id: thread_os2.cpp 27670 2016-10-30 17:29:33Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "../stdafx.h"
13 #include "thread.h"
14 
15 #define INCL_DOS
16 #include <os2.h>
17 #include <process.h>
18 
19 #include "../safeguards.h"
20 
25 private:
26  TID thread;
28  void *param;
30 
31 public:
36  thread(0),
37  proc(proc),
38  param(param),
39  self_destruct(self_destruct)
40  {
41  thread = _beginthread(stThreadProc, NULL, 1048576, this);
42  }
43 
44  /* virtual */ bool Exit()
45  {
46  _endthread();
47  return true;
48  }
49 
50  /* virtual */ void Join()
51  {
52  DosWaitThread(&this->thread, DCWW_WAIT);
53  this->thread = 0;
54  }
55 private:
60  static void stThreadProc(void *thr)
61  {
62  ((ThreadObject_OS2 *)thr)->ThreadProc();
63  }
64 
69  void ThreadProc()
70  {
71  /* Call the proc of the creator to continue this thread */
72  try {
73  this->proc(this->param);
74  } catch (OTTDThreadExitSignal e) {
75  } catch (...) {
76  NOT_REACHED();
77  }
78 
79  if (self_destruct) {
80  this->Exit();
81  delete this;
82  }
83  }
84 };
85 
86 /* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread, const char *name)
87 {
88  ThreadObject *to = new ThreadObject_OS2(proc, param, thread == NULL);
89  if (thread != NULL) *thread = to;
90  return true;
91 }
92 
96 class ThreadMutex_OS2 : public ThreadMutex {
97 private:
98  HMTX mutex;
99  HEV event;
101 
102 public:
104  {
105  DosCreateMutexSem(NULL, &mutex, 0, FALSE);
106  DosCreateEventSem(NULL, &event, 0, FALSE);
107  }
108 
109  /* virtual */ ~ThreadMutex_OS2()
110  {
111  DosCloseMutexSem(mutex);
112  DosCloseEventSem(event);
113  }
114 
115  /* virtual */ void BeginCritical(bool allow_recursive = false)
116  {
117  /* os2 mutex is recursive by itself */
118  DosRequestMutexSem(mutex, (unsigned long) SEM_INDEFINITE_WAIT);
119  this->recursive_count++;
120  if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
121  }
122 
123  /* virtual */ void EndCritical(bool allow_recursive = false)
124  {
125  if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
126  this->recursive_count--;
127  DosReleaseMutexSem(mutex);
128  }
129 
130  /* virtual */ void WaitForSignal()
131  {
132  assert(this->recursive_count == 1); // Do we need to call Begin/EndCritical multiple times otherwise?
133  this->EndCritical();
134  DosWaitEventSem(event, SEM_INDEFINITE_WAIT);
135  this->BeginCritical();
136  }
137 
138  /* virtual */ void SendSignal()
139  {
140  DosPostEventSem(event);
141  }
142 };
143 
144 /* static */ ThreadMutex *ThreadMutex::New()
145 {
146  return new ThreadMutex_OS2();
147 }