LoginSignup
6

More than 1 year has passed since last update.

posted at

updated at

C++20便利機能の紹介:同期出力ストリーム std::osyncstream

C++20標準ライブラリでは「同期出力ストリーム(synchronized output stream)」が追加されました。これによって並行実行される複数スレッドから 行単位のストリーム同時出力 を、安全かつ手軽に行えるようになります。1

C++17
#include <iostream>
#include <mutex>

// std::cout出力を保護するミューテックスを用意...
std::mutex g_cout_mutex;

// 複数スレッドからworker_thread関数が同時に呼び出されると仮定
void worker_thread(int id)
{
  {
    // 文字列"Worker#<N>"が1行で出力されることを保障するため
    // ミューテックスg_cout_mutexによる排他制御が必須!!
    std::lock_guard lk{g_cout_mutex};
    std::cout << "Worker#" << id << std::endl;
  }
  // ...
}

std::osyncstreamクラス

下記の例示ソースコードでは新ヘッダ<syncstream>をincludeし、標準出力ストリームstd::coutstd::osyncstreamでラップしています。

C++20
#include <iostream>
#include <syncstream>  // NEW

// 複数スレッドからworker_thread関数が同時に呼び出されると仮定
void worker_thread(int id)
{
  // 文字列"Worker#<N>"は他スレッド出力と混じることなく1行で出力される
  std::osyncstream{std::cout} << "Worker#" << id << std::endl;

  {
    // syncoutへのストリーム出力は一旦バッファリングされ...
    std::osyncstream syncout{std::cout};
    syncout << "Worker#" << id << " ";
    for (int n = 0; n < id; n++) {      
      syncout << (n ? "," : "[") << n;
    }
    syncout << "]" << std::endl;
  } // syncoutオブジェクト破棄時にstd::coutへアトミックに送出(emit)される
}

std::osyncstreamクラスでは、スレッド間の排他制御は「ラップ対象の出力ストリーム(先例ではstd::cout)」に対して行われます。つまりストリーム出力操作(operetor<<)を行う std::osyncstreamオブジェクト自体は異なっていてもよく、実際にストリーム出力を行う箇所で一時オブジェクトの生成/破棄を行えば十分です。

合わせて関連するマニピューレータ(emit_on_flush,noemit_on_flush,flush_emit)も追加され、より細かい制御も可能となっています。これらの機能詳細は記事「C++ Synchronized Buffered Ostream」でも紹介しています。

利用上の注意(2020/12/1現在)

2020/12/1現在、主要C++コンパイラGCC/Clang/MSVCいずれにおいても 標準ヘッダ<syncstream>は未実装 です。この便利機能を試すことはできません。どうして…

先行して試したい方向けに、提案時の参照実装を紹介しておきます。
https://github.com/PeterSommerlad/SC22WG21_Papers/tree/master/workspace/p0053_basic_osyncstreambuf

参考ページ


  1. そのままstd::cout出力すればいいんじゃね?何がダメなの?という方は記事「スレッドセーフという幻想と現実」や「C++11のcoutとスレッド安全性」をご一読ください。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
6