Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: third_party/smartany/shared_any.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/smartany/shared_any.h ('k') | third_party/smartany/smart_any_fwd.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //+---------------------------------------------------------------------------
2 //
3 // Copyright ( C ) Microsoft, 2002.
4 //
5 // File: shared_any.cpp
6 //
7 // Contents: pool allocator for reference counts
8 //
9 // Classes: ref_count_allocator and helpers
10 //
11 // Functions:
12 //
13 // Author: Eric Niebler ( ericne@microsoft.com )
14 //
15 //----------------------------------------------------------------------------
16
17 #ifdef _MT
18 # ifndef _WIN32_WINNT
19 # define _WIN32_WINNT 0x0403
20 # endif
21 # include <windows.h>
22 # include <unknwn.h>
23 #endif
24
25 #include <cassert>
26 #include <functional> // for std::less
27 #include <algorithm> // for std::swap
28
29 #pragma warning(push)
30 // C4640: construction of local static object is not thread-safe
31 #pragma warning(disable : 4640)
32 #include "shared_any.h"
33 #include "scoped_any.h"
34 #pragma warning(pop)
35
36 namespace detail
37 {
38 struct critsec
39 {
40 #ifdef _MT
41 CRITICAL_SECTION m_cs;
42
43 critsec()
44 {
45 InitializeCriticalSectionAndSpinCount( &m_cs, 4000 );
46 }
47 ~critsec()
48 {
49 DeleteCriticalSection( &m_cs );
50 }
51 void enter()
52 {
53 EnterCriticalSection( &m_cs );
54 }
55 void leave()
56 {
57 LeaveCriticalSection( &m_cs );
58 }
59 #endif
60 };
61
62 namespace
63 {
64 critsec g_critsec;
65 }
66
67 struct lock
68 {
69 #ifdef _MT
70 critsec & m_cs;
71
72 explicit lock( critsec & cs )
73 : m_cs(cs)
74 {
75 m_cs.enter();
76 }
77 ~lock()
78 {
79 m_cs.leave();
80 }
81 #else
82 explicit lock( critsec & )
83 {
84 }
85 #endif
86 private:
87 lock( lock const & );
88 lock & operator=( lock const & );
89 };
90
91 struct ref_count_block
92 {
93 static long const s_sizeBlock = 256;
94
95 short m_free_list; // offset to start of freelist
96 short m_available; // count of refcounts in this block that are availabl e
97 long m_refcounts[ s_sizeBlock ];
98
99 ref_count_block()
100 : m_free_list(0), m_available(s_sizeBlock)
101 {
102 for( long l=0; l<s_sizeBlock; ++l )
103 m_refcounts[l] = l+1;
104 }
105
106 bool empty() const // throw()
107 {
108 return s_sizeBlock == m_available;
109 }
110
111 bool full() const // throw()
112 {
113 return 0 == m_available;
114 }
115
116 long volatile *alloc( lock & )
117 {
118 assert( 0 != m_available );
119 long *refcount = m_refcounts + m_free_list;
120 m_free_list = static_cast<short>( *refcount );
121 --m_available;
122 return refcount;
123 }
124
125 void free( long volatile *refcount, lock & ) // throw()
126 {
127 assert( owns( refcount ) );
128 *refcount = m_free_list;
129 m_free_list = static_cast<short>( refcount - m_refcounts );
130 ++m_available;
131 }
132
133 bool owns( long volatile *refcount ) const // throw()
134 {
135 return ! std::less<void*>()( const_cast<long*>( refcount ), const_ca st<long*>( m_refcounts ) ) &&
136 std::less<void*>()( const_cast<long*>( refcount ), const_cas t<long*>( m_refcounts ) + s_sizeBlock );
137 }
138 };
139
140
141 struct ref_count_allocator::node
142 {
143 node *m_next;
144 node *m_prev;
145 ref_count_block m_block;
146 explicit node( node *next=0, node *prev=0 )
147 : m_next(next), m_prev(prev), m_block()
148 {
149 if( m_next )
150 m_next->m_prev = this;
151 if( m_prev )
152 m_prev->m_next = this;
153 }
154 };
155
156
157 ref_count_allocator::ref_count_allocator()
158 : m_list_blocks(0), m_last_alloc(0), m_last_free(0)
159 {
160 }
161
162 ref_count_allocator::~ref_count_allocator()
163 {
164 // Just leak the blocks. It's ok, really.
165 // If you need to clean up the blocks and
166 // you are certain that no refcounts are
167 // outstanding, you can use the finalize()
168 // method to force deallocation
169 }
170
171 void ref_count_allocator::finalize()
172 {
173 lock l( g_critsec );
174 for( node *next; m_list_blocks; m_list_blocks=next )
175 {
176 next = m_list_blocks->m_next;
177 delete m_list_blocks;
178 }
179 m_last_alloc = 0;
180 m_last_free = 0;
181 }
182
183 long volatile *ref_count_allocator::alloc()
184 {
185 lock l( g_critsec );
186 if( ! m_last_alloc || m_last_alloc->m_block.full() )
187 {
188 for( m_last_alloc = m_list_blocks;
189 m_last_alloc && m_last_alloc->m_block.full();
190 m_last_alloc = m_last_alloc->m_next );
191 if( ! m_last_alloc )
192 {
193 m_last_alloc = new( std::nothrow ) node( m_list_blocks );
194 if( ! m_last_alloc )
195 return 0;
196 m_list_blocks = m_last_alloc;
197 }
198 }
199 return m_last_alloc->m_block.alloc( l );
200 }
201
202 long volatile *ref_count_allocator::alloc( long val )
203 {
204 long volatile *refcount = alloc();
205 *refcount = val;
206 return refcount;
207 }
208
209 void ref_count_allocator::free( long volatile *refcount ) // throw()
210 {
211 // don't rearrange the order of these locals!
212 scoped_any<node*,close_delete> scoped_last_free;
213 lock l( g_critsec );
214
215 if( ! m_last_free || ! m_last_free->m_block.owns( refcount ) )
216 {
217 for( m_last_free = m_list_blocks;
218 m_last_free && ! m_last_free->m_block.owns( refcount );
219 m_last_free = m_last_free->m_next );
220 }
221
222 assert( m_last_free && m_last_free->m_block.owns( refcount ) );
223 m_last_free->m_block.free( refcount, l );
224
225 if( m_last_free != m_list_blocks && m_last_free->m_block.empty() )
226 {
227 if( 0 != ( m_last_free->m_prev->m_next = m_last_free->m_next ) )
228 m_last_free->m_next->m_prev = m_last_free->m_prev;
229
230 if( ! m_list_blocks->m_block.empty() )
231 {
232 m_last_free->m_next = m_list_blocks;
233 m_last_free->m_prev = 0;
234 m_list_blocks->m_prev = m_last_free;
235 m_list_blocks = m_last_free;
236 }
237 else
238 reset( scoped_last_free, m_last_free ); // deleted after critsec is released
239
240 m_last_free = 0;
241 }
242 }
243
244 // Here is the global reference count allocator.
245 ref_count_allocator ref_count_allocator::instance;
246 }
OLDNEW
« no previous file with comments | « third_party/smartany/shared_any.h ('k') | third_party/smartany/smart_any_fwd.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698