pool.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (c) 2014, Peter Thorson. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the WebSocket++ Project nor the
  12. * names of its contributors may be used to endorse or promote products
  13. * derived from this software without specific prior written permission.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. *
  26. */
  27. #ifndef WEBSOCKETPP_MESSAGE_BUFFER_ALLOC_HPP
  28. #define WEBSOCKETPP_MESSAGE_BUFFER_ALLOC_HPP
  29. #include <websocketpp/common/memory.hpp>
  30. #include <string>
  31. namespace websocketpp {
  32. namespace message_buffer {
  33. /* # message:
  34. * object that stores a message while it is being sent or received. Contains
  35. * the message payload itself, the message header, the extension data, and the
  36. * opcode.
  37. *
  38. * # connection_message_manager:
  39. * An object that manages all of the message_buffers associated with a given
  40. * connection. Implements the get_message_buffer(size) method that returns
  41. * a message buffer at least size bytes long.
  42. *
  43. * Message buffers are reference counted with shared ownership semantics. Once
  44. * requested from the manager the requester and it's associated downstream code
  45. * may keep a pointer to the message indefinitely at a cost of extra resource
  46. * usage. Once the reference count drops to the point where the manager is the
  47. * only reference the messages is recycled using whatever method is implemented
  48. * in the manager.
  49. *
  50. * # endpoint_message_manager:
  51. * An object that manages connection_message_managers. Implements the
  52. * get_message_manager() method. This is used once by each connection to
  53. * request the message manager that they are supposed to use to manage message
  54. * buffers for their own use.
  55. *
  56. * TYPES OF CONNECTION_MESSAGE_MANAGERS
  57. * - allocate a message with the exact size every time one is requested
  58. * - maintain a pool of pre-allocated messages and return one when needed.
  59. * Recycle previously used messages back into the pool
  60. *
  61. * TYPES OF ENDPOINT_MESSAGE_MANAGERS
  62. * - allocate a new connection manager for each connection. Message pools
  63. * become connection specific. This increases memory usage but improves
  64. * concurrency.
  65. * - allocate a single connection manager and share a pointer to it with all
  66. * connections created by this endpoint. The message pool will be shared
  67. * among all connections, improving memory usage and performance at the cost
  68. * of reduced concurrency
  69. */
  70. /// Custom deleter for use in shared_ptrs to message.
  71. /**
  72. * This is used to catch messages about to be deleted and offer the manager the
  73. * ability to recycle them instead. Message::recycle will return true if it was
  74. * successfully recycled and false otherwise. In the case of exceptions or error
  75. * this deleter frees the memory.
  76. */
  77. template <typename T>
  78. void message_deleter(T* msg) {
  79. try {
  80. if (!msg->recycle()) {
  81. delete msg;
  82. }
  83. } catch (...) {
  84. // TODO: is there a better way to ensure this function doesn't throw?
  85. delete msg;
  86. }
  87. }
  88. /// Represents a buffer for a single WebSocket message.
  89. /**
  90. *
  91. *
  92. */
  93. template <typename con_msg_manager>
  94. class message {
  95. public:
  96. typedef lib::shared_ptr<message> ptr;
  97. typedef typename con_msg_manager::weak_ptr con_msg_man_ptr;
  98. message(con_msg_man_ptr manager, size_t size = 128)
  99. : m_manager(manager)
  100. , m_payload(size) {}
  101. frame::opcode::value get_opcode() const {
  102. return m_opcode;
  103. }
  104. const std::string& get_header() const {
  105. return m_header;
  106. }
  107. const std::string& get_extension_data() const {
  108. return m_extension_data;
  109. }
  110. const std::string& get_payload() const {
  111. return m_payload;
  112. }
  113. /// Recycle the message
  114. /**
  115. * A request to recycle this message was received. Forward that request to
  116. * the connection message manager for processing. Errors and exceptions
  117. * from the manager's recycle member function should be passed back up the
  118. * call chain. The caller to message::recycle will deal with them.
  119. *
  120. * Recycle must *only* be called by the message shared_ptr's destructor.
  121. * Once recycled successfully, ownership of the memory has been passed to
  122. * another system and must not be accessed again.
  123. *
  124. * @return true if the message was successfully recycled, false otherwise.
  125. */
  126. bool recycle() {
  127. typename con_msg_manager::ptr shared = m_manager.lock();
  128. if (shared) {
  129. return shared->(recycle(this));
  130. } else {
  131. return false;
  132. }
  133. }
  134. private:
  135. con_msg_man_ptr m_manager;
  136. frame::opcode::value m_opcode;
  137. std::string m_header;
  138. std::string m_extension_data;
  139. std::string m_payload;
  140. };
  141. namespace alloc {
  142. /// A connection message manager that allocates a new message for each
  143. /// request.
  144. template <typename message>
  145. class con_msg_manager {
  146. public:
  147. typedef lib::shared_ptr<con_msg_manager> ptr;
  148. typedef lib::weak_ptr<con_msg_manager> weak_ptr;
  149. typedef typename message::ptr message_ptr;
  150. /// Get a message buffer with specified size
  151. /**
  152. * @param size Minimum size in bytes to request for the message payload.
  153. *
  154. * @return A shared pointer to a new message with specified size.
  155. */
  156. message_ptr get_message(size_t size) const {
  157. return lib::make_shared<message>(size);
  158. }
  159. /// Recycle a message
  160. /**
  161. * This method shouldn't be called. If it is, return false to indicate an
  162. * error. The rest of the method recycle chain should notice this and free
  163. * the memory.
  164. *
  165. * @param msg The message to be recycled.
  166. *
  167. * @return true if the message was successfully recycled, false otherwse.
  168. */
  169. bool recycle(message * msg) {
  170. return false;
  171. }
  172. };
  173. /// An endpoint message manager that allocates a new manager for each
  174. /// connection.
  175. template <typename con_msg_manager>
  176. class endpoint_msg_manager {
  177. public:
  178. typedef typename con_msg_manager::ptr con_msg_man_ptr;
  179. /// Get a pointer to a connection message manager
  180. /**
  181. * @return A pointer to the requested connection message manager.
  182. */
  183. con_msg_man_ptr get_manager() const {
  184. return lib::make_shared<con_msg_manager>();
  185. }
  186. };
  187. } // namespace alloc
  188. namespace pool {
  189. /// A connection messages manager that maintains a pool of messages that is
  190. /// used to fulfill get_message requests.
  191. class con_msg_manager {
  192. };
  193. /// An endpoint manager that maintains a shared pool of connection managers
  194. /// and returns an appropriate one for the requesting connection.
  195. class endpoint_msg_manager {
  196. };
  197. } // namespace pool
  198. } // namespace message_buffer
  199. } // namespace websocketpp
  200. #endif // WEBSOCKETPP_MESSAGE_BUFFER_ALLOC_HPP