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