Преглед изворни кода

Dolphin_srv: fix state load on startup (#731)

* Dolphin_srv: fix dolphin state load on startup
* Dolphin: new sync and async API, state autosave. Makefile: properly escaped asterisks.

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
its your bedtime пре 4 година
родитељ
комит
7a89791b2b

+ 2 - 2
applications/applications.mk

@@ -2,8 +2,8 @@ APP_DIR		= $(PROJECT_ROOT)/applications
 LIB_DIR		= $(PROJECT_ROOT)/lib
 
 CFLAGS		+= -I$(APP_DIR)
-C_SOURCES	+= $(shell find $(APP_DIR) -name *.c)
-CPP_SOURCES	+= $(shell find $(APP_DIR) -name *.cpp)
+C_SOURCES	+= $(shell find $(APP_DIR) -name "*.c")
+CPP_SOURCES	+= $(shell find $(APP_DIR) -name "*.cpp")
 
 
 APP_RELEASE ?= 1

+ 2 - 2
applications/desktop/scenes/desktop_scene_debug.c

@@ -26,7 +26,7 @@ bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) {
         switch(event.event) {
         case DesktopDebugEventExit:
             scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
-            dolphin_save(dolphin);
+            dolphin_flush(dolphin);
             consumed = true;
             break;
 
@@ -43,7 +43,7 @@ bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) {
             break;
 
         case DesktopDebugEventSaveState:
-            dolphin_save(dolphin);
+            dolphin_flush(dolphin);
             consumed = true;
             break;
 

+ 1 - 1
applications/desktop/views/desktop_debug.c

@@ -146,7 +146,7 @@ void desktop_debug_free(DesktopDebugView* debug_view) {
 
 void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view) {
     Dolphin* dolphin = furi_record_open("dolphin");
-    DolphinDeedWeight stats = dolphin_stats(dolphin);
+    DolphinStats stats = dolphin_stats(dolphin);
     with_view_model(
         debug_view->view, (DesktopDebugViewModel * model) {
             model->icounter = stats.icounter;

+ 60 - 27
applications/dolphin/dolphin.c

@@ -1,34 +1,39 @@
 #include "dolphin_i.h"
 #include <furi.h>
 
-bool dolphin_load(Dolphin* dolphin) {
-    furi_assert(dolphin);
-    return dolphin_state_load(dolphin->state);
-}
-
-void dolphin_save(Dolphin* dolphin) {
-    furi_assert(dolphin);
-    DolphinEvent event;
-    event.type = DolphinEventTypeSave;
-    furi_check(osMessageQueuePut(dolphin->event_queue, &event, 0, osWaitForever) == osOK);
-}
+#define DOLPHIN_LOCK_EVENT_FLAG (0x1)
 
 void dolphin_deed(Dolphin* dolphin, DolphinDeed deed) {
     furi_assert(dolphin);
     DolphinEvent event;
     event.type = DolphinEventTypeDeed;
     event.deed = deed;
-    furi_check(osMessageQueuePut(dolphin->event_queue, &event, 0, osWaitForever) == osOK);
+    dolphin_event_send_async(dolphin, &event);
 }
 
-DolphinDeedWeight dolphin_stats(Dolphin* dolphin) {
-    DolphinDeedWeight stats;
-    stats.butthurt = dolphin_state_get_butthurt(dolphin->state);
-    stats.icounter = dolphin_state_get_icounter(dolphin->state);
+DolphinStats dolphin_stats(Dolphin* dolphin) {
+    furi_assert(dolphin);
+
+    DolphinStats stats;
+    DolphinEvent event;
+
+    event.type = DolphinEventTypeStats;
+    event.stats = &stats;
+
+    dolphin_event_send_wait(dolphin, &event);
 
     return stats;
 }
 
+void dolphin_flush(Dolphin* dolphin) {
+    furi_assert(dolphin);
+
+    DolphinEvent event;
+    event.type = DolphinEventTypeFlush;
+
+    dolphin_event_send_wait(dolphin, &event);
+}
+
 Dolphin* dolphin_alloc() {
     Dolphin* dolphin = furi_alloc(sizeof(Dolphin));
 
@@ -47,27 +52,55 @@ void dolphin_free(Dolphin* dolphin) {
     free(dolphin);
 }
 
+void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event) {
+    furi_assert(dolphin);
+    furi_assert(event);
+    event->flag = NULL;
+    furi_check(osMessageQueuePut(dolphin->event_queue, event, 0, osWaitForever) == osOK);
+}
+
+void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event) {
+    furi_assert(dolphin);
+    furi_assert(event);
+    event->flag = osEventFlagsNew(NULL);
+    furi_check(event->flag);
+    furi_check(osMessageQueuePut(dolphin->event_queue, event, 0, osWaitForever) == osOK);
+    furi_check(
+        osEventFlagsWait(event->flag, DOLPHIN_LOCK_EVENT_FLAG, osFlagsWaitAny, osWaitForever) ==
+        DOLPHIN_LOCK_EVENT_FLAG);
+    furi_check(osEventFlagsDelete(event->flag) == osOK);
+}
+
+void dolphin_event_release(Dolphin* dolphin, DolphinEvent* event) {
+    if(event->flag) {
+        osEventFlagsSet(event->flag, DOLPHIN_LOCK_EVENT_FLAG);
+    }
+}
+
 int32_t dolphin_srv(void* p) {
     Dolphin* dolphin = dolphin_alloc();
     furi_record_create("dolphin", dolphin);
 
+    dolphin_state_load(dolphin->state);
+
     DolphinEvent event;
     while(1) {
-        furi_check(osMessageQueueGet(dolphin->event_queue, &event, NULL, osWaitForever) == osOK);
-        switch(event.type) {
-        case DolphinEventTypeDeed:
-            dolphin_state_on_deed(dolphin->state, event.deed);
-            break;
-
-        case DolphinEventTypeSave:
+        if(osMessageQueueGet(dolphin->event_queue, &event, NULL, 60000) == osOK) {
+            if(event.type == DolphinEventTypeDeed) {
+                dolphin_state_on_deed(dolphin->state, event.deed);
+            } else if(event.type == DolphinEventTypeStats) {
+                event.stats->icounter = dolphin_state_get_icounter(dolphin->state);
+                event.stats->butthurt = dolphin_state_get_butthurt(dolphin->state);
+            } else if(event.type == DolphinEventTypeFlush) {
+                dolphin_state_save(dolphin->state);
+            }
+            dolphin_event_release(dolphin, &event);
+        } else {
             dolphin_state_save(dolphin->state);
-            break;
-
-        default:
-            break;
         }
     }
 
     dolphin_free(dolphin);
+
     return 0;
 }

+ 12 - 16
applications/dolphin/dolphin.h

@@ -4,27 +4,23 @@
 
 typedef struct Dolphin Dolphin;
 
-/* Load Dolphin state
- * Thread safe
- */
-
-bool dolphin_load(Dolphin* dolphin);
+typedef struct {
+    uint32_t icounter;
+    uint32_t butthurt;
+} DolphinStats;
 
-/* Deed complete notification. Call it on deed completion.
+/** Deed complete notification. Call it on deed completion.
  * See dolphin_deed.h for available deeds. In futures it will become part of assets.
- * Thread safe
+ * Thread safe, async
  */
-
 void dolphin_deed(Dolphin* dolphin, DolphinDeed deed);
 
-/* Save Dolphin state (write to permanent memory)
- * Thread safe
+/** Retrieve dolphin stats
+ * Thread safe, blocking
  */
+DolphinStats dolphin_stats(Dolphin* dolphin);
 
-void dolphin_save(Dolphin* dolphin);
-
-/* Retrieve dolphin's icounter and butthurt values
- * Thread safe
+/** Flush dolphin queue and save state
+ * Thread safe, blocking
  */
-
-DolphinDeedWeight dolphin_stats(Dolphin* dolphin);
+void dolphin_flush(Dolphin* dolphin);

+ 10 - 2
applications/dolphin/dolphin_i.h

@@ -8,14 +8,16 @@
 
 typedef enum {
     DolphinEventTypeDeed,
-    DolphinEventTypeSave,
-    DolphinEventTypeTick,
+    DolphinEventTypeStats,
+    DolphinEventTypeFlush,
 } DolphinEventType;
 
 typedef struct {
     DolphinEventType type;
+    osEventFlagsId_t flag;
     union {
         DolphinDeed deed;
+        DolphinStats* stats;
     };
 } DolphinEvent;
 
@@ -29,3 +31,9 @@ struct Dolphin {
 Dolphin* dolphin_alloc();
 
 void dolphin_free(Dolphin* dolphin);
+
+void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event);
+
+void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event);
+
+void dolphin_event_release(Dolphin* dolphin, DolphinEvent* event);

+ 14 - 1
applications/dolphin/helpers/dolphin_state.c

@@ -35,6 +35,7 @@ typedef struct {
 struct DolphinState {
     Storage* fs_api;
     DolphinStoreData data;
+    bool dirty;
 };
 
 DolphinState* dolphin_state_alloc() {
@@ -49,8 +50,12 @@ void dolphin_state_free(DolphinState* dolphin_state) {
 }
 
 bool dolphin_state_save(DolphinState* dolphin_state) {
+    if(!dolphin_state->dirty) {
+        return true;
+    }
+
+    FURI_LOG_I("dolphin-state", "State is dirty, saving to \"%s\"", DOLPHIN_STORE_KEY);
     DolphinStore store;
-    FURI_LOG_I("dolphin-state", "Saving state to \"%s\"", DOLPHIN_STORE_KEY);
     // Calculate checksum
     uint8_t* source = (uint8_t*)&dolphin_state->data;
     uint8_t checksum = 0;
@@ -88,7 +93,10 @@ bool dolphin_state_save(DolphinState* dolphin_state) {
     storage_file_close(file);
     storage_file_free(file);
 
+    dolphin_state->dirty = !save_result;
+
     FURI_LOG_I("dolphin-state", "Saved");
+
     return save_result;
 }
 
@@ -153,6 +161,9 @@ bool dolphin_state_load(DolphinState* dolphin_state) {
 
     storage_file_close(file);
     storage_file_free(file);
+
+    dolphin_state->dirty = !load_result;
+
     return load_result;
 }
 
@@ -167,6 +178,8 @@ void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) {
     if(icounter >= 0) {
         dolphin_state->data.icounter = icounter;
     }
+
+    dolphin_state->dirty = true;
 }
 
 uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state) {