/******************************************************************************************* * * raylib [core] example - loading thread * * NOTE: This example requires linking with pthreads library on MinGW, * it can be accomplished passing -static parameter to compiler * * Example originally created with raylib 2.5, last time updated with raylib 3.0 * * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * * Copyright (c) 2014-2023 Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" // WARNING: This example does not build on Windows with MSVC compiler #include "pthread.h" // POSIX style threads management #include // C11 atomic data types #include // Required for: clock() // Using C11 atomics for synchronization // NOTE: A plain bool (or any plain data type for that matter) can't be used for inter-thread synchronization static atomic_bool dataLoaded = false; // Data Loaded completion indicator static void *LoadDataThread(void *arg); // Loading data thread function declaration static atomic_int dataProgress = 0; // Data progress accumulator //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - loading thread"); pthread_t threadId; // Loading data thread id enum { STATE_WAITING, STATE_LOADING, STATE_FINISHED } state = STATE_WAITING; int framesCounter = 0; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- switch (state) { case STATE_WAITING: { if (IsKeyPressed(KEY_ENTER)) { int error = pthread_create(&threadId, NULL, &LoadDataThread, NULL); if (error != 0) TraceLog(LOG_ERROR, "Error creating loading thread"); else TraceLog(LOG_INFO, "Loading thread initialized successfully"); state = STATE_LOADING; } } break; case STATE_LOADING: { framesCounter++; if (atomic_load_explicit(&dataLoaded, memory_order_relaxed)) { framesCounter = 0; int error = pthread_join(threadId, NULL); if (error != 0) TraceLog(LOG_ERROR, "Error joining loading thread"); else TraceLog(LOG_INFO, "Loading thread terminated successfully"); state = STATE_FINISHED; } } break; case STATE_FINISHED: { if (IsKeyPressed(KEY_ENTER)) { // Reset everything to launch again atomic_store_explicit(&dataLoaded, false, memory_order_relaxed); atomic_store_explicit(&dataProgress, 0, memory_order_relaxed); state = STATE_WAITING; } } break; default: break; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); switch (state) { case STATE_WAITING: DrawText("PRESS ENTER to START LOADING DATA", 150, 170, 20, DARKGRAY); break; case STATE_LOADING: { DrawRectangle(150, 200, atomic_load_explicit(&dataProgress, memory_order_relaxed), 60, SKYBLUE); if ((framesCounter/15)%2) DrawText("LOADING DATA...", 240, 210, 40, DARKBLUE); } break; case STATE_FINISHED: { DrawRectangle(150, 200, 500, 60, LIME); DrawText("DATA LOADED!", 250, 210, 40, GREEN); } break; default: break; } DrawRectangleLines(150, 200, 500, 60, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } // Loading data thread function definition static void *LoadDataThread(void *arg) { int timeCounter = 0; // Time counted in ms clock_t prevTime = clock(); // Previous time // We simulate data loading with a time counter for 5 seconds while (timeCounter < 5000) { clock_t currentTime = clock() - prevTime; timeCounter = currentTime*1000/CLOCKS_PER_SEC; // We accumulate time over a global variable to be used in // main thread as a progress bar atomic_store_explicit(&dataProgress, timeCounter/10, memory_order_relaxed); } // When data has finished loading, we set global variable atomic_store_explicit(&dataLoaded, true, memory_order_relaxed); return NULL; }