#include <unistd.h>
#include <math.h>
#include <time.h>
+#include <pthread.h>
#include <GLES3/gl3.h>
#include <GLFW/glfw3.h>
#define WINDOW_TITLE "N-Body Simulation"
// :ArbitraryConstant
-#define PARTICLE_COUNT 2500
+#define PARTICLE_COUNT 3000
+
+// :ArbitraryConstant
+#define NUM_THREADS 2
// TODO(Brendan): Maybe this can be removed because it isn't really necessary?
internal void
Camera camera;
};
+internal void
+update_bodies_partial(SimState *state, i32 index)
+{
+ i32 low = index * (PARTICLE_COUNT / NUM_THREADS);
+ i32 high = (index + 1) * (PARTICLE_COUNT / NUM_THREADS);
+
+ persist const f64 step = 0.01;
+
+ foreach (i, low, high)
+ {
+ body_accumulate_move(&state->bodies[i], &state->qt_bodies, step);
+ }
+
+ foreach (i, low, high)
+ {
+ body_apply_move(&state->bodies[i], step);
+ }
+}
+
+internal pthread_barrier_t thread_sync_barrier;
+internal pthread_t threads[NUM_THREADS - 1];
+
+struct ThreadData
+{
+ i32 id;
+ SimState* state;
+};
+
+internal void*
+thread_start(void* data)
+{
+ i32 thread_id = ((ThreadData *) data)->id;
+ SimState* state = ((ThreadData *) data)->state;
+
+ while (true)
+ {
+ pthread_barrier_wait(&thread_sync_barrier);
+ update_bodies_partial(state, thread_id + 1);
+ pthread_barrier_wait(&thread_sync_barrier);
+ pthread_barrier_wait(&thread_sync_barrier);
+ }
+
+ return NULL;
+}
+
internal void
sim_state_init(SimState* state)
{
state->qt_body_allocator.init(PARTICLE_COUNT);
- state->camera.offset = V2f { 0, 0 };
state->camera.scale = 1.0f;
+
+ pthread_barrier_init(&thread_sync_barrier, NULL, NUM_THREADS);
+
+ foreach (i, 0, NUM_THREADS - 1)
+ {
+ auto td = alloc<ThreadData>(1); // LEAK
+ td->id = i;
+ td->state = state;
+ pthread_create(&threads[i], NULL, thread_start, (void *) td);
+ }
}
// NOTE(Brendan): dt is expected to be in units of "per second".
if (glfwGetKey(window, GLFW_KEY_Q)) state->camera.scale *= 1.01f;
if (glfwGetKey(window, GLFW_KEY_A)) state->camera.scale /= 1.01f;
- persist const f64 step = 0.01;
-
state->qt_bodies.init(AABB { -2000, -2000, 4000, 4000 });
state->qt_body_allocator.reset();
For (state->bodies) state->qt_bodies.insert(&it, &state->qt_body_allocator);
+ pthread_barrier_wait(&thread_sync_barrier);
- For (state->bodies) body_accumulate_move(&it, &state->qt_bodies, step);
- For (state->bodies) body_apply_move(&it, step);
+ update_bodies_partial(state, 0);
+ pthread_barrier_wait(&thread_sync_barrier);
}
// NOTE CLEANUP(Brendan): Bunch of graphics state that should go elsewhere.
// NOTE(Brendan): Present the changes to the screen.
glfwSwapBuffers(window);
+ pthread_barrier_wait(&thread_sync_barrier);
}
internal void