Adapted to recent changes of %build_linklib.
[AROS-Contrib.git] / FryingPan / framework / Generic / Thread.cpp
blob39119187b993f64b8c15584592c56cdc4e4fd243
1 /*
2 * Amiga Generic Set - set of libraries and includes to ease sw development for all Amiga platforms
3 * Copyright (C) 2001-2011 Tomasz Wiszkowski Tomasz.Wiszkowski at gmail.com.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "Thread.h"
21 #include <exec/ports.h>
22 #include <dos/dos.h>
23 #include <exec/semaphores.h>
24 #include <dos/dosextens.h>
25 #include <dos/dostags.h>
26 #include <libclass/utility.h>
27 #include <libclass/exec.h>
28 #include <libclass/dos.h>
29 #include <dos/dosextens.h>
30 #include "HookAttrT.h"
31 #include "String.h"
32 #include "Timer.h"
33 #include "LibrarySpool.h"
35 #ifndef __MORPHOS__
36 #define NP_CodeType TAG_IGNORE
37 #define CODETYPE_PPC 0
38 #endif
40 using namespace GenNS;
42 void Thread::Create()
44 Message *m = 0;
45 MsgPort *p = 0;
47 ULONG tags[] = {
48 NP_Entry, (ULONG)&__proc_init_code,
49 NP_StackSize, 65536,
50 NP_Name, (unsigned long)hName.Data(),
51 NP_CodeType, CODETYPE_PPC,
52 TAG_DONE, 0
55 pProcess = DOS->CreateNewProc((TagItem*)tags);
56 p = Exec->CreateMsgPort();
57 m = new Message;
58 m->mn_Length = sizeof(Message);
59 m->mn_Node.ln_Name = (char*)this;
60 m->mn_ReplyPort = p;
61 Exec->PutMsg(&pProcess->pr_MsgPort, m);
62 Exec->WaitPort(p);
63 m = Exec->GetMsg(p);
64 Exec->DeleteMsgPort (p);
65 delete m;
68 void Thread::Terminate()
70 if (!Exec->AttemptSemaphore(pSemaphore))
72 Exec->Signal(&pProcess->pr_Task, lKillSignal);
73 Exec->ObtainSemaphore(pSemaphore);
75 Exec->ReleaseSemaphore(pSemaphore);
78 bool Thread::IsTerminated()
80 if (Exec->AttemptSemaphore(pSemaphore))
82 Exec->ReleaseSemaphore(pSemaphore);
83 return true;
85 return false;
88 void Thread::WaitTerminated()
90 Exec->ObtainSemaphore(pSemaphore);
91 Exec->ReleaseSemaphore(pSemaphore);
94 unsigned long Thread::GetSignals()
96 return lKillSignal | pTimer->GetSignals() | pPort->GetSignals();
99 bool Thread::HandleSignals(int32 ATimeout)
101 return HandleSignals(ATimeout, 0);
104 bool Thread::HandleSignals(int32 ATimeout, uint32 ASignals)
106 unsigned long lSignals = ASignals;
107 unsigned long lRes;
109 wasTimer = false;
111 if ((ATimeout != 0) && (ATimeout != -1))
113 pTimer->AddRequest(ATimeout);
115 else if (ATimeout == 0)
117 pTimer->AbortRequest();
120 lSignals |= GetSignals();
123 pPort->HandleSignals(); // if there are any pending messages, handle them at once
124 if (ATimeout) // if timeout has been set...
125 lRes = Exec->Wait(lSignals); // wait for any signal or timeout
126 else // otherwise
127 lRes = Exec->SetSignal(0, lSignals); // just check signals
129 if (lRes & lKillSignal) // if we got killed
130 return true; // exit immediately
131 if (lRes &pTimer->GetSignals())
132 wasTimer = true;
133 if (lRes &pPort->GetSignals()) // if we received a new message
134 pPort->HandleSignals(); // take care of all messages
135 if (lRes &~pPort->GetSignals()) // otherwise, if it was a timer or any other signal
136 return false; // quit & report
137 } while (ATimeout); // eventually loop.
138 return false;
141 bool Thread::IsTimerSignal()
143 return wasTimer;
146 void Thread::__proc_init_code()
148 Process *p; // pointer to this process
149 Message *m; // pointer to received message
150 Thread *d; // pointer to the class
152 p = (Process*) Exec->FindTask(0); // get process message
153 Exec->WaitPort(&p->pr_MsgPort); // we expect our class pointer
154 m = Exec->GetMsg(&p->pr_MsgPort); // handle it
155 d = (Thread*)m->mn_Node.ln_Name; // get class pointer
156 d->lKillSignal = 1<<Exec->AllocSignal(-1); // we dont have to free it.
157 d->pPort = new Port(0);
158 d->pTimer = new Timer();
159 Exec->ObtainSemaphore(d->pSemaphore);
160 Exec->ReplyMsg(m);
161 d->hHook(d, d->pData);
162 delete d->pPort;
163 delete d->pTimer;
164 d->pProcess = 0;
165 Exec->ReleaseSemaphore(d->pSemaphore);
168 Thread::Thread(const char* AName, const Hook *AHook, void* AData) :
169 hName(AName),
170 pData(AData),
171 hHook(AHook)
173 pSemaphore = new SignalSemaphore;
174 Exec->InitSemaphore(pSemaphore);
175 Create();
178 Thread::Thread(const char* AName) :
179 hName(AName),
180 pData(0),
181 hHook(hDefault)
183 hDefault.Initialize(this, &Thread::fDefaultHandler);
184 pSemaphore = new SignalSemaphore;
185 Exec->InitSemaphore(pSemaphore);
186 Create();
189 Thread::~Thread()
191 Terminate();
192 delete pSemaphore;
195 void Thread::SetHandler(const Hook *AHandler)
197 pPort->Handler = AHandler;
200 void Thread::DoAsync(unsigned long ACommand, void* ApData)
202 pPort->DoAsync(ACommand, ApData);
205 unsigned long Thread::DoSync(unsigned long ACommand, void* ApData)
207 return pPort->DoSync(ACommand, ApData);
210 void Thread::ProcMessages()
212 pPort->HandleSignals();
215 unsigned long Thread::fDefaultHandler(struct Thread *pThis, void*)
217 pThis->HandleSignals(0xffffffff);
218 return 0;