ActiveResult.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. //
  2. // ActiveResult.h
  3. //
  4. // Library: Foundation
  5. // Package: Threading
  6. // Module: ActiveObjects
  7. //
  8. // Definition of the ActiveResult 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. #ifndef Foundation_ActiveResult_INCLUDED
  16. #define Foundation_ActiveResult_INCLUDED
  17. #include "Poco/Foundation.h"
  18. #include "Poco/Mutex.h"
  19. #include "Poco/Event.h"
  20. #include "Poco/RefCountedObject.h"
  21. #include "Poco/Exception.h"
  22. #include <algorithm>
  23. namespace Poco {
  24. template <class ResultType>
  25. class ActiveResultHolder: public RefCountedObject
  26. /// This class holds the result of an asynchronous method
  27. /// invocation. It is used to pass the result from the
  28. /// execution thread back to the invocation thread.
  29. /// The class uses reference counting for memory management.
  30. /// Do not use this class directly, use ActiveResult instead.
  31. {
  32. public:
  33. ActiveResultHolder():
  34. _pData(0),
  35. _pExc(0),
  36. _event(false)
  37. /// Creates an ActiveResultHolder.
  38. {
  39. }
  40. ResultType& data()
  41. /// Returns a reference to the actual result.
  42. {
  43. poco_check_ptr(_pData);
  44. return *_pData;
  45. }
  46. void data(ResultType* pData)
  47. {
  48. delete _pData;
  49. _pData = pData;
  50. }
  51. void wait()
  52. /// Pauses the caller until the result becomes available.
  53. {
  54. _event.wait();
  55. }
  56. bool tryWait(long milliseconds)
  57. /// Waits up to the specified interval for the result to
  58. /// become available. Returns true if the result became
  59. /// available, false otherwise.
  60. {
  61. return _event.tryWait(milliseconds);
  62. }
  63. void wait(long milliseconds)
  64. /// Waits up to the specified interval for the result to
  65. /// become available. Throws a TimeoutException if the
  66. /// result did not became available.
  67. {
  68. _event.wait(milliseconds);
  69. }
  70. void notify()
  71. /// Notifies the invoking thread that the result became available.
  72. {
  73. _event.set();
  74. }
  75. bool failed() const
  76. /// Returns true if the active method failed (and threw an exception).
  77. /// Information about the exception can be obtained by calling error().
  78. {
  79. return _pExc != 0;
  80. }
  81. std::string error() const
  82. /// If the active method threw an exception, a textual representation
  83. /// of the exception is returned. An empty string is returned if the
  84. /// active method completed successfully.
  85. {
  86. if (_pExc)
  87. return _pExc->message();
  88. else
  89. return std::string();
  90. }
  91. Exception* exception() const
  92. /// If the active method threw an exception, a clone of the exception
  93. /// object is returned, otherwise null.
  94. {
  95. return _pExc;
  96. }
  97. void error(const Exception& exc)
  98. /// Sets the exception.
  99. {
  100. delete _pExc;
  101. _pExc = exc.clone();
  102. }
  103. void error(const std::string& msg)
  104. /// Sets the exception.
  105. {
  106. delete _pExc;
  107. _pExc = new UnhandledException(msg);
  108. }
  109. protected:
  110. ~ActiveResultHolder()
  111. {
  112. delete _pData;
  113. delete _pExc;
  114. }
  115. private:
  116. ResultType* _pData;
  117. Exception* _pExc;
  118. Event _event;
  119. };
  120. template <>
  121. class ActiveResultHolder<void>: public RefCountedObject
  122. {
  123. public:
  124. ActiveResultHolder():
  125. _pExc(0),
  126. _event(false)
  127. /// Creates an ActiveResultHolder.
  128. {
  129. }
  130. void wait()
  131. /// Pauses the caller until the result becomes available.
  132. {
  133. _event.wait();
  134. }
  135. bool tryWait(long milliseconds)
  136. /// Waits up to the specified interval for the result to
  137. /// become available. Returns true if the result became
  138. /// available, false otherwise.
  139. {
  140. return _event.tryWait(milliseconds);
  141. }
  142. void wait(long milliseconds)
  143. /// Waits up to the specified interval for the result to
  144. /// become available. Throws a TimeoutException if the
  145. /// result did not became available.
  146. {
  147. _event.wait(milliseconds);
  148. }
  149. void notify()
  150. /// Notifies the invoking thread that the result became available.
  151. {
  152. _event.set();
  153. }
  154. bool failed() const
  155. /// Returns true if the active method failed (and threw an exception).
  156. /// Information about the exception can be obtained by calling error().
  157. {
  158. return _pExc != 0;
  159. }
  160. std::string error() const
  161. /// If the active method threw an exception, a textual representation
  162. /// of the exception is returned. An empty string is returned if the
  163. /// active method completed successfully.
  164. {
  165. if (_pExc)
  166. return _pExc->message();
  167. else
  168. return std::string();
  169. }
  170. Exception* exception() const
  171. /// If the active method threw an exception, a clone of the exception
  172. /// object is returned, otherwise null.
  173. {
  174. return _pExc;
  175. }
  176. void error(const Exception& exc)
  177. /// Sets the exception.
  178. {
  179. delete _pExc;
  180. _pExc = exc.clone();
  181. }
  182. void error(const std::string& msg)
  183. /// Sets the exception.
  184. {
  185. delete _pExc;
  186. _pExc = new UnhandledException(msg);
  187. }
  188. protected:
  189. ~ActiveResultHolder()
  190. {
  191. delete _pExc;
  192. }
  193. private:
  194. Exception* _pExc;
  195. Event _event;
  196. };
  197. template <class RT>
  198. class ActiveResult
  199. /// This class holds the result of an asynchronous method
  200. /// invocation (see class ActiveMethod). It is used to pass the
  201. /// result from the execution thread back to the invocation thread.
  202. {
  203. public:
  204. typedef RT ResultType;
  205. typedef ActiveResultHolder<ResultType> ActiveResultHolderType;
  206. ActiveResult(ActiveResultHolderType* pHolder):
  207. _pHolder(pHolder)
  208. /// Creates the active result. For internal use only.
  209. {
  210. poco_check_ptr (pHolder);
  211. }
  212. ActiveResult(const ActiveResult& result)
  213. /// Copy constructor.
  214. {
  215. _pHolder = result._pHolder;
  216. _pHolder->duplicate();
  217. }
  218. ~ActiveResult()
  219. /// Destroys the result.
  220. {
  221. _pHolder->release();
  222. }
  223. ActiveResult& operator = (const ActiveResult& result)
  224. /// Assignment operator.
  225. {
  226. ActiveResult tmp(result);
  227. swap(tmp);
  228. return *this;
  229. }
  230. void swap(ActiveResult& result)
  231. {
  232. using std::swap;
  233. swap(_pHolder, result._pHolder);
  234. }
  235. ResultType& data() const
  236. /// Returns a reference to the result data.
  237. {
  238. return _pHolder->data();
  239. }
  240. void data(ResultType* pValue)
  241. {
  242. _pHolder->data(pValue);
  243. }
  244. void wait()
  245. /// Pauses the caller until the result becomes available.
  246. {
  247. _pHolder->wait();
  248. }
  249. bool tryWait(long milliseconds)
  250. /// Waits up to the specified interval for the result to
  251. /// become available. Returns true if the result became
  252. /// available, false otherwise.
  253. {
  254. return _pHolder->tryWait(milliseconds);
  255. }
  256. void wait(long milliseconds)
  257. /// Waits up to the specified interval for the result to
  258. /// become available. Throws a TimeoutException if the
  259. /// result did not became available.
  260. {
  261. _pHolder->wait(milliseconds);
  262. }
  263. bool available() const
  264. /// Returns true if a result is available.
  265. {
  266. return _pHolder->tryWait(0);
  267. }
  268. bool failed() const
  269. /// Returns true if the active method failed (and threw an exception).
  270. /// Information about the exception can be obtained by calling error().
  271. {
  272. return _pHolder->failed();
  273. }
  274. std::string error() const
  275. /// If the active method threw an exception, a textual representation
  276. /// of the exception is returned. An empty string is returned if the
  277. /// active method completed successfully.
  278. {
  279. return _pHolder->error();
  280. }
  281. Exception* exception() const
  282. /// If the active method threw an exception, a clone of the exception
  283. /// object is returned, otherwise null.
  284. {
  285. return _pHolder->exception();
  286. }
  287. void notify()
  288. /// Notifies the invoking thread that the result became available.
  289. /// For internal use only.
  290. {
  291. _pHolder->notify();
  292. }
  293. ResultType& data()
  294. /// Returns a non-const reference to the result data. For internal
  295. /// use only.
  296. {
  297. return _pHolder->data();
  298. }
  299. void error(const std::string& msg)
  300. /// Sets the failed flag and the exception message.
  301. {
  302. _pHolder->error(msg);
  303. }
  304. void error(const Exception& exc)
  305. /// Sets the failed flag and the exception message.
  306. {
  307. _pHolder->error(exc);
  308. }
  309. private:
  310. ActiveResult();
  311. ActiveResultHolderType* _pHolder;
  312. };
  313. template <>
  314. class ActiveResult<void>
  315. /// This class holds the result of an asynchronous method
  316. /// invocation (see class ActiveMethod). It is used to pass the
  317. /// result from the execution thread back to the invocation thread.
  318. {
  319. public:
  320. typedef ActiveResultHolder<void> ActiveResultHolderType;
  321. ActiveResult(ActiveResultHolderType* pHolder):
  322. _pHolder(pHolder)
  323. /// Creates the active result. For internal use only.
  324. {
  325. poco_check_ptr (pHolder);
  326. }
  327. ActiveResult(const ActiveResult& result)
  328. /// Copy constructor.
  329. {
  330. _pHolder = result._pHolder;
  331. _pHolder->duplicate();
  332. }
  333. ~ActiveResult()
  334. /// Destroys the result.
  335. {
  336. _pHolder->release();
  337. }
  338. ActiveResult& operator = (const ActiveResult& result)
  339. /// Assignment operator.
  340. {
  341. ActiveResult tmp(result);
  342. swap(tmp);
  343. return *this;
  344. }
  345. void swap(ActiveResult& result)
  346. {
  347. using std::swap;
  348. swap(_pHolder, result._pHolder);
  349. }
  350. void wait()
  351. /// Pauses the caller until the result becomes available.
  352. {
  353. _pHolder->wait();
  354. }
  355. bool tryWait(long milliseconds)
  356. /// Waits up to the specified interval for the result to
  357. /// become available. Returns true if the result became
  358. /// available, false otherwise.
  359. {
  360. return _pHolder->tryWait(milliseconds);
  361. }
  362. void wait(long milliseconds)
  363. /// Waits up to the specified interval for the result to
  364. /// become available. Throws a TimeoutException if the
  365. /// result did not became available.
  366. {
  367. _pHolder->wait(milliseconds);
  368. }
  369. bool available() const
  370. /// Returns true if a result is available.
  371. {
  372. return _pHolder->tryWait(0);
  373. }
  374. bool failed() const
  375. /// Returns true if the active method failed (and threw an exception).
  376. /// Information about the exception can be obtained by calling error().
  377. {
  378. return _pHolder->failed();
  379. }
  380. std::string error() const
  381. /// If the active method threw an exception, a textual representation
  382. /// of the exception is returned. An empty string is returned if the
  383. /// active method completed successfully.
  384. {
  385. return _pHolder->error();
  386. }
  387. Exception* exception() const
  388. /// If the active method threw an exception, a clone of the exception
  389. /// object is returned, otherwise null.
  390. {
  391. return _pHolder->exception();
  392. }
  393. void notify()
  394. /// Notifies the invoking thread that the result became available.
  395. /// For internal use only.
  396. {
  397. _pHolder->notify();
  398. }
  399. void error(const std::string& msg)
  400. /// Sets the failed flag and the exception message.
  401. {
  402. _pHolder->error(msg);
  403. }
  404. void error(const Exception& exc)
  405. /// Sets the failed flag and the exception message.
  406. {
  407. _pHolder->error(exc);
  408. }
  409. private:
  410. ActiveResult();
  411. ActiveResultHolderType* _pHolder;
  412. };
  413. } // namespace Poco
  414. #endif // Foundation_ActiveResult_INCLUDED