core_loading_thread.c 5.4 KB

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