SlideShare a Scribd company logo
メンバ変数のメンバ関数内での
    リソース管理


        高橋晶(Akira Takahashi)
            id:faith_and_brave
                    @cpp_akira
        Boost.勉強会 #8 大阪 2012/02/11(土)
RAII
• C++には、RAII(Resource Acquisition Is Initialization:リソース
  確保は初期化である)というイディオムがある。
• 簡単に言えば、確保したリソースはデストラクタで自動的に
  解放する、というもの。

void f()
{
    File file;
    file.open("a.txt");

    if (!file.write("xxxxxxxx")) {
        return; // 途中で抜けてもファイルは閉じられる
    }
} // ファイルが閉じられる

• これはローカル変数には非常に有効。
メンバ変数のリソース管理
• メンバ変数の寿命がクラスと同じでよければ、RAIIが有用。

class X {
    std::vector<User> users;

public:
    ~X()
    {
    } // ここでusersが解放される
};
ケーススタディ
ボタンの設計を考えてみよう
class Button {
public:
    void down(); // ボタン押した
    void up();   // ボタン離した

     bool is_down() const;        // ボタン押されてる?
     bool in_rect(Point p) const; // ある点が範囲内かを判定
};

down(), up()関数ではそれぞれ、ボタンの押下状態によって
表示画像を切替える処理が入っているとする。

ボタンが離されたら確実にup()関数を呼びたい。
どうするか?
ケーススタディ
ボタンを包含する画面クラスはこんな感じになるでしょう。
class View {
    Button ok_button;
public:
    void on_down(Point p)
    {
        if (ok_button.in_rect(p)) // 範囲内なら押す
            ok_button.down();
    }

     void on_up()
     {
         if (ok_button.is_down()) { // 押されていたら離して押下処理
             ok_button.up();
             on_ok_button();
         }
     }

     void on_ok_button() {} // OKボタンが押された
};
ケーススタディ
この設計だと、ボタンが複数あると破綻する。
class View {
    Button ok_button, cancel_button;
public:
    …
    void on_up()
    {
        if (ok_button.is_down()) { // 押されていたら離して押下処理
            ok_button.up();
            on_ok_button();
            return; // 余計な処理はしないで終了
        }
        if (cancel_button.is_down()) {
            cancel_button.up(); // ボタンが離されない可能性がある
            on_cancel_button();
            return;
        }
    }
    …
};
ケーススタディ
離されたら、全てのボタンが確実にup状態になるようにしたい。
Boost.ScopeExitを使おう。
void on_up()
{
    BOOST_SCOPE_EXIT((&)) { // スコープを抜けたら全てのボタンを離す
        ok_button.up();
        cancel_button.up();
    };
    if (ok_button.is_down()) { // 押されていたら離して押下処理
        on_ok_button();
        return; // 全てのボタンが離される
    }
    if (cancel_button.is_down()) {
        on_cancel_button();
        return; // 全てのボタンが離される
    }
} // 全てのボタンが離される

これで、メンバ変数が、特定のメンバ関数の抜けた際に、指定
した処理を確実に行わせることができるようになった。
Boost.ScopeExit
Boost.ScopeExitは、スコープを抜ける際に実行されるブロックを
記述するためのライブラリ。
int value = 0;

void f()
{
    value = 1;

    BOOST_SCOPE_EXIT((&)) { // スコープを抜ける際に実行されるブロック
        value = 3;
    };

    value = 2;
}

f();
assert(value == 3);

Boost.ScopeExitがやっていることは、デストラクタでそのブロック
を実行するクラスとそのオブジェクトを自動生成してるだけ。
Scoped Lockingパターン
Scope Exitの目的特化した例として、Scoped Lockingパターンと
いうのがある。

class Logger {
    Mutex mutex_;
public:
    void write(const std::string& s)
    {
        LockGuard<Mutex> lock(mutex_); // ロックする
        …
    } // スコープ抜けたらロック解除
};

複数ヶ所でロックされる可能性のあるミューテックスを、
それぞれの処理が終わった段階で確実にアンロックする。
まとめ
• RAIIはとても便利だが、メンバ変数をメンバ関数内で自動的
  に解放処理したい場合には、もう一つのRAIIを用意する必要
  がある。

• Boost.ScopeExitはこの手間を減らしてくれる。

• Scoped Locking Patternのように、いろいろな個所で同じことを
  するならScopeExitを直接使うのではなくライブラリ化しよう。

More Related Content

PDF
Python02
PPT
Online schema change in mysql casual #1(2010/12/11)
PDF
trueコマンドに0以外の終了コードをはかせる方法
PPTX
Javascript basic code
KEY
KEY
PPT
symfony 1.2を支えるサブフレームワーク
PPTX
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
Python02
Online schema change in mysql casual #1(2010/12/11)
trueコマンドに0以外の終了コードをはかせる方法
Javascript basic code
symfony 1.2を支えるサブフレームワーク
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。

What's hot (8)

PDF
Goの文法の実例と解説
PDF
Local php-100828 2
PDF
リナックスに置ける様々なリモートエキスプロイト手法 by スクハー・リー
PDF
WebAPIではじめるphp入門
PDF
JavaScript 講習会 #1
PPTX
Java並行処理プログラミング 第16章ver2
PDF
Android Lecture #03 @PRO&BSC Inc.
PDF
補足資料 太陽電池モデリング教材
Goの文法の実例と解説
Local php-100828 2
リナックスに置ける様々なリモートエキスプロイト手法 by スクハー・リー
WebAPIではじめるphp入門
JavaScript 講習会 #1
Java並行処理プログラミング 第16章ver2
Android Lecture #03 @PRO&BSC Inc.
補足資料 太陽電池モデリング教材
Ad

Similar to Scope Exit (20)

PDF
C++勉強会
PDF
Continuation with Boost.Context
PDF
オブジェクト指向できていますか?
PDF
Pfi Seminar 2010 1 7
PDF
Boost Tour 1_58_0 merge
PDF
C#coding guideline その2_20130325
PDF
マーク&スイープ勉強会
PDF
Replace Output Iterator and Extend Range JP
PDF
Boost Tour 1.53.0 merge
ODP
Boost9 session
PPT
shared_ptr & weak_ptr (ppt 初版, DL 専用)
PPTX
ぱっと見でわかるC++11
PDF
後戻りのある手続き型プログラミング
PDF
イマドキC++erのモテカワリソース管理術
PDF
Boost.Coroutine
PDF
Howtoよいデザイン
PDF
C# コーディングガイドライン 2013/02/26
PPT
オブジェクト指向入門7
ODP
Buffer overflow
PPT
プログラミングで言いたい聞きたいこと集
C++勉強会
Continuation with Boost.Context
オブジェクト指向できていますか?
Pfi Seminar 2010 1 7
Boost Tour 1_58_0 merge
C#coding guideline その2_20130325
マーク&スイープ勉強会
Replace Output Iterator and Extend Range JP
Boost Tour 1.53.0 merge
Boost9 session
shared_ptr & weak_ptr (ppt 初版, DL 専用)
ぱっと見でわかるC++11
後戻りのある手続き型プログラミング
イマドキC++erのモテカワリソース管理術
Boost.Coroutine
Howtoよいデザイン
C# コーディングガイドライン 2013/02/26
オブジェクト指向入門7
Buffer overflow
プログラミングで言いたい聞きたいこと集
Ad

More from Akira Takahashi (20)

PPTX
Cpp20 overview language features
PDF
Cppmix 02
PPTX
Cppmix 01
PDF
Modern C++ Learning
PDF
cpprefjp documentation
PDF
C++1z draft
PDF
Boost tour 1_61_0 merge
PDF
Boost tour 1_61_0
PDF
error handling using expected
PDF
Boost tour 1.60.0 merge
PDF
Boost tour 1.60.0
PDF
Boost container feature
PDF
Boost Tour 1_58_0
PDF
C++14 solve explicit_default_constructor
PDF
C++14 enum hash
PDF
Multi paradigm design
PDF
Start Concurrent
PDF
Programmer mind
PDF
Boost.Study 14 Opening
PDF
Executors and schedulers
Cpp20 overview language features
Cppmix 02
Cppmix 01
Modern C++ Learning
cpprefjp documentation
C++1z draft
Boost tour 1_61_0 merge
Boost tour 1_61_0
error handling using expected
Boost tour 1.60.0 merge
Boost tour 1.60.0
Boost container feature
Boost Tour 1_58_0
C++14 solve explicit_default_constructor
C++14 enum hash
Multi paradigm design
Start Concurrent
Programmer mind
Boost.Study 14 Opening
Executors and schedulers

Scope Exit