KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > realtime > PoolContext


1 /*
2  * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
3  * Copyright (C) 2005 - Javolution (http://javolution.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package javolution.realtime;
10
11 /**
12  * <p> This class represents a pool context; it is used to recycle objects
13  * transparently, reduce memory allocation and avoid garbage collection.</p>
14  *
15  * <p> Threads executing in a pool context may allocate objects from
16  * the context's pools (also called "stack") through an
17  * {@link ObjectFactory}. Allocated objects are recycled automatically
18  * upon {@link PoolContext#exit exit}. This recycling is almost
19  * instantaneous and has no impact on performance.</p>
20  *
21  * <p> Objects allocated within a pool context should not be directly
22  * referenced outside of the context unless they are
23  * {@link RealtimeObject#export exported} (e.g. result being returned)
24  * or {@link RealtimeObject#preserve preserved} (e.g. shared static
25  * instance). If this simple rule is followed, then pool context are
26  * completely safe. In fact, pool contexts promote the use of immutable
27  * objects (as their allocation cost is then negligible with no adverse
28  * effect on garbarge collection) and often lead to safer, faster and
29  * more robust applications.</p>
30  *
31  * <p> Upon thread termination, pool objects associated to a thread are
32  * candidate for garbage collection (the "export rule" guarantees that these
33  * objects are not referenced anymore). They will be collected after
34  * the thread finalization. It is also possible to move all pools' objects
35  * to the heap directly (for early garbage collection) by calling the
36  * {@link PoolContext#clear} static method.</p>
37  *
38  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
39  * @version 3.0, March 5, 2005
40  */

41 public final class PoolContext extends Context {
42
43     /**
44      * Holds the pools for this context.
45      */

46     final ObjectPool[] _pools = new ObjectPool[ObjectFactory.MAX];
47
48     /**
49      * Holds the pools in use.
50      */

51     private final ObjectPool[] _inUsePools = new ObjectPool[ObjectFactory.MAX];
52
53     /**
54      * Holds the number of pools used.
55      */

56     private int _inUsePoolsLength;
57
58     /**
59      * Default constructor.
60      */

61     PoolContext() {
62         for (int i=_pools.length; i > 0;) {
63             _pools[--i] = ObjectPool.NULL;
64         }
65     }
66
67     /**
68      * Enters a {@link PoolContext}.
69      */

70     public static void enter() {
71         PoolContext ctx = (PoolContext) push(POOL_CONTEXT_CLASS);
72         if (ctx == null) {
73             ctx = new PoolContext();
74             push(ctx);
75         }
76         PoolContext outer = ctx.getOuter().poolContext();
77         if (outer != null) {
78             outer.setInUsePoolsLocal(false);
79         }
80     }
81     private static final Class POOL_CONTEXT_CLASS = new PoolContext().getClass();
82
83     /**
84      * Exits the current {@link PoolContext}.
85      *
86      * @throws ClassCastException if the current context is not a
87      * {@link PoolContext}.
88      */

89     public static void exit() {
90         PoolContext ctx = (PoolContext) pop();
91         ctx.recyclePools();
92         PoolContext outer = ctx.getOuter().poolContext();
93         if (outer != null) {
94             outer.setInUsePoolsLocal(true);
95         }
96     }
97
98     // Overrides.
99
protected void dispose() {
100         for (int i = ObjectFactory.Count; i > 0;) {
101             ObjectPool pool = _pools[--i];
102             if (pool != ObjectPool.NULL) {
103                 pool.clearAll();
104             }
105         }
106         _inUsePoolsLength = 0;
107     }
108
109     /**
110      * Sets the pool currently being used as local or non-local.
111      *
112      * @param areLocal <code>true</code> if this context is the current
113      * pool context; <code>false</code> otherwise.
114      */

115     void setInUsePoolsLocal(boolean areLocal) {
116         Thread user = areLocal ? getOwner() : null;
117         for (int i = _inUsePoolsLength; i > 0;) {
118             _inUsePools[--i].user = user;
119         }
120     }
121
122     /**
123      * Returns the pool from the specified factory and marks it as local.
124      *
125      * @param index the factory index for the pool to return.
126      * @return the corresponding pool marked as local.
127      */

128     ObjectPool getLocalPool(int index) {
129         ObjectPool pool = _pools[index];
130         return (pool.user != null) ? pool : getLocalPool2(index);
131     }
132     private ObjectPool getLocalPool2(int index) {
133         ObjectPool pool = getPool(index);
134         pool.user = getOwner();
135         return pool;
136     }
137
138     /**
139      * Returns the pool from the specified factory in this context.
140      * The pool returned is marked "in use" and its outer is set.
141      *
142      * @param index the factory index of the pool to return.
143      * @return the corresponding pool.
144      */

145     private ObjectPool getPool(int index) {
146         ObjectPool pool = _pools[index];
147         if (pool == ObjectPool.NULL) { // Creates pool.
148
pool = ObjectFactory.INSTANCES[index].newPool();
149             _pools[index] = pool;
150         }
151         if (!pool.inUse) { // Marks it used and set its outer.
152
pool.inUse = true;
153             _inUsePools[_inUsePoolsLength++] = pool;
154             PoolContext outerPoolContext = this.getOuter().poolContext();
155             if (outerPoolContext != null) {
156                 synchronized (outerPoolContext) { // Not local.
157
pool.outer = outerPoolContext.getPool(index);
158                 }
159             } else {
160                 pool.outer = null;
161             }
162         }
163         return pool;
164     }
165
166     /**
167      * Recycles pools.
168      */

169     void recyclePools() {
170         // Recycles pools and reset pools used.
171
for (int i = _inUsePoolsLength; i > 0;) {
172             ObjectPool pool = _inUsePools[--i];
173             pool.recycleAll();
174             pool.user = null;
175             pool.inUse = false;
176         }
177         _inUsePoolsLength = 0;
178     }
179
180 }
Popular Tags