RPCZ中的智能指针单例
RPCZ中的智能指针单例
(金庆的专栏)
智能指针单例应用于 RPCZ 库以实现库的自动初始化与自动清理.
RPCZ: RPC implementation for Protocol Buffers over ZeroMQ
https://github.com/jinq0123/rpcz
代码来自: (A dynamic) Singleton using weak_ptr and shared_ptr
http://boost.2283326.n4.nabble.com/A-dynamic-Singleton-using-weak-ptr-and-shared-ptr-td2581447.html
以下为该文摘译与代码整理.
原作者 Martin Ba,
回复者 David Rodríguez Ibeas 提出了优化意见, 并被原作者认同.
本作者提出进一步优化, 附于本文尾部.
Singleton using boost weak_ptr and shared_ptr
应用 boost weak_ptr 和 shared_ptr 实现单例
------------------------------------------------------------------
by Martin Ba
Requirement: Singleton that is constructed on first use (not on process
start) and destroyed after the last "client-code" has finished with it.
需求: 初次使用时构造单例(而非进程开始时构造),
并且在最后的客户代码使用完后就销毁单例.
Note: It is therefore possible that more that one Singleton instances
exist within a process's lifetime, BUT there must only be at most one
Object active at any given time (Construction must not run before
destruction has finished.
注意: 因此有可能进程的生命期内会存在多个单例实例, 但是,
任一时刻最多只会有一个对象(析造完成后才允许新的构造).
Starting point: http://lists.boost.org/boost-users/2002/10/2014.php
Problem of the simple solution: No protection against multiple
initialization and against simultaneous deletion and construction.
简单方案的问题: 没有对同时初始化, 或者同时删除和构造进行保护.
Solution: The construction and destruction of the singleton instance(s)
has to be protected additionally.
解决方案: 对单例的构造和析构额外添加保护.
(金庆: 原代码中的 class atomic_bool 已替换为 boost::atomic_bool, 以简化代码.)
dynamic_singleton.h
#pragma once
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
class dynamic_singleton : private boost::noncopyable
{
public:
typedef boost::shared_ptr<dynamic_singleton> shared_t;
static shared_t get_instance();
// Interface:
void example(int cookie);
// ...
private:
dynamic_singleton();
virtual ~dynamic_singleton();
struct impl;
typedef boost::scoped_ptr<impl> impl_t;
impl_t pimpl;
struct deleter;
friend struct deleter;
};
dynamic_singleton.cpp
#include "dynamic_singleton.h"
#include <boost/atomic.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread.hpp>
#define MESG(msg) \
printf("%s\n", msg); \
/**/
struct dynamic_singleton::impl : private boost::noncopyable
{
impl() {}
~impl() {}
static void start_construction()
{
boost::xtime spin_time;
spin_time.sec = 1;
while(the_object_exists) {
boost::thread::sleep(spin_time);
}
}
static void finish_construction()
{
assert(!the_object_exists);
the_object_exists = true;
}
static void finish_destruction()
{
assert(the_object_exists);
the_object_exists = false;
}
typedef boost::weak_ptr<dynamic_singleton> internal_shared_t;
static internal_shared_t the_object;
static boost::recursive_mutex sync_init;
static boost::atomic_bool the_object_exists;
};
dynamic_singleton::impl::internal_shared_t
dynamic_singleton::impl::the_object;
boost::recursive_mutex
dynamic_singleton::impl::sync_init;
boost::atomic_bool
dynamic_singleton::impl::the_object_exists;
struct dynamic_singleton::deleter
{
void operator() (dynamic_singleton* p)
{
assert(p);
delete p;
impl::finish_destruction();
}
};
dynamic_singleton::shared_t dynamic_singleton::get_instance()
{
// Syncronise Initialization:
boost::recursive_mutex::scoped_lock lock(impl::sync_init);
MESG(__FUNCTION__);
// Acquire singleton pointer:
shared_t object_ptr = impl::the_object.lock();
if(!object_ptr.use_count()) {
impl::start_construction();
object_ptr.reset(new dynamic_singleton(), dynamic_singleton::deleter());
impl::the_object = object_ptr;
impl::finish_construction();
}
return object_ptr;
}
dynamic_singleton::dynamic_singleton()
{
pimpl.reset(new impl());
MESG(__FUNCTION__);
// For example open a unique system or process global resource
printf(" >> Singleton opens the global resouce.\n");
}
dynamic_singleton::~dynamic_singleton()
{
MESG(__FUNCTION__);
// For example close a unique system or process global resource
printf(" << Singleton closes the global resouce.\n");
}
void dynamic_singleton::example(int cookie)
{
printf("%s(%d)\n", __FUNCTION__, cookie);
}
main.cpp
#include "dynamic_singleton.h"
#include <iostream>
#include <boost/thread.hpp>
struct singleton_user
{
explicit singleton_user(int num)
: num_(num)
{ }
void operator()()
{
using namespace std;
printf("%d uses singleton ...\n", num_);
dynamic_singleton::shared_t s = dynamic_singleton::get_instance();
s->example(num_);
}
int num_;
};
int main(int argc, char* argv[])
{
boost::thread t1( singleton_user(1) );
boost::thread t2( singleton_user(2) );
boost::thread t3( singleton_user(3) );
boost::thread t4( singleton_user(4) );
boost::thread t5( singleton_user(5) );
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
return 0;
}
David Rodríguez Ibeas 提出建议:
* 用 condition 代替 sleep().
* 因为 condition 已有 mutex, 所以 the_object_exists 从 atomic_bool 改为 bool.
* 不需要创建 dynamic_singleton::impl 实例, 所以其构造析构改为私有.
* 把 the_object_exists = true; 从 finish_destruction() 移到 start_construction(),
finish_destruction()成为空函数可删除.
// Using boost::condition:
struct dynamic_singleton::impl : private boost::noncopyable
{
static void start_construction()
{
boost::recursive_mutex::scoped_lock lock( sync_ );
while ( the_object_exists ) {
cond_.wait( lock );
}
the_object_exists = true;
}
static void finish_destruction()
{
boost::recursive_mutex::scoped_lock lock( sync_ );
the_object_exists = false;
cond_.notify_one();
}
typedef boost::weak_ptr<dynamic_singleton> internal_shared_t;
static internal_shared_t the_object;
static boost::recursive_mutex sync_init;
static boost::recursive_mutex sync_; // moved from atomic_bool
static bool the_object_exists; // plain bool, synch'ed with sync_
static boost::condition_variable_any cond_;
private:
impl() {}
~impl() {}
};
dynamic_singleton::impl::internal_shared_t dynamic_singleton::impl::the_object;
boost::recursive_mutex dynamic_singleton::impl::sync_init;
boost::recursive_mutex dynamic_singleton::impl::sync_;
bool dynamic_singleton::impl::the_object_exists = false;
boost::condition_variable_any dynamic_singleton::impl::cond_;
RPCZ 中的进一步优化:
* get_instance()多数情况下不需要加锁, 仅当需要初始化时才加锁
dynamic_singleton::shared_t dynamic_singleton::impl::get_instance()
{
shared_t object_ptr = impl::the_object.lock();
if (object_ptr) return object_ptr;
// Syncronise Initialization:
boost::recursive_mutex::scoped_lock lock(impl::sync_init);
...
}
* get_instance() 内联
* 分离单件相关代码到独立的头文件与实现文件
(impl改名为helper)
dynamic_singleton.h
#pragma once
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
class dynamic_singleton : private boost::noncopyable
{
public:
typedef boost::shared_ptr<dynamic_singleton> shared_t;
inline static shared_t get_instance();
// Interface:
void example(int cookie);
// ...
private:
dynamic_singleton();
virtual ~dynamic_singleton();
struct helper;
struct deleter;
friend struct deleter;
};
#include "dynamic_singleton_helper.h"
inline dynamic_singleton::shared_t dynamic_singleton::get_instance()
{
return helper::get_instance();
}
dynamic_singleton.cpp
#include "dynamic_singleton.h"
#define MESG(msg) \
printf("%s\n", msg); \
/**/
dynamic_singleton::dynamic_singleton()
{
MESG(__FUNCTION__);
// For example open a unique system or process global resource
printf(" >> Singleton opens the global resouce.\n");
}
dynamic_singleton::~dynamic_singleton()
{
MESG(__FUNCTION__);
// For example close a unique system or process global resource
printf(" << Singleton closes the global resouce.\n");
}
void dynamic_singleton::example(int cookie)
{
printf("%s(%d)\n", __FUNCTION__, cookie);
}
dynamic_singleton_helper.h
#pragma once
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
#include <boost/weak_ptr.hpp>
struct dynamic_singleton::helper : private boost::noncopyable
{
static inline dynamic_singleton::shared_t get_instance();
static void start_construction();
static void finish_destruction();
typedef boost::weak_ptr<dynamic_singleton> internal_shared_t;
static internal_shared_t the_object;
static boost::recursive_mutex sync_init;
static boost::recursive_mutex sync_; // moved from atomic_bool
static bool the_object_exists; // plain bool, synch'ed with sync_
static boost::condition_variable_any cond_;
private:
helper() {}
~helper() {}
private:
static dynamic_singleton::shared_t make_instance();
};
inline dynamic_singleton::shared_t dynamic_singleton::helper::get_instance()
{
shared_t object_ptr = the_object.lock();
if (object_ptr) return object_ptr;
return make_instance();
}
dynamic_singleton_helper.cpp
#include "dynamic_singleton.h"
void dynamic_singleton::helper::start_construction()
{
boost::recursive_mutex::scoped_lock lock( sync_ );
while ( the_object_exists ) {
cond_.wait( lock );
}
the_object_exists = true;
}
void dynamic_singleton::helper::finish_destruction()
{
boost::recursive_mutex::scoped_lock lock( sync_ );
the_object_exists = false;
cond_.notify_one();
}
dynamic_singleton::helper::internal_shared_t dynamic_singleton::helper::the_object;
boost::recursive_mutex dynamic_singleton::helper::sync_init;
boost::recursive_mutex dynamic_singleton::helper::sync_;
bool dynamic_singleton::helper::the_object_exists = false;
boost::condition_variable_any dynamic_singleton::helper::cond_;
struct dynamic_singleton::deleter
{
void operator() (dynamic_singleton* p)
{
assert(p);
delete p;
helper::finish_destruction();
}
};
dynamic_singleton::shared_t dynamic_singleton::helper::make_instance()
{
// Syncronise Initialization:
boost::recursive_mutex::scoped_lock lock(sync_init);
// Acquire singleton pointer:
shared_t object_ptr = the_object.lock();
if (object_ptr) return object_ptr;
start_construction();
object_ptr.reset(new dynamic_singleton(), dynamic_singleton::deleter());
the_object = object_ptr;
return object_ptr;
}
代码打包下载:
http://download.csdn.net/detail/jq0123/8467399
RPCZ中的智能指针单例的更多相关文章
- OSG中的智能指针
在OpenSceneGraph中,智能指针(Smart pointer)的概念指的是一种类的模板,它针对某一特定类型的对象(即Referenced类及其派生类)构建,提供了自己的管理模式,以避免因为用 ...
- C++中的智能指针
一.动态内存管理 通常我们创建动态内存的时候,需要自己管理好内存,也就是说,new出来的对象一定要注意释放掉.下面通过例子可以看到这个问题所在: struct BBE{ int X; int Y; v ...
- Boost中的智能指针(转)
这篇文章主要介绍 boost中的智能指针的使用.(转自:http://www.cnblogs.com/sld666666/archive/2010/12/16/1908265.html) 内存管理是一 ...
- C++中的智能指针、轻量级指针、强弱指针学习笔记
一.智能指针学习总结 1.一个非const引用无法指向一个临时变量,但是const引用是可以的! 2.C++中的delete和C中的free()类似,delete NULL不会报"doubl ...
- ATL和vc++中的智能指针(分别是CComPtr和_com_ptr_t)
一.智能指针的概念 智能指针是一个类,不是指针,智能指针在所包含的指针不再被使用时候会自动释放该所包含指针所占用的系统资源,而不用手动释放. 原理:智能指针封装了包含指针的AddRef()函数和Rel ...
- 标准库中的智能指针shared_ptr
智能指针的出现是为了能够更加方便的解决动态内存的管理问题.注:曾经记得有本书上说可以通过vector来实现动态分配的内存的自动管理,但是经过试验,在gcc4.8.5下是不行的.这个是容易理解的,vec ...
- 智能指针类模板(中)——Qt中的智能指针
Qt中的智能指针-QPointer .当其指向的对象被销毁时,它会被自动置空 .析构时不会自动销毁所指向的对象-QSharedPointer .引用计数型智能指针 .可以被自由的拷贝和赋值 .当引用计 ...
- 智能指针类模板(上)——STL中的智能指针
智能指针类模板智能指针本质上就是一个对象,它可以像原生指针那样来使用. 智能指针的意义-现代C++开发库中最重要的类模板之一-C++中自动内存管理的主要手段-能够在很大程度上避开内存相关的问题 1.内 ...
- C++中的智能指针类模板
1,智能指针本质上是一个对象,这个对象可以像原生的指针一样使用,因为智能指 针相关的类通过重载的技术将指针相关的操作符都进行了重载,所以智能指针对象可以像原生指针一样操作,今天学习智能指针类模板,通过 ...
随机推荐
- 浅析Linux内核调度
1.调度器的概述 多任务操作系统分为非抢占式多任务和抢占式多任务.与大多数现代操作系统一样,Linux采用的是抢占式多任务模式.这表示对CPU的占用时间由操作系统决定的,具体为操作系统中的调度器.调度 ...
- [bzoj4405][wc2016]挑战NPC
来自FallDream的博客,未经允许,请勿转载,谢谢. 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. ...
- 阿里云负载均衡SSL证书配置
阿里云负载均衡SSL证书 转载请注明地址:http://www.cnblogs.com/funnyzpc/p/8908461.html 好久了呢,距上篇博客的这段时间中:考试.搬家.工作赶工.业务考察 ...
- Vue2学习结合bootstrapTable遇到的问题
Vue2学习 项目中在使用bootstrapTable的时候,在table里面会有操作结合vue使用过程中点击相应的操作不会起作用 解决办法 1.把事件绑定到父元素上即可,但要判断什么样的需要点击,用 ...
- spring的 @Scheduled的cron表达式
网上太多说的多,但却没什么用的文章了 序号 说明 是否必填 允许填写的值 允许的通配符1 秒 是 0-59 , ...
- node之fs模块
前言 fs是filesystem的缩写,该模块提供本地文件的读写能力,基本上是POSIX文件操作命令的简单包装.但是,这个模块几乎对所有操作提供异步和同步两种操作方式,供开发者选择. 一.文件读取 文 ...
- 基于PHP的对接免费电子面单接口平台的案例-快宝开放平台
一.电子面单对接平台 电子面单对接平台分为两类: 1 .各大快递公司自有的电子面单接口开放平台:对接起来麻烦,需要每个快递公司分别调试接口,费时费力. 2 .第三方快递开放平台:如快宝开放平台(htt ...
- linux下的静态库与动态库详解
静态库 先说说我们为什么需要库? 当有些代码我们大量会在程序中使用比如(scanf,printf等)这些函数我们需要在程序中频繁使用,于是我们就把这些代码编译为库文件,在需要使用时我们直接链接即可. ...
- UltraISO安装centos7系统
1. 使用最新版UltraISO将ISO镜像刻录到U盘一定要是最新版,试用版都可以,按下图操作: 2. U盘启动电脑进入安装界面正常情况下你应该会看到下面的这个界面: 选择第一项,然后按TAB键(在评 ...
- Python3 解释器
Linux/Unix的系统上,Python解释器通常被安装在 /usr/local/bin/python3.4 这样的有效路径(目录)里. 我们可以将路径 /usr/local/bin 添加到您的Li ...