Advertisement
aircampro

use of atomic and threading

Feb 27th, 2025
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.18 KB | Software | 0 0
  1. /*
  2.  * Example of stdatomic incrementing/decrementing a counter and setting a boolean flag when a data value is written, also example of xor on register
  3.  * also shows how to wait for condition variable
  4.  */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. // you define NO_LOCK if you do not have std atomic
  8. // #define NO_LOCK
  9. #ifndef NO_LOCK
  10. #include <stdatomic.h>
  11. #include <threads.h>
  12. #endif
  13. #include <atomic>
  14. #include <cassert>
  15. #include <iostream>
  16. //#include <thread>
  17. #include <bitset>
  18.  
  19. // set this data with a boolena lock flag between threads
  20. int data = 0;
  21. std::atomic<bool> ready(false);
  22.  
  23. // define the number of times the iterating thread operates
  24. const int loop_iter = 50000;
  25.  
  26. #define NR_THREADS 2
  27. int value = 0b1011;
  28. std::atomic_ref<int> x{value};
  29.  
  30. // define a condition variable which triggers a second thread to then run
  31. std::mutex mtx;
  32.  
  33. // create a function which will increment the count variable
  34. // it should wait for the condition variable set in the decrement function
  35. int func_thread(void *arg)
  36. {
  37.   int i;
  38.  
  39. #ifndef NO_LOCK
  40.   atomic_int *count = (atomic_int *) arg;
  41.   for (i = 0; i < loop_iter; i++) {
  42.     atomic_fetch_add_explicit(count, 1, memory_order_seq_cst);
  43.   }
  44. #else
  45.   int *count = (int *) arg;
  46.   for (i = 0; i < loop_iter; i++) {
  47.     (*count)++;
  48.   }
  49. #endif
  50.   x.fetch_xor(0b1110);
  51.   std::cout << std::bitset<4>(value).to_string() << std::endl;  
  52.  
  53.   return 0;
  54. }
  55.  
  56. int func_dec_thread(void *arg)
  57. {
  58.   int i;
  59.  
  60. #ifndef NO_LOCK
  61.   atomic_int *count = (atomic_int *) arg;
  62.  
  63.   for (i = 0; i < loop_iter; i++) {
  64.     atomic_fetch_sub_explicit(count, 1, memory_order_seq_cst);
  65.   }
  66. #else
  67.   int *count = (int *) arg;
  68.  
  69.   for (i = 0; i < loop_iter; i++) {
  70.     (*count)--;
  71.   }
  72. #endif
  73.  
  74.   return 0;
  75. }
  76.  
  77. // set a value
  78. int producer(void *arg) {
  79.   int *d_in = (int *) arg;
  80.   data = *d_in;
  81.   ready.store(true, std::memory_order_release);                                // Set flag
  82.   return 0;
  83. }
  84.  
  85. // check value is set to value expected
  86. int consumer(void *arg) {
  87.   int *d_in = (int *) arg;
  88.   while (!ready.load(std::memory_order_acquire));
  89.   assert(data == *d_in);
  90.   return 0;
  91. }
  92.  
  93. int main(void)
  94. {
  95.  
  96.   thrd_t th;
  97.   int set_val = 230;
  98.   thrd_start_t func_set = producer;
  99.   // start producer consumer tasks
  100.   if (thrd_create(&th, func_set, &set_val) != thrd_success) {
  101.     fprintf(stderr, "Error: thrd_create() on producer\n");
  102.     exit(1);
  103.   }
  104.   thrd_t cons;
  105.   thrd_start_t func_set2 = consumer;
  106.   if (thrd_create(&cons, func_set2, &set_val) != thrd_success) {
  107.     fprintf(stderr, "Error: thrd_create() on consumer\n");
  108.     exit(1);
  109.   }
  110.  
  111.   // now wait on completion the producer consumer tasks uses an atomic bool as the mutex
  112.   if (thrd_join(th, NULL) != thrd_success) {
  113.     fprintf(stderr, "Error: thrd_join() on producer\n");
  114.     exit(1);
  115.   }
  116.   if (thrd_join(cons, NULL) != thrd_success) {
  117.     fprintf(stderr, "Error: thrd_join() on consumer\n");
  118.     exit(1);
  119.   }
  120.  
  121.   thrd_t thrs[NR_THREADS];
  122.   int i;
  123.   thrd_start_t func = func_thread;
  124. #ifndef NO_LOCK
  125.   volatile atomic_int count = 0;
  126.   volatile atomic_int c_down = 990;
  127. #else
  128.   volatile int count = 0;
  129.   volatile int c_down = 990;
  130. #endif
  131.   thrd_t thrs_d;
  132.   thrd_start_t func_d = func_dec_thread;
  133.  
  134.   // start the count-up threads  
  135.   for (i = 0; i < NR_THREADS; i++) {
  136.     if (thrd_create(&thrs[i], func, (void*)&count) != thrd_success) {
  137.       fprintf(stderr, "Error: thrd_create() on increment\n");
  138.       exit(1);
  139.     }
  140.   }
  141.   printf("count up = %d\n", (int)count);
  142.   // start the count-down threads  
  143.   if (thrd_create(&thrs_d, func_d, (void*)&c_down) != thrd_success) {
  144.     fprintf(stderr, "Error: thrd_create() on decrement\n");
  145.     exit(1);
  146.   }
  147.   printf("count down = %d\n", (int)c_down);
  148.   printf("count up = %d\n", (int)count);
  149.  
  150.   // now join the threads on completion
  151.   if (thrd_join(thrs_d, NULL) != thrd_success) {
  152.     fprintf(stderr, "Error: thrd_join() on decrement\n");
  153.     exit(1);
  154.   }  
  155.   for (i = 0; i < NR_THREADS; i++) {
  156.     if (thrd_join(thrs[i], NULL) != thrd_success) {
  157.       fprintf(stderr, "Error: thrd_join() on increment\n");
  158.       exit(2);
  159.     }
  160.   }
  161.  
  162.   printf("count up = %d\n", (int)count);
  163.   printf("count down = %d\n", (int)c_down);
  164.  
  165.   return 0;
  166. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement