#ifndef KLX_SMARTC_HPP #define KLX_SMARTC_HPP //============================================================================ // <> library // // 複数のオブジェクトで共有される定数値オブジェクトを管理することが目的 // なテンプレート。参照カウントが0になった時点で登録された破棄関数を // 呼び出す機能を持つ。具体的には //  ・OSの返すハンドルをラップして管理 //  ・スマートポインタテンプレートの下支え //  ・簡易スコープガード // などとして使うことが出来る。 // // [interface] // // class smart_constant // { // construct(); // 値はデフォルト初期化、破棄関数無し // constrcut(T t, D d); // 値と破棄関数を指定して初期化 // construct(copy); // コピー // operator=(copy); // 代入 // const T operator*() const; // 格納されている値の取得 // } // // [note] // // ・循環参照はダメ // ・例外安全 // ・スレッドセーフ (#if KLX_MULTITHREAD) // // [dependency] // // ・マクロ KLX_MULTITHREAD によって動作が変わる // ・関数 InterlockedIncrement @ win32api (#if KLX_MULTITHREAD) // ・関数 InterlockedDecrement @ win32api (#if KLX_MULTITHREAD) // // [ref] // // ・http://www.boost.org/libs/smart_ptr/shared_ptr.htm // //============================================================================ #ifdef KLX_MULTITHREAD #define KLX_SMARTC_COUNTUP(v) ::InterlockedIncrement(&v) #define KLX_SMARTC_COUNTDN(v) ::InterlockedDecrement(&v) #else #define KLX_SMARTC_COUNTUP(v) (++v) #define KLX_SMARTC_COUNTDN(v) (--v) #endif namespace klx { //---------------------------------------------------------------------------- template class smart_constant { public: typedef smart_constant this_type; typedef T element_type; public: smart_constant() : body( new counted_body(T()) ) { } template smart_constant( const T& t, D d ) : body( new counted_body_with_deleter(t,d) ) { } smart_constant( const this_type& rhs ) : body( rhs.body->countUp() ) { } this_type& operator=( const this_type& rhs ) { body->countDown(); body = rhs.body->countUp(); // countUp は no throw ゆえこの順で安全 return *this; } ~smart_constant() { body->countDown(); } public: const T operator*() const { return body->getData(); } private: // 参照カウント機能 class counted_body { public: counted_body( const T& t ) : data(t), count(1) {} virtual ~counted_body() {} const T getData() const { return data; } counted_body* countUp() { KLX_SMARTC_COUNTUP(count); return this; } void countDown() { if( KLX_SMARTC_COUNTDN(count)==0 )delete this; } private: const T data; long count; }; // 破棄関数呼び出し機能 template class counted_body_with_deleter : public counted_body { public: counted_body_with_deleter( const T& t, D d ) : counted_body(t), deleter(d) {} private: virtual ~counted_body_with_deleter() { deleter(getData()); } D deleter; }; private: counted_body* body; }; //---------------------------------------------------------------------------- #undef KLX_SMARTC_COUNTUP #undef KLX_SMARTC_COUNTDN } // namespace end #endif // INCLUDE_GUARD