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.

105 lines
1.9KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. SafeQueue.cpp - Yet Another Lockless Ringbuffer
  4. Copyright (C) 2016 Mark McCurry
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. */
  10. namespace zyncarla {
  11. template<class T>
  12. SafeQueue<T>::SafeQueue(size_t maxlen)
  13. :writePtr(0), readPtr(0), bufSize(maxlen)
  14. {
  15. w_space.init(PTHREAD_PROCESS_PRIVATE, maxlen - 1);
  16. r_space.init(PTHREAD_PROCESS_PRIVATE, 0);
  17. buffer = new T[maxlen];
  18. }
  19. template<class T>
  20. SafeQueue<T>::~SafeQueue()
  21. {
  22. delete [] buffer;
  23. }
  24. template<class T>
  25. unsigned int SafeQueue<T>::size() const
  26. {
  27. return rSpace();
  28. }
  29. template<class T>
  30. unsigned int SafeQueue<T>::rSpace() const
  31. {
  32. return r_space.getvalue();
  33. }
  34. template<class T>
  35. unsigned int SafeQueue<T>::wSpace() const
  36. {
  37. return w_space.getvalue();
  38. }
  39. template<class T>
  40. int SafeQueue<T>::push(const T &in)
  41. {
  42. if(!wSpace())
  43. return -1;
  44. //ok, there is space to write
  45. size_t w = (writePtr + 1) % bufSize;
  46. buffer[w] = in;
  47. writePtr = w;
  48. //adjust ranges
  49. w_space.wait(); //guaranteed not to wait
  50. r_space.post();
  51. return 0;
  52. }
  53. template<class T>
  54. int SafeQueue<T>::peak(T &out) const
  55. {
  56. if(!rSpace())
  57. return -1;
  58. //ok, there is space to read
  59. size_t r = (readPtr + 1) % bufSize;
  60. out = buffer[r];
  61. return 0;
  62. }
  63. template<class T>
  64. int SafeQueue<T>::pop(T &out)
  65. {
  66. if(!rSpace())
  67. return -1;
  68. //ok, there is space to read
  69. size_t r = (readPtr + 1) % bufSize;
  70. out = buffer[r];
  71. readPtr = r;
  72. //adjust ranges
  73. r_space.wait(); //guaranteed not to wait
  74. w_space.post();
  75. return 0;
  76. }
  77. template<class T>
  78. void SafeQueue<T>::clear()
  79. {
  80. //thread unsafe
  81. while(!r_space.trywait())
  82. w_space.post();
  83. readPtr = writePtr;
  84. }
  85. }