资源分配和自动释放

时间:2010-05-25 12:40:31

标签: c++

在我的应用程序中,我得到了许多类CDbaOciNotifier 的实例。它们都共享指向类OCIEnv 的一个实例的指针。

我想要实现的是资源类OCIEnv 的分配和释放将在类CDbaOciNotifier 中自动处理。

理想的行为是,在类CDbaOciNotifier 的第一个实例中,将创建环境,之后所有后续通知程序都使用相同的环境。随着最后一个通知程序的破坏,环境也将被破坏(调用自定义删除程序)。 稍后,可以通过创建新环境重新开始此循环。

到目前为止我所拥有的(使用静态工厂方法创建通知程序):

#pragma once

#include <string>
#include <memory>
#include "boost\noncopyable.hpp"

class CDbaOciNotifier : private boost::noncopyable
{
public:

    virtual ~CDbaOciNotifier(void);

    static std::auto_ptr<CDbaOciNotifier> createNotifier(const std::string &tnsName, const std::string &user, const std::string &password);

private:
    CDbaOciNotifier(OCIEnv* envhp);

    // All notifiers share one environment
    static OCIEnv* m_ENVHP;

    // Custom deleter
    static void freeEnvironment(OCIEnv *env);

    OCIEnv* m_envhp;
};

CPP:

#include "DbaOciNotifier.h"

using namespace std;

OCIEnv* CDbaOciNotifier::m_ENVHP = 0;

CDbaOciNotifier::~CDbaOciNotifier(void)
{
}

CDbaOciNotifier::CDbaOciNotifier(OCIEnv* envhp)
                :m_envhp(envhp)
{

}

void CDbaOciNotifier::freeEnvironment(OCIEnv *env)
{
    OCIHandleFree((dvoid *) env, (ub4) OCI_HTYPE_ENV);
    *env = null;
}

auto_ptr<CDbaOciNotifier> CDbaOciNotifier::createNotifier(const string &tnsName, const string &user, const string &password)
{
    if(!m_ENVHP)
    {
        OCIEnvCreate( (OCIEnv **) &m_ENVHP, OCI_EVENTS|OCI_OBJECT, (dvoid *)0,
            (dvoid * (*)(dvoid *, size_t)) 0,
            (dvoid * (*)(dvoid *, dvoid *, size_t))0,
            (void (*)(dvoid *, dvoid *)) 0,
            (size_t) 0, (dvoid **) 0 );
    }

    //shared_ptr<OCIEnv> spEnvhp(m_ENVHP, freeEnvironment); ...got so far...

    return auto_ptr<CDbaOciNotifier>(new CDbaOciNotifier(m_ENVHP));
}

我想避免自己计算引用(通知程序),并使用像shared_ptr这样的东西。

您是否看到了解决我问题的简单方法?

2 个答案:

答案 0 :(得分:2)

您的代码中有很多内容。这是解决方案,但简化为基本要素。

class CDbaOciNotifier
{
public:
   CDbaOciNotifier() :
      m_resource(get_env())
   { }

private:
   shared_ptr<OCIEnv> m_env;

   struct Delete_env
   {
      void operator()(OCIEnv* env)
      {
         OCIHandleFree( ... );
      }
   };

   static shared_ptr<OCIEnv> get_env()
   {
        // make sure a mutex is involved if CDbaOciNotifier
        // can be constructed concurrently.

        static weak_ptr<OCIEnv> s_env;

        shared_ptr<OCIEnv> env = s_env.lock();
        if( ! env )
        {
            OCIEnv* env_ptr = OCIEnvCreate( ... );
            env.reset( env_ptr, Delete_env() );
            s_env = env;
        }
        return env;
   }
};

如上所述,您无法同时构建CDbaOciNotifier。如果你想要这种能力,你需要一个静态互斥锁来保护s_env

weak_ptr需要是本地静态函数,否则如果创建了全局或静态CDbaOciNotifier,则应用程序可能会爆炸(静态初始化顺序未定义)。

答案 1 :(得分:1)

这对你有用吗?

// In .h file
class CDbaOciNotifier
{
    // ...
    private:
        static shared_ptr<OCIEnv> envPtr;
};

// In .cpp file
// Write freeEnvironment as a free function.
shared_ptr<OCIEnv> CDbaOciNotifier::envPtr(new OCIEnv, freeEnvironment);