2012年12月26日水曜日

std::move と asio

いやー、C++11 素晴らしいですね〜。 とりあえず、頭に描いたシナリオどおりに事が運ぶか、実験くんしてみました。 シナリオは、

  1. 所有権のあるコピーできない Foo クラスがあり
  2. ref では、まずいので、shared_ptr で asio のハンドラに Foo を保持させ
  3. io_service で処理されたら所定の vector へ move しながら Foo をぶっ込む
  4. へっへっへっ、リソース管理しなくても、適当に処理できるぜ!

#include <iostream>
#include <vector>
#include <boost/bind.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/ref.hpp>

class Foo {
private:
  int n_;
public:
  Foo() : n_() {}
  Foo(int n) : n_(n)  {
    std::cout << "Foo(" << n << ");" << std::endl;
  }
  
  Foo(Foo&& f) : n_(f.n_) {
    f.n_ = 0;
  }
  
  ~Foo() { std::cout << "~Foo(); /* " << n_ << " */" << std::endl; }
  
  Foo& operator = (Foo&& rhs) { n_ = rhs.n_; rhs.n_ = 0; return *this; }
  
  int n() const { return n_; }
};

void post_move( boost::shared_ptr<Foo> f, std::vector<Foo>& v ) {
  std::cout << "post_move push_back : " << f.get()->n() << std::endl;
  v.push_back( std::move( *f.get() ) );
}

int main() {
  boost::asio::io_service service;
  std::vector<Foo> v;
  
  for( int i = 0; i < 10; ++i ) {
    Foo f(i+1);
    boost::shared_ptr<Foo> nf( new Foo( std::move(f) ) );
    service.post( boost::bind( post_move, nf, boost::ref(v) ) );
  }  

  std::cout << ">>> run! <<<" << std::endl;
  service.run();
  
  std::cout << ">>> done! <<<" << std::endl;
  
  boost::for_each( v, [](const Foo& f) { std::cout << f.n() << std::endl; } );

  return 0;
}
結果
Foo(1);
~Foo(); /* 0 */
Foo(2);
~Foo(); /* 0 */
Foo(3);
~Foo(); /* 0 */
Foo(4);
~Foo(); /* 0 */
Foo(5);
~Foo(); /* 0 */
Foo(6);
~Foo(); /* 0 */
Foo(7);
~Foo(); /* 0 */
Foo(8);
~Foo(); /* 0 */
Foo(9);
~Foo(); /* 0 */
Foo(10);
~Foo(); /* 0 */
>>> run! <<<
post_move push_back : 1
~Foo(); /* 0 */
post_move push_back : 2
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 3
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 4
~Foo(); /* 0 */
post_move push_back : 5
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 6
~Foo(); /* 0 */
post_move push_back : 7
~Foo(); /* 0 */
post_move push_back : 8
~Foo(); /* 0 */
post_move push_back : 9
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 10
~Foo(); /* 0 */
>>> done! <<<
1
2
3
4
5
6
7
8
9
10
~Foo(); /* 1 */
~Foo(); /* 2 */
~Foo(); /* 3 */
~Foo(); /* 4 */
~Foo(); /* 5 */
~Foo(); /* 6 */
~Foo(); /* 7 */
~Foo(); /* 8 */
~Foo(); /* 9 */
~Foo(); /* 10 */

0 件のコメント: