1. #ifndef BOUNDEDBUFFER_H // header guards
  2. #define BOUNDEDBUFFER_H
  3.  
  4. #include <uC++.h>
  5. #include <iostream>
  6. #include <queue>
  7.  
  8. using namespace std;
  9.  
  10. template<typename T> class BoundedBuffer {
  11. queue<T> buffer;
  12. int size;
  13. int curSize;
  14. uCondLock prodlk;
  15. uCondLock conlk;
  16. uOwnerLock mlk;
  17. #ifdef NOBUSY
  18. uCondLock barlk;
  19. bool done;
  20. #endif // NOBUSY
  21. public:
  22. BoundedBuffer( const unsigned int size = 10 ): size(size), curSize(0), done(true){};
  23. void insert( T elem );
  24. T remove();
  25. };
  26.  
  27. template<typename T>
  28.  
  29. void BoundedBuffer<T>::insert( T elem ){
  30. mlk.acquire();
  31. #ifdef NOBUSY
  32. if(!done) {
  33. cerr << "waiting 1" << endl;
  34. barlk.wait(mlk);
  35. cerr << "done waiting 1" << endl;
  36. }
  37. if(curSize == size) {
  38. if(!barlk.empty()) {
  39. done = true;
  40. barlk.signal();
  41. }
  42. prodlk.wait(mlk);
  43. done = true;
  44. }
  45. #endif
  46.  
  47. #ifdef BUSY
  48. while(curSize == size) {
  49. prodlk.wait(mlk);
  50. }
  51. #endif
  52.  
  53. assert(curSize < size);
  54. buffer.push(elem);
  55. curSize++;
  56. if(!conlk.empty()) {
  57. #ifdef NOBUSY
  58. done = false;
  59. #endif
  60. conlk.signal();
  61. }
  62.  
  63. #ifdef NOBUSY
  64. else if(!barlk.empty()){
  65. done = true;
  66. cerr << "signalling 1" << endl;
  67. barlk.signal();
  68. }
  69. #endif
  70. mlk.release();
  71. }
  72.  
  73. template<typename T>
  74.  
  75. T BoundedBuffer<T>::remove(){
  76. mlk.acquire();
  77.  
  78. #ifdef NOBUSY
  79. if(!done) {
  80. cerr << "waiting 2" << endl;
  81. barlk.wait(mlk);
  82. cerr << "done waiting 2" << endl;
  83. }
  84. if(curSize == 0) {
  85. if(!barlk.empty()) {
  86. done = true;
  87. barlk.signal();
  88. }
  89. conlk.wait(mlk);
  90. done = true;
  91. }
  92. #endif
  93.  
  94. #ifdef BUSY
  95. while(curSize == 0) {
  96. conlk.wait(mlk);
  97. }
  98. #endif
  99.  
  100. assert(curSize > 0);
  101. T popped = buffer.front();
  102. buffer.pop();
  103. curSize--;
  104. if(!prodlk.empty()) {
  105. #ifdef NOBUSY
  106. done = false;
  107. #endif
  108. prodlk.signal();
  109. }
  110. #ifdef NOBUSY
  111. else if(!barlk.empty()){
  112. done = true;
  113. cerr << "signalling 2" << endl;
  114. barlk.signal();
  115. }
  116. #endif
  117. mlk.release();
  118. return popped;
  119. }
  120.  
  121. #endif