1 /*******************************************************************************
2 
3     Interface for an object allocator.
4 
5     Copyright:
6         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
7         All rights reserved.
8 
9     License:
10         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
11         Alternatively, this file may be distributed under the terms of the Tango
12         3-Clause BSD License (see LICENSE_BSD.txt for details).
13 
14 *******************************************************************************/
15 
16 module ocean.util.container.map.model.IAllocator;
17 
18 /******************************************************************************/
19 
20 
21 
22 abstract class IAllocator
23 {
24     /***************************************************************************
25 
26         Tracks amount of memory used by this allocator.
27 
28     ***************************************************************************/
29 
30     private size_t used_memory;
31 
32     /***************************************************************************
33 
34         Stores the size of a single allocated element.
35 
36     ***************************************************************************/
37 
38     protected size_t bucket_element_size;
39 
40 
41     /***************************************************************************
42 
43         Constructor.
44 
45         Params:
46             bucket_element_sizeof = the amount of memory used by each allocated
47                 element.
48 
49     ***************************************************************************/
50 
51     public this ( size_t bucket_element_sizeof )
52     {
53         this.bucket_element_size = bucket_element_sizeof;
54     }
55 
56     /***************************************************************************
57 
58         Gets or allocates an object
59 
60         Returns:
61             an object that is ready to use.
62 
63     ***************************************************************************/
64 
65     public void* get ( )
66     {
67         this.used_memory += this.bucket_element_size;
68         return this.allocate();
69     }
70 
71     /***************************************************************************
72 
73         Performs the actual allocation of an object
74 
75         Returns:
76             an object that is ready to use.
77 
78     ***************************************************************************/
79 
80     protected abstract void* allocate ();
81 
82     /***************************************************************************
83 
84         Recycles or deletes an object that is no longer used.
85 
86         Note: Strictly specking old should be a ref to satisfy D's delete
87         expression which wants the pointer as an lvalue in order to set it to
88         null after deletion. However, would make code more complex and isn't
89         actually necessary in the particular use case of this interface (see
90         BucketSet.remove()/clear()).
91 
92         Params:
93             old = old object
94 
95     ***************************************************************************/
96 
97     public void recycle ( void* old )
98     {
99         this.used_memory -= this.bucket_element_size;
100         return this.deallocate(old);
101     }
102 
103     /***************************************************************************
104 
105         Performs the actual recycling of an object. See recycle() documentation.
106 
107         Params:
108             old = old object
109 
110     ***************************************************************************/
111 
112     protected abstract void deallocate ( void* old );
113 
114     /***************************************************************************
115 
116         Return the amount of memory currently used.
117 
118         Returns:
119             the size of the memory allocated by this allocator
120 
121     ***************************************************************************/
122 
123     public size_t memoryUsed ()
124     {
125         return this.used_memory;
126     }
127 
128     /***************************************************************************
129 
130         Helper class to temprarily park a certain number of objects.
131 
132     ***************************************************************************/
133 
134     static abstract /* scope */ class IParkingStack
135     {
136         import ocean.core.Verify;
137 
138         /**********************************************************************
139 
140             Maximum number of objects as passed to the constructor.
141 
142          **********************************************************************/
143 
144         public size_t max_length ( )
145         {
146             return this._max_length;
147         }
148 
149         private size_t _max_length;
150 
151         /**********************************************************************
152 
153             Number of elements currently on the stack. This value is always
154             at most max_length.
155 
156          **********************************************************************/
157 
158         private size_t n = 0;
159 
160         invariant ( )
161         {
162             assert(this.n <= this._max_length);
163         }
164 
165         /**********************************************************************
166 
167             Constructor.
168 
169             Params:
170                 max_length = maximum number of objects that will be stored
171 
172          **********************************************************************/
173 
174         protected this ( size_t max_length )
175         {
176             this._max_length = max_length;
177         }
178 
179         /**********************************************************************
180 
181             Pushes an object on the stack.
182 
183             Params:
184                 object = object to push
185 
186             Returns:
187                 object
188 
189             In:
190                 Less than max_length objects may be parked.
191 
192          **********************************************************************/
193 
194         public void* push ( void* object )
195         {
196             verify(this.n < this._max_length);
197 
198             this.push_(object, this.n++);
199 
200             return object;
201         }
202 
203         /**********************************************************************
204 
205             Pops an object from the stack.
206 
207             Returns:
208                 object popped from the stack or null if the stack is empty.
209 
210             Out:
211                 If an element is returned, less than max_length elements must be
212                 on the stack, otherwise the stack must be empty.
213 
214          **********************************************************************/
215 
216         public void* pop ( )
217         out (element)
218         {
219             if (element)
220             {
221                 assert(this.n < this._max_length);
222             }
223             else
224             {
225                 assert(!this.n);
226             }
227         }
228         do
229         {
230             if (this.n)
231             {
232                 return this.pop_(--this.n);
233             }
234             else
235             {
236                 return null;
237             }
238         }
239 
240         /**********************************************************************
241 
242             'foreach' iteration, each cycle pops an element from the stack and
243             iterates over it.
244 
245          **********************************************************************/
246 
247         public int opApply ( scope int delegate ( ref void* object ) dg )
248         {
249             int r = 0;
250 
251             for (void* object = this.pop(); object && !r; object = this.pop())
252             {
253                 r = dg(object);
254             }
255 
256             return r;
257         }
258 
259         /**********************************************************************
260 
261             Pushes an object on the stack.
262 
263             Params:
264                 object = object to push
265                 n      = number of parked objects before object is pushed
266                          (guaranteed to be less than max_length)
267 
268          **********************************************************************/
269 
270         abstract protected void push_ ( void* object, size_t n );
271 
272         /**********************************************************************
273 
274             Pops an object from the stack. This method is never called if the
275             stack is empty.
276 
277             Params:
278                 n = number of parked objects after object is popped (guaranteed
279                     to be less than max_length)
280 
281             Returns:
282                 object popped from the stack or null if the stack is empty.
283 
284          **********************************************************************/
285 
286         abstract protected void* pop_ ( size_t n );
287     }
288 
289     /***************************************************************************
290 
291         Calls dg with an IParkingStack instance that is set up to keep n
292         elements.
293 
294         Params:
295             n  = number of elements to park
296             dg = delegate to call with the IParkingStack instance
297 
298     ***************************************************************************/
299 
300     void parkElements ( size_t n, scope void delegate ( IParkingStack park ) dg );
301 }