您的位置:首页 > 编程语言 > C语言/C++

多备份数据更新管理器模板设计(C++ Template)

2013-07-27 12:56 267 查看
在网络服务等需要提供不间断服务的程序中,程序的运行时升级通常都是一项常规任务,例如:

1)运行时修改一些参数配置;

2)运行时修改一个算法模块(动态库);

为了在执行这些任务时,程序不停(仍使用旧配置或旧模块运行),常见的解决方案包括:

1)增加冗余的配置项或模块句柄的存储空间(所有这些数据打包成一个结构体),程序运行时使用其中的一份;当需要更新时,在更新的过程中将新的配置(或模块句柄)内容存储至备用内存;加载完成后将运行时配置(或模块句柄)指针指向新的内存地址。由于修改配置(或模块句柄)的频率远小于这些内容的读取频率,因此一个线程执行更新操作即可。另外,即使外加有多个线程同时读取,由于只涉及到配置项(或模块句柄)的整体结构体的这一个指针修改,读线程读到的值无非是“旧指针”和“新指针”二者之一(如果内存读写模型不支持这一点,或者在这种情况下可能有第三种,甚至第四种情况出现,本方案将不可用),因此程序仍能正常执行,并最终使用更新后的内容运行。

2)程序通过一个主进程协调,具体任务由工作进程完成。外界通知这个主进程使用新的配置(或模块),主进程便创建新的工作进程,这些新启动的进程自然会使用新的配置(或模块);当新创建的进程一切就绪之后,主进程便会通知其他进程结束,并在之后将新的任务委派给新创建的进程。Nginx的设计便是这种方案的一个典型。

这里设计的一个C++模板是上述解决方案1)的一种实现(完整地VS2008项目代码在这里):

//
// 数据清理函数指针类型
//
template<typename T>
struct DataCleaner {
typedef void (*ClearFun)(T*);
};

template<typename T>
void _default_reset_fun_(T* t)
{
memset(t, 0, sizeof(T));
};

//
// 多备份数据更新管理器
//
template<typename T, const size_t POOLSIZE=2, bool static_memory=true>
class LatestDataManager;

template<typename T, const size_t POOLSIZE>
class LatestDataManager<T, POOLSIZE, true>
{
public:
typedef T value_type;

LatestDataManager(){m_clf = _default_reset_fun_<T>;}
~LatestDataManager(){}

T& GetCurrent(){ return m_elem[m_current]; }
T& GetNext(){
size_t next = (m_current+1)%POOLSIZE;
m_clf(&m_elem[next]);
return m_elem[next];
}
void UseLatest(){ m_current = (m_current+1)%POOLSIZE; }
void SetClearFun(typename DataCleaner<T>::ClearFun f){ m_clf = f; }
private:
T                           m_elem[POOLSIZE];
size_t                      m_current;
typename DataCleaner<T>::ClearFun    m_clf;
};

template<typename T, const size_t POOLSIZE>
class LatestDataManager<T, POOLSIZE, false>
{
public:
typedef T value_type;

LatestDataManager(){memset(m_elem, 0, POOLSIZE*sizeof(T*));}
~LatestDataManager(){}

T* GetCurrent(){ return m_elem[m_current]; }
T* GetNext(){
size_t next = (m_current+1)%POOLSIZE;
if(NULL!=m_elem[next]){
delete m_elem[next];
m_elem[next] = NULL;
}
m_elem[next] = new T;
return m_elem[next];
}
void UseLatest(){ m_current = (m_current+1)%POOLSIZE; }
void SetClearFun(typename DataCleaner<T>::ClearFun){}
private:
T*                          m_elem[POOLSIZE];
size_t                      m_current;
};


测试代码:

template<typename T>
void _primdata_reset_fun_(T* t)
{
*t = 0;
}
typedef LatestDataManager<int, 2, true>  LatestConfig;

template<typename T>
void _container_reset_fun_(T* t)
{
if(t) t->clear();
}
typedef LatestDataManager<std::vector<std::string>, 2, false>  LatestMachines;

{
LatestConfig g_cfg;
g_cfg.SetClearFun( _primdata_reset_fun_< LatestConfig::value_type > );
{// 更新者 ... ...
g_cfg.GetNext() = 3;
g_cfg.UseLatest();
}
{// 使用者 ... ...
int config = g_cfg.GetCurrent();
std::cout << config << std::endl;
}
}

{
LatestMachines g_lm;
g_lm.SetClearFun( _container_reset_fun_< LatestMachines::value_type > );
{// 更新者 ... ...
std::vector<std::string>* machines = g_lm.GetNext();
machines->push_back("192.168.0.1");
machines->push_back("192.168.0.2");
machines->push_back("192.168.0.3");
g_lm.UseLatest();
}
{// 使用者 ... ...
std::vector<std::string>* machines = g_lm.GetCurrent();
for(std::vector<std::string>::iterator it=machines->begin(); it!=machines->end(); ++it)
{
std::cout << it->c_str() << std::endl;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: