1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 module hunt.pool.impl.SoftReferenceObjectPool; 18 19 // import java.lang.ref.Reference; 20 // import java.lang.ref.ReferenceQueue; 21 // import java.lang.ref.SoftReference; 22 // import java.util.ArrayList; 23 // import java.util.Iterator; 24 // import java.util.NoSuchElementException; 25 26 import hunt.Exceptions; 27 28 import hunt.pool.BaseObjectPool; 29 import hunt.pool.ObjectPool; 30 import hunt.pool.PoolUtils; 31 import hunt.pool.PooledObjectFactory; 32 33 /** 34 * A {@link java.lang.ref.SoftReference SoftReference} based {@link ObjectPool}. 35 * <p> 36 * This class is intended to be thread-safe. 37 * 38 * @param <T> 39 * Type of element pooled in this pool. 40 * 41 */ 42 // class SoftReferenceObjectPool(T) : BaseObjectPool!(T) { 43 44 // /** Factory to source pooled objects */ 45 // private PooledObjectFactory!(T) factory; 46 47 // /** 48 // * Queue of broken references that might be able to be removed from 49 // * <code>_pool</code>. This is used to help {@link #getNumIdle()} be more 50 // * accurate with minimal performance overhead. 51 // */ 52 // private ReferenceQueue!(T) refQueue = new ReferenceQueue<>(); 53 54 // /** Count of instances that have been checkout out to pool clients */ 55 // private int numActive = 0; // @GuardedBy("this") 56 57 // /** Total number of instances that have been destroyed */ 58 // private long destroyCount = 0; // @GuardedBy("this") 59 60 61 // /** Total number of instances that have been created */ 62 // private long createCount = 0; // @GuardedBy("this") 63 64 // /** Idle references - waiting to be borrowed */ 65 // private LinkedBlockingDeque!(PooledSoftReference!(T)) idleReferences = 66 // new LinkedBlockingDeque<>(); 67 68 // /** All references - checked out or waiting to be borrowed. */ 69 // private ArrayList!(PooledSoftReference!(T)) allReferences = 70 // new ArrayList<>(); 71 72 // /** 73 // * Create a <code>SoftReferenceObjectPool</code> with the specified factory. 74 // * 75 // * @param factory object factory to use. 76 // */ 77 // this(PooledObjectFactory!(T) factory) { 78 // this.factory = factory; 79 // } 80 81 // /** 82 // * Borrows an object from the pool. If there are no idle instances available 83 // * in the pool, the configured factory's 84 // * {@link PooledObjectFactory#makeObject()} method is invoked to create a 85 // * new instance. 86 // * <p> 87 // * All instances are {@link PooledObjectFactory#activateObject( 88 // * hunt.pool.PooledObject) activated} 89 // * and {@link PooledObjectFactory#validateObject( 90 // * hunt.pool.PooledObject) 91 // * validated} before being returned by this method. If validation fails or 92 // * an exception occurs activating or validating an idle instance, the 93 // * failing instance is {@link PooledObjectFactory#destroyObject( 94 // * hunt.pool.PooledObject) 95 // * destroyed} and another instance is retrieved from the pool, validated and 96 // * activated. This process continues until either the pool is empty or an 97 // * instance passes validation. If the pool is empty on activation or it does 98 // * not contain any valid instances, the factory's <code>makeObject</code> 99 // * method is used to create a new instance. If the created instance either 100 // * raises an exception on activation or fails validation, 101 // * <code>NoSuchElementException</code> is thrown. Exceptions thrown by 102 // * <code>MakeObject</code> are propagated to the caller; but other than 103 // * <code>ThreadDeath</code> or <code>VirtualMachineError</code>, exceptions 104 // * generated by activation, validation or destroy methods are swallowed 105 // * silently. 106 // * 107 // * @throws NoSuchElementException 108 // * if a valid object cannot be provided 109 // * @throws IllegalStateException 110 // * if invoked on a {@link #close() closed} pool 111 // * @throws Exception 112 // * if an exception occurs creating a new instance 113 // * @return a valid, activated object instance 114 // */ 115 // override 116 // T borrowObject() { // synchronized 117 // assertOpen(); 118 // T obj = null; 119 // bool newlyCreated = false; 120 // PooledSoftReference!(T) ref = null; 121 // // while (null == obj) { 122 // // if (idleReferences.isEmpty()) { 123 // // if (null == factory) { 124 // // throw new NoSuchElementException(); 125 // // } 126 // // newlyCreated = true; 127 // // obj = factory.makeObject().getObject(); 128 // // createCount++; 129 // // // Do not register with the queue 130 // // ref = new PooledSoftReference<>(new SoftReference<>(obj)); 131 // // allReferences.add(ref); 132 // // } else { 133 // // ref = idleReferences.pollFirst(); 134 // // obj = ref.getObject(); 135 // // // Clear the reference so it will not be queued, but replace with a 136 // // // a new, non-registered reference so we can still track this object 137 // // // in allReferences 138 // // ref.getReference().clear(); 139 // // ref.setReference(new SoftReference<>(obj)); 140 // // } 141 // // if (null != factory && null != obj) { 142 // // try { 143 // // factory.activateObject(ref); 144 // // if (!factory.validateObject(ref)) { 145 // // throw new Exception("ValidateObject failed"); 146 // // } 147 // // } catch (Throwable t) { 148 // // PoolUtils.checkRethrow(t); 149 // // try { 150 // // destroy(ref); 151 // // } catch (Throwable t2) { 152 // // PoolUtils.checkRethrow(t2); 153 // // // Swallowed 154 // // } finally { 155 // // obj = null; 156 // // } 157 // // if (newlyCreated) { 158 // // throw new NoSuchElementException( 159 // // "Could not create a validated object, cause: " ~ 160 // // t.getMessage()); 161 // // } 162 // // } 163 // // } 164 // // } 165 // // numActive++; 166 // // ref.allocate(); 167 // implementationMissing(false); 168 // return obj; 169 // } 170 171 // /** 172 // * Returns an instance to the pool after successful validation and 173 // * passivation. The returning instance is destroyed if any of the following 174 // * are true: 175 // * <ul> 176 // * <li>the pool is closed</li> 177 // * <li>{@link PooledObjectFactory#validateObject( 178 // * hunt.pool.PooledObject) validation} fails 179 // * </li> 180 // * <li>{@link PooledObjectFactory#passivateObject( 181 // * hunt.pool.PooledObject) passivation} 182 // *exception</li> 183 // * </ul> 184 // * Exceptions passivating or destroying instances are silently swallowed. 185 // * Exceptions validating instances are propagated to the client. 186 // * 187 // * @param obj 188 // * instance to return to the pool 189 // */ 190 // override 191 // synchronized void returnObject(T obj){ 192 // bool success = !isClosed(); 193 // PooledSoftReference!(T) ref = findReference(obj); 194 // if (ref is null) { 195 // throw new IllegalStateException( 196 // "Returned object not currently part of this pool"); 197 // } 198 // if (factory !is null) { 199 // if (!factory.validateObject(ref)) { 200 // success = false; 201 // } else { 202 // try { 203 // factory.passivateObject(ref); 204 // } catch (Exception e) { 205 // success = false; 206 // } 207 // } 208 // } 209 210 // bool shouldDestroy = !success; 211 // numActive--; 212 // if (success) { 213 214 // // Deallocate and add to the idle instance pool 215 // ref.deallocate(); 216 // idleReferences.add(ref); 217 // } 218 // notifyAll(); // numActive has changed 219 220 // if (shouldDestroy && factory !is null) { 221 // try { 222 // destroy(ref); 223 // } catch (Exception e) { 224 // // ignored 225 // } 226 // } 227 // } 228 229 // /** 230 // * {@inheritDoc} 231 // */ 232 // override 233 // synchronized void invalidateObject(T obj){ 234 // PooledSoftReference!(T) ref = findReference(obj); 235 // if (ref is null) { 236 // throw new IllegalStateException( 237 // "Object to invalidate is not currently part of this pool"); 238 // } 239 // if (factory !is null) { 240 // destroy(ref); 241 // } 242 // numActive--; 243 // notifyAll(); // numActive has changed 244 // } 245 246 // /** 247 // * Creates an object, and places it into the pool. addObject() is useful for 248 // * "pre-loading" a pool with idle objects. 249 // * <p> 250 // * Before being added to the pool, the newly created instance is 251 // * {@link PooledObjectFactory#validateObject( 252 // * hunt.pool.PooledObject) validated} and 253 // * {@link PooledObjectFactory#passivateObject( 254 // * hunt.pool.PooledObject) passivated}. If 255 // * validation fails, the new instance is 256 // * {@link PooledObjectFactory#destroyObject( 257 // * hunt.pool.PooledObject) destroyed}. Exceptions 258 // * generated by the factory <code>makeObject</code> or 259 // * <code>passivate</code> are propagated to the caller. Exceptions 260 // * destroying instances are silently swallowed. 261 // * 262 // * @throws IllegalStateException 263 // * if invoked on a {@link #close() closed} pool 264 // * @throws Exception 265 // * when the {@link #getFactory() factory} has a problem creating 266 // * or passivating an object. 267 // */ 268 // override 269 // synchronized void addObject(){ 270 // assertOpen(); 271 // if (factory is null) { 272 // throw new IllegalStateException( 273 // "Cannot add objects without a factory."); 274 // } 275 // T obj = factory.makeObject().getObject(); 276 // createCount++; 277 // // Create and register with the queue 278 // PooledSoftReference!(T) ref = new PooledSoftReference<>( 279 // new SoftReference<>(obj, refQueue)); 280 // allReferences.add(ref); 281 282 // bool success = true; 283 // if (!factory.validateObject(ref)) { 284 // success = false; 285 // } else { 286 // factory.passivateObject(ref); 287 // } 288 289 // bool shouldDestroy = !success; 290 // if (success) { 291 // idleReferences.add(ref); 292 // notifyAll(); // numActive has changed 293 // } 294 295 // if (shouldDestroy) { 296 // try { 297 // destroy(ref); 298 // } catch (Exception e) { 299 // // ignored 300 // } 301 // } 302 // } 303 304 // /** 305 // * Returns an approximation not less than the of the number of idle 306 // * instances in the pool. 307 // * 308 // * @return estimated number of idle instances in the pool 309 // */ 310 // override 311 // synchronized int getNumIdle() { 312 // pruneClearedReferences(); 313 // return idleReferences.size(); 314 // } 315 316 // /** 317 // * Returns the number of instances currently borrowed from this pool. 318 // * 319 // * @return the number of instances currently borrowed from this pool 320 // */ 321 // override 322 // synchronized int getNumActive() { 323 // return numActive; 324 // } 325 326 // /** 327 // * Clears any objects sitting idle in the pool. 328 // */ 329 // override 330 // synchronized void clear() { 331 // if (null != factory) { 332 // Iterator!(PooledSoftReference!(T)) iter = idleReferences.iterator(); 333 // while (iter.hasNext()) { 334 // try { 335 // PooledSoftReference!(T) ref = iter.next(); 336 // if (null != ref.getObject()) { 337 // factory.destroyObject(ref); 338 // } 339 // } catch (Exception e) { 340 // // ignore error, keep destroying the rest 341 // } 342 // } 343 // } 344 // idleReferences.clear(); 345 // pruneClearedReferences(); 346 // } 347 348 // /** 349 // * Closes this pool, and frees any resources associated with it. Invokes 350 // * {@link #clear()} to destroy and remove instances in the pool. 351 // * <p> 352 // * Calling {@link #addObject} or {@link #borrowObject} after invoking this 353 // * method on a pool will cause them to throw an 354 // * {@link IllegalStateException}. 355 // */ 356 // override 357 // void close() { 358 // super.close(); 359 // clear(); 360 // } 361 362 // /** 363 // * Returns the {@link PooledObjectFactory} used by this pool to create and 364 // * manage object instances. 365 // * 366 // * @return the factory 367 // */ 368 // synchronized PooledObjectFactory!(T) getFactory() { 369 // return factory; 370 // } 371 372 // /** 373 // * If any idle objects were garbage collected, remove their 374 // * {@link Reference} wrappers from the idle object pool. 375 // */ 376 // private void pruneClearedReferences() { 377 // // Remove wrappers for enqueued references from idle and allReferences lists 378 // removeClearedReferences(idleReferences.iterator()); 379 // removeClearedReferences(allReferences.iterator()); 380 // while (refQueue.poll() !is null) { 381 // // empty 382 // } 383 // } 384 385 // /** 386 // * Finds the PooledSoftReference in allReferences that points to obj. 387 // * 388 // * @param obj returning object 389 // * @return PooledSoftReference wrapping a soft reference to obj 390 // */ 391 // private PooledSoftReference!(T) findReference(T obj) { 392 // Iterator!(PooledSoftReference!(T)) iterator = allReferences.iterator(); 393 // while (iterator.hasNext()) { 394 // PooledSoftReference!(T) reference = iterator.next(); 395 // if (reference.getObject() !is null && reference.getObject() == obj) { 396 // return reference; 397 // } 398 // } 399 // return null; 400 // } 401 402 // /** 403 // * Destroys a {@code PooledSoftReference} and removes it from the idle and all 404 // * references pools. 405 // * 406 // * @param toDestroy PooledSoftReference to destroy 407 // * 408 // * @throws Exception If an error occurs while trying to destroy the object 409 // */ 410 // private void destroy(PooledSoftReference!(T) toDestroy){ 411 // toDestroy.invalidate(); 412 // idleReferences.remove(toDestroy); 413 // allReferences.remove(toDestroy); 414 // try { 415 // factory.destroyObject(toDestroy); 416 // } finally { 417 // destroyCount++; 418 // toDestroy.getReference().clear(); 419 // } 420 // } 421 422 // /** 423 // * Clears cleared references from iterator's collection 424 // * @param iterator iterator over idle/allReferences 425 // */ 426 // private void removeClearedReferences(Iterator!(PooledSoftReference!(T)) iterator) { 427 // PooledSoftReference!(T) ref; 428 // while (iterator.hasNext()) { 429 // ref = iterator.next(); 430 // if (ref.getReference() is null || ref.getReference().isEnqueued()) { 431 // iterator.remove(); 432 // } 433 // } 434 // } 435 436 // override 437 // protected void toStringAppendFields(StringBuilder builder) { 438 // super.toStringAppendFields(builder); 439 // builder.append(", factory="); 440 // builder.append(factory); 441 // builder.append(", refQueue="); 442 // builder.append(refQueue); 443 // builder.append(", numActive="); 444 // builder.append(numActive); 445 // builder.append(", destroyCount="); 446 // builder.append(destroyCount); 447 // builder.append(", createCount="); 448 // builder.append(createCount); 449 // builder.append(", idleReferences="); 450 // builder.append(idleReferences); 451 // builder.append(", allReferences="); 452 // builder.append(allReferences); 453 // } 454 // }