#ifndef __JBXL_CPP_EXTEND_GRAPHIC_DATA_H_ #define __JBXL_CPP_EXTEND_GRAPHIC_DATA_H_ /** @brief メモリ管理機能付グラフィックデータ定義用ヘッダ @file ExGdata.h @author Fumi.Iseki */ #include "Gdata.h" // namespace jbxl { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // メモリ管理機能付 ExMSGraph, ExCmnHead // /** @file ExGdata.h メモリ管理機能 --- @par メモリ管理を付ける事の利点: 色々な関数(クラス)から同時に使用(兼用)できるので,メモリの節約になる.メモリが沢山(無尽蔵に) あるのなら,その都度コピーして渡した方がアルゴリズムは簡単. @par 手法: メモリ(データ)に対して,ペアとなるint型の参照数変数を用意し,メモリへの参照数を参照数変数に格納する. そのため operator= をオーバーロードする.@n メモリ管理機能の無い変数から代入される場合は,予め参照数変数を結合しておかないと,メモリ管理 機能無しの状態になる.@n 例えば,msgにメモリ管理機能を持たせるには,以下のようにする. @code int ref; ExMSGraph<> msg; msg.setRefer(&ref); msg = vp; // vp: 管理機能無しの変数 @endcode また,以下の場合 xpがメモリ(データ)を持つ時は注意. @code ExMSGraph<> msg; msg = xp; // xp: 管理機能ありの変数 msg = vp; // vp: 管理機能無しの変数 @endcode msgは xpの参照数変数を引き継ぎ,メモリ(データ)管理機能付変数となる.@n msgのメモリ部(データ)が空の場合,msg = vp; では,引き続き参照数変数を使用して, vpのメモリ(データ)を管理する.@n msgにメモリ(データ)が存在する場合,msg = vp; でmsgはそのメモリ(データ)への参照を止め,vp をコピーする.@n すなわち,この場合はメモリ管理機能なしになる.@n つまり,xpがメモリ(データ)を持たなければ,xp, msgの参照数変数は 1になり,msgは vpのメモリを管理する.@n xpがメモリを持っていれば,msgはメモリ管理機能なしになる.@n @par 参照数変数 - 1以上 : メモリ(グラフィックデータ)が存在し,参照されている. - 0 : メモリ(グラフィックデータ)は存在するが,どこからも参照されていない. 通常この状態は一時的であり,次のステップで 1 か -1になる. - -1 : メモリ(グラフィックデータ)は存在しない. - -2以下 : 通常この状態は -1 に戻される.   @attention ディストラクタはメモリを解放しないので,必ず手動で解放すること. */ /** template class ExMSGraph : public MSGraph 必ず参照数変数(refnoの実体)を指定すること.無くても動くかも知れないが,保証は無い. 関数の中からディストラクトされるメモリ(のコピー)をリターンする場合は,returnの前に mfree()を実行させること. */ template class ExMSGraph : public MSGraph { public: //protected: int* refno; // メモリ領域への参照オブジェクト数 // public: ExMSGraph(int x, int y=1, int z=1, T v=(T)0, T b=(T)0, double rz=1.0, int* rn=NULL) { set(x, y, z, v, b, rz, rn);} ExMSGraph(RBound rb, T v=(T)0, T b=(T)0, double rz=1.0, int* rn=NULL){ set(rb, v, b, rz, rn);} ExMSGraph(int* rn=NULL) { MSGraph::init(); setRefer(rn);} virtual ~ExMSGraph(void) {} void set(int x, int y=1, int z=1, T v=(T)0, T b=(T)0, double rz=1.0, int*rn=NULL); void set(RBound rb, T v=(T)0, T b=(T)0, double rz=1.0, int*rn=NULL); void mimicry(ExMSGraph s) { set(s.xs, s.ys, s.zs, s.zero, s.base, s.RZxy, NULL);} bool isNull(void); ///< グラフィックデータを持いないか? void free(void); ///< グラフィックデータを開放する(メモリ管理なし兼用) void mfree(bool azero=false); ///< グラフィックデータを開放する void ffree(void); ///< グラフィックデータを強制開放する void setRefer(int* rn); ExMSGraph operator= (ExMSGraph& s); ExMSGraph operator= (MSGraph& s); }; // template void ExMSGraph::set(RBound rb, T v, T b, double rz, int* rn) { set(rb.xmax-rb.xmin+1, rb.ymax-rb.ymin+1, rb.zmax-rb.zmin+1, v, b, rz, rn); MSGraph::rbound = rb; return; } // template void ExMSGraph::set(int x, int y, int z, T v, T b, double rz, int* rn) { if (z<=0) z = 1; MSGraph::getm(x, y, z, v); if (MSGraph::gp==NULL) return; MSGraph::base = b; if (rz==0.0) MSGraph::RZxy = 1.0; else MSGraph::RZxy = rz; MSGraph::rbound.set(0, x-1, 0, y-1, 0, z-1); if (rn!=NULL) setRefer(rn); else if (refno!=NULL) { if (MSGraph::gp==NULL) *refno = -1; else *refno = 1; } return; } // template void ExMSGraph::setRefer(int* rn) { refno = rn; if (refno!=NULL) { if (MSGraph::gp==NULL) *refno = -1; else *refno = 1; } } // グラフィックデータを持いないか? template bool ExMSGraph::isNull(void) { if (MSGraph::gp==NULL) return true; #ifdef WIN32 if (MSGraph::gp==(T*)WIN_DD_NULL) return true; #endif if (refno!=NULL) { if (*refno<0) return true; else return false; } return false; } /** template void ExMSGraph::free(void) グラフィックデータを開放する メモリ管理をしている場合は,参照数を減らす. メモリ管理をしていない場合は,強制的に開放する. */ template void ExMSGraph::free(void) { if (refno==NULL) { if (!isNull()) { ::free(MSGraph::gp); MSGraph::init(); // gp = NULL; } } else { mfree(); } return; } /** template void ExMSGraph::mfree(bool azero) グラフィックデータを開放する メモリ管理をしている場合は,参照数を減らす. メモリ管理をしていない場合は,何もしない. @param azero @b true: 参照数 0 の状態を許す. */ template void ExMSGraph::mfree(bool azero) { if (refno!=NULL) { (*refno)--; if (!azero && *refno==0) { ::free(MSGraph::gp); *refno = -1; MSGraph::init(); // gp = NULL; } else if (*refno==-1) { DEBUG_MODE PRINT_MESG("ExMSGraph::mfree: [警告] 通常ありえない参照数 0\n"); } else if (*refno<-1) { *refno = -1; } } return; } /** template void ExMSGraph::ffree() グラフィックデータを強制的に開放する */ template void ExMSGraph::ffree() { if (refno==NULL) { if (!isNull()) { ::free(MSGraph::gp); } } else { if (*refno>=0) { ::free(MSGraph::gp); *refno = -1; } } MSGraph::init(); // gp = NULL; return; } // オペレータ // template ExMSGraph ExMSGraph::operator= (ExMSGraph& s) { ExMSGraph dm = *this; MSGraph::xs = s.xs; MSGraph::ys = s.ys; MSGraph::zs = s.zs; MSGraph::gp = s.gp; MSGraph::zero = s.zero; MSGraph::base = s.base; MSGraph::max = s.max; MSGraph::min = s.min; MSGraph::color = s.color; MSGraph::state = s.state; MSGraph::rbound = s.rbound; MSGraph::RZxy = s.RZxy; MSGraph::norm = s.norm; MSGraph::wRateX = s.wRateX; MSGraph::wRateY = s.wRateY; MSGraph::wRateZ = s.wRateZ; MSGraph::wZeroX = s.wZeroX; MSGraph::wZeroY = s.wZeroY; MSGraph::wZeroZ = s.wZeroZ; MSGraph::wNowX = s.wNowX; MSGraph::wNowY = s.wNowY; MSGraph::wNowZ = s.wNowZ; if (!s.isNull()) { // コピー元はデータを持っている. if (s.refno!=NULL) { // コピー元は参照数変数を持っている. if (*s.refno>=0) { // 相手の参照数変数を使う. refno = s.refno; (*refno)++; } else { DEBUG_MODE PRINT_MESG("ExMSGraph::= (ExMSGraph): コピー元参照数変数の不正!!\n"); } } else { // コピー元は参照数変数を持っていない. if (refno!=NULL) { // 自分の参照数変数を持っている. if (*refno<=-1) *refno = 1; // 自分の参照数変数が未使用ならそれを使う. else refno = NULL; // 参照数変数は誰かが使っているので,自分は参照数変数無しになる. } } } else { // コピー元はデータを持っていない MSGraph::gp = NULL; if (s.refno!=NULL) { // コピー元は参照数変数を持っている. refno = s.refno; // 相手の参照数変数を使う. *refno = -1; // データは無いので -1 に. } else { // コピー元は参照数変数を持っていない. if (refno!=NULL) { // 自分の参照数変数を持っている. if (*refno<=-1) *refno = -1; // 自分の参照数変数が未使用ならそれを使う. else refno = NULL; // 参照数変数は誰かが使っているので,自分は参照数変数無しになる. } } } if (!dm.isNull()) dm.mfree(); return *this; } // オペレータ // template ExMSGraph ExMSGraph::operator= (MSGraph& s) { if (!isNull()) mfree(); MSGraph::xs = s.xs; MSGraph::ys = s.ys; MSGraph::zs = s.zs; MSGraph::gp = s.gp; MSGraph::zero = s.zero; MSGraph::base = s.base; MSGraph::max = s.max; MSGraph::min = s.min; MSGraph::color = s.color; MSGraph::state = s.state; MSGraph::rbound = s.rbound; MSGraph::RZxy = s.RZxy; MSGraph::norm = s.norm; MSGraph::wRateX = s.wRateX; MSGraph::wRateY = s.wRateY; MSGraph::wRateZ = s.wRateZ; MSGraph::wZeroX = s.wZeroX; MSGraph::wZeroY = s.wZeroY; MSGraph::wZeroZ = s.wZeroZ; MSGraph::wNowX = s.wNowX; MSGraph::wNowY = s.wNowY; if (!s.isNull()) { // コピー元はデータを持っている. if (refno!=NULL) { // 自分の参照数変数を持っている. if (*refno<=-1) *refno = 1; // 自分の参照数変数が未使用ならそれを使う. else refno = NULL; // 参照数変数は誰かが使っているので,自分は参照数変数無しになる. } } else { // コピー元はデータを持っていない MSGraph::gp = NULL; if (refno!=NULL) { // 自分の参照数変数を持っている. if (*refno<=-1) *refno = -1; // 自分の参照数変数が未使用ならそれを使う. else refno = NULL; // 参照数変数は誰かが使っているので,自分は参照数変数無しになる. } } return *this; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // メモリ管理付 CmnHead // /** class ExCmnHead : public CmnHead 必ず参照数変数(refnoの実体)を指定すること.無くても動くかも知れないが,保証は無い. 関数の中からディストラクトされるメモリ(のコピー)をリターンする場合は,returnの前に mfree()を実行させること. */ class ExCmnHead : public CmnHead { public: int state; int dbyte; //protected: int* refno; public: ExCmnHead(int x, int y=1, int z=1, int d=8, int* rn=NULL) { set(x, y, z, d, rn);} ExCmnHead(RBound rb, int d=8, int* rn=NULL) { set(rb, d, rn);} ExCmnHead(int* rn=NULL) { init(); setRefer(rn);} ExCmnHead(ExCmnHead& cmhd) = default; virtual ~ExCmnHead(void) {} void init(void); void set (RBound rb, int d=8, int* rn=NULL); void set (int x, int y=1, int z=1, int d=8, int* rn=NULL); void getm(int x, int y=1, int z=1, int d=8); ///< グラフィックメモリを獲得する. void clear() {memset(grptr, 0, lsize);} uByte& point(int x, int y=0, int z=0) { return grptr[dbyte*(x+xsize*y+xsize*ysize*z)];} ///< 座標(x,y,z)の画素値の参照 bool isNull(void); ///< グラフィックデータを持いないか? void free(void); ///< グラフィックデータを開放する(メモリ管理なし兼用) void mfree(bool azero=false); ///< グラフィックデータを開放する void ffree(void); ///< グラフィックデータを強制開放する void setRefer(int* rn); // void decRefer() { (*refno)--;} ///< 次のステップで強制的に +1される場合,予め実行する. ExCmnHead operator= (ExCmnHead& m); ExCmnHead operator= (CmnHead& m); }; } // namespace #endif //__JBXL_CPP_EXTEND_GRAPHIC_DATA_H_