誰でも私はCopy-on-write (COW)イディオムのスレッドセーフな実装を指摘できますか? this siteのサンプルコードはうまく見えます - それはスレッドセーフですか?COW(Copy-On-Write)イディオムのスレッドセーフ実装ですか?
私はそれをどのように使用するのだろうかと疑問に思っている人はFoo
クラスにstd::map<int,double>
というメンバーがあります。 Foo
オブジェクトは私のコードに非常に頻繁にコピーされますが、コピーはほとんど含まれていませんmap
を変更します。私は、COWが、コピーコンストラクタFoo
でマップの内容全体をコピーするのと比較して22%のパフォーマンス向上を見出しましたが、複数のスレッドが使用されていると私の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_;
};
コピーライト時のメカニズムを使用して、このようなマップRcMap
を含むクラスFoo
があります。
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
を並列に使用すると、元のコードでクラッシュが発生します。しかし、誰かがスレッドセーフなバグを見つけられるかもしれません。
誰でも、ここでヒントされているように、Compare-and-Swapイディオムを使用して実装する方法を説明できますか(http://en.wikipedia.org/wiki/Copy-on-write)? – Frank
COWがクラッシュしている場合は、問題を示す最小限のコードサンプルを投稿できる場合に役立ちます。また、どのようなクラッシュがありますか? –
さて、最小限のコードサンプルを追加しました。クラッシュは 'Foo'デストラクタの' delete m_'で起こります。 – Frank