1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All rights reserved.
33*/
34#ifndef __FUNCTION_OBJECT__
35#define __FUNCTION_OBJECT__
36
37
38#include <Message.h>
39#include <Messenger.h>
40#include <MessageFilter.h>
41
42#include <Entry.h>
43#include <Node.h>
44
45
46// parameter binders serve to store a copy of a struct and
47// pass it in and out by pointers, allowing struct parameters to share
48// the same syntax as scalar ones
49
50// You will mostly want to use the NewFunctionObject... convenience
51// factories
52//
53
54// add more function objects and specialized binders as needed
55
56namespace BPrivate {
57
58template<class P>
59class ParameterBinder {
60// primitive default binder for scalars
61public:
62	ParameterBinder() {}
63	ParameterBinder(P p)
64		:	p(p)
65		{}
66
67	P Pass() const
68		{ return p; }
69private:
70	P p;
71};
72
73
74template<>
75class ParameterBinder<const BEntry*> {
76public:
77	ParameterBinder() {}
78	ParameterBinder(const BEntry* p)
79		:	p(*p)
80		{}
81
82	ParameterBinder &operator=(const BEntry* newp)
83		{ p = *newp; return *this; }
84
85	const BEntry* Pass() const
86		{ return &p; }
87private:
88	BEntry p;
89};
90
91
92template<>
93class ParameterBinder<const entry_ref*> {
94public:
95	ParameterBinder() {}
96	ParameterBinder(const entry_ref* p)
97		{
98			if (p)
99				this->p = *p;
100		}
101
102	ParameterBinder &operator=(const entry_ref* newp)
103		{ p = *newp; return *this; }
104
105	const entry_ref* Pass() const
106		{ return &p; }
107private:
108	entry_ref p;
109};
110
111
112template<>
113class ParameterBinder<const node_ref*> {
114public:
115	ParameterBinder() {}
116	ParameterBinder(const node_ref* p)
117		:	p(*p)
118		{}
119
120	ParameterBinder &operator=(const node_ref* newp)
121		{ p = *newp; return *this; }
122
123	const node_ref* Pass() const
124		{ return &p; }
125private:
126	node_ref p;
127};
128
129
130template<>
131class ParameterBinder<const BMessage*> {
132public:
133	ParameterBinder() {}
134	ParameterBinder(const BMessage* p)
135		:	p(p ? new BMessage(*p) : NULL)
136		{}
137
138	~ParameterBinder()
139		{
140			delete p;
141		}
142
143	ParameterBinder &operator=(const BMessage* newp)
144		{
145			delete p;
146			p = (newp ? new BMessage(*newp) : NULL);
147			return *this;
148		}
149
150	const BMessage* Pass() const
151		{ return p; }
152
153private:
154	BMessage* p;
155};
156
157
158class FunctionObject {
159public:
160	virtual void operator()() = 0;
161	virtual ~FunctionObject() {}
162};
163
164
165template<class R>
166class FunctionObjectWithResult : public FunctionObject {
167public:
168	const R &Result() const { return result; }
169
170protected:
171	R result;
172};
173
174
175template <class Param1>
176class SingleParamFunctionObject : public FunctionObject {
177public:
178	SingleParamFunctionObject(void (*callThis)(Param1),
179		Param1 p1)
180		:	function(callThis),
181			p1(p1)
182		{
183		}
184
185	virtual void operator()() { (function)(p1.Pass()); }
186
187private:
188	void (*function)(Param1);
189	ParameterBinder<Param1> p1;
190};
191
192
193template <class Result, class Param1>
194class SingleParamFunctionObjectWithResult : public
195	FunctionObjectWithResult<Result> {
196public:
197	SingleParamFunctionObjectWithResult(Result (*function)(Param1), Param1 p1)
198		:	function(function),
199			p1(p1)
200		{
201		}
202
203	virtual void operator()()
204		{ FunctionObjectWithResult<Result>::result = (function)(p1.Pass()); }
205
206private:
207	Result (*function)(Param1);
208	ParameterBinder<Param1> p1;
209};
210
211
212template <class Param1, class Param2>
213class TwoParamFunctionObject : public FunctionObject {
214public:
215	TwoParamFunctionObject(void (*callThis)(Param1, Param2),
216		Param1 p1, Param2 p2)
217		:	function(callThis),
218			p1(p1),
219			p2(p2)
220		{
221		}
222
223	virtual void operator()() { (function)(p1.Pass(), p2.Pass()); }
224
225private:
226	void (*function)(Param1, Param2);
227	ParameterBinder<Param1> p1;
228	ParameterBinder<Param2> p2;
229};
230
231
232template <class Param1, class Param2, class Param3>
233class ThreeParamFunctionObject : public FunctionObject {
234public:
235	ThreeParamFunctionObject(void (*callThis)(Param1, Param2, Param3),
236		Param1 p1, Param2 p2, Param3 p3)
237		:	function(callThis),
238			p1(p1),
239			p2(p2),
240			p3(p3)
241		{
242		}
243
244	virtual void operator()() { (function)(p1.Pass(), p2.Pass(), p3.Pass()); }
245
246private:
247	void (*function)(Param1, Param2, Param3);
248	ParameterBinder<Param1> p1;
249	ParameterBinder<Param2> p2;
250	ParameterBinder<Param3> p3;
251};
252
253
254template <class Result, class Param1, class Param2, class Param3>
255class ThreeParamFunctionObjectWithResult : public
256	FunctionObjectWithResult<Result> {
257public:
258	ThreeParamFunctionObjectWithResult(
259		Result (*callThis)(Param1, Param2, Param3),
260		Param1 p1, Param2 p2, Param3 p3)
261		:	function(callThis),
262			p1(p1),
263			p2(p2),
264			p3(p3)
265		{
266		}
267
268	virtual void operator()()
269		{ FunctionObjectWithResult<Result>::result
270			= (function)(p1.Pass(), p2.Pass(), p3.Pass()); }
271
272private:
273	Result (*function)(Param1, Param2, Param3);
274	ParameterBinder<Param1> p1;
275	ParameterBinder<Param2> p2;
276	ParameterBinder<Param3> p3;
277};
278
279
280template <class Param1, class Param2, class Param3, class Param4>
281class FourParamFunctionObject : public FunctionObject {
282public:
283	FourParamFunctionObject(void (*callThis)(Param1, Param2, Param3, Param4),
284		Param1 p1, Param2 p2, Param3 p3, Param4 p4)
285		:	function(callThis),
286			p1(p1),
287			p2(p2),
288			p3(p3),
289			p4(p4)
290		{
291		}
292
293	virtual void operator()()
294		{ (function)(p1.Pass(), p2.Pass(), p3.Pass(), p4.Pass()); }
295
296private:
297	void (*function)(Param1, Param2, Param3, Param4);
298	ParameterBinder<Param1> p1;
299	ParameterBinder<Param2> p2;
300	ParameterBinder<Param3> p3;
301	ParameterBinder<Param4> p4;
302};
303
304
305template <class Result, class Param1, class Param2, class Param3,
306	class Param4>
307class FourParamFunctionObjectWithResult : public
308	FunctionObjectWithResult<Result>  {
309public:
310	FourParamFunctionObjectWithResult(
311		Result (*callThis)(Param1, Param2, Param3, Param4),
312		Param1 p1, Param2 p2, Param3 p3, Param4 p4)
313		:	function(callThis),
314			p1(p1),
315			p2(p2),
316			p3(p3),
317			p4(p4)
318		{
319		}
320
321	virtual void operator()()
322		{ FunctionObjectWithResult<Result>::result
323			= (function)(p1.Pass(), p2.Pass(), p3.Pass(), p4.Pass()); }
324
325private:
326	Result (*function)(Param1, Param2, Param3, Param4);
327	ParameterBinder<Param1> p1;
328	ParameterBinder<Param2> p2;
329	ParameterBinder<Param3> p3;
330	ParameterBinder<Param4> p4;
331};
332
333
334template<class T>
335class PlainMemberFunctionObject : public FunctionObject {
336public:
337	PlainMemberFunctionObject(void (T::*function)(), T* onThis)
338		:	function(function),
339			target(onThis)
340		{
341		}
342
343	virtual void operator()()
344		{ (target->*function)(); }
345
346private:
347	void (T::*function)();
348	T* target;
349};
350
351
352template<class T>
353class PlainLockingMemberFunctionObject : public FunctionObject {
354public:
355	PlainLockingMemberFunctionObject(void (T::*function)(), T* target)
356		:	function(function),
357			messenger(target)
358		{
359		}
360
361	virtual void operator()()
362		{
363			T* target = dynamic_cast<T*>(messenger.Target(NULL));
364			if (!target || !messenger.LockTarget())
365				return;
366			(target->*function)();
367			target->Looper()->Unlock();
368		}
369
370private:
371	void (T::*function)();
372	BMessenger messenger;
373};
374
375
376template<class T, class R>
377class PlainMemberFunctionObjectWithResult : public
378	FunctionObjectWithResult<R> {
379public:
380	PlainMemberFunctionObjectWithResult(R (T::*function)(), T* onThis)
381		:	function(function),
382			target(onThis)
383		{
384		}
385
386	virtual void operator()()
387		{ FunctionObjectWithResult<R>::result = (target->*function)(); }
388
389
390private:
391	R (T::*function)();
392	T* target;
393};
394
395
396template<class T, class Param1>
397class SingleParamMemberFunctionObject : public FunctionObject {
398public:
399	SingleParamMemberFunctionObject(void (T::*function)(Param1),
400		T* onThis, Param1 p1)
401		:	function(function),
402			target(onThis),
403			p1(p1)
404		{
405		}
406
407	virtual void operator()()
408		{ (target->*function)(p1.Pass()); }
409
410private:
411	void (T::*function)(Param1);
412	T* target;
413	ParameterBinder<Param1> p1;
414};
415
416
417template<class T, class Param1, class Param2>
418class TwoParamMemberFunctionObject : public FunctionObject {
419public:
420	TwoParamMemberFunctionObject(void (T::*function)(Param1, Param2),
421		T* onThis, Param1 p1, Param2 p2)
422		:	function(function),
423			target(onThis),
424			p1(p1),
425			p2(p2)
426		{
427		}
428
429	virtual void operator()()
430		{ (target->*function)(p1.Pass(), p2.Pass()); }
431
432
433protected:
434	void (T::*function)(Param1, Param2);
435	T* target;
436	ParameterBinder<Param1> p1;
437	ParameterBinder<Param2> p2;
438};
439
440
441template<class T, class R, class Param1>
442class SingleParamMemberFunctionObjectWithResult : public
443	FunctionObjectWithResult<R> {
444public:
445	SingleParamMemberFunctionObjectWithResult(R (T::*function)(Param1),
446		T* onThis, Param1 p1)
447		:	function(function),
448			target(onThis),
449			p1(p1)
450		{
451		}
452
453	virtual void operator()()
454		{ FunctionObjectWithResult<R>::result
455			= (target->*function)(p1.Pass()); }
456
457protected:
458	R (T::*function)(Param1);
459	T* target;
460	ParameterBinder<Param1> p1;
461};
462
463
464template<class T, class R, class Param1, class Param2>
465class TwoParamMemberFunctionObjectWithResult : public
466	FunctionObjectWithResult<R> {
467public:
468	TwoParamMemberFunctionObjectWithResult(R (T::*function)(Param1, Param2),
469		T* onThis, Param1 p1, Param2 p2)
470		:	function(function),
471			target(onThis),
472			p1(p1),
473			p2(p2)
474		{
475		}
476
477	virtual void operator()()
478		{ FunctionObjectWithResult<R>::result
479			= (target->*function)(p1.Pass(), p2.Pass()); }
480
481protected:
482	R (T::*function)(Param1, Param2);
483	T* target;
484	ParameterBinder<Param1> p1;
485	ParameterBinder<Param2> p2;
486};
487
488
489// convenience factory functions
490// NewFunctionObject
491// NewMemberFunctionObject
492// NewMemberFunctionObjectWithResult
493// NewLockingMemberFunctionObject
494//
495// ... add the missing ones as needed
496
497template<class Param1>
498SingleParamFunctionObject<Param1>*
499NewFunctionObject(void (*function)(Param1), Param1 p1)
500{
501	return new SingleParamFunctionObject<Param1>(function, p1);
502}
503
504
505template<class Param1, class Param2>
506TwoParamFunctionObject<Param1, Param2>*
507NewFunctionObject(void (*function)(Param1, Param2), Param1 p1, Param2 p2)
508{
509	return new TwoParamFunctionObject<Param1, Param2>(function, p1, p2);
510}
511
512
513template<class Param1, class Param2, class Param3>
514ThreeParamFunctionObject<Param1, Param2, Param3>*
515NewFunctionObject(void (*function)(Param1, Param2, Param3),
516	Param1 p1, Param2 p2, Param3 p3)
517{
518	return new ThreeParamFunctionObject<Param1, Param2, Param3>
519		(function, p1, p2, p3);
520}
521
522
523template<class T>
524PlainMemberFunctionObject<T>*
525NewMemberFunctionObject(void (T::*function)(), T* onThis)
526{
527	return new PlainMemberFunctionObject<T>(function, onThis);
528}
529
530
531template<class T, class Param1>
532SingleParamMemberFunctionObject<T, Param1>*
533NewMemberFunctionObject(void (T::*function)(Param1), T* onThis, Param1 p1)
534{
535	return new SingleParamMemberFunctionObject<T, Param1>
536		(function, onThis, p1);
537}
538
539
540template<class T, class Param1, class Param2>
541TwoParamMemberFunctionObject<T, Param1, Param2>*
542NewMemberFunctionObject(void (T::*function)(Param1, Param2), T* onThis,
543		Param1 p1, Param2 p2)
544{
545	return new TwoParamMemberFunctionObject<T, Param1, Param2>
546		(function, onThis, p1, p2);
547}
548
549
550template<class T, class R, class Param1, class Param2>
551TwoParamMemberFunctionObjectWithResult<T, R, Param1, Param2>*
552NewMemberFunctionObjectWithResult(R (T::*function)(Param1, Param2),
553	T* onThis, Param1 p1, Param2 p2)
554{
555	return new TwoParamMemberFunctionObjectWithResult<T, R, Param1, Param2>
556		(function, onThis, p1, p2);
557}
558
559
560template<class HandlerOrSubclass>
561PlainLockingMemberFunctionObject<HandlerOrSubclass>*
562NewLockingMemberFunctionObject(void (HandlerOrSubclass::*function)(),
563	HandlerOrSubclass* onThis)
564{
565	return new PlainLockingMemberFunctionObject<HandlerOrSubclass>
566		(function, onThis);
567}
568
569} // namespace BPrivate
570
571using namespace BPrivate;
572
573#endif	// __FUNCTION_OBJECT__
574