Re: Однопоточный smart-ptr с подсчетом ссылок.
От: Linuxoid  
Дата: 26.11.05 18:11
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Никто не подскажет, где взять сабж?

А>Синхронизация не нужна. Нужен неинтрузивный подсчет ссылок на объекты.

А>Скажем, нужен boost::shared_ptr с отключенной синхронизацией. или способ отключить ее без хирургического вмешательства.


Попробуй вот это. Автор я, сам с удовольствием пользуюсь. Класс используется в реальном коммерческом проекте.
Буду благодарен за любую конструктивную критику.


////////////////////////////////////////////////////////////////////////////////////
// countable.h
//
// Author:  Vitaliy Ivanchenko, <vtal@ukr.net>
// Copyright (c) Kiev, 2005
//
// Implementation of class that stores a pointer to allocated object of type T. 
// The stored pointer must either be NULL or designate an object allocated by a new
// expression.
//
////////////////////////////////////////////////////////////////////////////////////
//
//    History
// _________________________________________________________________________________
//
// [15.07.2005]
// _countable class was implemented.
// -----------------------------------------------------------------------
// [19.07.2005]
// Bugs were fixed in assignment operator:
// 1) Release of the stored object performed incorrectly before copying.
// 2) Memory used for reference counter was not free if the object is 
//    the same but counters are different.
// -----------------------------------------------------------------------
// [22.10.2005]
// Bug was fixed in assignment operator: 
// Memory used for reference counter was not release if pointer to stored 
// object equals NULL.
// -----------------------------------------------------------------------
// [22.10.2005]
// Assignment operator of pointer to countable object was implemented.
// -----------------------------------------------------------------------
//
#if !defined(__COUNTABLE_H_A1ECF5CC_FDB0_4f27_9D50_7F75C07AF8F4_INCLUDED_)
#define __COUNTABLE_H_A1ECF5CC_FDB0_4f27_9D50_7F75C07AF8F4_INCLUDED_

#include <assert.h>

template <typename T> class _countable 
{
public:
    typedef T element_type;
    
    //
    // Default constructor
    //
    explicit _countable(T * p = 0) throw() : m_pObj(p), m_pRef(NULL)
    {
        m_pRef = new long(0L);
        _increment();
    }
    
    //
    // Copying constructor
    //
    _countable(const _countable<T>& Y) throw() : m_pObj(Y.m_pObj), m_pRef(Y.m_pRef)
    {
        _increment();
    }
    
    //
    // Assignment operators
    //
    _countable<T>& operator=(const _countable<T>& Y) throw()
    {
        if (this != &Y)
        {
            if (m_pObj != Y.get())
            {
                _decrement();

                m_pObj = Y.get();
                m_pRef = Y.m_pRef;

                _increment();
            }
            else if (m_pRef != Y.m_pRef)
            {
                //
                // Usage counter (i.e. value of *m_pRef) must be equal to 1 always here;
                // otherwise we have unsolvable problem caused by incorrect _countable usage.
                //
                assert(1 == *m_pRef);
                if (1 == *m_pRef) delete m_pRef;
                m_pRef = Y.m_pRef;
                _increment();
            }
        }
        return (*this);
    }
    
    _countable<T>& operator=(typename T * pT) throw()
    {
        if( m_pObj != pT )
        {
            _decrement();
            m_pRef = new long(0L);
            m_pObj = pT;
            _increment();
        }

        return (*this);
    }

    //
    // Destructor
    //
    virtual ~_countable()
    {
        _decrement();
    }
    
    T& operator*() const throw()
    {
        return (*get());
    }

    T *operator->() const throw()
    {
        return (get());
    }

    T *get() const throw() 
    {
        return m_pObj;
    }
    
    long _increment()
    {
        return ++(*m_pRef);
    }
    
    long _decrement()
    {
        if (--(*m_pRef)) return (*m_pRef);
        
        //
        // Do something useful when counter reaches 0 (e.g. destroy object)
        //
        delete m_pObj;
        delete m_pRef;

        return 0;
    }

private:
    T * m_pObj;    // storage object pointer
    long * m_pRef;    // reference counter
};

#endif //__COUNTABLE_H_A1ECF5CC_FDB0_4f27_9D50_7F75C07AF8F4_INCLUDED_
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.