|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2021 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // シングルプロデューサ/シングルコンシューマのロックレス固定長キュー ! 9: // ! 10: ! 11: #pragma once ! 12: ! 13: #include "header.h" ! 14: #include <array> ! 15: #include <atomic> ! 16: ! 17: // reader が 1 スレッド、writer が 1 スレッドの場合にのみスレッドセーフ。 ! 18: // 要素型 T はデストラクト不要な型(プリミティブまたはその構造体など)を ! 19: // 期待している。 ! 20: template <typename T, size_t CAPACITY> ! 21: class SPSCQueue ! 22: { ! 23: public: ! 24: SPSCQueue() ! 25: { ! 26: } ! 27: ! 28: // 読み込みを開始する。 ! 29: // 読み込み要素のポインタを返す。 ! 30: // 読み込み要素がないときは nullptr を返す。 ! 31: const T *BeginRead() ! 32: { ! 33: if (length == 0) { ! 34: return nullptr; ! 35: } ! 36: return &mem[ri]; ! 37: } ! 38: ! 39: // 書き込みを開始する。 ! 40: // 書き込み要素のポインタを返す。 ! 41: // 書き込み要素がないときは nullptr を返す。 ! 42: T *BeginWrite() ! 43: { ! 44: if (length >= CAPACITY) { ! 45: return nullptr; ! 46: } ! 47: return &mem[wi]; ! 48: } ! 49: ! 50: // BeginRead で開始した読み込みをキャンセルする。 ! 51: void CancelRead() ! 52: { ! 53: // nop ! 54: } ! 55: ! 56: // BeginWrite で開始した書き込みをキャンセルする。 ! 57: void CancelWrite() ! 58: { ! 59: // nop ! 60: } ! 61: ! 62: // BeginRead で開始した読み込みを終了する。 ! 63: // これ以降は BeginRead で返された要素にアクセスしてはならない。 ! 64: // BeginRead を呼び出していないのに EndRead を呼び出してはならない。 ! 65: void EndRead() ! 66: { ! 67: assert(length > 0); ! 68: ri = (ri + 1) % CAPACITY; ! 69: --length; ! 70: } ! 71: ! 72: // BeginWrite で開始した書き込みを終了する。 ! 73: // これ以降は BeginWrite で返された要素にアクセスしてはならない。 ! 74: // BeginWrite を呼び出していないのに EndWrite を呼び出してはならない。 ! 75: void EndWrite() ! 76: { ! 77: assert(length < CAPACITY); ! 78: wi = (wi + 1) % CAPACITY; ! 79: ++length; ! 80: } ! 81: ! 82: // item をコピー投入する。 ! 83: bool Enqueue(const T& item) ! 84: { ! 85: T *p = BeginWrite(); ! 86: if (p == nullptr) { ! 87: return false; ! 88: } ! 89: *p = item; ! 90: EndWrite(); ! 91: return true; ! 92: } ! 93: ! 94: // pitem にコピー取り出しする。 ! 95: bool Dequeue(T *pitem) ! 96: { ! 97: const T *p = BeginRead(); ! 98: if (p == nullptr) { ! 99: return false; ! 100: } ! 101: *pitem = *p; ! 102: EndRead(); ! 103: return true; ! 104: } ! 105: ! 106: // 最大要素数を返す。 ! 107: constexpr size_t Capacity() const { return CAPACITY; } ! 108: ! 109: // 現在の要素数を返す。 ! 110: // 取得した直後に変化するかもしれないことに注意。 ! 111: size_t Length() const { return length; } ! 112: ! 113: private: ! 114: std::atomic<size_t> length {}; ! 115: int ri {}; // reader の index ! 116: int wi {}; // writer の index ! 117: std::array<T, CAPACITY> mem {}; ! 118: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.