最終更新日時: 2025年07月12日 02時16分44秒 (JST)
Koichi Murase が更新

履歴 編集

class
<mutex>

# std::recursive_timed_mutex(C++11)

    namespace std {
      class recursive_timed_mutex;
    }

## 概要

`recursive_timed_mutex`は、スレッド間で使用する共有リソースを排他制御するためのクラスであり、再帰的なロックと、ロック取得のタイムアウト機能をサポートする。`lock()`メンバ関数によってリソースのロックを取得し、`unlock()`メンバ関数でリソースのロックを手放す。

このクラスのデストラクタは自動的に`unlock()`メンバ関数を呼び出すことはないため、通常このクラスのメンバ関数は直接は呼び出さず、`lock_guard`や`unique_lock`といったロック管理クラスと併用する。

## メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++11
`(destructor)` | デストラクタ | C++11
`operator=(const recursive_timed_mutex&) = delete` | 代入演算子 | C++11
`lock` | ロックを取得する | C++11
`try_lock` | ロックの取得を試みる | C++11
`try_lock_for` | タイムアウトする相対時間を指定してロックの取得を試みる | C++11
`try_lock_until` | タイムアウトする絶対時間を指定してロックの取得を試みる | C++11
`unlock` | ロックを手放す | C++11
`native_handle` | ミューテックスのハンドルを取得する | C++11

## メンバ型

名前 | 説明 | 対応バージョン
--- | --- | ---
`native_handle_type` | 実装依存のハンドル型 | C++11

## 例

    #include <iostream>
    #include <mutex>
    #include <thread>
    #include <chrono>
    #include <system_error>

    class counter {
      int count_ = 0;
      std::recursive_timed_mutex mtx_;
    public:
      int add(int value)
      {
        // ロックを取得する(3秒でタイムアウト)
        if (!mtx_.try_lock_for(std::chrono::seconds(3))) {
          // ロック取得がタイムアウト
          std::error_code ec(static_cast<int>(std::errc::device_or_resource_busy), std::generic_category());
          throw std::system_error(ec);
        }

        int result = count_ += value;

        mtx_.unlock();

        return result;
      }

      int increment()
      {
        // ロックを取得する(3秒でタイムアウト)
        if (!mtx_.try_lock_for(std::chrono::seconds(3))) {
          // ロック取得がタイムアウト
          std::error_code ec(static_cast<int>(std::errc::device_or_resource_busy), std::generic_category());
          throw std::system_error(ec);
        }

        int result = add(1); // add()関数内でも同じミューテックスからロックを取得する

        mtx_.unlock();

        return result;
      }
    };

    std::mutex print_mtx_;
    void print_value(int value)
    {
      std::lock_guard<std::mutex> lock(print_mtx_);
      std::cout << "count == " << value << std::endl;
    }

    counter c;
    void change_count()
    {
      int value = c.increment();
      print_value(value);
    }

    int main()
    {
      std::thread t1(change_count);
      std::thread t2(change_count);

      t1.join();
      t2.join();
    }

### 出力例

    count == 1
    count == 2

## バージョン

### 言語

- C++11

### 処理系

- Clang: ??
- GCC: 4.7.0 ✅
- ICC: ??
- Visual C++: 2012 ✅, 2013 ✅, 2015 ✅
  - 2012, 2013は、(2)での実引数の受け渡しにムーブを使用しない問題がある。上記の例でも、`std::unique_ptr<int>`の実引数でコンパイルエラーになる。

## 参照