zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

MultiPseudoStack.h (1768B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   MultiPseudoStack.h - Multiple-Writer Lock Free Datastructure
      5   Copyright (C) 2016 Mark McCurry
      6 
      7   This program is free software; you can redistribute it and/or
      8   modify it under the terms of the GNU General Public License
      9   as published by the Free Software Foundation; either version 2
     10   of the License, or (at your option) any later version.
     11 */
     12 #pragma once
     13 #include <atomic>
     14 
     15 namespace zyn {
     16 
     17 //XXX rename this thing
     18 typedef struct QueueListItem qli_t;
     19 //! Queue item for LockFreeQueue
     20 struct QueueListItem
     21 {
     22     QueueListItem(void);
     23     char     *memory;
     24     uint32_t  size;
     25 };
     26 
     27 
     28 //! Many reader many writer queue of fixed size memory chunks
     29 class LockFreeQueue
     30 {
     31     qli_t *const           data;
     32     const int              elms;
     33     std::atomic<uint32_t> *tag;
     34     std::atomic<int32_t>   next_r;
     35     std::atomic<int32_t>   next_w;
     36     std::atomic<int32_t>   avail;
     37 public:
     38     LockFreeQueue(qli_t *data_, int n);
     39     ~LockFreeQueue(void);
     40     qli_t *read(void);
     41     void write(qli_t *Q);
     42 };
     43 
     44 
     45 /**
     46  * Many reader many writer capiable queue of fixed size memory chunks
     47  *
     48  * - lock free
     49  * - allocation free (post initialization)
     50  */
     51 class MultiQueue
     52 {
     53     qli_t *pool;          //!< actual storage
     54     LockFreeQueue m_free; //!< queue of unused items
     55     LockFreeQueue m_msgs; //!< actual queue
     56 
     57 public:
     58     MultiQueue(void);
     59     ~MultiQueue(void);
     60     //! return a fresh item, e.g. to write to
     61     qli_t *alloc(void)   { return m_free.read();   }
     62     //! free an item
     63     void free(qli_t  *q) {        m_free.write(q); }
     64     //! write item into the queue
     65     void write(qli_t *q) {        m_msgs.write(q); }
     66     //! take an item from the queue, must be freed
     67     qli_t *read(void)    { return m_msgs.read();   }
     68 };
     69 
     70 }