pool.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #pragma once
  2. #include <iostream>
  3. #include <mutex>
  4. #include <memory>
  5. #include "ybase/error.h"
  6. #include "ybase/exception.h"
  7. #include "yutil/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_TIMEOUT,
  38. SR_FAILED,
  39. SR_SUCCESS
  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. EXAMPLE* get()
  129. {
  130. std::unique_lock<std::mutex> sp(m_mutex);
  131. if (m_closing)
  132. {
  133. throw ylib::exception("pool is shutting down");
  134. }
  135. void* example = nullptr;
  136. if (m_queue.pop(example) == false)
  137. {
  138. if (m_pop_size < m_max_size)
  139. {
  140. bool init_success = false;
  141. example = new EXAMPLE;
  142. //example->pool((void*)this);
  143. ((EXAMPLE*)example)->pool(this);
  144. for (uint32 i = 0; i < 3; i++)
  145. {
  146. auto SR = ((EXAMPLE*)example)->start(m_info);
  147. if (SR == SR_SUCCESS)
  148. {
  149. init_success = true;
  150. break;
  151. }
  152. else if (SR == SR_TIMEOUT)
  153. {
  154. std::cout << "start failed." << ((EXAMPLE*)example)->last_error().c_str() << std::endl;
  155. std::cout << "restart " << std::to_string(i + 1).c_str() << "." << std::endl;
  156. }
  157. else if (SR == SR_FAILED)
  158. {
  159. break;
  160. }
  161. }
  162. if (init_success)
  163. {
  164. m_pop_size++;
  165. ((EXAMPLE*)example)->task_out();
  166. return ((EXAMPLE*)example);
  167. }
  168. else
  169. {
  170. std::string last_error = ((EXAMPLE*)example)->last_error();
  171. delete ((EXAMPLE*)example);
  172. throw ylib::exception(last_error);
  173. }
  174. }
  175. else
  176. {
  177. throw ylib::exception("maximum capacity exceeded");
  178. }
  179. }
  180. else
  181. {
  182. m_pop_size++;
  183. ((EXAMPLE*)example)->pool(this);
  184. ((EXAMPLE*)example)->task_out();
  185. return ((EXAMPLE*)example);
  186. }
  187. }
  188. size_t size()
  189. {
  190. return m_max_size-m_pop_size;
  191. }
  192. public:
  193. INFO m_info;
  194. };
  195. }