You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
5.9 KiB

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