Annotation of nono/lib/spscqueue.h, revision 1.1.1.1

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: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.