boost.lockfreeのring_bufferを使ってみることにする。

公開:2011-09-09 20:43
更新:2020-02-15 04:36
カテゴリ:c++,boost,dawもどきの作成,windows,audio

boost.lockfreeのexamplesを見るとなんとなく使い方がわかったので、スレッド間データ共有用のバッファとしてring_bufferを使うことにした。

ring_bufferはenqueueで値を入れ、dequeueで値を取り出す。この値をメモリブロックへのポインタとする。ストレージからデータを読取りメモリブロックに格納し、そのアドレスをring_bufferにenqueueするのである。

メモリブロックの大きさはWAVファイルのフォーマットやwaspaiのバッファサイズに応じて変化するので、静的には確保できず、動的確保となる。でもメモリブロックをディスクを読み込む都度生成・破棄するのは非効率なのでメモリブロックのポインタ配列を持つことにする。ポインタ配列に予めメモリブロックを確保・格納しておき、使いまわすのである。ポインタ配列は解放忘れのおそれがあるのでスマートポインタの配列にする。メモリブロックの解放はスマポのカスタムデリータで行う。

メモリブロックは16byteにアラインし確保することにする。これは_aligned_malloc_aligned_freeを使うことにする。

そんな感じでtypedefしてみたのが下記。実際にちゃんと動作するかはこれから。


namespace sf {

  // アラインされたメモリの解放
  struct buffer_deleter{
    void operator()(void *mem)
    {
      _aligned_free(mem);
    };
  };

  // バッファメモリのスマートポインタ
  // アラインされたメモリを想定
  typedef std::unique_ptr<uint8_t *,buffer_deleter> memory_block_t;

  // メモリブロックの配列
  // ストレージからのデータはここに一時的に格納する
  // この配列値のunique_ptrをget()してリングバッファに渡す
  typedef boost::array<memory_block_t,128> buffer_t;

  // リングバッファ マルチスレッド対応
  typedef boost::lockfree::ringbuffer<uint8_t* ,128> ringbuffer_t;
}