core_loading_thread.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*******************************************************************************************
  2. *
  3. * raylib [cpre] example - loading thread
  4. *
  5. * NOTE: This example requires linking with pthreads library on MinGW,
  6. * it can be accomplished passing -static parameter to compiler
  7. *
  8. * Example originally created with raylib 2.5, last time updated with raylib 3.0
  9. *
  10. * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
  11. *
  12. * Copyright (c) 2014-2022 Ramon Santamaria (@raysan5)
  13. *
  14. ********************************************************************************************/
  15. #include "raylib.h"
  16. #include "pthread.h" // POSIX style threads management
  17. #include <stdatomic.h> // C11 atomic data types
  18. #include <time.h> // Required for: clock()
  19. // Using C11 atomics for synchronization
  20. // NOTE: A plain bool (or any plain data type for that matter) can't be used for inter-thread synchronization
  21. static atomic_bool dataLoaded = ATOMIC_VAR_INIT(false); // Data Loaded completion indicator
  22. static void *LoadDataThread(void *arg); // Loading data thread function declaration
  23. static int dataProgress = 0; // Data progress accumulator
  24. //------------------------------------------------------------------------------------
  25. // Program main entry point
  26. //------------------------------------------------------------------------------------
  27. int main(void)
  28. {
  29. // Initialization
  30. //--------------------------------------------------------------------------------------
  31. const int screenWidth = 800;
  32. const int screenHeight = 450;
  33. InitWindow(screenWidth, screenHeight, "raylib [core] example - loading thread");
  34. pthread_t threadId; // Loading data thread id
  35. enum { STATE_WAITING, STATE_LOADING, STATE_FINISHED } state = STATE_WAITING;
  36. int framesCounter = 0;
  37. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  38. //--------------------------------------------------------------------------------------
  39. // Main game loop
  40. while (!WindowShouldClose()) // Detect window close button or ESC key
  41. {
  42. // Update
  43. //----------------------------------------------------------------------------------
  44. switch (state)
  45. {
  46. case STATE_WAITING:
  47. {
  48. if (IsKeyPressed(KEY_ENTER))
  49. {
  50. int error = pthread_create(&threadId, NULL, &LoadDataThread, NULL);
  51. if (error != 0) TraceLog(LOG_ERROR, "Error creating loading thread");
  52. else TraceLog(LOG_INFO, "Loading thread initialized successfully");
  53. state = STATE_LOADING;
  54. }
  55. } break;
  56. case STATE_LOADING:
  57. {
  58. framesCounter++;
  59. if (atomic_load(&dataLoaded))
  60. {
  61. framesCounter = 0;
  62. state = STATE_FINISHED;
  63. }
  64. } break;
  65. case STATE_FINISHED:
  66. {
  67. if (IsKeyPressed(KEY_ENTER))
  68. {
  69. // Reset everything to launch again
  70. atomic_store(&dataLoaded, false);
  71. dataProgress = 0;
  72. state = STATE_WAITING;
  73. }
  74. } break;
  75. default: break;
  76. }
  77. //----------------------------------------------------------------------------------
  78. // Draw
  79. //----------------------------------------------------------------------------------
  80. BeginDrawing();
  81. ClearBackground(RAYWHITE);
  82. switch (state)
  83. {
  84. case STATE_WAITING: DrawText("PRESS ENTER to START LOADING DATA", 150, 170, 20, DARKGRAY); break;
  85. case STATE_LOADING:
  86. {
  87. DrawRectangle(150, 200, dataProgress, 60, SKYBLUE);
  88. if ((framesCounter/15)%2) DrawText("LOADING DATA...", 240, 210, 40, DARKBLUE);
  89. } break;
  90. case STATE_FINISHED:
  91. {
  92. DrawRectangle(150, 200, 500, 60, LIME);
  93. DrawText("DATA LOADED!", 250, 210, 40, GREEN);
  94. } break;
  95. default: break;
  96. }
  97. DrawRectangleLines(150, 200, 500, 60, DARKGRAY);
  98. EndDrawing();
  99. //----------------------------------------------------------------------------------
  100. }
  101. // De-Initialization
  102. //--------------------------------------------------------------------------------------
  103. CloseWindow(); // Close window and OpenGL context
  104. //--------------------------------------------------------------------------------------
  105. return 0;
  106. }
  107. // Loading data thread function definition
  108. static void *LoadDataThread(void *arg)
  109. {
  110. int timeCounter = 0; // Time counted in ms
  111. clock_t prevTime = clock(); // Previous time
  112. // We simulate data loading with a time counter for 5 seconds
  113. while (timeCounter < 5000)
  114. {
  115. clock_t currentTime = clock() - prevTime;
  116. timeCounter = currentTime*1000/CLOCKS_PER_SEC;
  117. // We accumulate time over a global variable to be used in
  118. // main thread as a progress bar
  119. dataProgress = timeCounter/10;
  120. }
  121. // When data has finished loading, we set global variable
  122. atomic_store(&dataLoaded, true);
  123. return NULL;
  124. }