View Javadoc

1   package cz.cuni.amis.utils.objectmanager;
2   
3   import java.lang.ref.SoftReference;
4   import java.util.LinkedList;
5   import java.util.Queue;
6   
7   
8   /**
9    * ObjectManager is a class that helps you to keep unused objects 
10   * in the memory. Rather then to create the objects again and again you can
11   * retrieve their old instances. Of course those objects must be reusable and
12   * have support for resetting it's crucial variables to your liking.
13   * <p><p>
14   * Implementation is using soft references therefore you don't have to worry
15   * about memory leakage - if JVM will need more memory it will purge those
16   * soft references.
17   * <p><p>
18   * Note that the manager is thread-safe + get() will always return you
19   * an old (or possibly) new instance of the object.
20   * <p><p>
21   * We discourage you to use ObjectManager for objects that have multiple
22   * references throughout your code as it is hard to know whether the object
23   * is not referenced from other parts of your code so you can give it back
24   * to the manager.
25   * 
26   * @author Jimmy
27   *
28   * @param <MANAGED_OBJECT>
29   */
30  public class ObjectManager<MANAGED_OBJECT> {
31  
32  	/**
33  	 * Queue with unused objects, using soft references.
34  	 */
35  	private Queue<SoftReference<MANAGED_OBJECT>> freeObjects;
36  	
37  	/**
38  	 * Factory that allows us to produce new objects as needed.
39  	 */
40  	private IObjectFactory<MANAGED_OBJECT> objectFactory;
41  	
42  	/**
43  	 * How many new objects should be created if there is a shortage of 
44  	 * free objects.
45  	 */
46  	private int moreNewObjectsCount;
47  	
48  	public ObjectManager(IObjectFactory<MANAGED_OBJECT> objectFactory) {
49  		this(objectFactory, 10, 5);
50  	}
51  	
52  	/**
53  	 * @param objectFactory
54  	 * @param initialObjectCount how many objects to create in advance
55  	 */
56  	public ObjectManager(IObjectFactory<MANAGED_OBJECT> objectFactory, int initialObjectCount) {
57  		this(objectFactory, initialObjectCount, 5);
58  	}
59  	
60  	/**
61  	 * @param objectFactory
62  	 * @param initialObjectCount how many objects to create in advance 
63  	 * @param moreNewObjectsCount how many new objects to create in advance in case of shortage of free objects
64  	 */
65  	public ObjectManager(IObjectFactory<MANAGED_OBJECT> objectFactory, int initialObjectCount, int moreNewObjectsCount) {
66  		
67  		if (moreNewObjectsCount <= 0) moreNewObjectsCount = 1;
68  		
69  		this.moreNewObjectsCount = moreNewObjectsCount;
70  		
71  		this.objectFactory = objectFactory;
72  		
73  		freeObjects = new LinkedList<SoftReference<MANAGED_OBJECT>>();
74  		
75  		generateNewObjects(initialObjectCount);
76  	}
77  
78  	/**
79  	 * Generate 'count' new objects into the queue.
80  	 * @param count
81  	 */
82  	private void generateNewObjects(int count) {
83  		for (int i = 0; i < count; ++i) {
84  			freeObjects.add(new SoftReference<MANAGED_OBJECT>(objectFactory.newObject()));
85  		}
86  	}
87  	
88  	/**
89  	 * Returns you an instance of object. Note that it might be used one.  
90  	 * @return
91  	 */
92  	public MANAGED_OBJECT get() {
93  		synchronized(freeObjects) {
94  			if (freeObjects.size() == 0) generateNewObjects(moreNewObjectsCount);			
95  			SoftReference<MANAGED_OBJECT> reference = freeObjects.poll();
96  			MANAGED_OBJECT obj = reference.get();
97  			while (obj == null && freeObjects.size() > 0) {
98  				reference = freeObjects.poll();
99  				obj = reference.get();
100 			}
101 			if (obj != null) return obj;
102 			return objectFactory.newObject();
103 		}
104 	}
105 	
106 	/**
107 	 * Returns an instance of object to the manager, it will be stored in the manager
108 	 * via soft reference. Note that you have to ensure that returned objects
109 	 * are still usable! Also - you must be sure that this object is not used
110 	 * in any part of your code!
111 	 * 
112 	 * @param obj
113 	 */
114 	public void giveBack(MANAGED_OBJECT obj) {
115 		synchronized(freeObjects) {
116 			freeObjects.add(new SoftReference<MANAGED_OBJECT>(obj));
117 		}
118 	}
119 
120 }