惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
Stack Overflow Blog
Stack Overflow Blog
MongoDB | Blog
MongoDB | Blog
腾讯CDC
V
V2EX
Martin Fowler
Martin Fowler
A
About on SuperTechFans
大猫的无限游戏
大猫的无限游戏
Blog — PlanetScale
Blog — PlanetScale
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Check Point Blog
博客园 - 【当耐特】
Cisco Talos Blog
Cisco Talos Blog
The Hacker News
The Hacker News
K
Kaspersky official blog
Security Latest
Security Latest
H
Help Net Security
博客园_首页
美团技术团队
Spread Privacy
Spread Privacy
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
S
SegmentFault 最新的问题
G
Google Developers Blog
NISL@THU
NISL@THU
爱范儿
爱范儿
I
Intezer
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
N
News and Events Feed by Topic
P
Privacy International News Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Security @ Cisco Blogs
Schneier on Security
Schneier on Security
雷峰网
雷峰网
人人都是产品经理
人人都是产品经理
V
Vulnerabilities – Threatpost
W
WeLiveSecurity
P
Palo Alto Networks Blog
G
GRAHAM CLULEY
Hacker News: Ask HN
Hacker News: Ask HN
I
InfoQ
The Cloudflare Blog
F
Full Disclosure
SecWiki News
SecWiki News
宝玉的分享
宝玉的分享
N
Netflix TechBlog - Medium

博客园 - cpunion

使用dpkt和pcap抓包 [收藏] jfwan实现的一个C++委托类 [c++] c++0x中的auto和typeof ACE_TP_Reactor的限制 ACE_SOCK_Stream send和recv超时设置 哀悼18位在车祸中死去的人 对ACE_TP_Reactor定时器处理机制做一点修改。 C++编写“异步调用代理组件”的一点想法 有趣的东西:Test () () () () () () () () () (); - cpunion VC2005 Beta 2 模板偏特化有些问题 [python] and or 表达式陷阱一则。 Media Player Classic外挂字幕时间调整脚本 我们的标准化委员会网站在哪? 不就是个座嘛 answers.com真是个不错的网站 《星际之门》和《亚特兰蒂斯》总算是更新了 生成gb2312码表 - cpunion - 博客园 [假如设计一个新语言] 哪些语言特性是我想要的 Python写的一个适配器类。
写一个CopyOnWrite的通用实现(C++) - cpunion - 博客园
cpunion · 2005-07-29 · via 博客园 - cpunion

这项技术最常用的是字符串类,如下:
string s1 ("long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long string");
string s2 = s1;   /
如果直接复制字符串缓冲区,那么会极大地损失效率,所以一般不这么做,而是让2个字符串共享同一个数据,当某个字符串对象要修改缓冲区时,再给它复制一份。

实现了一个简单的CopyOnWrite类,并用vector模拟了一个字符串,当然还没写完它,也只模拟了CopyOnWrite部分。


#include <vector>
#include 
<iostream>
#include 
<cassert>
using namespace std;#define DEBUG_TEST

#ifdef DEBUG_TEST
# define TRACE1(x) cout 

<< x << endl
# define TRACE2(x,y) cout 
<< x << y << endl
#endif

template 

<typename T>
class CopyOnWriteData
{
    size_t    _ref_count;
    T        _data;

    CopyOnWriteData (

const CopyOnWriteData& data)
        : _ref_count (
1), _data(data._data)
    {
        TRACE2 (
"CopyOnWriteData (const CopyOnWriteData& data) | "this);
    }

    CopyOnWriteData

& operator = (const CopyOnWriteData& data);
public:
    CopyOnWriteData ()
        : _ref_count (
0)
    {
        TRACE2 (
"CopyOnWriteData () | "this);
    }

    CopyOnWriteData (T data)
        : _ref_count (

1), _data(data)
    {
        TRACE2 (
"CopyOnWriteData (T data) | "this);
    }
~CopyOnWriteData ()
    {
        TRACE2 (
"~CopyOnWriteData () | "this);
        release ();
    }

    CopyOnWriteData

* copy ()
    {
        CopyOnWriteData
* cp = new CopyOnWriteData (*this);
        release ();
        
return cp;
    }

    T

& data ()
    {
        
return _data;
    }

    size_t ref_count () 

const
    {
        
return _ref_count;
    }

    size_t addRef ()
    {

return ++ _ref_count;
    }

    size_t release ()
    {

return -- _ref_count;
    }
};

template 

<typename T>
struct CopyOnWrite
{
    CopyOnWriteData
<T>* holder;void auto_copy ()
    {
        
if (holder->ref_count () > 1)
            holder 
= holder->copy ();
    }

    CopyOnWrite (CopyOnWriteData

<T>* p = 0)
        : holder (p)
    {
        TRACE2 (
"CopyOnWrite (CopyOnWriteData<T>* p = 0) | "this);
        
if (holder)
            holder
->addRef ();
    }

    CopyOnWrite (

const CopyOnWrite& o)
        : holder (o.holder)
    {
        TRACE2 (
"CopyOnWrite (const CopyOnWrite& o) | "this);
        
if (holder)
            holder
->addRef ();
    }

    CopyOnWrite

& operator = (const CopyOnWrite& o)
    {
        TRACE2 (
"CopyOnWrite& operator = (const CopyOnWrite& o) | "this);
        cout 
<< "" << this << endl;
        holder 
= o.holder;
        
if (holder)
            holder
->addRef ();
        
return *this;
    }
~CopyOnWrite ()
    {
        TRACE2 (
"~CopyOnWrite () | "this);
        
if (holder)
            holder
->release ();
        
if (!holder->ref_count ())
            delete holder;
    }
};
class String
{
#ifdef DEBUG_TEST
public:
#endif
    CopyOnWrite 
<vector<char> > _data;
public:
    String (
const char* p = 0)
    {
        TRACE2 (
"String (const char* p = 0) | "this);
        _data.holder 
= new CopyOnWriteData<vector<char> >;
        
if (!p)
        {
            _data.holder
->data ().push_back ('\0');
        }
        
else
        {
            size_t len 
= strlen(p) + 1;
            copy (p, p 
+ len, back_insert_iterator <vector<char> > (_data.holder->data ()));
        }
        _data.holder
->addRef ();
    }

    String (

const String& o)
        : _data (o._data)
    {
        TRACE2 (
"String (const String& o) | "this);
    }

    String

& operator = (const String& o)
    {
        TRACE2 (
"String& operator = (const String& o) | "this);
        _data 
= o._data;
        
return *this;
    }
~String ()
    {
        TRACE2 (
"~String () | "this);
    }
const char* c_str () const
    {
        
return (const char*)&_data.holder->data ()[0];
    }

    size_t find (

const char* fstr) const
    {
        
// 
    }void append (const char* p)
    {
        _data.auto_copy ();
        
// 
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    String s (
"hello");
    assert (s._data.holder
->ref_count () == 1);
    String s1 
= s;

    assert (s._data.holder

->ref_count () == 2);
    assert (s1._data.holder
->ref_count () == 2);
    String s2 (s);
    assert (s._data.holder
->ref_count () == 3);
    assert (s1._data.holder
->ref_count () == 3);
    assert (s2._data.holder
->ref_count () == 3);

    assert (strcmp (

"hello", s.c_str ()) == 0);

    assert (s._data.holder 

== s1._data.holder);
    assert (s2._data.holder 
== s1._data.holder);

    s.append (

"aa");
    assert (s._data.holder
->ref_count () == 1);
    assert (strcmp (
"hello", s.c_str ()) == 0);
    assert (s1._data.holder
->ref_count () == 2);
    assert (strcmp (
"hello", s.c_str ()) == 0);
    assert (s2._data.holder
->ref_count () == 2);
    assert (strcmp (
"hello", s.c_str ()) == 0);return 0;
}