Streaming copy-on-write (COW) idiom?

Can someone point me to a thread safe implementation of Copy-on-write (COW) idioms? Sample code on this site looks good - is it thread-safe?

If anyone is interested in why I will use it: I have a class Foothat has a member std::map<int,double>. Fooobjects are copied very often in my code, but copies rarely change the contents map. I found that COW gives me a 22% performance improvement over copying the entire contents of the map in the copy constructor Foo, but my COW implementation crashes when using multiple threads.

UPDATE:

Ok, here is the code cast to a minimal example, since you asked for it:

First, a reference counting map:

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_;
};

And here is a class Foothat contains such a map RcMapusing the Copy-on-write mechanism:

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_;
};

I have not yet been able to reproduce the failure using this minimal example, but in my source code this happens when I use the copy constructor or the object assignment operator in parallel Foo. But maybe someone can spot the error in streaming security?

+3
source share
3 answers

RcMap , . g++ 4.1 .

+2

COW , , , , . :

  • , . , (, ).
  • , , , . , , .
    • , , , , , COW.
+3

( ), . ( , , .)

, ( ), . , .

+1

Source: https://habr.com/ru/post/1777568/


All Articles