package jp.nyatla.nyartoolkit.core.utils;
import java.lang.reflect.Array;
import jp.nyatla.nyartoolkit.NyARException;
/**
* このクラスは、参照カウンタ付きのObjectPoolの基本クラスです。
* {@link NyARManagedObject}から派生したオブジェクト型Tのオブジェクトプールを実現します。
*
* オブジェクトプールは、未割当リストを使って、オブジェクト要素を管理します。
* はじめ、全てのオブジェクト要素は未割当リストにあります。オブジェクト要素の生成要求があると、オブジェクトプール
* は未割当リストにあるオブジェクト要素の参照カウンタを1加算して、未割当リストから削除します。
* 逆に、オブジェクト要素の解放を要求があると、オブジェクト要素の参照カウンタを1減算して、その数が 0になったら、
* オブジェクト要素を未割当リストへ加えます。
* <br/>
* このクラスは、NyARManagedObjectと密接に関係して動作することに注意してください。
* 割り当て関数はオブジェクトプールの{@link NyARManagedObjectPool#newObject}、解放関数にはオブジェクト要素の
* {@link NyARManagedObject#releaseObject()}を使います。
* <br/>
* また、このクラスは{@link NyARManagedObject}に対して、特殊な関数を持つインタフェイスを提供します。
* このインタフェイスは、{@link NyARManagedObject}が{@link NyARManagedObjectPool}のリストを操作するために使います。
* <p>継承クラスの実装について -
* このクラスは、そのまま実体化できません。継承クラスを実装する必要があります。
* 実装するには、{@link #createElement}をオーバライドして、コンストラクタから{@link #initInstance}を呼び出します。
* {@link #initInstance}には2種類の関数があります。要素生成パラメータの有無で、どちらかを選択して呼び出してください。
* </p>
*
* @param <T>
*/
public class NyARManagedObjectPool<T extends NyARManagedObject>
{
/**
* このクラスは、{@link NyARManagedObject}へ提供する操作インタフェイスの実体です。
* 未割当リストを操作する関数を定義します。
* Javaの都合でバッファを所有させていますが、別にこの形で実装しなくてもかまいません。
*/
public class Operator implements NyARManagedObject.INyARManagedObjectPoolOperater
{
/** 要素の実体の保管用リスト*/
public NyARManagedObject[] _buffer;
/** 未割当オブジェクトのリスト*/
public NyARManagedObject[] _pool;
public int _pool_stock;
public void deleteObject(NyARManagedObject i_object)
{
assert(i_object!=null);
assert(this._pool_stock<this._pool.length);
this._pool[this._pool_stock]=i_object;
this._pool_stock++;
}
}
/**
* オブジェクト要素から参照する操作インタフェイス。ユーザが使用することはありません。
* <p>メモ - このスコープはprotectedではないか?</p>
*/
public Operator _op_interface=new Operator();
/**
* この関数は、新しいオブジェクトを1個割り当てて返します。
* @return
* 新しいオブジェクト。失敗した場合はnull
*/
@SuppressWarnings("unchecked")
public T newObject() throws NyARException
{
Operator pool=this._op_interface;
if(pool._pool_stock<1){
return null;
}
pool._pool_stock--;
//参照オブジェクトを作成して返す。
return (T)(pool._pool[pool._pool_stock].initObject());
}
/**
* コンストラクタです。
* 生成拒否の為に、コンストラクタを隠蔽します。
* 継承クラスを作成してください。
*/
protected NyARManagedObjectPool()
{
}
/**
* この関数は、インスタンスを初期化します。
* 継承クラスのコンストラクタから呼び出します。
* {@link #initInstance(int, Class, Object)}との違いは、オブジェクトの生成に引数を渡すかどうかです。
* 引数が必要な時は、こちらの関数を使って、{@link #createElement()}をオーバライドします。
* @param i_length
* 配列の最大長さ
* @param i_element_type
* 配列型を示すクラスタイプ
* @throws NyARException
*/
@SuppressWarnings("unchecked")
protected void initInstance(int i_length,Class<T> i_element_type) throws NyARException
{
Operator pool=this._op_interface;
//領域確保
pool._buffer = (T[])Array.newInstance(i_element_type, i_length);
pool._pool = (T[])Array.newInstance(i_element_type, i_length);
//使用中個数をリセット
pool._pool_stock=i_length;
//オブジェクトを作成
for(int i=pool._pool.length-1;i>=0;i--)
{
pool._buffer[i]=pool._pool[i]=createElement();
}
return;
}
/**
* この関数は、インスタンスを初期化します。
* 継承クラスのコンストラクタから呼び出します。
* {@link #initInstance(int, Class)}との違いは、オブジェクトの生成に引数を渡すかどうかです。
* 引数が必要な時は、こちらの関数を使って、{@link #createElement(Object)}をオーバライドします。
* @param i_length
* 配列の最大長さ
* @param i_element_type
* 配列型を示すクラスタイプ
* @param i_param
* 配列要素を生成するときに渡すパラメータ
* @throws NyARException
*/
@SuppressWarnings("unchecked")
protected void initInstance(int i_length,Class<T> i_element_type,Object i_param) throws NyARException
{
Operator pool=this._op_interface;
//領域確保
pool._buffer = (T[])Array.newInstance(i_element_type, i_length);
pool._pool = (T[])Array.newInstance(i_element_type, i_length);
//使用中個数をリセット
pool._pool_stock=i_length;
//オブジェクトを作成
for(int i=pool._pool.length-1;i>=0;i--)
{
pool._buffer[i]=pool._pool[i]=createElement(i_param);
}
return;
}
/**
* この関数は、配列要素のオブジェクトを1個作ります。
* {@link #initInstance(int, Class)}から呼び出されます。
* 継承クラスでオーバライドして、要素オブジェクトを1個生成して返す処理を実装してください。
* @return
* 新しいオブジェクトを返してください。
* @throws NyARException
*/
protected T createElement() throws NyARException
{
throw new NyARException();
}
/**
* この関数は、配列要素のオブジェクトを(引数付きで)1個作ります。
* {@link #initInstance(int, Class, Object)}から呼び出されます。
* 継承クラスでオーバライドして、要素オブジェクトを1個生成して返す処理を実装してください。
* @return
* 新しいオブジェクトを返してください。
* @throws NyARException
*/
protected T createElement(Object i_param) throws NyARException
{
throw new NyARException();
}
}