refined (and final) support for race detection for singleton object pool
[dyninst.git] / common / src / singleton_object_pool.h
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #if !defined(SINGLETON_OBJECT_POOL_H)
31 #define SINGLETON_OBJECT_POOL_H
32
33 //#define BOOST_POOL_NO_MT
34 //#undef BOOST_HAS_THREADS
35
36 #include <boost/pool/pool.hpp>
37 #include "pool_allocators.h"
38 #include "dthread.h"
39 #include "race-detector-annotations.h"
40
41 // This is only safe for objects with nothrow constructors...
42 template <typename T, typename Alloc = boost::default_user_allocator_new_delete>
43 class singleton_object_pool
44 {
45     typedef boost::singleton_pool<T, sizeof(T), Alloc> parent_t;
46     typedef singleton_object_pool<T, Alloc> pool_t;
47
48     inline static void free(T* free_me)
49     {
50         parent_t::free(free_me);
51         race_detector_forget_access_history(free_me, sizeof(T));
52     }
53
54     inline static T* malloc()
55     {
56         void* buf = parent_t::malloc();
57         race_detector_forget_access_history(buf, sizeof(T));
58         return reinterpret_cast<T*>(buf);
59     }
60
61 public:
62
63     inline static bool is_from(T* t)
64     {
65         return parent_t::is_from(t);
66     }
67
68   inline static T* construct()
69   {
70
71     T* const temp = malloc();
72     if(temp == 0) return temp;
73     new(temp) T();
74     return temp;
75   }
76   template <typename A1>
77   inline static T* construct(const A1& a1)
78   {
79
80     T* const temp = malloc();
81     if(temp == 0) return temp;
82     new(temp) T(a1);
83     return temp;
84   }
85   template <typename A1, typename A2>
86   inline static T* construct(const A1& a1, const A2& a2)
87   {
88
89     T* const temp = malloc();
90     if(temp == 0) return temp;
91     new(temp) T(a1, a2);
92     return temp;
93   }
94   template <typename A1, typename A2, typename A3>
95   inline static T* construct(const A1& a1, const A2& a2, const A3& a3)
96   {
97
98     T* const temp = malloc();
99     if(temp == 0) return temp;
100     new(temp) T(a1, a2, a3);
101     return temp;
102   }
103   template <typename A1, typename A2, typename A3, typename A4>
104   inline static T* construct(const A1& a1, const A2& a2, const A3& a3, const A4& a4)
105   {
106
107     T* const temp = malloc();
108     if(temp == 0) return temp;
109     new(temp) T(a1, a2, a3, a4);
110     return temp;
111   }
112   template <typename A1, typename A2, typename A3, typename A4, typename A5>
113   inline static T* construct(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
114   {
115
116       T* const temp = malloc();
117     if(temp == 0) return temp;
118     new(temp) T(a1, a2, a3, a4, a5);
119     return temp;
120   }
121   template <typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
122   inline static T* construct(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
123   {
124
125     T* const temp = malloc();
126     if(temp == 0) return temp;
127     new(temp) T(a1, a2, a3, a4, a5, a6);
128     return temp;
129   }
130
131     inline static void destroy(T* const kill_me)
132     {
133         if(is_from(kill_me)) {
134           kill_me->~T();
135           free(kill_me);
136         }
137     }
138
139 };
140
141 template <typename T>
142 struct PoolDestructor
143 {
144   inline void operator()(T* e) 
145   {
146     // We'll see if this kills performance or not...
147     if(singleton_object_pool<T>::is_from(e)) {  singleton_object_pool<T>::destroy(e);
148   }}
149 };
150
151 template <typename T> inline
152 boost::shared_ptr<T> make_shared(T* t)
153 {
154     return boost::shared_ptr<T>(t, PoolDestructor<T>()/*, typename unlocked_fast_alloc<T>::type()*/);
155 }
156
157
158 #endif //!defined(SINGLETON_OBJECT_POOL_H)