スポンサーリンク

unique_resourceを使ってみる

前置き

Boost.Scopeにも実装されているらしい。

https://www.boost.org/doc/libs/1_85_0/libs/scope/doc/html/index.html

ただBoostの導入は面倒なので、今回は有志がGithubで公開しているものを使う。

https://github.com/okdshin/unique_resource

例えば、C++にはstd::unique_ptrがあり、メモリリークを防げる。この時、カスタムデリータを指定すれば、普通のnew/deleteとは異なった破棄処理を行うこともできる。

// ファイルをクローズするデリータ
struct MyFileCloser {
  void operator()(FILE* ptr) const {
    fclose(ptr);
  }
};
int main()
{
  {
    // ファイルを開く
    std::unique_ptr<FILE, MyFileCloser> pfile(fopen("test", "r"), MyFileCloser());

    char buffer[1024];
    fgets(buffer, sizeof(buffer), pfile.get());

    std::cout << buffer << std::endl;

    // ファイルはスコープを抜けると自動的にクローズされる
  }

}

ポインタでない場合

問題は管理したい参照がポインタでない場合で、unique_ptrではエラーになる。

#include <memory>
#include <unordered_map>

// リソースはハンドルでアクセス
using HANDLE = int;

// リソース管理用のコンテナ
std::unordered_map<HANDLE, int*> myresource;

// リソースの確保
HANDLE MyNew(size_t size)
{
  HANDLE handle = 0;
  myresource.insert({ handle,new int[size] });
  return handle++;
}
      
      
// リソースの解放
void MyDelete(HANDLE handle)
{
  delete[] myresource[handle];
  myresource.erase(handle);
}
     
struct My_HANDLE_Release {
  void operator()(HANDLE handle) const {
    MyDelete(handle);
  }
};

int main()
{
  // エラー MyNew が返す HANDLE はポインタでない
  std::unique_ptr<HANDLE, My_HANDLE_Release> uptr(MyNew(100), My_HANDLE_Release());

}

unique_resource

導入

以下から、unique_resource.hpp をダウンロード。

https://github.com/okdshin/unique_resource

include

#include "unique_resource.hpp"

使用例

int main()
{
  HANDLE test;
  {
    auto unique_handle
      = std_experimental::make_unique_resource<HANDLE, My_HANDLE_Release>(MyNew(100), My_HANDLE_Release());

    test = unique_handle.get();

    // リソースを使う
    int* p = myresource.at(unique_handle.get());
    std::cout << "access     " << p << std::endl;

    for (size_t i = 0; i < 100; ++i)
    {
      p[i] = i;
    }
// リソースが解放される
  }
// リソースが解放されているかチェック if( myresource.find(test) == myresource.end() ) { std::cout << "リソースは解放されています" << std::endl; } else { std::cout << "リソースは解放されていません" << std::endl; } }

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: