gpt4 book ai didi

c++ - 写时复制 (COW) 习惯用法的线程安全实现?

转载 作者:太空狗 更新时间:2023-10-29 20:31:25 31 4
gpt4 key购买 nike

任何人都可以指出 Copy-on-write (COW) 的线程安全实现吗?成语? this site 上的示例代码看起来不错——它是线程安全的吗?

如果有人想知道我将用它做什么:我有一个 Foo具有 std::map<int,double> 的类成员。 Foo对象在我的代码中被频繁复制,但拷贝很少修改包含的 map .我发现与复制 Foo 中的整个 map 内容相比,COW 提高了 22% 的性能。复制构造函数,但我的 COW 实现在使用多线程时崩溃。

更新:

好的,这是代码,简化为一个最小的例子,因为你要求它:

首先是引用计数图:

class RcMap {                             
public:
typedef std::map<int,double> Container;
typedef Container::const_iterator const_iterator;
typedef Container::iterator iterator;

RcMap() : count_(1) {}

RcMap(const RcMap& other) : count_(1) {
m_ = other.Get();
}

unsigned Count() const { return count_; }
unsigned IncCount() { return ++count_; }
unsigned DecCount() {
if(count_ > 0) --count_;
return count_;
}
void insert(int i, double d) {
m_.insert(std::make_pair(i,d));
}
iterator begin() { return m_.begin(); }
iterator end() { return m_.end(); }
const_iterator begin() const { return m_.begin(); }
const_iterator end() const { return m_.end(); }

protected:
const Container& Get() const { return m_; }

private:
void operator=(const RcMap&); // disallow

Container m_;
unsigned count_;
};

这是类 Foo包含这样一张 map RcMap ,使用写时复制机制:

class Foo {
public:
Foo() : m_(NULL) {}

Foo(const Foo& other) : m_(other.m_) {
if (m_) m_->IncCount();
}

Foo& operator= (const Foo& other) {
RcMap* const old = m_;
m_ = other.m_;
if(m_ != 0)
m_->IncCount();
if (old != 0 && old->DecCount() == 0) {
delete old;
}
return *this;
}

virtual ~Foo() {
if(m_ != 0 && m_->DecCount() == 0){
delete m_;
m_ = 0;
}
}

const RcMap& GetMap() const {
if(m_ == 0)
return EmptyStaticRcMap();
return *m_;
}

RcMap& GetMap() {
if(m_ == 0)
m_ = new RcMap();
if (m_->Count() > 1) {
RcMap* d = new RcMap(*m_);
m_->DecCount();
m_ = d;
}
assert(m_->Count() == 1);
return *m_;
}

static const RcMap& EmptyStaticRcMap(){
static const RcMap empty;
return empty;
}

private:
RcMap* m_;
};

我还不能使用这个最小示例重现崩溃,但在我的原始代码中,当我使用 Foo 的复制构造函数或赋值运算符时,它就会发生。对象并列。但也许有人可以发现线程安全错误?

最佳答案

COW 本质上是线程安全的,因为原始版本本质上是不可变的,只有诱导复制的线程才能看到正在创建的复制版本。您只需要注意两件事:

  1. 确保在复制过程中原始文件不会被其他线程删除。不过,这是一个正交问题(例如,您可以使用线程安全的引用计数)。
  2. 确保您在复制时执行的所有读取操作都是线程安全的。这很少是个问题,但有时读取可能会填充缓存,例如。
    • 事实上,如果违反了这个假设,那就是读取操作不是线程安全的问题,并且可能会影响更多的代码,而不仅仅是 COW。

关于c++ - 写时复制 (COW) 习惯用法的线程安全实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4309548/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com