谁能指出我的线程安全实现写时复制 (COW) http://en.wikipedia.org/wiki/Copy-on-write成语?示例代码在这个网站 http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-on-write看起来不错——它是线程安全的吗?
如果有人想知道我将用它做什么:我有一个Foo
类有一个std::map<int,double>
成员。Foo
在我的代码中,对象被频繁复制,但副本很少修改所包含的内容map
。我发现与复制整个地图内容相比,COW 的性能提升了 22%Foo
复制构造函数,但是当使用多个线程时,我的 COW 实现会崩溃。
UPDATE:
好的,这是代码,根据您的要求,简化为最小的示例:
首先,引用计数图:
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
包含这样一张地图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 本质上是线程安全的,因为原始版本本质上是不可变的,并且只有引发副本的线程才能在创建过程中看到复制的版本。您只需要注意两件事:
- 确保在进行复制时原始内容不会被另一个线程删除。不过,这是一个正交问题(例如,您可以使用线程安全的引用计数)。
- Make sure all the read operations you perform while copying are thread-safe. This is rarely a problem, but sometimes a read might populate a cache, for instance.
- 事实上,如果违反了这个假设,那就是读取操作不是线程安全的问题,并且可能会影响更多的代码,而不仅仅是 COW。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)