KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > realtime > RealtimeObject


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 import j2me.lang.UnsupportedOperationException;
12 import javolution.JavolutionError;
13 import javolution.lang.Text;
14
15 /**
16  * <p> This class provides a default implementation of the {@link Realtime}
17  * interface.</p>
18  * <p> Instances of this class should be created using the inner
19  * {@link Factory Factory} class. For example:<pre>
20  * public class Foo extends RealtimeObject {
21  * static final Factory&lt;Foo&gt; FACTORY = new Factory&lt;Foo&gt;() {
22  * protected Foo create() {
23  * return new Foo();
24  * }
25  * };
26  * protected Foo() {} // Default constructor for sub-classes.
27  * public static Foo newInstance() { // Static factory method.
28  * return FACTORY.object();
29  * }
30  *
31  * // Optional (see {@link Realtime} interface).
32  * public boolean move(ObjectSpace os) { ... }
33  * }</pre></p>
34  * <p> Instances of this class can be immutable. Instances allocated in a
35  * {@link PoolContext pool context} must be {@link #export exported}
36  * (e.g. return value) or {@link #preserve preserved} (e.g. static instance)
37  * if referenced after exiting the pool context.</p>
38  *
39  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
40  * @version 3.0, February 16, 2004
41  */

42 public abstract class RealtimeObject implements Realtime {
43
44     /**
45      * The pool this object belongs to or <code>null</code> if this object
46      * is on the heap (e.g. created using a class constructor).
47      */

48     private transient Factory.Pool _pool;
49
50     /**
51      * Holds the next object in the pool.
52      */

53     private transient RealtimeObject _next;
54
55     /**
56      * Holds the previous object in the pool.
57      */

58     private transient RealtimeObject _previous;
59
60     /**
61      * Holds the preserve counter.
62      */

63     private transient int _preserved;
64
65     /**
66      * Default constructor.
67      */

68     protected RealtimeObject() {
69     }
70
71     /**
72      * Returns the <code>String</code> representation of this object.
73      * This method is final to ensure consistency with {@link #toText()}
74      * (which is the method to override).
75      *
76      * @return <code>toText().stringValue()</code>
77      */

78     public final String toString() {
79         return toText().stringValue();
80     }
81
82     /**
83      * Returns the default textual representation of this realtime object.
84      *
85      * @return the textual representation of this object.
86      */

87     public Text toText() {
88         return Text.valueOf(getClass().getName()).concat(Text.valueOf('@'))
89                 .concat(Text.valueOf(System.identityHashCode(this), 16));
90     }
91
92     /**
93      * Exports this object and its <b>local</b> real-time associations out of
94      * the current pool context
95      * (equivalent to <code>{@link #move move}(ObjectSpace.OUTER)</code>).
96      * This method affects only local objects allocated on the stack
97      * and has no effect on heap objects or objects allocated outside of
98      * the current pool context.
99      *
100      * @return <code>this</code>
101      */

102     public final /*<T>*/ Object/*T*/ export() {
103         move(ObjectSpace.OUTER);
104         return (Object/*T*/) this;
105     }
106
107     /**
108      * Moves this object and its real-time associations to the heap
109      * (equivalent to <code>{@link #move move}(ObjectSpace.HEAP)</code>).
110      *
111      * @return <code>this</code>
112      */

113     public final /*<T>*/ Object/*T*/ moveHeap() {
114         move(ObjectSpace.HEAP);
115         return (Object/*T*/) this;
116     }
117
118     /**
119      * Prevents this object and its real-time associations to be recycled
120      * (equivalent to <code>{@link #move move}(ObjectSpace.HOLD)</code>).
121      * This method increments this object preserved counter.
122      *
123      * @return <code>this</code>
124      * @see #unpreserve
125      */

126     public final /*<T>*/ Object/*T*/ preserve() {
127         move(ObjectSpace.HOLD);
128         return (Object/*T*/) this;
129     }
130
131     /**
132      * Allows this object and its real-time associations to
133      * be recycled if not preserved any more (equivalent to
134      * <code>{@link #move move}(ObjectSpace.LOCAL)</code>).
135      * This method decrements this object preserved counter.
136      *
137      * @return <code>this</code>
138      * @see #preserve
139      */

140     public final /*<T>*/ Object/*T*/ unpreserve() {
141         move(ObjectSpace.LOCAL);
142         return (Object/*T*/) this;
143     }
144
145     // Implements Realtime interface.
146
public boolean move(ObjectSpace os) {
147
148         // export()
149
if (os == ObjectSpace.OUTER) {
150             if ((_pool == null) || (!_pool.isLocal())) {
151                 return false; // Not on the stack.
152
}
153             detach();
154             ObjectPool outer = _pool.getOuter();
155             if (outer == null) { // Heap.
156
_next = null;
157                 _previous = null;
158                 _pool = null;
159             } else {
160                 synchronized (outer) {
161                     _pool = (Factory.Pool) outer;
162                     insertBefore(_pool._next);
163                 }
164             }
165             return true;
166
167             // moveHeap()
168
} else if (os == ObjectSpace.HEAP) {
169             if (_pool == null) {
170                 return false; // Already on the heap.
171
}
172             synchronized (_pool) { // Might not be local.
173
detach();
174             }
175             _next = null;
176             _previous = null;
177             _pool = null;
178             return true;
179
180             // preserve()
181
} else if (os == ObjectSpace.HOLD) {
182             synchronized (this) {
183                 if (_preserved++ == 0) {
184                     if (_pool != null) {
185                         synchronized (_pool) { // Might not be local.
186
detach();
187                             insertBefore(_pool._holdTail);
188                         }
189                     }
190                     return true;
191                 } else {
192                     return false;
193                 }
194             }
195
196             // unpreserve()
197
} else if (os == ObjectSpace.LOCAL) {
198             synchronized (this) {
199                 if ((_preserved != 0) && (--_preserved == 0)) {
200                     if (_pool != null) {
201                         synchronized (_pool) { // Might not be local
202
detach();
203                             insertBefore(_pool._next);
204                         }
205                     }
206                     return true;
207                 } else {
208                     return false;
209                 }
210             }
211
212             // Ignores others context space (possible extensions).
213
} else {
214             return true; // Propagates by default.
215
}
216     }
217
218     /**
219      * Recycles this object and its internals only. This method should only be
220      * called when it can be asserted that this object is not going to be
221      * referenced anymore.
222      * This method affects only local objects and has no effect on heap objects
223      * or objects allocated outside of the current pool context.
224      * Unlike the {@link #move move} operations, recycling is limited to this
225      * object and its internals and has no effect on shared
226      * variable members ({@link javolution.realtime.Realtime real-time} or not).
227      */

228     protected void recycle() {
229         if (((_pool != null) && _pool.isLocal())) {
230             _pool.recycle(this);
231         }
232     }
233
234     /**
235      * Inserts this object before the one specified.
236      *
237      * @param the next object after insertion.
238      */

239     final void insertBefore(RealtimeObject next) {
240         _previous = next._previous;
241         _next = next;
242         _next._previous = this;
243         _previous._next = this;
244     }
245
246     /**
247      * Detaches this object from its linked list (but does not reset the
248      * objects variable members).
249      */

250     final void detach() {
251         _next._previous = _previous;
252         _previous._next = _next;
253     }
254
255     /**
256      * This abstract class represents the factory responsible for the
257      * creation of {@link RealtimeObject} instances.
258      */

259     public static abstract class Factory/*<T>*/ extends ObjectFactory/*<T>*/{
260
261         /**
262          * Holds the last used pools from this factory.
263          */

264         private Pool _cachedPool = new Pool();
265
266         /**
267          * Default constructor.
268          */

269         protected Factory() {
270         }
271
272         /**
273          * Returns a new or recycled object from this factory.
274          *
275          * @return an object from the local stack or from the heap if not
276          * executing in a pool context.
277          */

278         public final Object/*T*/object() {
279             Pool pool = _cachedPool;
280             if (pool.getUser() == Thread.currentThread()) {
281                 // Inline next()
282
final RealtimeObject next = pool._next;
283                 final RealtimeObject tmp = pool._next = next._next;
284                 return (Object/*T*/) ((tmp != null) ? next : pool.allocate());
285             } else {
286                 final ObjectPool/*<T>*/currentPool = currentPool();
287                 if (currentPool == heapPool()) {
288                     return newObject();
289                 } else {
290                     _cachedPool = pool = (Pool) currentPool;
291                     return pool.next();
292                 }
293             }
294         }
295
296         // Overrides.
297
protected ObjectPool/*<T>*/newPool() {
298             return new Pool();
299         }
300
301         /**
302          * This inner class represents a pool of {@link RealtimeObject}.
303          */

304         private final class Pool extends ObjectPool/*<T>*/{
305
306             /**
307              * Indicates if clean-up has to be performed (switches to false if
308              * UnsupportedOperationException raised during clean-up).
309              */

310             private boolean _doCleanup = true;
311
312             /**
313              * Holds the head object.
314              */

315             private final RealtimeObject _activeHead;
316
317             /**
318              * Holds the tail object.
319              */

320             private final RealtimeObject _activeTail;
321
322             /**
323              * Holds the objects on hold
324              */

325             private final RealtimeObject _holdHead;
326
327             /**
328              * Holds the objects on hold
329              */

330             private final RealtimeObject _holdTail;
331
332             /**
333              * Holds the next object to return.
334              */

335             private RealtimeObject _next;
336
337             /**
338              * Default constructor.
339              */

340             private Pool() {
341                 _activeHead = new Bound();
342                 _activeTail = new Bound();
343                 _activeHead._next = _activeTail;
344                 _activeTail._previous = _activeHead;
345
346                 _holdHead = new Bound();
347                 _holdTail = new Bound();
348                 _holdHead._next = _holdTail;
349                 _holdTail._previous = _holdHead;
350
351                 _next = _activeTail;
352             }
353
354             public Object/*T*/next() {
355                 final RealtimeObject next = _next;
356                 _next = next._next;
357                 return (Object/*T*/) ((_next != null) ? next : allocate());
358             }
359
360             private RealtimeObject allocate() {
361                 _next = _activeTail;
362                 ObjectPool outer = getOuter();
363                 RealtimeObject obj;
364                 if (outer == null) { // Heap.
365
obj = (RealtimeObject) newObject();
366                 } else {
367                     synchronized (outer) {
368                         obj = (RealtimeObject) outer.next();
369                         obj.detach();
370                     }
371                 }
372                 obj.insertBefore(_activeTail);
373                 obj._pool = this;
374                 return obj;
375             }
376
377             public void recycle(Object/*T*/obj) {
378                 // Cleanups object.
379
if (_doCleanup) {
380                     try {
381                         cleanup(obj);
382                     } catch (UnsupportedOperationException ex) {
383                         _doCleanup = false;
384                     }
385                 }
386
387                 RealtimeObject rtObj = (RealtimeObject) obj;
388                 if (rtObj._pool == this) {
389                     rtObj.detach();
390                     rtObj.insertBefore(_next);
391                     _next = _next._previous;
392                 } else {
393                     throw new JavolutionError("Object not in the pool");
394                 }
395             }
396
397             protected void recycleAll() {
398                 // Cleanups objects.
399
if (_doCleanup) {
400                     try {
401                         for (RealtimeObject rt = _activeHead._next; rt != _next;) {
402                             cleanup((Object/*T*/) rt);
403                             rt = rt._next;
404                         }
405                     } catch (UnsupportedOperationException ex) {
406                         _doCleanup = false;
407                     }
408                 }
409                 _next = _activeHead._next;
410             }
411
412             protected void clearAll() {
413                 _activeHead._next = _activeTail;
414                 _activeTail._previous = _activeHead;
415             }
416         }
417     }
418
419     /**
420      * This inner class represents internal linked list bounds
421      * (to avoid testing for null when inserting/removing).
422      */

423     private static final class Bound extends RealtimeObject {
424     }
425 }
Popular Tags