From 745d5a072d8669d1bc35e7c1f28b75b3484542e8 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Wed, 30 Mar 2016 20:29:08 +0200 Subject: Finish ITC; implement async sim control. --- src/common.h | 38 ++++++++++++++++++++++----- src/itc.c | 77 +++++++++++++++++++------------------------------------ src/main.c | 7 ++--- src/physics.c | 82 ++++++++++++++++++++++++++++++++--------------------------- src/ui.c | 21 +++++++++++---- 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 -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++; } } -- cgit