1//
2// ActiveMethod.h
3//
4// Library: Foundation
5// Package: Threading
6// Module: ActiveObjects
7//
8// Definition of the ActiveMethod class.
9//
10// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_ActiveMethod_INCLUDED
18#define Foundation_ActiveMethod_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/ActiveResult.h"
23#include "Poco/ActiveRunnable.h"
24#include "Poco/ActiveStarter.h"
25#include "Poco/AutoPtr.h"
26
27
28namespace Poco {
29
30
31template <class ResultType, class ArgType, class OwnerType, class StarterType = ActiveStarter<OwnerType> >
32class ActiveMethod
33 /// An active method is a method that, when called, executes
34 /// in its own thread. ActiveMethod's take exactly one
35 /// argument and can return a value. To pass more than one
36 /// argument to the method, use a struct.
37 /// The following example shows how to add an ActiveMethod
38 /// to a class:
39 ///
40 /// class ActiveObject
41 /// {
42 /// public:
43 /// ActiveObject():
44 /// exampleActiveMethod(this, &ActiveObject::exampleActiveMethodImpl)
45 /// {
46 /// }
47 ///
48 /// ActiveMethod<std::string, std::string, ActiveObject> exampleActiveMethod;
49 ///
50 /// protected:
51 /// std::string exampleActiveMethodImpl(const std::string& arg)
52 /// {
53 /// ...
54 /// }
55 /// };
56 ///
57 /// And following is an example that shows how to invoke an ActiveMethod.
58 ///
59 /// ActiveObject myActiveObject;
60 /// ActiveResult<std::string> result = myActiveObject.exampleActiveMethod("foo");
61 /// ...
62 /// result.wait();
63 /// std::cout << result.data() << std::endl;
64 ///
65 /// The way an ActiveMethod is started can be changed by passing a StarterType
66 /// template argument with a corresponding class. The default ActiveStarter
67 /// starts the method in its own thread, obtained from a thread pool.
68 ///
69 /// For an alternative implementation of StarterType, see ActiveDispatcher.
70 ///
71 /// For methods that do not require an argument or a return value, the Void
72 /// class can be used.
73{
74public:
75 typedef ResultType (OwnerType::*Callback)(const ArgType&);
76 typedef ActiveResult<ResultType> ActiveResultType;
77 typedef ActiveRunnable<ResultType, ArgType, OwnerType> ActiveRunnableType;
78
79 ActiveMethod(OwnerType* pOwner, Callback method):
80 _pOwner(pOwner),
81 _method(method)
82 /// Creates an ActiveMethod object.
83 {
84 poco_check_ptr (pOwner);
85 }
86
87 ActiveResultType operator () (const ArgType& arg)
88 /// Invokes the ActiveMethod.
89 {
90 ActiveResultType result(new ActiveResultHolder<ResultType>());
91 ActiveRunnableBase::Ptr pRunnable(new ActiveRunnableType(_pOwner, _method, arg, result));
92 StarterType::start(_pOwner, pRunnable);
93 return result;
94 }
95
96 ActiveMethod(const ActiveMethod& other):
97 _pOwner(other._pOwner),
98 _method(other._method)
99 {
100 }
101
102 ActiveMethod& operator = (const ActiveMethod& other)
103 {
104 ActiveMethod tmp(other);
105 swap(tmp);
106 return *this;
107 }
108
109 void swap(ActiveMethod& other)
110 {
111 std::swap(_pOwner, other._pOwner);
112 std::swap(_method, other._method);
113 }
114
115private:
116 ActiveMethod();
117
118 OwnerType* _pOwner;
119 Callback _method;
120};
121
122
123
124template <class ResultType, class OwnerType, class StarterType>
125class ActiveMethod <ResultType, void, OwnerType, StarterType>
126 /// An active method is a method that, when called, executes
127 /// in its own thread. ActiveMethod's take exactly one
128 /// argument and can return a value. To pass more than one
129 /// argument to the method, use a struct.
130 /// The following example shows how to add an ActiveMethod
131 /// to a class:
132 ///
133 /// class ActiveObject
134 /// {
135 /// public:
136 /// ActiveObject():
137 /// exampleActiveMethod(this, &ActiveObject::exampleActiveMethodImpl)
138 /// {
139 /// }
140 ///
141 /// ActiveMethod<std::string, std::string, ActiveObject> exampleActiveMethod;
142 ///
143 /// protected:
144 /// std::string exampleActiveMethodImpl(const std::string& arg)
145 /// {
146 /// ...
147 /// }
148 /// };
149 ///
150 /// And following is an example that shows how to invoke an ActiveMethod.
151 ///
152 /// ActiveObject myActiveObject;
153 /// ActiveResult<std::string> result = myActiveObject.exampleActiveMethod("foo");
154 /// ...
155 /// result.wait();
156 /// std::cout << result.data() << std::endl;
157 ///
158 /// The way an ActiveMethod is started can be changed by passing a StarterType
159 /// template argument with a corresponding class. The default ActiveStarter
160 /// starts the method in its own thread, obtained from a thread pool.
161 ///
162 /// For an alternative implementation of StarterType, see ActiveDispatcher.
163 ///
164 /// For methods that do not require an argument or a return value, simply use void.
165{
166public:
167 typedef ResultType (OwnerType::*Callback)(void);
168 typedef ActiveResult<ResultType> ActiveResultType;
169 typedef ActiveRunnable<ResultType, void, OwnerType> ActiveRunnableType;
170
171 ActiveMethod(OwnerType* pOwner, Callback method):
172 _pOwner(pOwner),
173 _method(method)
174 /// Creates an ActiveMethod object.
175 {
176 poco_check_ptr (pOwner);
177 }
178
179 ActiveResultType operator () (void)
180 /// Invokes the ActiveMethod.
181 {
182 ActiveResultType result(new ActiveResultHolder<ResultType>());
183 ActiveRunnableBase::Ptr pRunnable(new ActiveRunnableType(_pOwner, _method, result));
184 StarterType::start(_pOwner, pRunnable);
185 return result;
186 }
187
188 ActiveMethod(const ActiveMethod& other):
189 _pOwner(other._pOwner),
190 _method(other._method)
191 {
192 }
193
194 ActiveMethod& operator = (const ActiveMethod& other)
195 {
196 ActiveMethod tmp(other);
197 swap(tmp);
198 return *this;
199 }
200
201 void swap(ActiveMethod& other)
202 {
203 std::swap(_pOwner, other._pOwner);
204 std::swap(_method, other._method);
205 }
206
207private:
208 ActiveMethod();
209
210 OwnerType* _pOwner;
211 Callback _method;
212};
213
214
215} // namespace Poco
216
217
218#endif // Foundation_ActiveMethod_INCLUDED
219