+/**
+ * @function BeforeDraw
+ * @purpose Called in graphics thread before the draw loop
+ * When --pedantic-graphics enabled, will wait for position computations to finish before drawing
+ * Otherwise does nothing
+ */
+void BeforeDraw()
+{
+ if (options.verbosity != 0 && universe.steps % options.verbosity == 0)
+ DisplayStatistics();
+ //printf("BEFORE DRAW\n");
+ if (!options.pedantic_graphics)
+ return;
+
+ Barrier_Wait(&position_barrier);
+
+
+ Barrier_Enter(&graphics_barrier);
+}
+
+/**
+ * @function AfterDraw
+ * @purpose Called in graphics thread after the draw loop
+ * When --pedantic-graphics is supplied, will signal computation thread that drawing is finished
+ * So that positions can be safely altered
+ * Otherwise does nothing
+ */
+void AfterDraw()
+{
+ universe.steps += 1;
+ if (!options.pedantic_graphics)
+ return;
+ Barrier_Leave(&graphics_barrier);
+
+}
+
+#ifdef PERSISTENT_THREADS
+
+/**
+ * @function Worker_Thread
+ * @purpose Thread - Calculate stuff
+ */
+void * Worker_Thread(void * arg)
+{
+ System * s = (System*)(arg);
+
+
+ pthread_t * nested_workers = NULL;
+ System_ForcePair * system_pairs = NULL;
+ System * nested_position = NULL;
+
+ Barrier nested_barrier;
+ Barrier_Init(&nested_barrier);
+
+ printf("options.nested_threads == %d\n", (int)(options.nested_threads));
+
+ if (options.nested_threads != 1)
+ {
+
+ system_pairs = (System_ForcePair*)(calloc(options.nested_threads, sizeof(System_ForcePair)));
+ if (system_pairs == NULL) // Handle tedious error cases
+ {
+ perror("Couldn't allocate array of system pairs");
+ QuitProgram(true);
+ pthread_exit(NULL);
+ }
+ nested_workers = Allocate_Threads(options.nested_threads);
+ nested_position =
+
+ for (unsigned i = 0; i < options.nested_threads; ++i)
+ {
+ system_pairs[i].A = s;
+ system_pairs[i].B = nested_sub_system+i;
+ }
+ }
+
+ while (!ExitCondition())
+ {
+
+ if (options.nested_threads == 1)
+ {
+ Barrier_Enter(&force_barrier);
+ System_Forces(s, &universe);
+ Barrier_Leave(&force_barrier);
+ }
+ else
+ {
+ for (unsigned i = 0; i < options.nested_threads; ++i)
+ {
+ if (pthread_create(nested_workers+i, &attr, Force_Thread, (void*)(system_pairs+i)) != 0)
+ {
+ perror("In worker thread, couldn't create nested worker thread (force)");
+ QuitProgram(true);
+ free(nested_workers);
+ pthread_exit(NULL);
+ }
+ }
+ }
+ //printf("Computed forces for %p\n", arg);
+ Barrier_Wait(&force_barrier);
+ //printf("Computed ALL forces\n");
+
+ if (options.draw_graphics && options.pedantic_graphics)
+ Barrier_Wait(&graphics_barrier);
+
+ Barrier_Enter(&position_barrier);
+
+ System_Positions(s);
+
+ Barrier_Leave(&position_barrier);
+ //printf("Computed positions for %p\n", arg);
+ Barrier_Wait(&position_barrier);
+ //printf("Computed ALL positions\n");
+ }
+ printf("Worker thread exits\n");
+ QuitProgram(false);
+ pthread_exit(NULL);
+}
+
+#endif //PERSISTENT_THREADS
+