Guest User

Untitled

a guest
Oct 18th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.55 KB | None | 0 0
  1. /*
  2. # compilation
  3. $ g++ queue.cpp -O2 -g -pthread -o queue_without_lock -DLOCK_FREE
  4. $ g++ queue.cpp -O2 -g -pthread -o queue_with_lock
  5.  
  6. # execution time
  7. $ time ./queue_with_lock
  8. real 0m0.035s 0m0.153s 0m0.055s
  9. user 0m0.040s 0m0.270s 0m0.070s
  10. sys 0m0.020s 0m0.030s 0m0.030s
  11.  
  12. $ time ./queue_without_lock
  13. real 0m0.007s 0m0.007s 0m0.009s
  14. user 0m0.010s 0m0.010s 0m0.010s
  15. sys 0m0.000s 0m0.000s 0m0.000s
  16. */
  17. #include <cstdio>
  18. #include <pthread.h>
  19. #include <unistd.h>
  20.  
  21. static const int QUEUE_SIZE = 10;
  22. static const int TEST_ROUND = 100000;
  23.  
  24. //#define LOCK_FREE
  25.  
  26. class ScopeLock
  27. {
  28. public:
  29. ScopeLock(pthread_mutex_t* mutex) : m_mutex(mutex)
  30. {
  31. pthread_mutex_lock(mutex);
  32. }
  33.  
  34. ~ScopeLock()
  35. {
  36. pthread_mutex_unlock(m_mutex);
  37. }
  38.  
  39. private:
  40. pthread_mutex_t *m_mutex;
  41. };
  42.  
  43.  
  44. template <typename T>
  45. class Queue
  46. {
  47. public:
  48. Queue() : m_head(0)
  49. , m_tail(0)
  50. {
  51. #ifndef LOCK_FREE
  52. pthread_mutexattr_t attr;
  53. pthread_mutexattr_init(&attr);
  54. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
  55. pthread_mutex_init(&m_mutex, &attr);
  56. pthread_mutexattr_destroy(&attr);
  57. #endif
  58. }
  59.  
  60. ~Queue()
  61. {
  62. }
  63.  
  64. bool append(T val)
  65. {
  66. #ifndef LOCK_FREE
  67. ScopeLock lock(&m_mutex);
  68. #endif
  69.  
  70. if (is_full()) {
  71. return false;
  72. }
  73.  
  74. m_data[m_tail] = val;
  75. m_tail = (m_tail + 1) % QUEUE_SIZE;
  76. return true;
  77. }
  78.  
  79. bool pop(T* val)
  80. {
  81. #ifndef LOCK_FREE
  82. ScopeLock lock(&m_mutex);
  83. #endif
  84.  
  85. if (is_empty()) {
  86. return false;
  87. }
  88.  
  89. *val = m_data[m_head];
  90. m_head = (m_head + 1) % QUEUE_SIZE;
  91. return true;
  92. }
  93.  
  94. private:
  95. bool is_full()
  96. {
  97. return ((m_tail + 1 + QUEUE_SIZE) % QUEUE_SIZE) == m_head;
  98. }
  99.  
  100. bool is_empty()
  101. {
  102. return m_head == m_tail;
  103. }
  104.  
  105.  
  106. #ifdef LOCK_FREE
  107. volatile int m_head;
  108. volatile int m_tail;
  109. #else
  110. int m_head;
  111. int m_tail;
  112. pthread_mutex_t m_mutex;
  113. #endif
  114. T m_data[QUEUE_SIZE];
  115. };
  116.  
  117.  
  118. void* producer(void *arg)
  119. {
  120. Queue<int> *queue = (Queue<int>*)arg;
  121.  
  122. for (int i = 1; i <= TEST_ROUND; ) {
  123. if (queue->append(i)) {
  124. i++;
  125. }
  126. }
  127. return 0;
  128. }
  129.  
  130. void consumer(void *arg)
  131. {
  132. Queue<int> *queue = (Queue<int>*)arg;
  133.  
  134. long long sum = 0;
  135. int val;
  136. bool result;
  137. for (int i = 1; i <= TEST_ROUND; i++) {
  138. do {
  139. result = queue->pop(&val);
  140. } while (!result);
  141.  
  142. if (i != val) {
  143. printf("error\n");
  144. break;
  145. } else {
  146. sum += i;
  147. }
  148. }
  149. printf("sum %lld\n", sum);
  150. }
  151.  
  152. int main(void) {
  153. pthread_t tid;
  154. Queue<int> queue;
  155.  
  156. pthread_create(&tid, NULL, producer, &queue);
  157. consumer(&queue);
  158. pthread_join(tid, NULL);
  159.  
  160. return 0;
  161. }
Add Comment
Please, Sign In to add comment