xref: /haiku/headers/private/shared/Thread.h (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 #ifndef __THREAD__
35 #define __THREAD__
36 
37 
38 #include <Debug.h>
39 #include <Looper.h>
40 #include <OS.h>
41 
42 #include "ObjectList.h"
43 #include "FunctionObject.h"
44 
45 
46 namespace BPrivate {
47 
48 class MessengerAutoLocker {
49 	// move this into AutoLock.h
50 	public:
51 		MessengerAutoLocker(BMessenger* messenger)
52 			:	fMessenger(messenger),
53 				fHasLock(messenger->LockTarget())
54 		{}
55 
56 		~MessengerAutoLocker()
57 		{
58 			Unlock();
59 		}
60 
61 		bool operator!() const
62 		{
63 			return !fHasLock;
64 		}
65 
66 		bool IsLocked() const
67 		{
68 			return fHasLock;
69 		}
70 
71 		void Unlock()
72 		{
73 			if (fHasLock) {
74 				BLooper* looper;
75 				fMessenger->Target(&looper);
76 				if (looper)
77 					looper->Unlock();
78 				fHasLock = false;
79 			}
80 		}
81 
82 	private:
83 		BMessenger* fMessenger;
84 		bool fHasLock;
85 };
86 
87 
88 class SimpleThread {
89 	// this should only be used as a base class,
90 	// subclass needs to add proper locking mechanism
91 public:
92 	SimpleThread(int32 priority = B_LOW_PRIORITY, const char* name = 0);
93 	virtual ~SimpleThread();
94 
95 	void Go();
96 
97 private:
98 	static status_t RunBinder(void*);
99 	virtual void Run() = 0;
100 
101 protected:
102 	thread_id fScanThread;
103 	int32 fPriority;
104 	const char* fName;
105 };
106 
107 
108 class Thread : private SimpleThread {
109 public:
110 	static void Launch(FunctionObject* functor,
111 		int32 priority = B_LOW_PRIORITY, const char* name = 0);
112 
113 private:
114 	Thread(FunctionObject*, int32 priority, const char* name);
115 	~Thread();
116 	virtual void Run();
117 
118 	FunctionObject* fFunctor;
119 };
120 
121 
122 class ThreadSequence : private SimpleThread {
123 public:
124 	static void Launch(BObjectList<FunctionObject>*, bool async = true,
125 		int32 priority = B_LOW_PRIORITY);
126 
127 private:
128 	ThreadSequence(BObjectList<FunctionObject>*, int32 priority);
129 	~ThreadSequence();
130 
131 	virtual void Run();
132 	static void Run(BObjectList<FunctionObject>*list);
133 
134 	BObjectList<FunctionObject>* fFunctorList;
135 };
136 
137 
138 // would use SingleParamFunctionObjectWithResult, except mwcc won't handle this
139 template <class Param1>
140 class SingleParamFunctionObjectWorkaround : public
141 	FunctionObjectWithResult<status_t> {
142 public:
143 	SingleParamFunctionObjectWorkaround(
144 		status_t (*function)(Param1), Param1 param1)
145 		:	fFunction(function),
146 			fParam1(param1)
147 		{
148 		}
149 
150 	virtual void operator()()
151 		{ (fFunction)(fParam1); }
152 
153 	virtual ulong Size() const { return sizeof(*this); }
154 
155 private:
156 	status_t (*fFunction)(Param1);
157 	Param1 fParam1;
158 };
159 
160 
161 template <class T>
162 class SimpleMemberFunctionObjectWorkaround : public
163 	FunctionObjectWithResult<status_t> {
164 public:
165 	SimpleMemberFunctionObjectWorkaround(status_t (T::*function)(), T* onThis)
166 		:	fFunction(function),
167 			fOnThis(onThis)
168 		{
169 		}
170 
171 	virtual void operator()()
172 		{ (fOnThis->*fFunction)(); }
173 
174 	virtual ulong Size() const { return sizeof(*this); }
175 
176 private:
177 	status_t (T::*fFunction)();
178 	T fOnThis;
179 };
180 
181 
182 template <class Param1, class Param2>
183 class TwoParamFunctionObjectWorkaround : public
184 	FunctionObjectWithResult<status_t>  {
185 public:
186 	TwoParamFunctionObjectWorkaround(status_t (*callThis)(Param1, Param2),
187 		Param1 param1, Param2 param2)
188 		:	function(callThis),
189 			fParam1(param1),
190 			fParam2(param2)
191 		{
192 		}
193 
194 	virtual void operator()()
195 		{ (function)(fParam1, fParam2); }
196 
197 	virtual uint32 Size() const { return sizeof(*this); }
198 
199 private:
200 	status_t (*function)(Param1, Param2);
201 	Param1 fParam1;
202 	Param2 fParam2;
203 };
204 
205 
206 template <class Param1, class Param2, class Param3>
207 class ThreeParamFunctionObjectWorkaround : public
208 	FunctionObjectWithResult<status_t>  {
209 public:
210 	ThreeParamFunctionObjectWorkaround(
211 		status_t (*callThis)(Param1, Param2, Param3),
212 		Param1 param1, Param2 param2, Param3 param3)
213 		:	function(callThis),
214 			fParam1(param1),
215 			fParam2(param2),
216 			fParam3(param3)
217 		{
218 		}
219 
220 	virtual void operator()()
221 		{ (function)(fParam1, fParam2, fParam3); }
222 
223 	virtual uint32 Size() const { return sizeof(*this); }
224 
225 private:
226 	status_t (*function)(Param1, Param2, Param3);
227 	Param1 fParam1;
228 	Param2 fParam2;
229 	Param3 fParam3;
230 };
231 
232 
233 template <class Param1, class Param2, class Param3, class Param4>
234 class FourParamFunctionObjectWorkaround : public
235 	FunctionObjectWithResult<status_t>  {
236 public:
237 	FourParamFunctionObjectWorkaround(
238 		status_t (*callThis)(Param1, Param2, Param3, Param4),
239 		Param1 param1, Param2 param2, Param3 param3, Param4 param4)
240 		:	function(callThis),
241 			fParam1(param1),
242 			fParam2(param2),
243 			fParam3(param3),
244 			fParam4(param4)
245 		{
246 		}
247 
248 	virtual void operator()()
249 		{ (function)(fParam1, fParam2, fParam3, fParam4); }
250 
251 	virtual uint32 Size() const { return sizeof(*this); }
252 
253 private:
254 	status_t (*function)(Param1, Param2, Param3, Param4);
255 	Param1 fParam1;
256 	Param2 fParam2;
257 	Param3 fParam3;
258 	Param4 fParam4;
259 };
260 
261 
262 template<class Param1>
263 void
264 LaunchInNewThread(const char* name, int32 priority, status_t (*func)(Param1),
265 	Param1 p1)
266 {
267 	Thread::Launch(new SingleParamFunctionObjectWorkaround<Param1>(func, p1),
268 		priority, name);
269 }
270 
271 
272 template<class T>
273 void
274 LaunchInNewThread(const char* name, int32 priority, status_t (T::*function)(),
275 	T* onThis)
276 {
277 	Thread::Launch(new SimpleMemberFunctionObjectWorkaround<T>(function,
278 		onThis), priority, name);
279 }
280 
281 
282 template<class Param1, class Param2>
283 void
284 LaunchInNewThread(const char* name, int32 priority,
285 	status_t (*func)(Param1, Param2),
286 	Param1 p1, Param2 p2)
287 {
288 	Thread::Launch(new
289 		TwoParamFunctionObjectWorkaround<Param1, Param2>(func, p1, p2),
290 			priority, name);
291 }
292 
293 
294 template<class Param1, class Param2, class Param3>
295 void
296 LaunchInNewThread(const char* name, int32 priority,
297 	status_t (*func)(Param1, Param2, Param3),
298 	Param1 p1, Param2 p2, Param3 p3)
299 {
300 	Thread::Launch(new ThreeParamFunctionObjectWorkaround<Param1, Param2,
301 		Param3>(func, p1, p2, p3), priority, name);
302 }
303 
304 
305 template<class Param1, class Param2, class Param3, class Param4>
306 void
307 LaunchInNewThread(const char* name, int32 priority,
308 	status_t (*func)(Param1, Param2, Param3, Param4),
309 	Param1 p1, Param2 p2, Param3 p3, Param4 p4)
310 {
311 	Thread::Launch(new FourParamFunctionObjectWorkaround<Param1, Param2,
312 		Param3, Param4>(func, p1, p2, p3, p4), priority, name);
313 }
314 
315 
316 template<class View>
317 class MouseDownThread {
318 public:
319 	static void TrackMouse(View* view, void (View::*)(BPoint),
320 		void (View::*)(BPoint, uint32) = 0,
321 		bigtime_t pressingPeriod = 100000);
322 
323 protected:
324 	MouseDownThread(View* view, void (View::*)(BPoint),
325 		void (View::*)(BPoint, uint32), bigtime_t pressingPeriod);
326 
327 	virtual ~MouseDownThread();
328 
329 	void Go();
330 	virtual void Track();
331 
332 	static status_t TrackBinder(void*);
333 
334 private:
335 	BMessenger fOwner;
336 	void (View::*fDonePressing)(BPoint);
337 	void (View::*fPressing)(BPoint, uint32);
338 	bigtime_t fPressingPeriod;
339 	volatile thread_id fThreadID;
340 };
341 
342 
343 template<class View>
344 void
345 MouseDownThread<View>::TrackMouse(View* view,
346 	void(View::*donePressing)(BPoint),
347 	void(View::*pressing)(BPoint, uint32), bigtime_t pressingPeriod)
348 {
349 	(new MouseDownThread(view, donePressing, pressing, pressingPeriod))->Go();
350 }
351 
352 
353 template<class View>
354 MouseDownThread<View>::MouseDownThread(View* view,
355 	void (View::*donePressing)(BPoint),
356 	void (View::*pressing)(BPoint, uint32), bigtime_t pressingPeriod)
357 	:	fOwner(view, view->Window()),
358 		fDonePressing(donePressing),
359 		fPressing(pressing),
360 		fPressingPeriod(pressingPeriod)
361 {
362 }
363 
364 
365 template<class View>
366 MouseDownThread<View>::~MouseDownThread()
367 {
368 }
369 
370 
371 template<class View>
372 void
373 MouseDownThread<View>::Go()
374 {
375 	fThreadID = spawn_thread(&MouseDownThread::TrackBinder,
376 		"MouseTrackingThread", B_NORMAL_PRIORITY, this);
377 
378 	if (fThreadID <= 0 || resume_thread(fThreadID) != B_OK)
379 		// didn't start, don't leak self
380 		delete this;
381 }
382 
383 
384 template<class View>
385 status_t
386 MouseDownThread<View>::TrackBinder(void* castToThis)
387 {
388 	MouseDownThread* self = static_cast<MouseDownThread*>(castToThis);
389 	self->Track();
390 	// dead at this point
391 	return B_OK;
392 }
393 
394 
395 template<class View>
396 void
397 MouseDownThread<View>::Track()
398 {
399 	for (;;) {
400 		MessengerAutoLocker lock(&fOwner);
401 		if (!lock)
402 			break;
403 
404 		BLooper* looper;
405 		View* view = dynamic_cast<View*>(fOwner.Target(&looper));
406 		if (!view)
407 			break;
408 
409 		uint32 buttons;
410 		BPoint location;
411 		view->GetMouse(&location, &buttons, false);
412 		if (!buttons) {
413 			(view->*fDonePressing)(location);
414 			break;
415 		}
416 		if (fPressing)
417 			(view->*fPressing)(location, buttons);
418 
419 		lock.Unlock();
420 		snooze(fPressingPeriod);
421 	}
422 
423 	delete this;
424 }
425 
426 
427 } // namespace BPrivate
428 
429 using namespace BPrivate;
430 
431 #endif	// __THREAD__
432