PageRenderTime 30ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/lleventfilter.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 203 lines | 55 code | 21 blank | 127 comment | 0 complexity | 66f3db20b812af1785de6c4618cd5740 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lleventfilter.h
  3. * @author Nat Goodspeed
  4. * @date 2009-03-05
  5. * @brief Define LLEventFilter: LLEventStream subclass with conditions
  6. *
  7. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #if ! defined(LL_LLEVENTFILTER_H)
  29. #define LL_LLEVENTFILTER_H
  30. #include "llevents.h"
  31. #include "stdtypes.h"
  32. #include "lltimer.h"
  33. #include <boost/function.hpp>
  34. /**
  35. * Generic base class
  36. */
  37. class LL_COMMON_API LLEventFilter: public LLEventStream
  38. {
  39. public:
  40. /// construct a standalone LLEventFilter
  41. LLEventFilter(const std::string& name="filter", bool tweak=true):
  42. LLEventStream(name, tweak)
  43. {}
  44. /// construct LLEventFilter and connect it to the specified LLEventPump
  45. LLEventFilter(LLEventPump& source, const std::string& name="filter", bool tweak=true);
  46. /// Post an event to all listeners
  47. virtual bool post(const LLSD& event) = 0;
  48. };
  49. /**
  50. * Pass through only events matching a specified pattern
  51. */
  52. class LLEventMatching: public LLEventFilter
  53. {
  54. public:
  55. /// Pass an LLSD map with keys and values the incoming event must match
  56. LLEventMatching(const LLSD& pattern);
  57. /// instantiate and connect
  58. LLEventMatching(LLEventPump& source, const LLSD& pattern);
  59. /// Only pass through events matching the pattern
  60. virtual bool post(const LLSD& event);
  61. private:
  62. LLSD mPattern;
  63. };
  64. /**
  65. * Wait for an event to be posted. If no such event arrives within a specified
  66. * time, take a specified action. See LLEventTimeout for production
  67. * implementation.
  68. *
  69. * @NOTE This is an abstract base class so that, for testing, we can use an
  70. * alternate "timer" that doesn't actually consume real time.
  71. */
  72. class LL_COMMON_API LLEventTimeoutBase: public LLEventFilter
  73. {
  74. public:
  75. /// construct standalone
  76. LLEventTimeoutBase();
  77. /// construct and connect
  78. LLEventTimeoutBase(LLEventPump& source);
  79. /// Callable, can be constructed with boost::bind()
  80. typedef boost::function<void()> Action;
  81. /**
  82. * Start countdown timer for the specified number of @a seconds. Forward
  83. * all events. If any event arrives before timer expires, cancel timer. If
  84. * no event arrives before timer expires, take specified @a action.
  85. *
  86. * This is a one-shot timer. Once it has either expired or been canceled,
  87. * it is inert until another call to actionAfter().
  88. *
  89. * Calling actionAfter() while an existing timer is running cheaply
  90. * replaces that original timer. Thus, a valid use case is to detect
  91. * idleness of some event source by calling actionAfter() on each new
  92. * event. A rapid sequence of events will keep the timer from expiring;
  93. * the first gap in events longer than the specified timer will fire the
  94. * specified Action.
  95. *
  96. * Any post() call cancels the timer. To be satisfied with only a
  97. * particular event, chain on an LLEventMatching that only passes such
  98. * events:
  99. *
  100. * @code
  101. * event ultimate
  102. * source ---> LLEventMatching ---> LLEventTimeout ---> listener
  103. * @endcode
  104. *
  105. * @NOTE
  106. * The implementation relies on frequent events on the LLEventPump named
  107. * "mainloop".
  108. */
  109. void actionAfter(F32 seconds, const Action& action);
  110. /**
  111. * Like actionAfter(), but where the desired Action is LL_ERRS
  112. * termination. Pass the timeout time and the desired LL_ERRS @a message.
  113. *
  114. * This method is useful when, for instance, some async API guarantees an
  115. * event, whether success or failure, within a stated time window.
  116. * Instantiate an LLEventTimeout listening to that API and call
  117. * errorAfter() on each async request with a timeout comfortably longer
  118. * than the API's time guarantee (much longer than the anticipated
  119. * "mainloop" granularity).
  120. *
  121. * Then if the async API breaks its promise, the program terminates with
  122. * the specified LL_ERRS @a message. The client of the async API can
  123. * therefore assume the guarantee is upheld.
  124. *
  125. * @NOTE
  126. * errorAfter() is implemented in terms of actionAfter(), so all remarks
  127. * about calling actionAfter() also apply to errorAfter().
  128. */
  129. void errorAfter(F32 seconds, const std::string& message);
  130. /**
  131. * Like actionAfter(), but where the desired Action is a particular event
  132. * for all listeners. Pass the timeout time and the desired @a event data.
  133. *
  134. * Suppose the timeout should only be satisfied by a particular event, but
  135. * the ultimate listener must see all other incoming events as well, plus
  136. * the timeout @a event if any:
  137. *
  138. * @code
  139. * some LLEventMatching LLEventMatching
  140. * event ---> for particular ---> LLEventTimeout ---> for timeout
  141. * source event event \
  142. * \ \ ultimate
  143. * `-----------------------------------------------------> listener
  144. * @endcode
  145. *
  146. * Since a given listener can listen on more than one LLEventPump, we can
  147. * set things up so it sees the set union of events from LLEventTimeout
  148. * and the original event source. However, as LLEventTimeout passes
  149. * through all incoming events, the "particular event" that satisfies the
  150. * left LLEventMatching would reach the ultimate listener twice. So we add
  151. * an LLEventMatching that only passes timeout events.
  152. *
  153. * @NOTE
  154. * eventAfter() is implemented in terms of actionAfter(), so all remarks
  155. * about calling actionAfter() also apply to eventAfter().
  156. */
  157. void eventAfter(F32 seconds, const LLSD& event);
  158. /// Pass event through, canceling the countdown timer
  159. virtual bool post(const LLSD& event);
  160. /// Cancel timer without event
  161. void cancel();
  162. protected:
  163. virtual void setCountdown(F32 seconds) = 0;
  164. virtual bool countdownElapsed() const = 0;
  165. private:
  166. bool tick(const LLSD&);
  167. LLBoundListener mMainloop;
  168. Action mAction;
  169. };
  170. /// Production implementation of LLEventTimoutBase
  171. class LL_COMMON_API LLEventTimeout: public LLEventTimeoutBase
  172. {
  173. public:
  174. LLEventTimeout();
  175. LLEventTimeout(LLEventPump& source);
  176. protected:
  177. virtual void setCountdown(F32 seconds);
  178. virtual bool countdownElapsed() const;
  179. private:
  180. LLTimer mTimer;
  181. };
  182. #endif /* ! defined(LL_LLEVENTFILTER_H) */