Advertisement
TheBirkIsReal

parser.cpp

Aug 26th, 2019
799
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.37 KB | None | 0 0
  1. #if 1
  2. struct ParserWorkerThreadData {
  3.     Parser *parser;
  4.  
  5.     gbSemaphore error_handled; //NOTE(thebirk): Use to signal that the worker thead has a new work to do
  6.     ParseFileError err;
  7.  
  8.     gbMutex lock; //NOTE(thebirk): All variables below are locked by this mutex
  9.     bool error_available;
  10.     bool should_exit;
  11. };
  12.  
  13.  
  14. GB_THREAD_PROC(parse_worker_file_proc) {
  15.     GB_ASSERT(thread != nullptr);
  16.  
  17.     ParserWorkerThreadData* data = cast(ParserWorkerThreadData*) thread->user_data;
  18.  
  19.     for(;;) {
  20.         gb_semaphore_wait(&data->error_handled);
  21.         //printf("I am a worker and got signalled to start working!\n");
  22.  
  23.         gb_mutex_lock(&data->lock);
  24.         //printf("I am a worker and got a lock!\n");
  25.         if (data->should_exit) {
  26.             gb_mutex_unlock(&data->lock);
  27.             //printf("I am being told to quit!\n");
  28.             return isize(0);
  29.         }
  30.  
  31.         Parser *p = data->parser;
  32.         isize index = thread->user_index;
  33.         gb_mutex_lock(&p->file_add_mutex);
  34.         auto file_to_process = p->files_to_process[index];
  35.         gb_mutex_unlock(&p->file_add_mutex);
  36.         data->err = process_imported_file(p, file_to_process);
  37.  
  38.         data->error_available = true;
  39.         gb_mutex_unlock(&data->lock);
  40.         //printf("I am a worker and did unlock!\n");
  41.     }
  42.  
  43.     //GB_PANIC("A worker thread should not be able to reach the end!!!");
  44.     //return isize(0);
  45. }
  46. #else
  47. GB_THREAD_PROC(parse_worker_file_proc) {
  48.     if (thread == nullptr) return 0;
  49.     auto *p = cast(Parser *)thread->user_data;
  50.     isize index = thread->user_index;
  51.     gb_mutex_lock(&p->file_add_mutex);
  52.     auto file_to_process = p->files_to_process[index];
  53.     gb_mutex_unlock(&p->file_add_mutex);
  54.     ParseFileError err = process_imported_file(p, file_to_process);
  55.     return cast(isize)err;
  56. }
  57. #endif
  58.  
  59. ParseFileError parse_packages(Parser *p, String init_filename) {
  60.     GB_ASSERT(init_filename.text[init_filename.len] == 0);
  61.  
  62.     // char *fullpath_str = gb_path_get_full_name(heap_allocator(), cast(char const *)&init_filename[0]);
  63.     // String init_fullpath = string_trim_whitespace(make_string_c(fullpath_str));
  64.     String init_fullpath = path_to_full_path(heap_allocator(), init_filename);
  65.     if (!path_is_directory(init_fullpath)) {
  66.         String const ext = str_lit(".odin");
  67.         if (!string_ends_with(init_fullpath, ext)) {
  68.             gb_printf_err("Expected either a directory or a .odin file, got '%.*s'\n", LIT(init_filename));
  69.             return ParseFile_WrongExtension;
  70.         }
  71.     }
  72.  
  73.  
  74.     TokenPos init_pos = {};
  75.     if (!build_context.generate_docs) {
  76.         String s = get_fullpath_core(heap_allocator(), str_lit("runtime"));
  77.         try_add_import_path(p, s, s, init_pos, Package_Runtime);
  78.     }
  79.  
  80.     try_add_import_path(p, init_fullpath, init_fullpath, init_pos, Package_Init);
  81.     p->init_fullpath = init_fullpath;
  82.  
  83. #if 1
  84.     isize thread_count = gb_max(build_context.thread_count, 1);
  85.     if (thread_count > 1) {
  86.         isize volatile curr_import_index = 0;
  87.         isize initial_file_count = p->files_to_process.count;
  88.         // NOTE(bill): Make sure that these are in parsed in this order
  89.         for (isize i = 0; i < initial_file_count; i++) {
  90.             ParseFileError err = process_imported_file(p, p->files_to_process[i]);
  91.             if (err != ParseFile_None) {
  92.                 return err;
  93.             }
  94.             curr_import_index++;
  95.         }
  96.  
  97.         auto worker_threads_data = array_make<ParserWorkerThreadData>(heap_allocator(), thread_count);
  98.         defer (array_free(&worker_threads_data));
  99.  
  100.         for_array(i, worker_threads_data) {
  101.             ParserWorkerThreadData* data = &worker_threads_data[i];
  102.             gb_mutex_init(&data->lock);
  103.             gb_semaphore_init(&data->error_handled);
  104.             data->parser = p;
  105.             data->err = ParseFile_None;
  106.             data->should_exit = false;
  107.             data->error_available = false;
  108.         }
  109.  
  110.         defer(for_array(i, worker_threads_data) {
  111.             ParserWorkerThreadData* data = &worker_threads_data[i];
  112.             gb_mutex_destroy(&data->lock);
  113.             gb_semaphore_destroy(&data->error_handled);
  114.         });
  115.  
  116.         auto worker_threads = array_make<gbThread>(heap_allocator(), thread_count);
  117.         defer (array_free(&worker_threads));
  118.  
  119.         for_array(i, worker_threads) {
  120.             gbThread* t = &worker_threads[i];
  121.             gb_thread_init(t);
  122.             char buffer[64];
  123.             gb_snprintf(buffer, 64, "Parser Worker #%lld", i);
  124.             gb_thread_set_name(t, buffer);
  125.             gb_thread_start(t, parse_worker_file_proc, &worker_threads_data[i]);
  126.         }
  127.         defer(for_array(i, worker_threads) {
  128.             gb_thread_destroy(&worker_threads[i]);
  129.         });
  130.  
  131.         auto errors = array_make<ParseFileError>(heap_allocator(), 0, 16);
  132.  
  133.         for (;;) {
  134.             bool are_any_alive = false;
  135.  
  136.             for_array(i, worker_threads) {
  137.                 gbThread *t = &worker_threads[i];
  138.                 ParserWorkerThreadData* data = &worker_threads_data[i];
  139.  
  140.                 if (gb_mutex_try_lock(&data->lock)) {
  141.                     if (data->error_available) {
  142.                         auto curr_err = data->err;
  143.                         if (curr_err != ParseFile_None) {
  144.                             array_add(&errors, curr_err);
  145.                         }
  146.  
  147.                         data->error_available = false;
  148.                     }
  149.  
  150.                     if (curr_import_index < p->files_to_process.count) {
  151.                         t->user_index = curr_import_index;
  152.                         curr_import_index++;
  153.                         are_any_alive = true;
  154.  
  155.                         gb_semaphore_release(&data->error_handled);
  156.                     }
  157.  
  158.                     gb_mutex_unlock(&data->lock);
  159.                 } else {
  160.                     //NOTE(thebirk): If we cant lock a thread it must be working
  161.                     are_any_alive = true;
  162.                 }
  163. #if 0
  164.                 if (gb_thread_is_running(t)) {
  165.                     are_any_alive = true;
  166.                 } else if (curr_import_index < p->files_to_process.count) {
  167.                     auto curr_err = cast(ParseFileError)t->return_value;
  168.                     if (curr_err != ParseFile_None) {
  169.                         array_add(&errors, curr_err);
  170.                     } else {
  171.                         t->user_index = curr_import_index;
  172.                         curr_import_index++;
  173.                         gb_thread_start(t, parse_worker_file_proc, p);
  174.                         are_any_alive = true;
  175.                     }
  176.                 }
  177. #endif
  178.             }
  179.  
  180.             //NOTE(thebirk): Everything collapses without this, but it shouldnt really
  181.             gb_yield();
  182.  
  183.             if (!are_any_alive && (curr_import_index >= p->files_to_process.count)) {
  184.                 break;
  185.             }
  186.         }
  187.  
  188.         for_array(i, worker_threads_data) {
  189.             ParserWorkerThreadData* data = &worker_threads_data[i];
  190.             data->should_exit = true;
  191.             gb_semaphore_release(&data->error_handled);
  192.         }
  193.  
  194.         if (errors.count > 0) {
  195.             return errors[errors.count-1];
  196.         }
  197.     } else {
  198.         for_array(i, p->files_to_process) {
  199.             ParseFileError err = process_imported_file(p, p->files_to_process[i]);
  200.             if (err != ParseFile_None) {
  201.                 return err;
  202.             }
  203.         }
  204.     }
  205. #else
  206.     for_array(i, p->files_to_process) {
  207.         ImportedFile f = p->files_to_process[i];
  208.         ParseFileError err = process_imported_file(p, f);
  209.         if (err != ParseFile_None) {
  210.             return err;
  211.         }
  212.     }
  213. #endif
  214.  
  215.     return ParseFile_None;
  216. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement