////////////////////////////////////////////////////////////////////////////
// VClsPtr.h
// オブジェクトの構築・破棄を管理する仮想上のポインタ
//

#if !defined( VCLSPTR_H_1BAF81E6_F936_4acd_BB26_4016D85338D1_INCLUDED_ )
#define VCLSPTR_H_1BAF81E6_F936_4acd_BB26_4016D85338D1_INCLUDED_

//#pragma message( "VClsPtr.h (C) 2003 nabiki_t. All rights reserved." )

#include "Semaphore.h"

namespace NNabikiVClsPtr {

// VClsPtrを適用するクラスが継承すべきクラス
// VClsPtrで使用する機能を実装する
class CCPInterface
{
public:
	// 参照カウンタ計算用のセマフォを構築する
	CCPInterface();

	// 参照カウンタ計算用のセマフォを破棄する
	virtual ~CCPInterface();

private:
	// 通称：参照カウンタの加算
	bool AddRef();

	// 通称：参照カウンタの減算
	bool Release();

	// 通称：クリティカルセクションに入る
	bool in();

	// 通称：クリティカルセクションから抜ける
	bool out();

	int RefCnt;	// 参照カウンタ
	CSemaphore m_Semaphore;	// セマフォ

public:
	// このクラスのAddRef及びReleaseを呼び出すための関数
	static bool glb_AddRef( CCPInterface *p );
	static bool glb_Release( CCPInterface *p );

protected:
	// 自身を破棄する
	virtual void DeleteThis();

};


// スマートポインタを実装
template < typename _T >
class VClsPtr
{
public:
	// コンストラクタ
	VClsPtr() : ptr( NULL ){};

	VClsPtr( _T *p ) : ptr( NULL ){
		Set( p );
	};

	VClsPtr( const VClsPtr< _T >& r ) : ptr( NULL ){
		Set( r );
	};

	// デストラクタ
	~VClsPtr(){
		Release();
	};

	// 代入
	const VClsPtr& operator =( const VClsPtr< _T >& r ){
		if ( this == &r ) return *this;
		Set( r );
		return *this;
	};
	const VClsPtr& operator =( _T *p ){
		Set( p );
		return *this;
	};

	// 等号
	bool operator ==( const VClsPtr< _T > &r ) const {
		return ( ptr == r.ptr );
	};

	// 値の設定
	void Set( const VClsPtr< _T >& r )
	{ Set( r.ptr ); };

	void Set( _T *p ){
		if ( ptr == p ) return ;	// 既存のポインタと同じアドレスであれば、処理しない
		Release();		// 参照カウンタを減算する
		ptr = p;		// アドレスを取得
		AddRef();		// 参照カウンタを加算する
	};

	// ポインタの取得
	_T* operator->() const{
		return ptr;
	};
	_T* GetPtr() const {
		return operator ->();
	};

	bool IsNull() const {
		return ( NULL == ptr );
	};

	// キャスト
	operator _T*() const {
		return operator ->();
	};
	/*operator bool() const{
		return ( NULL != ptr );
	};*/

	// 開放
	bool Release(){
		bool b = true;	// 戻り値記憶用
		// 開放
		if ( ptr ) b = CCPInterface::glb_Release( ptr );
		// if ( b ) ptr = NULL;	// ポインタのクリア
		return b;
	};

	// 参照カウンタの加算
	bool AddRef(){
		if ( NULL == ptr ) return false;
		return CCPInterface::glb_AddRef( ptr );
	};

protected:
	_T *ptr;	// 対象オブジェクトへのポインタ
};


}; // NNabikiVClsPtr

#pragma warning( pop )

#endif // VCLSPTR_H_1BAF81E6_F936_4acd_BB26_4016D85338D1_INCLUDED_
