/*
 * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
 * Copyright (C) 2005 - Javolution (http://javolution.org/)
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and distribute this software is
 * freely granted, provided that this notice is preserved.
 */
package javolution37.javolution.realtime;

import java.lang.UnsupportedOperationException;
import javax.realtime.MemoryArea;

import javolution37.javolution.lang.Text;

/**
 * 

This class provides a default implementation of the {@link Realtime} * interface.

* *

Instances of this class should be created using the inner * {@link Factory Factory} class. For example:[code] * public class Foo extends RealtimeObject { * static final Factory FACTORY = new Factory() { * protected Foo create() { * return new Foo(); * } * }; * protected Foo() {} // Default constructor for sub-classes. * public static Foo newInstance() { // Static factory method. * return FACTORY.object(); * } * * // Optional. * public boolean move(ObjectSpace os) { ... } * }[/code]

* *

Instances of this class can be immutable. Instances allocated in a * {@link PoolContext pool context} must be {@link #export exported} * (e.g. return value) or {@link #preserve preserved} (e.g. static instance) * if referenced after exiting the pool context.

* * @author Jean-Marie Dautelle * @version 3.7, January 1, 2006 */ public abstract class RealtimeObject implements Realtime { /** * The pool this object belongs to or null if this object * is on the heap (e.g. created using a class constructor). */ private transient Pool _pool; /** * Holds the next object in the pool. */ private transient RealtimeObject _next; /** * Holds the previous object in the pool. */ private transient RealtimeObject _previous; /** * Holds the preserve counter. */ private transient int _preserved; /** * Default constructor. */ protected RealtimeObject() { } /** * Returns the String representation of this object. * This method is final to ensure consistency with {@link #toText()} * (which is the method to override). * * @return toText().stringValue() */ public final String toString() { return toText().stringValue(); } /** * Returns the default textual representation of this realtime object. * * @return the textual representation of this object. */ public Text toText() { return Text.valueOf(getClass().getName()).concat(Text.valueOf('@')) .concat(Text.valueOf(System.identityHashCode(this), 16)); } /** * Exports this object and its local real-time associations out of * the current pool context (equivalent to {@link #move move} * (ObjectSpace.OUTER)). * This method affects only local objects allocated on the stack * and has no effect on heap objects or objects allocated outside of * the current pool context. * *

Note: To avoid pool depletion when exporting to outer pool, * the object is actually exchanged with an outer pool object.

* * @return this */ public final T export() { move(ObjectSpace.OUTER); return ( T ) this; } /** * Moves this object and its real-time associations to the heap * (equivalent to {@link #move move}(ObjectSpace.HEAP)). * * @return this */ public final T moveHeap() { move(ObjectSpace.HEAP); return ( T ) this; } /** * Prevents this object and its real-time associations to be recycled * (equivalent to {@link #move move}(ObjectSpace.HOLD)). * This method increments this object preserved counter. * * @return this * @see #unpreserve */ public final T preserve() { move(ObjectSpace.HOLD); return ( T ) this; } /** * Allows this object and its real-time associations to * be recycled if not preserved any more (equivalent to * {@link #move move}(ObjectSpace.STACK)). * This method decrements this object preserved counter. * * @return this * @see #preserve */ public final T unpreserve() { move(ObjectSpace.STACK); return ( T ) this; } // Implements Realtime interface. public boolean move(ObjectSpace os) { if (os == ObjectSpace.OUTER) { // export() if ((_pool == null) || (!_pool.isLocal())) return false; // Not on the stack. Pool outer = (Pool) _pool.outer; if (outer == null) return move(ObjectSpace.HEAP); detach(); // Exchanges with outer. synchronized (outer) { // Might be shared. RealtimeObject outerObj = (RealtimeObject) outer.next(); outerObj.detach(); outerObj.insertBefore(_pool._activeTail); // Marks unused. outerObj._pool = _pool; insertBefore(outer._next); // Marks used. _pool = outer; } return true; } else if (os == ObjectSpace.HEAP) { // moveHeap() synchronized (this) { // Might not be local. if (_pool == null) return false; // Already on the heap. synchronized (_pool) { // Might be shared. detach(); _pool._size--; // Object removed from pool. _next = null; _previous = null; _pool = null; return true; } } } else if (os == ObjectSpace.HOLD) { // preserve() synchronized (this) { // Might not be local. if (_pool == null) return false; // On the heap. if (_preserved++ == 0) { synchronized (_pool) { // Might be shared. detach(); insertBefore(_pool._holdTail); } return true; } else { return false; } } } else if (os == ObjectSpace.STACK) { // unpreserve() synchronized (this) { // Might not be local. if ((_preserved != 0) && (--_preserved == 0)) { if (_pool != null) { synchronized (_pool) { // Might be shared. detach(); insertBefore(_pool._next); } } return true; } else { return false; } } // Ignores others context space (possible extensions). } else { return true; // Propagates by default. } } /** * Recycles this object and its internals only. This method should only be * called when it can be asserted that this object is not going to be * referenced anymore. * This method affects only local objects and has no effect on heap objects * or objects allocated outside of the current pool context. * Unlike the {@link #move move} operations, recycling is limited to this * object and its internals and has no effect on external * variable members ({@link javolution37.javolution.realtime.Realtime real-time} or not). */ protected void recycle() { if (((_pool != null) && _pool.isLocal())) { _pool.recycle(this); } } /** * Inserts this object before the one specified. * * @param the next object after insertion. */ final void insertBefore(RealtimeObject next) { _previous = next._previous; _next = next; _next._previous = this; _previous._next = this; } /** * Detaches this object from its linked list (but does not reset the * objects variable members). * Note: pool._next should never be detached. */ final void detach() { _next._previous = _previous; _previous._next = _next; } /** * This abstract class represents the factory responsible for the * creation of {@link RealtimeObject} instances. */ public static abstract class Factoryextends ObjectFactory { /** * Holds the last used pool from this factory. */ private Pool _cachedPool = new Pool(null); /** * Default constructor. */ protected Factory() { } /** * Returns a new or recycled object from this factory. * * @return an object from the local stack or from the heap if not * executing in a pool context. */ public final T object() { final Thread currentThread = Thread.currentThread(); Pool pool = _cachedPool; if (pool.user == currentThread) { // Inline next() final RealtimeObject next = pool._next; return ( T ) (((pool._next = next._next) != null) ? next : pool.allocate()); } final PoolContext poolContext = Context.poolContext(currentThread); if (poolContext == null) return create(); pool = (Pool) poolContext.getLocalPool(_index); T obj = ( T ) pool.next(); _cachedPool = pool; // Do it last. return obj; } // Overrides. protected ObjectPool newPool() { ObjectPool pool = new Pool(this); return (ObjectPool ) pool; } } /** * This inner class represents a pool of {@link RealtimeObject}. */ private static final class Pool extends ObjectPool { /** * Holds the factory. */ private final Factory _factory; /** * Holds the memory area of this pool. */ private final MemoryArea _memoryArea; /** * Holds number of objects held by this pool. */ private int _size; /** * Indicates if clean-up has to be performed (switches to false if * UnsupportedOperationException raised during clean-up). */ private boolean _doCleanup = true; /** * Holds the head object. */ private final RealtimeObject _activeHead; /** * Holds the tail object. */ private final RealtimeObject _activeTail; /** * Holds the objects on hold */ private final RealtimeObject _holdHead; /** * Holds the objects on hold */ private final RealtimeObject _holdTail; /** * Holds the next object to return. */ private RealtimeObject _next; /** * Default constructor. */ private Pool(Factory factory) { _factory = factory; _memoryArea = MemoryArea.getMemoryArea(this); _activeHead = new Bound(); _activeTail = new Bound(); _activeHead._next = _activeTail; _activeTail._previous = _activeHead; _holdHead = new Bound(); _holdTail = new Bound(); _holdHead._next = _holdTail; _holdTail._previous = _holdHead; _next = _activeTail; } // Implements ObjectPool abstract method. public int size() { return _size; } // Implements ObjectPool abstract method. public Object next() { final RealtimeObject next = _next; _next = next._next; return ((_next != null) ? next : allocate()); } private RealtimeObject allocate() { _next = _activeTail; _memoryArea.executeInArea(new Runnable() { public void run() { RealtimeObject obj = (RealtimeObject) _factory.create(); _size++; obj.insertBefore(_activeTail); obj._pool = Pool.this; } }); return _activeTail._previous; } // Implements ObjectPool abstract method. public void recycle(Object obj) { // Cleanups object. if (_doCleanup) { try { _factory.cleanup(obj); } catch (UnsupportedOperationException ex) { _doCleanup = false; } } RealtimeObject rtObj = (RealtimeObject) obj; if (rtObj._pool == this) { rtObj.detach(); rtObj.insertBefore(_next); _next = _next._previous; } else { throw new IllegalArgumentException("Object not in the pool"); } } // Implements ObjectPool abstract method. protected void recycleAll() { // Cleanups objects. if (_doCleanup) { try { for (RealtimeObject rt = _activeHead._next; rt != _next;) { _factory.cleanup(rt); rt = rt._next; } } catch (UnsupportedOperationException ex) { _doCleanup = false; } } _next = _activeHead._next; } // Implements ObjectPool abstract method. protected void clearAll() { _activeHead._next = _activeTail; _activeTail._previous = _activeHead; } } /** * This inner class represents internal linked list bounds * (to avoid testing for null when inserting/removing). */ private static final class Bound extends RealtimeObject { } }

Ads help maintain this website.