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 }