diff --git a/applications/menu/menu.c b/applications/menu/menu.c index a0261bf5..546fccea 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -25,23 +24,30 @@ struct Menu { void menu_widget_callback(CanvasApi* canvas, void* context); -Menu* menu_init() { +ValueMutex* menu_init() { Menu* menu = furi_alloc(sizeof(Menu)); // Event dispatcher menu->event = menu_event_alloc(); + ValueMutex* menu_mutex = furi_alloc(sizeof(ValueMutex)); + if(menu_mutex == NULL || !init_mutex(menu_mutex, menu, sizeof(Menu))) { + printf("[menu_task] cannot create menu mutex\n"); + furiac_exit(NULL); + } + // Allocate and configure widget menu->widget = widget_alloc(); - widget_draw_callback_set(menu->widget, menu_widget_callback, menu); - widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event); // Open GUI and register fullscreen widget GuiApi* gui = furi_open("gui"); assert(gui); gui->add_widget(gui, menu->widget, WidgetLayerFullscreen); - return menu; + widget_draw_callback_set(menu->widget, menu_widget_callback, menu_mutex); + widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event); + + return menu_mutex; } void menu_build_main(Menu* menu) { @@ -79,10 +85,9 @@ void menu_settings_item_add(Menu* menu, MenuItem* item) { void menu_widget_callback(CanvasApi* canvas, void* context) { assert(canvas); assert(context); - - Menu* menu = context; - - menu_event_lock(menu->event); + + Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex + if(menu == NULL) return; // redraw fail if(!menu->current) { canvas->clear(canvas); @@ -102,7 +107,8 @@ void menu_widget_callback(CanvasApi* canvas, void* context) { } } - menu_event_unlock(menu->event); + release_mutex((ValueMutex*)context, menu); + } void menu_update(Menu* menu) { @@ -172,10 +178,22 @@ void menu_exit(Menu* menu) { } void menu_task(void* p) { - Menu* menu = menu_init(); - menu_build_main(menu); + ValueMutex* menu_mutex = menu_init(); - if(!furi_create_deprecated("menu", menu, sizeof(menu))) { + MenuEvent* menu_event = NULL; + { + Menu* menu = acquire_mutex_block(menu_mutex); + assert(menu); + + menu_build_main(menu); + + // immutable thread-safe object + menu_event = menu->event; + + release_mutex(menu_mutex, menu); + } + + if(!furi_create("menu", menu_mutex)) { printf("[menu_task] cannot create the menu record\n"); furiac_exit(NULL); } @@ -183,10 +201,12 @@ void menu_task(void* p) { furiac_ready(); while(1) { - MenuMessage m = menu_event_next(menu->event); + MenuMessage m = menu_event_next(menu_event); + + Menu* menu = acquire_mutex_block(menu_mutex); if(!menu->current && m.type != MenuMessageTypeOk) { - continue; + } else if(m.type == MenuMessageTypeUp) { menu_up(menu); } else if(m.type == MenuMessageTypeDown) { @@ -204,5 +224,7 @@ void menu_task(void* p) { } else { // TODO: fail somehow? } + + release_mutex(menu_mutex, menu); } } diff --git a/applications/menu/menu_event.c b/applications/menu/menu_event.c index bd479972..4470ffd6 100644 --- a/applications/menu/menu_event.c +++ b/applications/menu/menu_event.c @@ -12,7 +12,6 @@ struct MenuEvent { osMessageQueueId_t mqueue; osTimerId_t timeout_timer; - osMutexId_t lock_mutex; }; void MenuEventimeout_callback(void* arg) { @@ -32,29 +31,15 @@ MenuEvent* menu_event_alloc() { osTimerNew(MenuEventimeout_callback, osTimerOnce, menu_event, NULL); assert(menu_event->timeout_timer); - menu_event->lock_mutex = osMutexNew(NULL); - assert(menu_event->lock_mutex); - - menu_event_lock(menu_event); - return menu_event; } void menu_event_free(MenuEvent* menu_event) { assert(menu_event); - menu_event_unlock(menu_event); assert(osMessageQueueDelete(menu_event->mqueue) == osOK); free(menu_event); } -void menu_event_lock(MenuEvent* menu_event) { - assert(osMutexAcquire(menu_event->lock_mutex, osWaitForever) == osOK); -} - -void menu_event_unlock(MenuEvent* menu_event) { - assert(osMutexRelease(menu_event->lock_mutex) == osOK); -} - void menu_event_activity_notify(MenuEvent* menu_event) { assert(menu_event); osTimerStart(menu_event->timeout_timer, 60000U); // 1m timeout, return to main @@ -63,10 +48,8 @@ void menu_event_activity_notify(MenuEvent* menu_event) { MenuMessage menu_event_next(MenuEvent* menu_event) { assert(menu_event); MenuMessage message; - menu_event_unlock(menu_event); while(osMessageQueueGet(menu_event->mqueue, &message, NULL, osWaitForever) != osOK) { }; - menu_event_lock(menu_event); return message; } diff --git a/applications/menu/menu_event.h b/applications/menu/menu_event.h index 858dc27b..031b8f4e 100644 --- a/applications/menu/menu_event.h +++ b/applications/menu/menu_event.h @@ -25,10 +25,6 @@ MenuEvent* menu_event_alloc(); void menu_event_free(MenuEvent* menu_event); -void menu_event_lock(MenuEvent* menu_event); - -void menu_event_unlock(MenuEvent* menu_event); - void menu_event_activity_notify(MenuEvent* menu_event); MenuMessage menu_event_next(MenuEvent* menu_event);