RemoteProcedure.h
1 /*
2  * Copyright (C) 2009-2014 by Dr. Marc Boris Duerner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #ifndef Pt_Remoting_RemoteProcedure_h
30 #define Pt_Remoting_RemoteProcedure_h
31 
32 #include <Pt/Remoting/Api.h>
33 #include <Pt/Remoting/Client.h>
34 #include <Pt/SerializationContext.h>
35 #include <Pt/NonCopyable.h>
36 #include <Pt/Signal.h>
37 #include <Pt/String.h>
38 #include <string>
39 
40 namespace Pt {
41 
42 namespace Remoting {
43 
46 class PT_REMOTING_API RemoteCall : private Pt::NonCopyable
47 {
48  public:
49  RemoteCall(Client& client, const String& name);
50 
51  RemoteCall(Client& client, const std::string& name);
52 
53  RemoteCall(Client& client, const char* name);
54 
55  virtual ~RemoteCall();
56 
57  Client& client()
58  { return *_client; }
59 
60  const String& name() const
61  { return _name; }
62 
63  bool isFailed() const
64  { return _client->isFailed(); }
65 
66  void cancel();
67 
68  void setReady();
69 
70  void endCall();
71 
72  protected:
73  virtual void onReady() = 0;
74 
75  virtual void onReset() = 0;
76 
77  virtual void onClear() = 0;
78 
79  private:
80  Client* _client;
81  String _name;
82 };
83 
86 template <typename R>
87 class Result : private Pt::NonCopyable
88 {
89  public:
92  explicit Result(RemoteCall* call = 0)
93  : _call(call)
94  , _result(0)
95  {
96  _result = new (_mem) R;
97  }
98 
99  ~Result()
100  {
101  _result->~R();
102  }
103 
104  void init(RemoteCall* call)
105  { _call = call; }
106 
111  bool isFailed() const
112  {
113  return _call->isFailed();
114  }
115 
118  R& value()
119  { return *_result; }
120 
128  const R& get() const
129  {
130  _call->endCall();
131  return *_result;
132  }
133 
134  void clear()
135  {
136  _result->~R();
137  _result = new (_mem) R;
138  }
139 
140  private:
141  RemoteCall* _call;
142  char _mem[ sizeof(R) ];
143  R* _result;
144 };
145 
148 template <typename R>
149 class RemoteProcedureBase : public RemoteCall
150 {
151  public:
152  RemoteProcedureBase(Client& client, const std::string& name)
153  : RemoteCall(client, name)
154  , _result(0)
155  , _r(0)
156  {
157  _result.init(this);
158  }
159 
160  ~RemoteProcedureBase()
161  {
162  if(_r)
163  _r->~BasicComposer<R>();
164  }
165 
166  Result<R>& result()
167  {
168  return _result;
169  }
170 
171  const Result<R>& result() const
172  {
173  return _result;
174  }
175 
176  Signal< const Result<R>& >& finished()
177  { return _finished; }
178 
179  protected:
180  void onReady()
181  { _finished.send(_result); }
182 
183  BasicComposer<R>& beginResult()
184  {
185  if(_r)
186  {
187  _r->~BasicComposer<R>();
188  _r = 0;
189  }
190 
191  _r = new (_mem) BasicComposer<R>( &client().context() );
192  _r->begin( result().value() );
193  return *_r;
194  }
195 
196  virtual void onReset()
197  {
198  if(_r)
199  {
200  _r->~BasicComposer<R>();
201  _r = 0;
202  }
203  }
204 
205  virtual void onClear()
206  {
207  this->onReset();
208  _result.clear();
209  }
210 
211  private:
212  Signal< const Result<R>& > _finished;
213  Result<R> _result;
214  char _mem[ sizeof(BasicComposer<R>) ];
215  BasicComposer<R>* _r;
216 };
217 
218 
219 template <typename A>
220 class RemoteArgument : private Pt::NonCopyable
221 {
222  public:
223  RemoteArgument(SerializationContext* )
224  : _decomposer(0)
225  { }
226 
227  ~RemoteArgument()
228  {
229  if(_decomposer)
230  _decomposer->~BasicDecomposer<A>();
231  }
232 
233  void begin(const A& a, const char* name, SerializationContext& ctx)
234  {
235  if(_decomposer)
236  {
237  _decomposer->~BasicDecomposer<A>();
238  _decomposer = 0;
239  }
240 
241  _decomposer = new (_mem) BasicDecomposer<A>(&ctx);
242  _decomposer->begin(a, name);
243  }
244 
245  void clear(SerializationContext* )
246  {
247  if(_decomposer)
248  {
249  _decomposer->~BasicDecomposer<A>();
250  _decomposer = 0;
251  }
252  }
253 
254  // TODO: return decomposer pointer from begin
255  BasicDecomposer<A>* decomposer()
256  { return reinterpret_cast<BasicDecomposer<A>*>(_mem); }
257 
258  private:
259  char _mem[ sizeof(BasicDecomposer<A>) ];
260  BasicDecomposer<A>* _decomposer;
261 };
262 
263 } // namespace Remoting
264 
265 } // namespace Pt
266 
267 #include <Pt/Remoting/RemoteProcedure.tpp>
268 
269 #endif // Pt_Remoting_RemoteProcedure_h
Result(RemoteCall *call=0)
Constructor.
Definition: RemoteProcedure.h:92
Protects derived classes from being copied.
Definition: NonCopyable.h:54
Result of a remote procedure call.
Definition: RemoteProcedure.h:87
bool isFailed() const
Indicates if the procedure has failed.
Definition: RemoteProcedure.h:111
Unicode capable basic_string.
Definition: String.h:42
A client for remote procedure calls.
Definition: Client.h:47
R & value()
The return value.
Definition: RemoteProcedure.h:118