/**
 *  @file   intrusive_ptr_ref_count.h
 *  @brief  intrusive_ptrで指すクラスの参照カウンタ実装用クラス(継承して使う)
 *  @note
 *  -   deleteで開放するので、必ずnewで確保されること.
 *  -   delete (T*)this; がちゃんと実行できるように継承する必要がある.
 *      → intrusive_ptr_ref_count<T,C>を継承の1番目にする.
 */
#ifndef INTRUSIVE_PTR_REF_COUNT_INCLUDED
#define INTRUSIVE_PTR_REF_COUNT_INCLUDED
#ifndef assert
#include <cassert>
#endif

/// intrusive_ptrで指すクラスの参照カウンタ実装用クラス(継承して使う)
template< class T, typename C = unsigned>
class intrusive_ptr_ref_count {
public:
    intrusive_ptr_ref_count() : cnt_(0) {;}

    void add_ref_for_intrusive_ptr() {
        if (this) {
            ++cnt_;
            assert(cnt_ > 0);
        }
    }

    void release_for_intrusive_ptr() {
        if (this && cnt_ && --cnt_==0)
            delete (T*)(this);
    }

    C    ref_count() const { return this ? cnt_ : 0; }

private:
    C    cnt_;
};

template< class T, typename C > inline
void intrusive_ptr_add_ref(intrusive_ptr_ref_count<T,C>* p) {
    p->add_ref_for_intrusive_ptr();
}

template< class T, typename C > inline
void intrusive_ptr_release(intrusive_ptr_ref_count<T, C>* p) {
    p->release_for_intrusive_ptr();
}

#endif  // INTRUSIVE_PTR_REF_COUNT_INCLUDED