Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
2.6KB

  1. #include "MultiPseudoStack.h"
  2. #include <cassert>
  3. #include <cstdio>
  4. #define INVALID ((int32_t)0xffffffff)
  5. #define MAX ((int32_t)0x7fffffff)
  6. QueueListItem::QueueListItem(void)
  7. :memory(0), size(0)
  8. {
  9. }
  10. LockFreeQueue::LockFreeQueue(qli_t *data_, int n)
  11. :data(data_), elms(n), next_r(0), next_w(0), avail(0)
  12. {
  13. tag = new std::atomic<uint32_t>[n];
  14. for(int i=0; i<n; ++i)
  15. tag[i] = INVALID;
  16. }
  17. qli_t *LockFreeQueue::read(void) {
  18. retry:
  19. int8_t free_elms = avail.load();
  20. if(free_elms <= 0)
  21. return 0;
  22. int32_t next_tag = next_r.load();
  23. int32_t next_next_tag = (next_tag+1)&MAX;
  24. assert(next_tag != INVALID);
  25. for(int i=0; i<elms; ++i) {
  26. uint32_t elm_tag = tag[i].load();
  27. //attempt to remove tagged element
  28. //if and only if it's next
  29. if(((uint32_t)next_tag) == elm_tag) {
  30. if(!tag[i].compare_exchange_strong(elm_tag, INVALID))
  31. goto retry;
  32. //Ok, now there is no element that can be removed from the list
  33. //Effectively there's mutual exclusion over other readers here
  34. //Set the next element
  35. int sane_read = next_r.compare_exchange_strong(next_tag, next_next_tag);
  36. assert(sane_read && "No double read on a single tag");
  37. //Decrement available elements
  38. int32_t free_elms_next = avail.load();
  39. while(!avail.compare_exchange_strong(free_elms_next, free_elms_next-1));
  40. //printf("r%d ", free_elms_next-1);
  41. return &data[i];
  42. }
  43. }
  44. goto retry;
  45. }
  46. //Insert Node Q
  47. void LockFreeQueue::write(qli_t *Q) {
  48. retry:
  49. if(!Q)
  50. return;
  51. int32_t write_tag = next_w.load();
  52. int32_t next_write_tag = (write_tag+1)&MAX;
  53. if(!next_w.compare_exchange_strong(write_tag, next_write_tag))
  54. goto retry;
  55. uint32_t invalid_tag = INVALID;
  56. //Update tag
  57. int sane_write = tag[Q-data].compare_exchange_strong(invalid_tag, write_tag);
  58. assert(sane_write);
  59. //Increment available elements
  60. int32_t free_elms = avail.load();
  61. while(!avail.compare_exchange_strong(free_elms, free_elms+1))
  62. assert(free_elms <= 32);
  63. //printf("w%d ", free_elms+1);
  64. }
  65. MultiQueue::MultiQueue(void)
  66. :pool(new qli_t[32]), m_free(pool, 32), m_msgs(pool, 32)
  67. {
  68. //32 instances of 2kBi memory chunks
  69. for(int i=0; i<32; ++i) {
  70. qli_t &ptr = pool[i];
  71. ptr.size = 2048;
  72. ptr.memory = new char[2048];
  73. free(&ptr);
  74. }
  75. }
  76. MultiQueue::~MultiQueue(void)
  77. {
  78. for(int i=0; i<32; ++i)
  79. delete [] pool[i].memory;
  80. delete [] pool;
  81. }