スマートポインタの先もコピー

シングルスレッドで走っていたプログラムを並列で走らせようとしたら案の定困ったことが起きたりしたので、メモ。Chinese Restaurant Processとかでポインタを使ったりしていて、tableに座っている客の数を増減させたりする。生ポインタはあれなので、スマートポインタにつっこんでいるが、コピーしたときにポインタが指してる先が同じなことから客の数がマイナスになったりしていた。これじゃいかん。

ai-aさんに質問したところ、コピーコンストラクタや代入演算子を自分で再定義してあげる必要があるとのこと。試しにこんな感じで書いてみた。コピーコンストラクタを書かないと一回しかMyCounterクラスのオブジェクトは生成されないが、コピーコンストラクタを定義してあげると二回生まれて二回死ぬようになってくれる。

#include <iostream>
#include <boost/shared_ptr.hpp>

class MyCounter {
public:
  MyCounter() {
	std::cout << "Created!!!" << std::endl;
  };
  MyCounter(const MyCounter& my_counter) {
	std::cout << "Created!!!" << std::endl;
  };
  ~MyCounter() {
	std::cout << "Deleted!!!" << std::endl;
  };
};

class Restaurant {
public:
  Restaurant() {
  };
  Restaurant(const Restaurant& r) {
	//	ptr_.reset(new MyCounter(*(r.ptr_)));
	ptr_ = boost::shared_ptr<MyCounter>(new MyCounter(*(r.ptr_)));
  };
  void set_ptr(const boost::shared_ptr<MyCounter>& ptr) {
	ptr_ = ptr;
  };
//   Restaurant& operator=(const Restaurant& r) {
// 	ptr_.reset(new MyCounter(*(r.ptr_)));
// 	return *this;
//   };
  boost::shared_ptr<MyCounter> ptr_;
};

int main(int argc, char *argv[]) {
  Restaurant r1;
  r1.set_ptr(boost::shared_ptr<MyCounter>(new MyCounter()));
  Restaurant r2(r1);
  //  Restaurant r2;
  //  r2 = r1;
  return 0;
};

ポインタの実態もポインタを持っているというようなグラフの関係にある場合は、トポロジカルソートできるようならトポロジカルのオーダーでコピーしていけばよい。