summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2016-03-30 20:29:08 +0200
committerPaweł Redman <pawel.redman@gmail.com>2016-03-30 20:29:08 +0200
commit745d5a072d8669d1bc35e7c1f28b75b3484542e8 (patch)
treeecc9cbd03511764e79251ec256c81cb8796f7c36
parentbc50836fdcd20fda174df392c264cc6f03030cdf (diff)
Finish ITC; implement async sim control.
-rw-r--r--src/common.h38
-rw-r--r--src/itc.c77
-rw-r--r--src/main.c7
-rw-r--r--src/physics.c82
-rw-r--r--src/ui.c21
5 files changed, 121 insertions, 104 deletions
diff --git a/src/common.h b/src/common.h
index ee9c3fe..1b8e719 100644
--- a/src/common.h
+++ b/src/common.h
@@ -149,6 +149,28 @@ static inline void mst2_dump(mst2_t M)
printf("[%f\t%f\t%f]\n", 0.0, 0.0, 1.0);
}
+// itc
+
+typedef struct itc_message_s itc_message;
+struct itc_message_s {
+ int number;
+ void *data;
+
+ itc_message *older, *newer;
+};
+
+typedef struct {
+ itc_message *newest, *oldest;
+ SDL_mutex *mutex;
+ SDL_sem *sem;
+} itc_chan;
+
+void itc_chan_create(itc_chan *chan);
+void itc_chan_destroy(itc_chan *chan);
+void itc_chan_push(itc_chan *chan, int number, void *data);
+int itc_chan_pop(itc_chan *chan, int *number, void **data);
+int itc_chan_pop_block(itc_chan *chan, int *number, void **data);
+
// physics
typedef struct {
@@ -164,12 +186,12 @@ typedef struct {
float *H;
} phy_field_em;
-/*
-typedef struct {
- int num;
- void *data;
-} phy_command;
-*/
+enum {
+ PHY_CMD_QUIT,
+ PHY_CMD_PAUSE,
+ PHY_CMD_RESUME,
+ PHY_CMD_STEP
+};
typedef struct {
phy_field_info field_info;
@@ -177,6 +199,9 @@ typedef struct {
float *field_eps, *field_mu; //permittivity and permeability
float time;
+ // UI stuff
+ bool running;
+ itc_chan ctl;
SDL_mutex *rotate_lock;
} phy_sim;
@@ -253,4 +278,3 @@ void ui_renderer_window_register(r_window *rw);
void ui_event(SDL_Event *event);
void ui_draw(phy_sim *sim);
-
diff --git a/src/itc.c b/src/itc.c
index 62e6208..ac13018 100644
--- a/src/itc.c
+++ b/src/itc.c
@@ -1,33 +1,22 @@
#include "common.h"
#include <unistd.h>
-typedef struct itc_message_s itc_message;
-struct itc_message_s {
- int number;
- void *data;
-
- itc_message *older, *newer;
-};
-
-typedef struct {
- itc_message *newest, *oldest;
- SDL_mutex *mutex;
-
-} itc_chan;
-
-
void itc_chan_create(itc_chan *chan)
{
memset(chan, 0, sizeof(itc_chan));
chan->mutex = SDL_CreateMutex();
assert(chan->mutex);
+
+ chan->sem = SDL_CreateSemaphore(0);
+ assert(chan->sem);
}
void itc_chan_destroy(itc_chan *chan)
{
// todo: free queue
+ SDL_DestroySemaphore(chan->sem);
SDL_DestroyMutex(chan->mutex);
}
@@ -57,6 +46,7 @@ void itc_chan_push(itc_chan *chan, int number, void *data)
chan->newest = msg;
}
+ SDL_SemPost(chan->sem);
SDL_UnlockMutex(chan->mutex);
}
@@ -81,6 +71,7 @@ int itc_chan_pop(itc_chan *chan, int *number, void **data)
chan->oldest = NULL;
}
+ SDL_SemWait(chan->sem); // should be instant
SDL_UnlockMutex(chan->mutex);
*number = msg->number;
@@ -90,49 +81,33 @@ int itc_chan_pop(itc_chan *chan, int *number, void **data)
return 0;
}
-
-
-itc_chan gulg_chan;
-
-int gulgulator(void *unused)
+int itc_chan_pop_block(itc_chan *chan, int *number, void **data)
{
- int cmd_num;
- void *cmd_data;
+ itc_message *msg;
- while (1) {
- while (!itc_chan_pop(&gulg_chan, &cmd_num, &cmd_data)) {
- printf("gulgulator: pop %i %p\n", cmd_num, cmd_data);
- }
+ SDL_SemWait(chan->sem);
+ SDL_LockMutex(chan->mutex);
- usleep(100 * 1000);
+ if (!chan->oldest) {
+ SDL_UnlockMutex(chan->mutex);
+ return 1;
}
-}
-
-void itc_test(void)
-{
- SDL_Thread *thread;
- char line[512];
-
- itc_chan_create(&gulg_chan);
- thread = SDL_CreateThread(gulgulator, "gulgulator", NULL);
- while (1) {
- int cmd_num;
-
- printf("> ");
- fflush(stdout);
-
- if (!fgets(line, sizeof(line), stdin))
- break;
-
- cmd_num = atoi(line);
+ msg = chan->oldest;
- printf("main: push %i %p\n", cmd_num, 0xDEADBEEF);
- itc_chan_push(&gulg_chan, cmd_num, (void*)0xDEADBEEF);
+ if (msg->newer) {
+ msg->newer->older = NULL;
+ chan->oldest = msg->newer;
+ } else {
+ chan->newest = NULL;
+ chan->oldest = NULL;
}
- printf("EOF\n");
+ SDL_UnlockMutex(chan->mutex);
- SDL_WaitThread(thread, NULL);
-}
+ *number = msg->number;
+ *data = msg->data;
+ free(msg);
+ return 0;
+}
diff --git a/src/main.c b/src/main.c
index a313cc1..4cd8a6f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -30,9 +30,6 @@ int main(void)
phy_sim sim;
SDL_Thread *sim_thread;
- itc_test();
- return;
-
if (r_init()) {
con_printf("fatal error: renderer initialization failed\n");
rv = 1;
@@ -87,7 +84,11 @@ int main(void)
quit:
con_printf("main: exitting, rv=%i\n", rv);
+
+ itc_chan_push(&sim.ctl, PHY_CMD_QUIT, NULL);
+ SDL_WaitThread(sim_thread, NULL);
phy_sim_destroy(&sim);
+
ui_quit();
r_quit();
SDL_Quit();
diff --git a/src/physics.c b/src/physics.c
index be6a426..c8a7cbd 100644
--- a/src/physics.c
+++ b/src/physics.c
@@ -4,6 +4,8 @@ void phy_sim_destroy(phy_sim *sim) {
size_t i;
SDL_DestroyMutex(sim->rotate_lock);
+
+ itc_chan_destroy(&sim->ctl);
for (i = 0; i < 3; i++) {
free(sim->fields[i].E);
@@ -48,6 +50,9 @@ int phy_sim_create(phy_sim *sim) {
phy_sim_compute_const_fields(sim);
+ itc_chan_create(&sim->ctl);
+ sim->running = false;
+
sim->rotate_lock = SDL_CreateMutex();
assert(sim->rotate_lock);
@@ -62,15 +67,11 @@ void phy_sim_compute_const_fields(phy_sim *sim)
{
size_t x, y, z;
phy_field_info *fi = &sim->field_info;
- size_t border_width;
-
- border_width = 3;
for (z = 0; z < fi->depth; z++)
for (y = 0; y < fi->height; y++)
for (x = 0; x < fi->width; x++) {
float *eps, *mu;
- float border_fx, border_fy, border_fz, border_f;
eps = sim->field_eps + z * fi->zstr1 + y * fi->ystr1 +
x * fi->xstr1;
@@ -79,36 +80,6 @@ void phy_sim_compute_const_fields(phy_sim *sim)
*eps = 1.129409066837282e+11;
*mu = -7.957747154594767e+5;
-
-/*
- if (x < border_width) {
- border_fx = (float)x / border_width;
- } else if (x >= fi->width - border_width) {
- border_fx = 1.0f - ((float)x - fi->width + border_width + 1) / border_width;
- } else {
- border_fx = 1.0f;
- }
-
- if (y < border_width) {
- border_fy = (float)y / border_width;
- } else if (y >= fi->height - border_width) {
- border_fy = 1.0f - ((float)y - fi->height + border_width + 1) / border_width;
- } else {
- border_fy = 1.0f;
- }
-
- if (z < border_width) {
- border_fz = (float)y / border_width;
- } else if (z >= fi->depth - border_width) {
- border_fz = 1.0f - ((float)z - fi->depth + border_width + 1) / border_width;
- } else {
- border_fz = 1.0f;
- }
-
- border_f = min3(border_fx, border_fy, border_fz);
-
- *eps *= border_f;
- *mu *= border_f;*/
}
}
@@ -228,17 +199,52 @@ void phy_sim_step(phy_sim *sim, float dt) {
sim->time += dt;
}
-/*
-void phy_control(phy_command cmd, void *data)
+void phy_run_command(phy_sim *sim, int number, void *data)
+{
+ switch (number) {
+ case PHY_CMD_PAUSE:
+ sim->running = false;
+ break;
+
+ case PHY_CMD_RESUME:
+ sim->running = true;
+ break;
-} */
+ case PHY_CMD_STEP:
+ phy_sim_step(sim, 0.1);
+ break;
+ }
+}
int phy_thread(phy_sim *sim)
{
+ int rv, cmd_num;
+ void *cmd_data;
+
while (1) {
- phy_sim_step(sim, 0.1);
+ if (sim->running) {
+ while (!itc_chan_pop(&sim->ctl, &cmd_num, &cmd_data)) {
+ if (cmd_num == PHY_CMD_QUIT)
+ goto out;
+
+ phy_run_command(sim, cmd_num, cmd_data);
+ }
+
+ phy_sim_step(sim, 0.1);
+ } else {
+ // do it only once per iteration
+ if (!itc_chan_pop_block(&sim->ctl, &cmd_num,
+ &cmd_data)) {
+ if (cmd_num == PHY_CMD_QUIT)
+ goto out;
+
+ phy_run_command(sim, cmd_num, cmd_data);
+ }
+ }
}
+out:
+
printf("phy_thread: quitting\n");
}
diff --git a/src/ui.c b/src/ui.c
index feabc28..f55f18b 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -22,6 +22,8 @@ struct {
#define MAX_INFO 1024
typedef struct {
+ phy_sim *sim;
+
bool dragging;
r_xsection_type xsection_type;
float xsection_frac;
@@ -246,6 +248,14 @@ void ui_event_window(SDL_Event *event, ui_window *uiw)
if (sv->xsection_frac < 0.0f)
sv->xsection_frac = 0.0f;
break;
+
+ case SDLK_o:
+ itc_chan_push(&sv->sim->ctl, PHY_CMD_PAUSE, NULL);
+ break;
+
+ case SDLK_p:
+ itc_chan_push(&sv->sim->ctl, PHY_CMD_RESUME, NULL);
+ break;
}
}
}
@@ -295,10 +305,10 @@ void ui_animate_exp(float *val, float targ, float lambda, float dt)
*val = targ + (*val - targ) * exp(-lambda * dt);
}
-void ui_draw_window_simview(ui_window *uiw, phy_sim *sim, int64_t time,
- float dt)
+void ui_draw_window_simview(ui_window *uiw, int64_t time, float dt)
{
ui_simview *sv = &uiw->simview;
+ phy_sim *sim = sv->sim;
float aspect_ratio;
vec2_t origin_s, scale_s;
phy_field_em *field_em = sim->fields + 2;
@@ -413,7 +423,7 @@ void ui_draw_window_simview(ui_window *uiw, phy_sim *sim, int64_t time,
}
}
-void ui_draw_window(ui_window *uiw, phy_sim *sim)
+void ui_draw_window(ui_window *uiw)
{
ui_simview *sv = &uiw->simview;
int64_t time;
@@ -443,7 +453,7 @@ void ui_draw_window(ui_window *uiw, phy_sim *sim)
dt = (get_time() - uiw->last_frame) * 1.0e-9;
r_clear(uiw->rw, r_color_black);
- ui_draw_window_simview(uiw, sim, time, dt);
+ ui_draw_window_simview(uiw, time, dt);
r_flip(uiw->rw);
uiw->last_frame = time;
@@ -455,7 +465,8 @@ void ui_draw(phy_sim *sim)
for (uiw = uis.windows; uiw; uiw = uiw->next) {
SDL_GetWindowSize(uiw->rw->window, &uiw->w, &uiw->h);
- ui_draw_window(uiw, sim);
+ uiw->simview.sim = sim;
+ ui_draw_window(uiw);
uiw->frame_count++;
}
}