MyEnigma

とある自律移動システムエンジニアのブログです。#Robotics #Programing #C++ #Python #MATLAB #Vim #Mathematics #Book #Movie #Traveling #Mac #iPhone

各プログラミング言語におけるAuto resource management実装


【電子合本版】Code Complete 第2版 完全なプログラミングを目指して

目次

はじめに

プログラミングをしていると、

リソースを使った時に、

処理が終わったり、処理中に例外が発生しても、

必ずリソースをクローズしたい

いう処理をよく実装すると思います。

 

このような処理を

Auto resource management

と呼ぶらしいのですが、

多くのプログラミング言語は、

言語の機能として、

このような仕組みを簡単に実装する機能を提供しています。

 

そこで、今回は

各プログラミング言語で

Auto resource managementを実装する方法をまとめておきたいと思います。

 

Python

Pythonでは、Auto resource managementを実現するコードを

コンテキストマネージャと呼びます。

docs.python.org

blog.mtb-production.info

python.keicode.com

 

コンテキストマネージャは、下記のコードのように

__enter____exit__関数を実装したクラスを準備して、

with文と一緒に使うと、withに入った時に__enter__関数を実行し、

出た時に、__exit__関数を実行してくれます。

withのasの部分は、__enter__関数の返り値が入ります。

 

class MyContextManager:
    def __enter__(self):
        print('enter')
        return "yield"

    def __exit__(self, exc_type, exc_value, traceback):
        print('enter')


def main():
    with MyContextManager() as e:
        print(f'hello context manager:{e}')


if __name__ == '__main__':
    # === Output ===
    # enter
    # hello context manager:yield
    # exit
    main()

また、公式ライブラリのcontextlibcontextmanagerを使うと、

yeild文と組み合わせて、

簡単にAuto resource managementが実現できます。

from contextlib import contextmanager


@contextmanager
def context_manager_sample():
    print('enter')
    yield "yield"
    print('exit')


def main():
    with context_manager_sample() as e:
        print(f'hello context manager:{e}')


if __name__ == '__main__':
    # === Output ===
    # enter
    # hello context manager:yield
    # exit
    main()

 

Java

Javaでは、Java8から導入されたtry-with-resourcesを使うことで、

簡単にAuto resource managementを実現できます。

qiita.com

stackoverflow.com

 

下記のような、AutoClosableやClosableをimplementし、

コンストラクタでリソースを開く時の実装をし、

closeで、リソースを閉じる処理を実装します。

import java.lang.AutoCloseable;

public class AutoResource implements AutoCloseable {

    public static AutoResource setUpAutoLock(){
        return new AutoResource();
    }

    private AutoResource(){
        System.out.println("enter");
    }

    @Override
    public void close() {
        System.out.println("exit");
    }
}

あとは、下記のようにtry-with-resource構文を使って、

Auto resource managementを実現できます。

try (AutoResource _lock = setUpAutoLock()){
      System.out.println("aaa");
}

また、下記にように、複数のリソースをまとめて管理することも可能です。

try (Socket soc server.accept();
      var isr = new InputStreamReader(soc.getInputStream());
      var bur = new BufferedReader(isr);
      var w = PrintWriter(soc.getOutputStream()
  ){
  ....
}

C++

C++の場合は、デストラクタがあるので、

リソースのOpen - Closeの関数を、コンストラクタとデストラクタで定義し、

ローカル変数としてクラスをインスタンス化しておけば、

ローカル変数が破棄される時に、簡単にAuto resource managementできます。

 

そもそもC++には言語的にはfinallyが無いのですが、

stackoverflow.com

下記の記事のように、テンプレートを使って、

finallyのような機能を実装することもできます。

koturn.hatenablog.com

 

Julia

Juliaは、finalizerを使うことで、あるオブジェクトがgcかかった時に、

呼ぶ関数を指定することができます。

docs.julialang.org

これを使うことで、Auto resource managementを実現できそうですが、

ただこの方法はあまり推奨されていないようです。

github.com

 

また、前述のPythonと同様に、Juliaもwith文があるのですが、

それをAuto resource managementに使えるように、

議論が続いていますが、まだ結論は出ていないようです。

github.com

現時点では、try_catch_finallyを使うのが良さそうです。

 

参考資料

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com


【電子合本版】Code Complete 第2版 完全なプログラミングを目指して

 

MyEnigma Supporters

もしこの記事が参考になり、

ブログをサポートしたいと思われた方は、

こちらからよろしくお願いします。

myenigma.hatenablog.com