pool.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #pragma once
  2. #include <iostream>
  3. #include <mutex>
  4. #include <memory>
  5. #include "base/error.h"
  6. #include "base/exception.h"
  7. #include "util/queue.hpp"
  8. namespace ylib {
  9. class example_core{
  10. public:
  11. virtual void recover() = 0;
  12. virtual void task_out() = 0;
  13. };
  14. class poolcore:public ylib::error_base
  15. {
  16. public:
  17. void recover(void* example)
  18. {
  19. if(example == NULL)
  20. return;
  21. ((ylib::example_core*)example)->recover();
  22. std::unique_lock<std::mutex> sp(m_mutex);
  23. m_pop_size--;
  24. m_queue.push(example);
  25. }
  26. public:
  27. void* env = nullptr;
  28. protected:
  29. ylib::queue<void*> m_queue;
  30. std::mutex m_mutex;
  31. bool m_closing;
  32. size_t m_max_size;
  33. size_t m_pop_size;
  34. };
  35. enum EXAMPLE_START_RESULT
  36. {
  37. SR_SUCCESS,
  38. SR_TIMEOUT,
  39. SR_FAILED,
  40. };
  41. template<typename INFO>
  42. class example:public example_core
  43. {
  44. public:
  45. public:
  46. example()
  47. {
  48. m_pool = nullptr;
  49. }
  50. virtual EXAMPLE_START_RESULT start(const INFO& info) = 0;
  51. virtual void close() = 0;
  52. inline void pool(poolcore *pool)
  53. {
  54. m_pool = pool;
  55. }
  56. inline poolcore *pool()
  57. {
  58. return m_pool;
  59. }
  60. protected:
  61. poolcore *m_pool;
  62. };
  63. template<typename EXAMPLE>
  64. //自动连接释放器
  65. class conn_autofree
  66. {
  67. public:
  68. conn_autofree(EXAMPLE* conn){
  69. m_conn = conn;
  70. }
  71. ~conn_autofree(){
  72. if (m_conn != nullptr)
  73. {
  74. m_conn->pool()->recover(m_conn);
  75. }
  76. }
  77. EXAMPLE* operator->() {
  78. if (m_conn == nullptr)
  79. {
  80. throw ylib::exception("The connection is nullptr and an exception is thrown");
  81. }
  82. return m_conn;
  83. }
  84. EXAMPLE* get(){
  85. if(m_conn == nullptr){
  86. throw ylib::exception("conn is nullptr");
  87. }
  88. return m_conn;
  89. }
  90. private:
  91. EXAMPLE* m_conn;
  92. };
  93. template<typename EXAMPLE,typename INFO>
  94. class pool :public poolcore
  95. {
  96. public:
  97. pool()
  98. {
  99. m_max_size = 0;
  100. m_pop_size = 0;
  101. m_closing = false;
  102. }
  103. ~pool()
  104. {
  105. close();
  106. }
  107. bool start(const INFO& info,size_t size)
  108. {
  109. m_closing = false;
  110. m_info = info;
  111. m_max_size = size;
  112. return true;
  113. }
  114. void close()
  115. {
  116. std::unique_lock<std::mutex> sp(m_mutex);
  117. m_closing = true;
  118. for (size_t i = 0; i < m_queue.size(); i++)
  119. {
  120. void* example = NULL;
  121. if (m_queue.pop(example) == false)
  122. break;
  123. EXAMPLE*f = ((EXAMPLE*)example);
  124. ((EXAMPLE*)example)->pool(nullptr);
  125. delete ((EXAMPLE*)example);
  126. }
  127. }
  128. void* get_ptr() { return (void*)get(); }
  129. EXAMPLE* get()
  130. {
  131. std::unique_lock<std::mutex> sp(m_mutex);
  132. if (m_closing)
  133. {
  134. throw ylib::exception("pool is shutting down");
  135. }
  136. void* example = nullptr;
  137. if (m_queue.pop(example) == false)
  138. {
  139. if (m_pop_size < m_max_size)
  140. {
  141. bool init_success = false;
  142. example = new EXAMPLE;
  143. //example->pool((void*)this);
  144. ((EXAMPLE*)example)->pool(this);
  145. for (uint32 i = 0; i < 3; i++)
  146. {
  147. auto SR = ((EXAMPLE*)example)->start(m_info);
  148. if (SR == SR_SUCCESS)
  149. {
  150. init_success = true;
  151. break;
  152. }
  153. else if (SR == SR_TIMEOUT)
  154. {
  155. std::cout << "start failed." << ((EXAMPLE*)example)->last_error().c_str() << std::endl;
  156. std::cout << "restart " << std::to_string(i + 1).c_str() << "." << std::endl;
  157. }
  158. else if (SR == SR_FAILED)
  159. {
  160. break;
  161. }
  162. }
  163. if (init_success)
  164. {
  165. m_pop_size++;
  166. ((EXAMPLE*)example)->task_out();
  167. return ((EXAMPLE*)example);
  168. }
  169. else
  170. {
  171. std::string last_error = ((EXAMPLE*)example)->last_error();
  172. delete ((EXAMPLE*)example);
  173. throw ylib::exception(last_error);
  174. }
  175. }
  176. else
  177. {
  178. throw ylib::exception("maximum capacity exceeded");
  179. }
  180. }
  181. else
  182. {
  183. m_pop_size++;
  184. ((EXAMPLE*)example)->pool(this);
  185. ((EXAMPLE*)example)->task_out();
  186. return ((EXAMPLE*)example);
  187. }
  188. }
  189. size_t size()
  190. {
  191. return m_max_size-m_pop_size;
  192. }
  193. public:
  194. INFO m_info;
  195. };
  196. }