Changes between Version 13 and Version 14 of HowTo/BoostStudy4


Ignore:
Timestamp:
Feb 26, 2011, 4:12:14 PM (14 years ago)
Author:
村山 俊之
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • HowTo/BoostStudy4

    v13 v14  
    380380   * 0x でそれなりに改善
    381381
     382=== スライド ===
     383
     384 * http://www.slideshare.net/tanakh/ccdis
     385
    382386
    383387== なぜ僕はProtoをぺろぺろするのか ==
     
    540544 * dtl で採用したのは Wu
    541545
     546
     547== 実践 shared_ptr ==
     548
     549=== ガベコレ ===
     550
     551 * GC のほうが適した問題領域も…
     552 * 無いものはないので我慢
     553
     554=== カスタムデリータ ===
     555
     556 * 動的にリソースの解放方法を決める
     557 * 所有者が居なくなったら呼ばれる (参照カウンタ)
     558 * 同じ型でも確保、解放処理は異なる
     559 * shared_ptr = カウンタ + デリータ
     560   * 大事です
     561
     562=== 具体例 ===
     563
     564 * boost::checked_deleter
     565   * 単に delete する
     566 * boost::checked_array_deleter
     567   * delete[]
     568 * 関数 (オブジェクト) なので何でもできます
     569   * ログ仕込んだり…
     570 * 典型例: ハンドルのクローズ
     571{{{
     572HHOGE raw_handle = ::OpenHoge(...);
     573::ReleaseHoge(raw_handle);
     574}}}
     575 * 確実にハンドルをクローズするには…?
     576 * 勝手に解放して下さい
     577{{{
     578typedef
     579  shared_ptr<remove_pointer<HHOGE>::type>
     580  HogePtr;
     581HHOGE raw_handle = ::OpenHoge(...);
     582HogePtr hoge_h(raw_handle, ::CloseHoge);
     583}}}
     584
     585=== リソース間の依存 ===
     586
     587 * 権利だけ主張する人もいます
     588{{{
     589struct Legacy {
     590  Buffer* buffer;  // ちゃんと有効なバッファ指してね!
     591};
     592}}}
     593 * Legacy::buffer の管理は誰の責任?
     594 * 所有権ちょいたし
     595{{{
     596struct LegacyDeleter {
     597  explicit LegacyDeleter(shared_ptr<Buffer> buffer)
     598  : buffer(buffer) {}
     599  void operator()(Legacy* ptr) const { delete ptr; }
     600  shared_ptr<Buffer> buffer; // 所有
     601};
     602shared_ptr<Legacy> create(shared_ptr<Buffer> buffer) {
     603  LegacyDeleter deleter(buffer); // デリータが所有
     604  shared_ptr<Legacy> ret(new legacy(), deleter);
     605  ret->bufer = buffer.get();
     606  return ret;
     607};
     608}}}
     609
     610=== Null デリータ ===
     611
     612 * 何もしないデリータです。
     613{{{
     614struct NullDeleter {
     615  void operator()(void*) const{}
     616};
     617
     618void nullDeleter(void *){
     619}
     620}}}
     621 * 誰かが管理しているリソース
     622   * コンテキストと生死を共にしている
     623     * スタック、data領域、TLS ...
     624   * 何らかの仕組みで管理されている
     625     * 強調できるのが一番良いのですが…
     626 * ポインタのフリしてるだけ
     627   * reinterpret_cast<void *>(...)
     628{{{
     629static vecter<int> vi;
     630shared_ptr<vector<int> > vi_ptr(&vi, NullDeleter());
     631
     632void* val = reinterpret_cast<void*>(-1);
     633shared_ptr<void> val_ptr(val, NullDeleter());
     634
     635shared_ptr<pair<int, int> > iip = ...;
     636shared_ptr<int> iptr(&iip->first, NullDeleter());
     637}}}
     638 * ところで (上記 3つ目) もし iip が有効じゃなかったら…
     639   * 他の手を考えましょう。
     640 * boost もしくは 0x なら...
     641   * 参照カウンタの共有!
     642     * iip.use_count() == iptr.use_count()
     643   * でも tr1 にはありません…
     644   * tr1 なら Null デリータ + 延命
     645{{{
     646struct FirstDeleter {
     647  explicet firstDeleter(shared_ptr<pair<int, int> > parent)
     648  :parent(parent){}
     649  void operator()(int*) const {};
     650  shared_ptr<pair<int, int> > parent;
     651};
     652
     653=== 応用 ===
     654
     655 * 参照はしたい、所有はしたくない、リソースが有効じゃなくても良い、でも安全だと嬉しい。
     656   * ↑お前は何を(ry
     657 * どうしても所有してしまう
     658{{{
     659weak_ptr<T> weak = ...;
     660shared_ptr<T> ptr = weak.lock();
     661}}}
     662 * リソース安全に扱うための仕組み
     663 * 安全とか要らん
     664 * これでもくらえ
     665{{{
     666struct Deleter {
     667  void operator()(T* ptr) const { not_onwer.reset(); ... }
     668  shared_ptr<T> not_owner;
     669} deleter;
     670shared_ptr<T> owner(ptr, deleter);
     671deleter.not_owner.reset(owner.get(), NullDeleter());
     672weak_ptr<T> not_owner_ref = deleter.not_owner;
     673}}}
     674 * ex) HWND ... ウィンドウを生成したのとは別のスレッドで解放してはいけない
     675
     676=== 注意 ===
     677
     678 * コンテキストに注意
     679   * デリータはどこでも呼び出される
     680
     681=== みんな大好き void* ===
     682
     683 * 何でも参照できる魔法のポインタ型
     684 * ただのポインタ
     685   * 参照なのか所有なのか?
     686   * 有効なのか無効なのか?
     687 * shared_ptr<void>
     688{{{
     689vector<shared_ptr<void>> delay;
     690delay.push_back(make_shared<int>(1));
     691delay.push_back(make_shared<string>("one"));
     692}}}
     693 * 何でも入るぞ-
     694 * カスタムデリータ-で正しく解放できる
     695 * とりあえず寿命伸ばしたいときとかに
     696 * 実践例: Blob
     697{{{
     698struct Blob {
     699  char* data;
     700  size_t size;
     701  shared_ptr<void> resource;
     702};
     703}}}
     704{{{
     705Blob createBlob(const vector<char>& v){
     706  shared_ptr<vector<char>> res(new vector<char>(v));
     707  return Blob(res->data().res->size(), res);
     708}
     709Blob createBlob(const string& str){
     710  shared_ptr<string> res(new string(str));
     711  return Blob(res->data().res->size(), res);
     712}
     713}}}
     714
     715=== 複数のリソースを返す API ===
     716
     717 * unique_ptr -> shared_ptr