Advertisement
Tkap1

Untitled

Dec 19th, 2024 (edited)
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.29 KB | None | 0 0
  1. // @Note(tkap, 02/01/2024): Returns true if semaphore got signaled. False otherwise
  2. func b8 acquire_semaphore(s_thread_pool* thread_pool, DWORD timeout_ms)
  3. {
  4.     DWORD result = WaitForSingleObjectEx(thread_pool->semaphore, timeout_ms, FALSE);
  5.     return result == WAIT_OBJECT_0;
  6. }
  7.  
  8. // @Note(tkap, 10/08/2023): Bug when "b" wraps around (u32 max)
  9. func s_maybe_do_work maybe_do_work(s_thread_pool* thread_pool)
  10. {
  11.     s_maybe_do_work result = zero;
  12.     u32 max_work = thread_pool->max_work;
  13.     u32 current_work = thread_pool->current_work;
  14.     if(thread_pool->work_completed < max_work) {
  15.         result.is_there_work_left_to_do = true;
  16.         if(current_work < max_work) {
  17.             u32 foo = InterlockedCompareExchange((LONG volatile*)&thread_pool->current_work, current_work + 1, current_work);
  18.             if(current_work == foo) {
  19.                 u32 index = foo % c_max_thread_queue_elements;
  20.  
  21.                 s_work_data data = thread_pool->work[index];
  22.                 ((void_func)data.func_ptr)(data.arg);
  23.                 result.did_work = true;
  24.  
  25.                 _WriteBarrier();
  26.                 _mm_sfence();
  27.                 InterlockedIncrement((LONG volatile*)&thread_pool->work_completed);
  28.             }
  29.         }
  30.     }
  31.     return result;
  32. }
  33.  
  34.  
  35. #ifdef m_platform
  36. DWORD WINAPI thread_proc(void* param)
  37. {
  38.     s_thread_data thread_data = *(s_thread_data*)param;
  39.     g_thread_id = thread_data.id;
  40.  
  41.     while(true) {
  42.         acquire_semaphore(thread_data.thread_pool, INFINITE);
  43.         while(true) {
  44.             s_maybe_do_work data = maybe_do_work(thread_data.thread_pool);
  45.             if(data.did_work) { break; }
  46.         }
  47.     }
  48.     return 0;
  49. }
  50.  
  51. func int get_thread_id()
  52. {
  53.     return g_thread_id;
  54. }
  55.  
  56. #else // m_platform
  57. func void add_work(s_thread_pool* thread_pool, void* func_ptr, void* arg)
  58. {
  59.     int temp = thread_pool->max_work;
  60.     temp %= c_max_thread_queue_elements;
  61.     thread_pool->work[temp].func_ptr = func_ptr;
  62.     thread_pool->work[temp].arg = arg;
  63.  
  64.     _WriteBarrier();
  65.     _mm_sfence();
  66.     InterlockedIncrement((LONG volatile*)&thread_pool->max_work);
  67.  
  68.     _WriteBarrier();
  69.     _mm_sfence();
  70.  
  71.     BOOL result = ReleaseSemaphore(thread_pool->semaphore, 1, null);
  72.     unreferenced(result);
  73.     assert(result);
  74. }
  75.  
  76. func void do_work_until_completed(s_thread_pool* thread_pool)
  77. {
  78.     while(acquire_semaphore(thread_pool, 0)) {
  79.         while(true) {
  80.             s_maybe_do_work data = maybe_do_work(thread_pool);
  81.             if(data.did_work) { break; }
  82.         }
  83.     }
  84.     while(thread_pool->work_completed < thread_pool->max_work) {}
  85.     reset_thread_arenas_thread_id();
  86. }
  87.  
  88. #endif // m_platform
  89.  
  90.  
  91.  
  92. // EXAMPLE USAGE
  93. // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv     TOWER STATS START       vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  94. {
  95.     int start = towers->index_data.lowest_index;
  96.     int count = get_how_many_entities_to_process_per_call(towers->index_data);
  97.     s_generic_entity_thread_data* data = (s_generic_entity_thread_data*)la_get_zero(frame_arena, sizeof(s_generic_entity_thread_data) * g_num_threads_including_main);
  98.     for(int thread_i = 0; thread_i < g_num_threads_including_main && count > 0; thread_i += 1) {
  99.         data[thread_i].start = start;
  100.         data[thread_i].count = count;
  101.         data[thread_i].frame_arena = &g_thread_arenas[thread_i];
  102.         add_work(thread_pool, set_tower_stats, &data[thread_i]);
  103.         if(!advance_entity_start(&start, &count, towers->index_data.max_index_plus_one)) { break; }
  104.     }
  105.     do_work_until_completed(thread_pool);
  106. }
  107. // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     TOWER STATS END     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement