]> git.sesse.net Git - casparcg/blob - server/utils/object_pool.h
1.8.1:
[casparcg] / server / utils / object_pool.h
1 #ifndef _OBJECTPOOL_H_\r
2 #define _OBJECTPOOL_H_\r
3 \r
4 #include <functional>\r
5 #include <memory>\r
6 #include <type_traits>\r
7 \r
8 #include <tbb/concurrent_queue.h>\r
9 \r
10 namespace caspar\r
11 {\r
12 \r
13 namespace utils\r
14 {\r
15 \r
16 template<typename T>\r
17 struct default_new_delete_allocator\r
18 {       \r
19         static T* construct()\r
20         { return new T(); }\r
21 \r
22         \r
23         template<typename P0>\r
24         static T* construct(P0&& p0)\r
25         { return new T(std::forward<P0>(p0)); }\r
26 \r
27         template<typename P0, typename P1>\r
28         static T* construct(P0&& p0, P1&& p1)\r
29         { return new T(std::forward<P0>(p0), std::forward<P1>(p1)); }\r
30         \r
31         template<typename P0, typename P1, typename P2>\r
32         static T* construct(P0&& p0, P1&& p1, P2&& p2)\r
33         { return new T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)); }\r
34 \r
35         static void destroy(T* const block)\r
36         { delete block; }\r
37 };\r
38 \r
39 template<typename T, typename allocator = default_new_delete_allocator<T>>\r
40 class object_pool\r
41 {\r
42         typedef std::shared_ptr<T> Ptr;\r
43 public:\r
44 \r
45         ~object_pool()\r
46         {\r
47                 T* item;\r
48                 while(pool_.try_pop(item))\r
49                         allocator::destroy(item);\r
50         }\r
51 \r
52         Ptr construct()\r
53         {\r
54                 T* item = pool_.try_pop(item) ? item : allocator::construct();\r
55                 return Ptr(item, [&](T* item){ pool_.push(item); });\r
56         }\r
57         \r
58         template<typename P0>\r
59         Ptr construct(P0&& p0)\r
60         {\r
61                 T* item = pool_.try_pop(item) ? item : allocator::construct(std::forward<P0>(p0));\r
62                 return Ptr(item, [&](T* item){ pool_.push(item); });\r
63         }\r
64         \r
65         template<typename P0, typename P1>\r
66         Ptr construct(P0&& p0, P1&& p1)\r
67         {\r
68                 T* item = pool_.try_pop(item) ? item : allocator::construct(std::forward<P0>(p0), std::forward<P1>(p1));\r
69                 return Ptr(item, [&](T* item){ pool_.push(item); });\r
70         }\r
71         \r
72         template<typename P0, typename P1, typename P2>\r
73         Ptr construct(P0&& p0, P1&& p1, P1&& p2)\r
74         {\r
75                 T* item = pool_.try_pop(item) ? item : allocator::construct(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2));\r
76                 return Ptr(item, [&](T* item){ pool_.push(item); });\r
77         }\r
78 private:\r
79         tbb::concurrent_queue<T*> pool_;\r
80 };\r
81 \r
82 }}\r
83 \r
84 #endif