llpumpio.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /**
  2. * @file llpumpio.h
  3. * @author Phoenix
  4. * @date 2004-11-19
  5. * @brief Declaration of pump class which manages io chains.
  6. *
  7. * $LicenseInfo:firstyear=2004&license=viewergpl$
  8. *
  9. * Copyright (c) 2004-2009, Linden Research, Inc.
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #ifndef LL_LLPUMPIO_H
  35. #define LL_LLPUMPIO_H
  36. #include <list>
  37. #include <vector>
  38. #if LL_LINUX
  39. # include <sys/param.h> // For PATH_MAX in APR.
  40. #endif
  41. #include "apr_pools.h"
  42. #include "llbuffer.h"
  43. #include "llframetimer.h"
  44. #include "lliopipe.h"
  45. // The respond() feature is not used in the viewer. HB
  46. #define LL_PUMPIO_RESPOND 0
  47. // LLPumpIO is a class to manage sets of I/O chains.
  48. // The pump class provides a thread abstraction for doing I/O based
  49. // communication between two threads in a structured way and optimized for
  50. // processor time. The primary usage is to create a pump, and call pump() on a
  51. // thread used for I/O and call respond() on a thread that is expected to do
  52. // higher level processing. You can call almost any other method from any
  53. // thread (see notes for each method for details). The LLPumpIO instance (there
  54. // is only one in the viewer) uses gAPRPoolp as the APR pool for locking.
  55. // A pump instance manages much of the state for the pipe, including the list
  56. // of pipes in the chain, the channel for each element in the chain, the
  57. // buffer, and if any pipe has marked the stream or process as done. Pipes can
  58. // also set file descriptor based conditional statements so that calls to
  59. // process do not happen until data is ready to be read or written. Pipes
  60. // control execution of calls to process by returning a status code such as
  61. // STATUS_OK or STATUS_BREAK. One way to conceptualize the way IO will work is
  62. // that a pump combines the unit processing of pipes to behave like file pipes
  63. // on the UNIX command line.
  64. class LLPumpIO
  65. {
  66. protected:
  67. LOG_CLASS(LLPumpIO);
  68. public:
  69. LLPumpIO();
  70. ~LLPumpIO();
  71. // Typedef for having a chain of pipes.
  72. typedef std::vector<LLIOPipe::ptr_t> chain_t;
  73. // Adds a chain to this pump and process in the next cycle. This method
  74. // will automatically generate a buffer and assign each link in the chain
  75. // as if it were the consumer to the previous. 'chain' is the pipes for the
  76. // chain and 'timeout' the number of seconds in the future to expire (0.f
  77. // to never expire). Returns true if anything was added to the pump.
  78. bool addChain(const chain_t& chain, F32 timeout);
  79. // Structure to associate a pipe with it's buffer io indexes.
  80. struct LLLinkInfo
  81. {
  82. LLIOPipe::ptr_t mPipe;
  83. LLChannelDescriptors mChannels;
  84. };
  85. // Typedef for having a chain of LLLinkInfo instances.
  86. typedef std::vector<LLLinkInfo> links_t;
  87. // Adds a chain to this pump and process in the next cycle. This method
  88. // provides a slightly more sophisticated method for adding a chain where
  89. // the caller can specify which link elements are on what channels. It will
  90. // fail if no buffer is provided since any call to generate new channels
  91. // for the buffers will cause unpredictable interleaving of data. 'links'
  92. // are the pipes and io indexes for the chain, 'datap' is a shared pointer
  93. // to the data buffer, 'context' (potentially undefined) context meta-data
  94. // for the chain and 'timeout' is the number of seconds in the future to
  95. // expire (0.f to never expire). Returns true if anything was added to the
  96. // pump.
  97. bool addChain(const links_t& links, LLIOPipe::buffer_ptr_t datap,
  98. LLSD context, F32 timeout);
  99. // Sets or clears a timeout for the running chain with 'timeout' the number
  100. // of seconds in the future to expire (0.f to never expire). Returns true
  101. // if the timer was set.
  102. bool setTimeoutSeconds(F32 timeout);
  103. // Adjusts the timeout of the running chain. This has no effect if there is
  104. // no timeout on the chain. 'delta' is the number of seconds to add to or
  105. // remove from the timeout.
  106. void adjustTimeoutSeconds(F32 delta);
  107. // Sets up file descriptors for for the running chain (also see
  108. // rebuildPollset()). There is currently a limit of one conditional per
  109. // pipe. 'pipep' is the pipe which is setting a conditional and 'pollp'
  110. // the entire socket and read/write condition (NULL to remove). Returns
  111. // true if the poll state was set.
  112. // NOTE: the internal mechanism for building a pollset based on pipe/
  113. // pollfd/chain generates an epoll error on Linux (and probably behaves
  114. // similarly on other platforms) because the pollset rebuilder will add
  115. // each apr_pollfd_t serially. This does not matter for pipes on the same
  116. // chain, since any signalled pipe will eventually invoke a call to
  117. // process(), but is a problem if the same apr_pollfd_t is on different
  118. // chains. Once we have more than just network i/o on the pump, this might
  119. // matter.
  120. // FIXME: Given the structure of the pump and pipe relationship, this
  121. // should probably go through a different mechanism than the pump. It might
  122. // be best if the pipe had some kind of controller which was passed into
  123. // process() rather than the pump which exposed thisinterface.
  124. bool setConditional(LLIOPipe* pipep, const apr_pollfd_t* pollp);
  125. // Invoke this method to call process on all running chains; it iterates
  126. // through the running chains, and if all pipe on a chain are
  127. // unconditionally ready or if any pipe has any conditional processiong
  128. // condition then process will be called on every chain which has requested
  129. // processing. That chain has a file descriptor ready, process() will be
  130. // called for all pipes which have requested it.
  131. void pump(S32 poll_timeout);
  132. // Calls the above method with the default timeout, then calls callback(),
  133. // when LL_PUMPIO_RESPOND is non zero. HB
  134. void pump();
  135. #if LL_PUMPIO_RESPOND
  136. // Adds pipe to a special queue which will be called during the next call
  137. // to callback() and then dropped from the queue. This call will add a
  138. // single pipe, with no buffer, context, or channel information to the
  139. // callback queue. It will be called once, and then dropped. 'pipe p is a
  140. // single I/O pipe which will be called. Returns true if anything was added
  141. // to the pump.
  142. bool respond(LLIOPipe* pipep);
  143. // Adds a chain to a special queue which will be called during the next
  144. // call to callback() and then dropped from the queue. It is important to
  145. // remember that you should not add a data buffer or context which may
  146. // still be in another chain (that will almost certainly lead to problems).
  147. // Ensure that you are done reading and writing to those parameters, have
  148. // new generated, or empty pointers. 'links' are the pipes and I/O indexes
  149. // for the chain, 'datap' is a shared pointer to the data buffer, and
  150. // 'context' (potentially undefined) is the context meta-data for chain.
  151. // Returns true if anything was added to the pump.
  152. bool respond(const links_t& links, LLIOPipe::buffer_ptr_t datap,
  153. LLSD context);
  154. // Runs through the callback queue and calls process(). This will process
  155. // all prending responses and call process on each, and will then drop all
  156. // processed callback requests (which may lead to deleting the referenced
  157. // objects).
  158. void callback();
  159. #endif
  160. // This structure is the stuff we track while running chains.
  161. struct LLChainInfo
  162. {
  163. LLChainInfo();
  164. void setTimeoutSeconds(F32 timeout);
  165. void adjustTimeoutSeconds(F32 delta);
  166. // Basic member data
  167. links_t::iterator mHead;
  168. links_t mChainLinks;
  169. LLIOPipe::buffer_ptr_t mData;
  170. LLFrameTimer mTimer;
  171. LLSD mContext;
  172. bool mInit;
  173. bool mEOS;
  174. // Tracking inside the pump
  175. typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
  176. typedef std::vector<pipe_conditional_t> conditionals_t;
  177. conditionals_t mDescriptors;
  178. };
  179. typedef std::list<LLChainInfo> running_chains_t;
  180. typedef running_chains_t::iterator current_chain_t;
  181. current_chain_t removeRunningChain(current_chain_t& chain);
  182. // Given the internal state of the chains, rebuilds the pollset. Also see
  183. // setConditional().
  184. void rebuildPollset();
  185. // Processes the chain passed in. This will potentially modify the
  186. // internals of the chain. On end, the chain.mHead will equal
  187. // chain.mChainLinks.end().
  188. void processChain(LLChainInfo& chain);
  189. // Rewinds through the chain to try to recover from an error. This will
  190. // potentially modify the internals of the chain. Retuns true if someone
  191. // handled the error.
  192. bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error);
  193. protected:
  194. apr_pollset_t* mPollset;
  195. // Memory allocator for pollsets & mutexes.
  196. apr_pool_t* mCurrentPool;
  197. S32 mCurrentPoolReallocCount;
  198. // All the running chains & info
  199. typedef std::vector<LLChainInfo> pending_chains_t;
  200. pending_chains_t mPendingChains;
  201. running_chains_t mRunningChains;
  202. current_chain_t mCurrentChain;
  203. #if LL_PUMPIO_RESPOND
  204. // Structures necessary for doing callbacks. Since the callbacks only get
  205. // one chance to run, we do not have to maintain a list.
  206. typedef std::vector<LLChainInfo> callbacks_t;
  207. callbacks_t mPendingCallbacks;
  208. callbacks_t mCallbacks;
  209. #endif
  210. S32 mPollsetClientID;
  211. bool mRebuildPollset;
  212. };
  213. #endif // LL_LLPUMPIO_H