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