1 /*******************************************************************************
2 
3     Pool class template which stores class instances, has the
4     following features:
5         * Get and recycle items. Recycled items will be re-used before creating
6           new items.
7         * The total number of items, as well as the number of idle or busy items
8           in the pool can be queried.
9         * A limit can be applied to the pool, which prevents more than the
10           specified number of items from being created.
11         * A specified number of items can be pre-allocated in the pool using the
12           fill() method.
13         * The entire pool can be emptied, returning all items to the idle state,
14           with clear().
15         * Iteration over all items in the pool, or all busy or idle items. (See
16           further notes in the super class.)
17         * For classes with a default (parameterless) constructor, get() and
18           fill() methods exist which automatically create new pool items,
19           without requiring them to be passed via a lazy argument.
20 
21     An additional class template exists, the AutoCtorPool, which automatically
22     creates new instances of the specified class by calling the constructor
23     with a fixed set of parameters.
24 
25     Also see: ocean.util.container.pool.model.IAggregatePool, for more detailed
26     documentation and usage examples.
27 
28     Copyright:
29         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
30         All rights reserved.
31 
32     License:
33         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
34         Alternatively, this file may be distributed under the terms of the Tango
35         3-Clause BSD License (see LICENSE_BSD.txt for details).
36 
37 *******************************************************************************/
38 
39 module ocean.util.container.pool.ObjectPool;
40 
41 
42 
43 
44 import ocean.util.container.pool.model.IAggregatePool;
45 import ocean.util.container.pool.model.IResettable;
46 
47 
48 /*******************************************************************************
49 
50     Manages a pool of class instances of type T.
51 
52     Does not create the items ("new T") internally but receives them as lazy
53     arguments in get().
54 
55     Params:
56         T = type stored in pool
57 
58 *******************************************************************************/
59 
60 public class ObjectPool ( T ) : IAggregatePool!(T)
61 {
62     /***************************************************************************
63 
64         Asserts that T is a class.
65 
66     ***************************************************************************/
67 
68     static assert(is(T == class));
69 
70     /***************************************************************************
71 
72         Resets item.
73 
74         Params:
75             item = item to reset
76 
77     ***************************************************************************/
78 
79     protected override void resetItem ( Item item )
80     {
81         static if (is(T : Resettable))
82         {
83             this.fromItem(item).reset();
84         }
85     }
86 }
87 
88 
89 
90 /*******************************************************************************
91 
92     Extends ObjectPool by creating items (instances of T) automatically with
93     "new T(Args)".
94 
95     Params:
96         T = type stored in pool
97         Args = tuple of T constructor argument types.
98 
99 *******************************************************************************/
100 
101 public class AutoCtorPool ( T, Args ... ) : ObjectPool!(T)
102 {
103     /***************************************************************************
104 
105         Asserts that at least one constructor argument is specified in the Args
106         tuple.
107 
108     ***************************************************************************/
109 
110     static assert(Args.length > 0, "if you want to use a constructor with no arguments, just use ObjectPool");
111 
112     /***************************************************************************
113 
114         Arguments used to construct pool items. These items are set in the
115         class' constructor and are then used to construct all requested pool
116         items.
117 
118     ***************************************************************************/
119 
120     private Args args;
121 
122     /***************************************************************************
123 
124         Constructor
125 
126         Params:
127             args = T constructor arguments to be used each time an
128                    object is created
129 
130     ***************************************************************************/
131 
132     public this ( Args args )
133     {
134         this.args = args;
135     }
136 
137     /**************************************************************************
138 
139         Gets an object from the object pool.
140 
141         Returns:
142             object from the object pool
143 
144      **************************************************************************/
145 
146     public ItemType get ( )
147     {
148         return super.get(new T(args));
149     }
150 
151     /**************************************************************************
152 
153         Ensures that the pool contains at least the specified number of items.
154         Useful to pre-allocate a pool of a certain size.
155 
156         Params:
157             num = minimum number of items desired in pool
158 
159         Returns:
160             this
161 
162         Throws:
163             LimitExceededException if the requested number of items exceeds
164             the previously specified limit.
165 
166      **************************************************************************/
167 
168     public typeof(this) fill ( size_t num )
169     {
170         super.fill_(num, this.toItem(new T(args)));
171         return this;
172     }
173 
174     /**************************************************************************
175 
176         Creates a new instance.
177 
178         Params:
179             args = T constructor arguments to be used each time an object is
180                    created
181 
182      **************************************************************************/
183 
184     static typeof (this) newPool ( Args args )
185     {
186         return new typeof (this)(args);
187     }
188 }
189 
190 
191 
192 version (unittest)
193 {
194     class Class
195     {
196         size_t object_pool_index;
197 
198         override equals_t opEquals(Object rhs)
199         {
200             auto crhs = cast(typeof(this)) rhs;
201             return this.i == crhs.i && this.s == crhs.s;
202         }
203 
204         size_t i;
205         char[] s;
206     }
207 
208     import ocean.core.Test;
209 
210     alias ObjectPool!(Class) MyPool;
211     class ObjectPoolTester : IAggregatePoolTester!(Class)
212     {
213 
214         public this ( )
215         {
216             super(new MyPool);
217         }
218 
219         protected override Item newItem ( )
220         {
221             return new Class;
222         }
223 
224         protected override void setItem ( ref Item item, size_t i )
225         {
226             item.i = i;
227             item.s.length = 1;
228             item.s[0] = cast(char)(i + 32);
229         }
230 
231         protected override void checkItem ( ref Item item, size_t i )
232         {
233             .test!("==")(item.i, i, "item integer wrong");
234             .test!("==")(item.s.length, 1, "item string length wrong");
235             .test!("==")(item.s[0], cast(char)(i + 32), "item string content wrong");
236         }
237     }
238 }
239 
240 unittest
241 {
242     scope op = new ObjectPoolTester;
243     op.test();
244 }
245