]> granicus.if.org Git - esp-idf/commitdiff
esp_event: dispatch order follows registration order
authorRenz Christian Bagaporo <renz@espressif.com>
Mon, 10 Dec 2018 00:37:46 +0000 (08:37 +0800)
committerRenz Christian Bagaporo <renz@espressif.com>
Wed, 30 Jan 2019 12:59:47 +0000 (20:59 +0800)
components/esp_event/esp_event.c
components/esp_event/esp_event_private.c
components/esp_event/include/esp_event.h
components/esp_event/private_include/esp_event_internal.h

index eba9bcc676fec2ada82e655e2587673d3d47b5e9..d9f65c4a2f4b44ade0eb16f17db73d2fa7233d38 100644 (file)
 /* ---------------------------- Definitions --------------------------------- */
 
 #ifdef CONFIG_EVENT_LOOP_PROFILING
-// loop@<address,name> rx:<total_recieved> dr:<total_dropped> inv:<total_number_of_invocations> run:<total_runtime>
-#define LOOP_DUMP_FORMAT              "loop@%p,%s rx:%u dr:%u inv:%u run:%lld us\n"
-// event@<base:id> proc:<total_processed> run:<total_runtime>
-#define EVENT_DUMP_FORMAT             "\tevent@%s:%d proc:%u run:%lld us\n"
- // handler@<address> inv:<total_invoked> run:<total_runtime>
-#define HANDLER_DUMP_FORMAT           "\t\thandler@%p inv:%u run:%lld us\n"
+// LOOP @<address, name> rx:<recieved events no.> dr:<dropped events no.>
+#define LOOP_DUMP_FORMAT              "LOOP @%p,%s rx:%u dr:%u\n"
+ // handler @<address> ev:<base, id> inv:<times invoked> time:<runtime>
+#define HANDLER_DUMP_FORMAT           "  HANDLER @%p ev:%s,%s inv:%u time:%lld us\n"
 
 #define PRINT_DUMP_INFO(dst, sz, ...)  do { \
                                             int cb = snprintf(dst, sz, __VA_ARGS__); \
@@ -63,33 +61,33 @@ static portMUX_TYPE s_event_loops_spinlock = portMUX_INITIALIZER_UNLOCKED;
 static int esp_event_dump_prepare()
 {
     esp_event_loop_instance_t* loop_it;
-    esp_event_base_instance_t* base_it;
-    esp_event_id_instance_t* id_it;
+    esp_event_loop_node_t *loop_node_it;
+    esp_event_base_node_t* base_node_it;
+    esp_event_id_node_t* id_node_it;
     esp_event_handler_instance_t* handler_it;
 
     // Count the number of items to be printed. This is needed to compute how much memory to reserve.
-    int loops = 0, events = 0, handlers = 0;
+    int loops = 0, handlers = 0;
 
     portENTER_CRITICAL(&s_event_loops_spinlock);
 
-    SLIST_FOREACH(loop_it, &s_event_loops, loop_entry) {
-        SLIST_FOREACH(handler_it, &(loop_it->loop_handlers), handler_entry) {
-            handlers++;
-        }
-        SLIST_FOREACH(base_it, &(loop_it->event_bases), event_base_entry) {
-            SLIST_FOREACH(handler_it, &(base_it->base_handlers), handler_entry) {
+    SLIST_FOREACH(loop_it, &s_event_loops, next) {
+        SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) {
+            SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) {
                 handlers++;
             }
-            // Print event-level handlers
-            SLIST_FOREACH(id_it, &(base_it->event_ids), event_id_entry) {
-                SLIST_FOREACH(handler_it, &(id_it->handlers), handler_entry) {
+
+            SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) {
+                SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) {
                     handlers++;
                 }
-                events++;
+                SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) {
+                    SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) {
+                        handlers++;
+                    }
+                }
             }
-            events++;
         }
-        events++;
         loops++;
     }
 
@@ -97,9 +95,8 @@ static int esp_event_dump_prepare()
 
     // Reserve slightly more memory than computed
     int allowance = 3;
-    int size = (((loops + allowance) * (sizeof(LOOP_DUMP_FORMAT) + 10 + 20 + 3 * 11  + 20 )) +
-                        ((events + allowance) * (sizeof(EVENT_DUMP_FORMAT) + 10 + 20 + 11 + 20)) +
-                        ((handlers + allowance) * (sizeof(HANDLER_DUMP_FORMAT) + 10 + 11 + 20)));
+    int size = (((loops + allowance) * (sizeof(LOOP_DUMP_FORMAT) + 10 + 20 + 2 * 11)) +
+                        ((handlers + allowance) * (sizeof(HANDLER_DUMP_FORMAT) + 10 + 2 * 20 + 11 + 20)));
 
     return size;
 }
@@ -123,167 +120,257 @@ static void esp_event_loop_run_task(void* args)
     vTaskSuspend(NULL);
 }
 
-// Functions that operate on handler instance
-static esp_event_handler_instance_t* handler_instance_create(esp_event_handler_t event_handler, void* event_handler_arg)
+static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_instance_t *handler, esp_event_post_instance_t post)
 {
-    esp_event_handler_instance_t* handler_instance = calloc(1, sizeof(*handler_instance));
+    ESP_LOGD(TAG, "running post %s:%d with handler %p on loop %p", post.base, post.id, handler->handler, loop);
 
-    if (handler_instance != NULL) {
-        handler_instance->handler = event_handler;
-        handler_instance->arg = event_handler_arg;
-    }
+#ifdef CONFIG_EVENT_LOOP_PROFILING
+    int64_t start, diff;
+    start = esp_timer_get_time();
+#endif
+    // Execute the handler
+    (*(handler->handler))(handler->arg, post.base, post.id, post.data);
 
-    return handler_instance;
-}
+#ifdef CONFIG_EVENT_LOOP_PROFILING
+    diff = esp_timer_get_time() - start;
 
-static void handler_instance_delete(esp_event_handler_instance_t* handler_instance)
-{
-    free(handler_instance);
+    xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY);
+
+    handler->invoked++;
+    handler->time += diff;
+
+    xSemaphoreGive(loop->profiling_mutex);
+#endif
 }
 
-// Functions that operate on handler instance list
-static esp_event_handler_instance_t* handler_instances_find(esp_event_handler_instances_t* handlers, esp_event_handler_t handler)
+static esp_err_t handler_instances_add(esp_event_handler_instances_t* handlers, esp_event_handler_t handler, void* handler_arg)
 {
-    esp_event_handler_instance_t* it;
+    esp_event_handler_instance_t* handler_instance = calloc(1, sizeof(*handler_instance));
 
-    SLIST_FOREACH(it, handlers, handler_entry) {
-        if (it->handler == handler) {
-            break;
+    if (!handler_instance) {
+        return ESP_ERR_NO_MEM;
+    }
+
+    handler_instance->handler = handler;
+    handler_instance->arg = handler_arg;
+
+    if(SLIST_EMPTY(handlers)) {
+        SLIST_INSERT_HEAD(handlers, handler_instance, next);
+    }
+    else {
+        esp_event_handler_instance_t *it = NULL, *last = NULL;
+
+        SLIST_FOREACH(it, handlers, next) {
+            if (handler == it->handler) {
+                it->arg = handler_arg;
+                ESP_LOGW(TAG, "handler already registered, overwriting");
+                return ESP_OK;
+            }
+            last = it;
         }
+
+        SLIST_INSERT_AFTER(last, handler_instance, next);
     }
 
-    return it;
+    return ESP_OK;
 }
 
-static void handler_instances_add(esp_event_handler_instances_t* handlers, esp_event_handler_instance_t* handler_instance)
+static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler, void* handler_arg)
 {
-    SLIST_INSERT_HEAD(handlers, handler_instance, handler_entry);
-}
+    if (id == ESP_EVENT_ANY_ID) {
+        return handler_instances_add(&(base_node->handlers), handler, handler_arg);
+    }
+    else {
+        esp_err_t err = ESP_OK;
+        esp_event_id_node_t *it = NULL, *id_node = NULL, *last_id_node = NULL;
 
-static void handler_instances_remove(esp_event_handler_instances_t* handlers, esp_event_handler_instance_t* handler_instance)
-{
-    SLIST_REMOVE(handlers, handler_instance, esp_event_handler_instance, handler_entry);
-    handler_instance_delete(handler_instance);
-}
+        SLIST_FOREACH(it, &(base_node->id_nodes), next) {
+            if (it->id == id) {
+                id_node = it;
+            }
+            last_id_node = it;
+        }
 
-static void handler_instances_remove_all(esp_event_handler_instances_t* handlers)
-{
-    esp_event_handler_instance_t* it;
-    esp_event_handler_instance_t* temp;
+        if (!last_id_node || !id_node) {
+            id_node = (esp_event_id_node_t*) calloc(1, sizeof(*id_node));
+
+            if (!id_node) {
+                ESP_LOGI(TAG, "alloc for new id node failed");
+                return ESP_ERR_NO_MEM;
+            }
+
+            id_node->id = id;
+
+            SLIST_INIT(&(id_node->handlers));
+
+            err = handler_instances_add(&(id_node->handlers), handler, handler_arg);
 
-    SLIST_FOREACH_SAFE(it, handlers, handler_entry, temp) {
-        handler_instances_remove(handlers, it);
+            if (err == ESP_OK) {
+                if (!last_id_node) {
+                    SLIST_INSERT_HEAD(&(base_node->id_nodes), id_node, next);
+                }
+                else {
+                    SLIST_INSERT_AFTER(last_id_node, id_node, next);
+                }
+            }
+
+            return err;
+        }
+        else {
+            return handler_instances_add(&(id_node->handlers), handler, handler_arg);
+        }
     }
 }
 
-// Functions that operate on event id instance
-static void* event_id_instance_create(int32_t event_id)
+static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler, void* handler_arg)
 {
-    esp_event_id_instance_t* event_id_instance = calloc(1, sizeof(*event_id_instance));
-
-    if (event_id_instance != NULL) {
-        event_id_instance->id = event_id;
-        SLIST_INIT(&(event_id_instance->handlers));
+    if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) {
+        return handler_instances_add(&(loop_node->handlers), handler, handler_arg);
     }
+    else {
+        esp_err_t err = ESP_OK;
+        esp_event_base_node_t *it = NULL, *base_node = NULL, *last_base_node = NULL;
 
-    return event_id_instance;
-}
+        SLIST_FOREACH(it, &(loop_node->base_nodes), next) {
+            if (it->base == base) {
+                base_node = it;
+            }
+            last_base_node = it;
+        }
 
-static void event_id_instance_delete(esp_event_id_instance_t* event_id_instance)
-{
-    handler_instances_remove_all(&(event_id_instance->handlers));
-    free(event_id_instance);
-}
+        if (!last_base_node ||
+               !base_node ||
+            (base_node && !SLIST_EMPTY(&(base_node->id_nodes)) && id == ESP_EVENT_ANY_ID) ||
+            (last_base_node && last_base_node->base != base && !SLIST_EMPTY(&(last_base_node->id_nodes)) && id == ESP_EVENT_ANY_ID)) {
+            base_node = (esp_event_base_node_t*) calloc(1, sizeof(*base_node));
 
-// Functions that operate on event id instance list
-static void event_id_instances_remove(esp_event_id_instances_t* head, esp_event_id_instance_t* event_id_instance)
-{
-    SLIST_REMOVE(head, event_id_instance, esp_event_id_instance, event_id_entry);
-    event_id_instance_delete(event_id_instance);
-}
+            if (!base_node) {
+                ESP_LOGE(TAG, "alloc mem for new base node failed");
+                return ESP_ERR_NO_MEM;
+            }
 
-// Functions that operate on event base instance
-static esp_event_base_instance_t* event_base_instance_create(esp_event_base_t event_base)
-{
-    esp_event_base_instance_t* event_base_instance = calloc(1, sizeof(*event_base_instance));
+            base_node->base = base;
 
-    if (event_base_instance != NULL) {
-        event_base_instance->base = event_base;
-        SLIST_INIT(&(event_base_instance->base_handlers));
-        SLIST_INIT(&(event_base_instance->event_ids));
-    }
+            SLIST_INIT(&(base_node->handlers));
+            SLIST_INIT(&(base_node->id_nodes));
+
+            err = base_node_add_handler(base_node, id, handler, handler_arg);
 
-    return event_base_instance;
+            if (err == ESP_OK) {
+                if (!last_base_node) {
+                    SLIST_INSERT_HEAD(&(loop_node->base_nodes), base_node, next);
+                }
+                else {
+                    SLIST_INSERT_AFTER(last_base_node, base_node, next);
+                }
+            }
+
+            return err;
+        } else {
+            return base_node_add_handler(base_node, id, handler, handler_arg);
+        }
+    }
 }
 
-static void event_base_instance_delete(esp_event_base_instance_t* event_base_instance)
+static esp_err_t handler_instances_remove(esp_event_handler_instances_t* handlers, esp_event_handler_t handler)
 {
-    esp_event_id_instance_t* it;
-    esp_event_id_instance_t* temp;
+    esp_event_handler_instance_t *it, *temp;
 
-    handler_instances_remove_all(&(event_base_instance->base_handlers));
-
-    SLIST_FOREACH_SAFE(it, &(event_base_instance->event_ids), event_id_entry, temp) {
-        event_id_instances_remove(&(event_base_instance->event_ids), it);
+    SLIST_FOREACH_SAFE(it, handlers, next, temp) {
+        if (it->handler == handler) {
+            SLIST_REMOVE(handlers, it, esp_event_handler_instance, next);
+            free(it);
+            return ESP_OK;
+        }
     }
 
-    free(event_base_instance);
+    return ESP_ERR_NOT_FOUND;
 }
 
-static void event_base_instance_add_event_id_instance(esp_event_base_instance_t* event_base_instance, esp_event_id_instance_t* event_id_instance)
-{
-    SLIST_INSERT_HEAD(&(event_base_instance->event_ids), event_id_instance, event_id_entry);
-}
 
-static esp_event_id_instance_t* event_base_instance_find_event_id_instance(esp_event_base_instance_t* event_base_instance, int32_t event_id)
+static esp_err_t base_node_remove_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler)
 {
-    esp_event_id_instance_t* it;
-
-    SLIST_FOREACH(it, &(event_base_instance->event_ids), event_id_entry) {
-        if (it->id == event_id) {
-            break;
+    if (id == ESP_EVENT_ANY_ID) {
+        return handler_instances_remove(&(base_node->handlers), handler);
+    }
+    else {
+        esp_event_id_node_t *it, *temp;
+        SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) {
+            if (it->id == id) {
+                esp_err_t res = handler_instances_remove(&(it->handlers), handler);
+
+                if (res == ESP_OK) {
+                    if (SLIST_EMPTY(&(it->handlers))) {
+                        SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next);
+                        free(it);
+                        return ESP_OK;
+                    }
+                }
+            }
         }
     }
 
-    return it;
+    return ESP_ERR_NOT_FOUND;
 }
 
-// Functions that operate on event base instances list
-static void event_base_instances_remove(esp_event_base_instances_t* head, esp_event_base_instance_t* event_base_instance)
+static esp_err_t loop_node_remove_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler)
 {
-    SLIST_REMOVE(head, event_base_instance, esp_event_base_instance, event_base_entry);
-    event_base_instance_delete(event_base_instance);
+    if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) {
+        return handler_instances_remove(&(loop_node->handlers), handler);
+    }
+    else {
+        esp_event_base_node_t *it, *temp;
+        SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) {
+            if (it->base == base) {
+                esp_err_t res = base_node_remove_handler(it, id, handler);
+
+                if (res == ESP_OK) {
+                    if (SLIST_EMPTY(&(it->handlers)) && SLIST_EMPTY(&(it->id_nodes))) {
+                        SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next);
+                        free(it);
+                        return ESP_OK;
+                    }
+                }
+            }
+        }
+    }
+
+    return ESP_ERR_NOT_FOUND;
 }
 
-// Functions that operate on loop instances
-static void loop_add_event_base_instance(esp_event_loop_instance_t* loop, esp_event_base_instance_t* event_base_instance) {
-    SLIST_INSERT_HEAD(&(loop->event_bases), event_base_instance, event_base_entry);
+static void handler_instances_remove_all(esp_event_handler_instances_t* handlers)
+{
+    esp_event_handler_instance_t *it, *temp;
+    SLIST_FOREACH_SAFE(it, handlers, next, temp) {
+        SLIST_REMOVE(handlers, it, esp_event_handler_instance, next);
+        free(it);
+    }
 }
 
-static void loop_remove_all_event_base_instance(esp_event_loop_instance_t* loop)
+static void base_node_remove_all_handler(esp_event_base_node_t* base_node)
 {
-    esp_event_base_instance_t* it;
-    esp_event_base_instance_t* temp;
+    handler_instances_remove_all(&(base_node->handlers));
 
-    SLIST_FOREACH_SAFE(it, &(loop->event_bases), event_base_entry, temp) {
-        event_base_instances_remove(&(loop->event_bases), it);
+    esp_event_id_node_t *it, *temp;
+    SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) {
+        handler_instances_remove_all(&(it->handlers));
+        SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next);
+        free(it);
     }
 }
 
-static esp_event_base_instance_t* loop_find_event_base_instance(esp_event_loop_instance_t* loop, esp_event_base_t event_base)
+static void loop_node_remove_all_handler(esp_event_loop_node_t* loop_node)
 {
-    esp_event_base_instance_t* it;
+    handler_instances_remove_all(&(loop_node->handlers));
 
-    SLIST_FOREACH(it, &(loop->event_bases), event_base_entry) {
-        if (it->base == event_base) {
-            break;
-        }
+    esp_event_base_node_t *it, *temp;
+    SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) {
+        base_node_remove_all_handler(it);
+        SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next);
+        free(it);
     }
-
-    return it;
 }
 
-// Functions that operate on post instance
 static esp_err_t post_instance_create(esp_event_base_t event_base, int32_t event_id, void* event_data, int32_t event_data_size, esp_event_post_instance_t* post)
 {
     void* event_data_copy = NULL;
@@ -314,33 +401,6 @@ static void post_instance_delete(esp_event_post_instance_t* post)
     free(post->data);
 }
 
-static esp_event_handler_instances_t* find_handlers_list(esp_event_loop_instance_t* loop, esp_event_base_t event_base,
-                                        int32_t event_id)
-{
-    esp_event_handler_instances_t* handlers = NULL;
-    
-    esp_event_base_instance_t* base = NULL;
-    esp_event_id_instance_t* event = NULL;
-
-    if (event_base == esp_event_any_base && event_id == ESP_EVENT_ANY_ID) {
-        handlers = &(loop->loop_handlers);
-    } else {
-        base = loop_find_event_base_instance(loop, event_base);
-        if (base != NULL) {
-            if (event_id == ESP_EVENT_ANY_ID) {
-                handlers = &(base->base_handlers);
-            } else {
-                event = event_base_instance_find_event_id_instance(base, event_id);
-                if (event != NULL) {
-                    handlers = &(event->handlers);
-                }
-            }
-        }
-    }
-
-    return handlers;
-}
-
 /* ---------------------------- Public API --------------------------------- */
 
 esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop)
@@ -376,8 +436,7 @@ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, es
     }
 #endif
 
-    SLIST_INIT(&(loop->loop_handlers));
-    SLIST_INIT(&(loop->event_bases));
+    SLIST_INIT(&(loop->loop_nodes));
 
     // Create the loop task if requested
     if (event_loop_args->task_name != NULL) {
@@ -403,7 +462,7 @@ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, es
 
 #ifdef CONFIG_EVENT_LOOP_PROFILING
     portENTER_CRITICAL(&s_event_loops_spinlock);
-    SLIST_INSERT_HEAD(&s_event_loops, loop, loop_entry);
+    SLIST_INSERT_HEAD(&s_event_loops, loop, next);
     portEXIT_CRITICAL(&s_event_loops_spinlock);
 #endif
 
@@ -447,7 +506,6 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick
     esp_event_post_instance_t post;
     TickType_t marker = xTaskGetTickCount();
     TickType_t end = 0;
-    esp_event_handler_instance_t* temp;
 
 #if( configUSE_16_BIT_TICKS == 1 )
     int32_t remaining_ticks = ticks_to_run;
@@ -456,76 +514,46 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick
 #endif
 
     while(xQueueReceive(loop->queue, &post, ticks_to_run) == pdTRUE) {
-        esp_event_base_instance_t* base = NULL;
-        esp_event_id_instance_t* event = NULL;
-
-        // Reserve space for three possible matches: (1) the entry for handlers registered to all events in the loop, the
-        // (2) entry matching events with a specified base and (3) the entry matching both base and id.
-        #define LOOP_LEVEL_HANDLER 0
-        #define BASE_LEVEL_HANDLER 1
-        #define EVENT_LEVEL_HANDLER 2
-
-        esp_event_handler_instances_t* handlers_list[EVENT_LEVEL_HANDLER + 1] = {0};
-
         // The event has already been unqueued, so ensure it gets executed.
         xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY);
-        
+
         loop->running_task = xTaskGetCurrentTaskHandle();
-        
-        handlers_list[LOOP_LEVEL_HANDLER] = &(loop->loop_handlers);
-
-        base = loop_find_event_base_instance(loop, post.base);
-        if (base) {
-            event = event_base_instance_find_event_id_instance(base, post.id);
-            handlers_list[BASE_LEVEL_HANDLER] = &(base->base_handlers);
-            if (event) {
-                handlers_list[EVENT_LEVEL_HANDLER] = &(event->handlers);
-            }
-        }
 
         bool exec = false;
 
-        for (int i = LOOP_LEVEL_HANDLER; i <= EVENT_LEVEL_HANDLER; i++) {
-            if (handlers_list[i] != NULL) {
-                esp_event_handler_instance_t* it;
-                
-                SLIST_FOREACH_SAFE(it, handlers_list[i], handler_entry, temp) {
-                    ESP_LOGD(TAG, "running post %s:%d with handler %p on loop %p", post.base, post.id, it->handler, event_loop);
+        esp_event_handler_instance_t *handler;
+        esp_event_loop_node_t *loop_node;
+        esp_event_base_node_t *base_node;
+        esp_event_id_node_t *id_node;
 
-#ifdef CONFIG_EVENT_LOOP_PROFILING
-                    int64_t start, diff;
-                    start = esp_timer_get_time();
-#endif
-                    // Execute the handler
-                    (*(it->handler))(it->arg, post.base, post.id, post.data);
+        SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) {
+            // Execute loop level handlers
+            SLIST_FOREACH(handler, &(loop_node->handlers), next) {
+                handler_execute(loop, handler, post);
+                exec |= true;
+            }
 
-#ifdef CONFIG_EVENT_LOOP_PROFILING
-                    diff = esp_timer_get_time() - start;
-
-                    xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY);
-
-                    it->total_times_invoked++;
-                    it->total_runtime += diff;
-
-                    if (i == LOOP_LEVEL_HANDLER) {
-                        loop->loop_handlers_invoked++;
-                        loop->loop_handlers_runtime += diff;
-                    } else if (i == BASE_LEVEL_HANDLER) {
-                        base->base_handlers_invoked++;
-                        base->base_handlers_runtime += diff;
-                    } else {
-                        event->handlers_invoked++;
-                        event->handlers_runtime += diff;
+            SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) {
+                if (base_node->base == post.base) {
+                    // Execute base level handlers
+                    SLIST_FOREACH(handler, &(base_node->handlers), next) {
+                        handler_execute(loop, handler, post);
+                        exec |= true;
                     }
 
-                    loop->total_handlers_invoked++;
-                    loop->total_handlers_runtime += diff;
-
-                    xSemaphoreGive(loop->profiling_mutex);
-#endif
+                    SLIST_FOREACH(id_node, &(base_node->id_nodes), next) {
+                        if(id_node->id == post.id) {
+                            // Execute id level handlers
+                            SLIST_FOREACH(handler, &(id_node->handlers), next) {
+                                handler_execute(loop, handler, post);
+                                exec |= true;
+                            }
+                            // Skip to next base node
+                            break;
+                        }
+                    }
                 }
             }
-            exec |= true;
         }
 
         post_instance_delete(&post);
@@ -570,7 +598,7 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop)
 #ifdef CONFIG_EVENT_LOOP_PROFILING
     xSemaphoreTakeRecursive(loop->profiling_mutex, portMAX_DELAY);
     portENTER_CRITICAL(&s_event_loops_spinlock);
-    SLIST_REMOVE(&s_event_loops, loop, esp_event_loop_instance, loop_entry);
+    SLIST_REMOVE(&s_event_loops, loop, esp_event_loop_instance, next);
     portEXIT_CRITICAL(&s_event_loops_spinlock);
 #endif
 
@@ -579,9 +607,13 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop)
         vTaskDelete(loop->task);
     }
 
-    // Remove all registered events in the loop
-    handler_instances_remove_all(&(loop->loop_handlers));
-    loop_remove_all_event_base_instance(loop);
+    // Remove all registered events and handlers in the loop
+    esp_event_loop_node_t *it, *temp;
+    SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) {
+        loop_node_remove_all_handler(it);
+        SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next);
+        free(it);
+    }
 
     // Drop existing posts on the queue
     esp_event_post_instance_t post;
@@ -618,89 +650,55 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, es
 
     esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop;
 
-    esp_event_base_instance_t* base = NULL;
-    esp_event_id_instance_t* event = NULL;
-    esp_event_handler_instance_t* handler = NULL;
-    esp_event_handler_instances_t* handlers = NULL;
-
-    bool base_created = false;
-    bool event_created = false;
-
     if (event_base == ESP_EVENT_ANY_BASE) {
         event_base = esp_event_any_base;
     }
 
+    esp_err_t err = ESP_OK;
+
     xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY);
 
-    if (event_base == esp_event_any_base && event_id == ESP_EVENT_ANY_ID) {
-        // Add to the loop-level handlers
-        handlers = &(loop->loop_handlers);
-    } else {
-        // If base instance does not exist, create one
-        if ((base = loop_find_event_base_instance(loop, event_base)) == NULL) {
-            base = event_base_instance_create(event_base);
-            if (base == NULL) {
-                xSemaphoreGiveRecursive(loop->mutex);
-                return ESP_ERR_NO_MEM;
-            }
-            base_created = true;
-        }
-        // Add to the event base instance level handlers
-        if (event_id == ESP_EVENT_ANY_ID) {
-            handlers = &(base->base_handlers);
-        } else {
-            if (base_created ||
-                (event = event_base_instance_find_event_id_instance(base, event_id)) == NULL) {
-                event = event_id_instance_create(event_id);
-                // If it does not exist, create one
-                if (event == NULL) {
-                    if (base_created) {
-                        event_base_instance_delete(base);
-                    }
-                    xSemaphoreGiveRecursive(loop->mutex);
-                    return ESP_ERR_NO_MEM;
-                }
-                event_created = true;
-            }
-            // Add to the event id instance level handlers
-            handlers = &(event->handlers);
-        }
+    esp_event_loop_node_t *loop_node = NULL, *last_loop_node = NULL;
+
+    SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) {
+        last_loop_node = loop_node;
     }
 
-    // Add handler to the list
-    if (base_created || event_created ||
-        (handler = handler_instances_find(handlers, event_handler)) == NULL) {
-        handler = handler_instance_create(event_handler, event_handler_arg);
-        if (handler == NULL) {
-            if (event_created) {
-                event_id_instance_delete(event);
+    bool is_loop_level_handler = (event_base == esp_event_any_base) && (event_id == ESP_EVENT_ANY_ID);
+
+    if (!last_loop_node ||
+       (last_loop_node && !SLIST_EMPTY(&(last_loop_node->base_nodes)) && is_loop_level_handler)) {
+        loop_node = (esp_event_loop_node_t*) calloc(1, sizeof(*loop_node));
+
+        SLIST_INIT(&(loop_node->handlers));
+        SLIST_INIT(&(loop_node->base_nodes));
+
+        if (!loop_node) {
+            ESP_LOGE(TAG, "alloc for new loop node failed");
+            err = ESP_ERR_NO_MEM;
+            goto on_err;
+        }
+
+        err = loop_node_add_handler(loop_node, event_base, event_id, event_handler, event_handler_arg);
+
+        if (err == ESP_OK) {
+            if (!last_loop_node) {
+                SLIST_INSERT_HEAD(&(loop->loop_nodes), loop_node, next);
             }
-            if (base_created) {
-                event_base_instance_delete(base);
+            else {
+                SLIST_INSERT_AFTER(last_loop_node, loop_node, next);
             }
-            xSemaphoreGiveRecursive(loop->mutex);
-            return ESP_ERR_NO_MEM;
-        }
-        handler_instances_add(handlers, handler);
-        // If a new event base/ event id instance was created, add them to the appropriate list
-        if (event_created) {
-            event_base_instance_add_event_id_instance(base, event);
         }
-        if (base_created) {
-            loop_add_event_base_instance(loop, base);
-        }
-        ESP_LOGD(TAG, "registered handler %p for event %s:%d", event_handler, event_base, event_id);
-    } else {
-        handler->arg = event_handler_arg;
-        ESP_LOGW(TAG, "handler %p for event %s:%d already registered, overwriting", event_handler, event_base, event_id);
+    }
+    else {
+        err = loop_node_add_handler(last_loop_node, event_base, event_id, event_handler, event_handler_arg);
     }
 
+on_err:
     xSemaphoreGiveRecursive(loop->mutex);
-
-    return ESP_OK;
+    return err;
 }
 
-
 esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base,
                                             int32_t event_id, esp_event_handler_t event_handler)
 {
@@ -718,17 +716,18 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop,
 
     esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop;
 
-    esp_event_handler_instance_t* handler = NULL;
-    esp_event_handler_instances_t* handlers = find_handlers_list(loop, event_base, event_id);
-
     xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY);
 
-    if (handlers != NULL &&
-        (handler = handler_instances_find(handlers, event_handler)) != NULL) {
-        handler_instances_remove(handlers, handler);
-        ESP_LOGD(TAG, "unregistered handler %p from event %s:%d", event_handler, event_base, event_id);
-    } else {
-        ESP_LOGW(TAG, "handler %p for event %s:%d not registered, ignoring", event_handler, event_base, event_id);
+    esp_event_loop_node_t *it, *temp;
+
+    SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) {
+        esp_err_t res = loop_node_remove_handler(it, event_base, event_id, event_handler);
+
+        if (res == ESP_OK && SLIST_EMPTY(&(it->base_nodes)) && SLIST_EMPTY(&(it->handlers))) {
+            SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next);
+            free(it);
+            break;
+        }
     }
 
     xSemaphoreGiveRecursive(loop->mutex);
@@ -804,14 +803,16 @@ esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t
     return ESP_OK;
 }
 
+
 esp_err_t esp_event_dump(FILE* file)
 {
 #ifdef CONFIG_EVENT_LOOP_PROFILING
     assert(file);
 
     esp_event_loop_instance_t* loop_it;
-    esp_event_base_instance_t* base_it;
-    esp_event_id_instance_t* id_it;
+    esp_event_loop_node_t *loop_node_it;
+    esp_event_base_node_t* base_node_it;
+    esp_event_id_node_t* id_node_it;
     esp_event_handler_instance_t* handler_it;
 
     // Allocate memory for printing
@@ -819,46 +820,52 @@ esp_err_t esp_event_dump(FILE* file)
     char* buf = calloc(sz, sizeof(char));
     char* dst = buf;
 
+    char id_str_buf[20];
+
     // Print info to buffer
     portENTER_CRITICAL(&s_event_loops_spinlock);
-    SLIST_FOREACH(loop_it, &s_event_loops, loop_entry) {
-        PRINT_DUMP_INFO(dst, sz, LOOP_DUMP_FORMAT, loop_it, loop_it->name, loop_it->events_recieved,
-                        loop_it->events_dropped, loop_it->total_handlers_invoked, loop_it->total_handlers_runtime);
-
-        // Print loop-level handler
-        PRINT_DUMP_INFO(dst, sz, esp_event_any_base, ESP_EVENT_ANY_ID, loop_it->loop_handlers_invoked,
-                        loop_it->loop_handlers_runtime);
-        SLIST_FOREACH(handler_it, &(loop_it->loop_handlers), handler_entry) {
-            PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, handler_it->total_times_invoked,
-                            handler_it->total_runtime);
-        }
 
-        SLIST_FOREACH(base_it, &(loop_it->event_bases), event_base_entry) {
-            // Print base-level handler
-            PRINT_DUMP_INFO(dst, sz, EVENT_DUMP_FORMAT, base_it->base, ESP_EVENT_ANY_ID,
-                            base_it->base_handlers_invoked, base_it->base_handlers_runtime);
-            SLIST_FOREACH(handler_it, &(base_it->base_handlers), handler_entry) {
-                PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler,
-                                handler_it->total_times_invoked, handler_it->total_runtime);
+    SLIST_FOREACH(loop_it, &s_event_loops, next) {
+        PRINT_DUMP_INFO(dst, sz, LOOP_DUMP_FORMAT, loop_it, loop_it->task != NULL ? loop_it->name : "none" ,
+                        loop_it->events_recieved, loop_it->events_dropped);
+
+        int sz_bak = sz;
+
+        SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) {
+            SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) {
+                PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, "ESP_EVENT_ANY_BASE",
+                                "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time);
             }
 
-            // Print event-level handlers
-            SLIST_FOREACH(id_it, &(base_it->event_ids), event_id_entry) {
-                PRINT_DUMP_INFO(dst, sz, EVENT_DUMP_FORMAT, base_it->base, id_it->id,
-                                id_it->handlers_invoked, id_it->handlers_runtime);
+            SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) {
+                SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) {
+                    PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base ,
+                                    "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time);
+                }
 
-                SLIST_FOREACH(handler_it, &(id_it->handlers), handler_entry) {
-                    PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler,
-                                    handler_it->total_times_invoked, handler_it->total_runtime);
+                SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) {
+                    SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) {
+                        memset(id_str_buf, 0, sizeof(id_str_buf));
+                        snprintf(id_str_buf, sizeof(id_str_buf), "%d", id_node_it->id);
+
+                        PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base ,
+                                        id_str_buf, handler_it->invoked, handler_it->time);
+                    }
                 }
             }
         }
+
+        // No handlers registered for this loop
+        if (sz == sz_bak) {
+            PRINT_DUMP_INFO(dst, sz, "  NO HANDLERS REGISTERED\n");
+        }
     }
+
     portEXIT_CRITICAL(&s_event_loops_spinlock);
-    
+
     // Print the contents of the buffer to the file
     fprintf(file, buf);
-    
+
     // Free the allocated buffer
     free(buf);
 #endif
index 8e14284c794cf0f8f0975d0e99acf36a58888032..828e458c6d72c6c25a943d5d31ec3a24f899fbed 100644 (file)
@@ -22,17 +22,41 @@ bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_eve
     esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop;
 
     bool result = false;
-    xSemaphoreTake(loop->mutex, portMAX_DELAY);
-
-    esp_event_base_instance_t* base_it;
-    SLIST_FOREACH(base_it, &(loop->event_bases), event_base_entry) {
-        esp_event_id_instance_t* event_it;
-        SLIST_FOREACH(event_it, &(base_it->event_ids), event_id_entry) {
-            esp_event_handler_instance_t* handler_it;
-            SLIST_FOREACH(handler_it, &(event_it->handlers), handler_entry) {
-                if (base_it->base == event_base && event_it->id == event_id && handler_it->handler == event_handler) {
-                    result = true;
-                    goto out;
+
+    esp_event_loop_node_t* loop_node;
+    esp_event_base_node_t* base_node;
+    esp_event_id_node_t* id_node;
+    esp_event_handler_instance_t* handler;
+
+    SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) {
+        SLIST_FOREACH(handler, &(loop_node->handlers), next) {
+            if(event_base == ESP_EVENT_ANY_BASE && event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler)
+            {
+                result = true;
+                goto out;
+            }
+        }
+
+        SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) {
+            if (base_node->base == event_base) {
+                SLIST_FOREACH(handler, &(base_node->handlers), next) {
+                    if(event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler)
+                    {
+                        result = true;
+                        goto out;
+                    }
+                }
+
+                SLIST_FOREACH(id_node, &(base_node->id_nodes), next) {
+                    if(id_node->id == event_id) {
+                        SLIST_FOREACH(handler, &(id_node->handlers), next) {
+                            if(handler->handler == event_handler)
+                            {
+                                result = true;
+                                goto out;
+                            }
+                        }       
+                    }
                 }
             }
         }
index f095844a72b21869852658af89f210135331764c..f97deaf8b4ab09ea55c64e55aa4e91928a193692 100644 (file)
@@ -33,11 +33,11 @@ extern "C" {
 /// Configuration for creating event loops
 typedef struct {
     int32_t queue_size;                         /**< size of the event loop queue */
-    const char* task_name;                      /**< name of the event loop task; if NULL, 
+    const char* task_name;                      /**< name of the event loop task; if NULL,
                                                         a dedicated task is not created for event loop*/
     UBaseType_t task_priority;                  /**< priority of the event loop task, ignored if task name is NULL */
     uint32_t task_stack_size;                   /**< stack size of the event loop task, ignored if task name is NULL */
-    BaseType_t task_core_id;                    /**< core to which the event loop task is pinned to, 
+    BaseType_t task_core_id;                    /**< core to which the event loop task is pinned to,
                                                         ignored if task name is NULL */
 } esp_event_loop_args_t;
 
@@ -47,7 +47,7 @@ typedef struct {
  * @param[in] event_loop_args configuration structure for the event loop to create
  * @param[out] event_loop handle to the created event loop
  *
- * @return 
+ * @return
  *  - ESP_OK: Success
  *  - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list
  *  - ESP_FAIL: Failed to create task loop
@@ -60,7 +60,7 @@ esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, es
  *
  * @param[in] event_loop event loop to delete
  *
- * @return 
+ * @return
  *  - ESP_OK: Success
  *  - Others: Fail
  */
@@ -68,8 +68,8 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop);
 
 /**
  * @brief Create default event loop
- * 
- * @return 
+ *
+ * @return
  *  - ESP_OK: Success
  *  - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list
  *  - ESP_FAIL: Failed to create task loop
@@ -79,8 +79,8 @@ esp_err_t esp_event_loop_create_default();
 
 /**
  * @brief Delete the default event loop
- * 
- * @return 
+ *
+ * @return
  *  - ESP_OK: Success
  *  - Others: Fail
  */
@@ -89,18 +89,18 @@ esp_err_t esp_event_loop_delete_default();
 /**
  * @brief Dispatch events posted to an event loop.
  *
- * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL 
- * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time 
- * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee 
- * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have 
+ * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL
+ * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time
+ * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee
+ * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have
  * been dispatched during the call, as the function might have spent all of the alloted time waiting on the event queue.
- * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being 
- * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued 
- * event, and (2) during  dispatch of the unqueued event there is no way to control the time occupied by handler code 
+ * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being
+ * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued
+ * event, and (2) during  dispatch of the unqueued event there is no way to control the time occupied by handler code
  * execution. The guaranteed time of exit is therefore the alloted time + amount of time required to dispatch
  * the last unqueued event.
  *
- * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is 
+ * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is
  * normal behavior.
  *
  * @param[in] event_loop event loop to dispatch posted events from
@@ -108,7 +108,7 @@ esp_err_t esp_event_loop_delete_default();
  *
  * @note encountering an unknown event that has been posted to the loop will only generate a warning, not an error.
  *
- * @return 
+ * @return
  *  - ESP_OK: Success
  *  - Others: Fail
  */
@@ -124,8 +124,8 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick
  *  - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id
  *  - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id
  *
- * Registering multiple handlers to events is possible. Registering a single handler to multiple events is 
- * also possible. However, registering the same handler to the same event multiple times would cause the 
+ * Registering multiple handlers to events is possible. Registering a single handler to multiple events is
+ * also possible. However, registering the same handler to the same event multiple times would cause the
  * previous registrations to be overwritten.
  *
  * @param[in] event_base the base id of the event to register the handler for
@@ -133,24 +133,24 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick
  * @param[in] event_handler the handler function which gets called when the event is dispatched
  * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called
  *
- * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should 
+ * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should
  * ensure that event_handler_arg still points to a valid location by the time the handler gets called
  *
- * @return 
+ * @return
  *  - ESP_OK: Success
  *  - ESP_ERR_NO_MEM: Cannot allocate memory for the handler
- *  - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id
+ *  - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id
  *  - Others: Fail
  */
-esp_err_t esp_event_handler_register(esp_event_base_t event_base, 
-                                        int32_t event_id, 
-                                        esp_event_handler_t event_handler, 
+esp_err_t esp_event_handler_register(esp_event_base_t event_base,
+                                        int32_t event_id,
+                                        esp_event_handler_t event_handler,
                                         void* event_handler_arg);
 
 /**
  * @brief Register an event handler to a specific loop.
  *
- * This function behaves in the same manner as esp_event_handler_register, except the additional 
+ * This function behaves in the same manner as esp_event_handler_register, except the additional
  * specification of the event loop to register the handler to.
  *
  * @param[in] event_loop the event loop to register this handler function to
@@ -159,23 +159,26 @@ esp_err_t esp_event_handler_register(esp_event_base_t event_base,
  * @param[in] event_handler the handler function which gets called when the event is dispatched
  * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called
  *
- * @return 
+ * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should
+ * ensure that event_handler_arg still points to a valid location by the time the handler gets called
+ *
+ * @return
  *  - ESP_OK: Success
  *  - ESP_ERR_NO_MEM: Cannot allocate memory for the handler
- *  - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id
+ *  - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id
  *  - Others: Fail
  */
-esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, 
-                                            esp_event_base_t event_base, 
-                                            int32_t event_id, 
-                                            esp_event_handler_t event_handler, 
+esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop,
+                                            esp_event_base_t event_base,
+                                            int32_t event_id,
+                                            esp_event_handler_t event_handler,
                                             void* event_handler_arg);
 
 /**
  * @brief Unregister a handler with the system event loop.
  *
  * This function can be used to unregister a handler so that it no longer gets called during dispatch.
- * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, 
+ * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base,
  * or (3) all events known by the system event loop
  *
  *  - specific events: specify exact event_base and event_id
@@ -189,7 +192,7 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop,
  * @param[in] event_handler the handler to unregister
  *
  * @return ESP_OK success
- * @return ESP_ERR_INVALIG_ARG invalid combination of event base and event id
+ * @return ESP_ERR_INVALID_ARG invalid combination of event base and event id
  * @return others fail
  */
 esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler);
@@ -197,7 +200,7 @@ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t even
 /**
  * @brief Unregister a handler with the system event loop.
  *
- * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of 
+ * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of
  * the event loop to unregister the handler with.
  *
  * @param[in] event_loop the event loop with which to unregister this handler function
@@ -205,21 +208,21 @@ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t even
  * @param[in] event_id the id of the event with which to unregister the handler
  * @param[in] event_handler the handler to unregister
  *
- * @return 
+ * @return
  *  - ESP_OK: Success
- *  - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id
+ *  - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id
  *  - Others: Fail
  */
-esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, 
-                                            esp_event_base_t event_base, 
-                                            int32_t event_id, 
+esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop,
+                                            esp_event_base_t event_base,
+                                            int32_t event_id,
                                             esp_event_handler_t event_handler);
 
 /**
- * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages 
- * the copy's lifetime automatically (allocation + deletion); this ensures that the data the 
+ * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages
+ * the copy's lifetime automatically (allocation + deletion); this ensures that the data the
  * handler recieves is always valid.
- * 
+ *
  * @param[in] event_base the event base that identifies the event
  * @param[in] event_id the the event id that identifies the event
  * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler
@@ -228,21 +231,21 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop,
  *
  * @note posting events from an ISR is not supported
  *
- * @return 
+ * @return
  *  - ESP_OK: Success
  *  - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired
- *  - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id
+ *  - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id
  *  - Others: Fail
  */
-esp_err_t esp_event_post(esp_event_base_t event_base, 
-                            int32_t event_id, 
-                            void* event_data, 
-                            size_t event_data_size, 
+esp_err_t esp_event_post(esp_event_base_t event_base,
+                            int32_t event_id,
+                            void* event_data,
+                            size_t event_data_size,
                             TickType_t ticks_to_wait);
 
 /**
- * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages 
- * the copy's lifetime automatically (allocation + deletion); this ensures that the data the 
+ * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages
+ * the copy's lifetime automatically (allocation + deletion); this ensures that the data the
  * handler recieves is always valid.
  *
  * This function behaves in the same manner as esp_event_post_to, except the additional specification of the event loop
@@ -256,73 +259,60 @@ esp_err_t esp_event_post(esp_event_base_t event_base,
  * @param[in] ticks_to_wait number of ticks to block on a full event queue
  *
  * @note posting events from an ISR is not supported
- * 
- * @return 
+ *
+ * @return
  *  - ESP_OK: Success
  *  - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired
- *  - ESP_ERR_INVALIG_ARG: Invalid combination of event base and event id
+ *  - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id
  *  - Others: Fail
  */
-esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, 
-                            esp_event_base_t event_base, 
-                            int32_t event_id, 
-                            void* event_data, 
-                            size_t event_data_size, 
+esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop,
+                            esp_event_base_t event_base,
+                            int32_t event_id,
+                            void* event_data,
+                            size_t event_data_size,
                             TickType_t ticks_to_wait);
 
 /**
  * @brief Dumps statistics of all event loops.
  *
  * Dumps event loop info in the format:
- * 
+ *
  @verbatim
        event loop
-           event
-               handler
-               handler
-           event
-               handler
-               handler
+           handler
+           handler
+           ...
        event loop
-           event
-               handler
-               ...
+           handler
+           handler
            ...
-       ...
+
   where:
+
    event loop
-       format: address,name rx:total_recieved dr:total_dropped inv:total_number_of_invocations run:total_runtime
+       format: address,name rx:total_recieved dr:total_dropped
        where:
            address - memory address of the event loop
-           name - name of the event loop
+           name - name of the event loop, 'none' if no dedicated task
            total_recieved - number of successfully posted events
-           total_number_of_invocations - total number of handler invocations performed so far
-           total_runtime - total runtime of all invocations so far
-   event
-       format: base:id proc:total_processed run:total_runtime
-       where:
-           base - event base
-           id - event id
-           total_processed - number of instances of this event that has been processed
-           total_runtime - total amount of time in microseconds used for invoking handlers of this event
+           total_dropped - number of events unsucessfully posted due to queue being full
+
    handler
-       format: address inv:total_invoked run:total_runtime
+       format: address ev:base,id inv:total_invoked run:total_runtime
        where:
            address - address of the handler function
+           base,id - the event specified by event base and id this handler executes
            total_invoked - number of times this handler has been invoked
            total_runtime - total amount of time used for invoking this handler
+
  @endverbatim
  *
  * @param[in] file the file stream to output to
  *
  * @note this function is a noop when CONFIG_EVENT_LOOP_PROFILING is disabled
  *
- * @return 
+ * @return
  *  - ESP_OK: Success
  *  - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list
  *  - Others: Fail
index 8b29c8628b31646c29791254168e6d0773a99a07..734def58688c191a5d1746f592f0b1008fab0f2e 100644 (file)
 extern "C" {
 #endif
 
+typedef SLIST_HEAD(base_nodes, base_node) base_nodes_t;
+
 /// Event handler
 typedef struct esp_event_handler_instance {
     esp_event_handler_t handler;                                    /**< event handler function*/
     void* arg;                                                      /**< event handler argument */
 #ifdef CONFIG_EVENT_LOOP_PROFILING
-    uint32_t total_times_invoked;                                   /**< number of times this handler has been invoked */
-    int64_t total_runtime;                                          /**< total runtime of this handler across all calls */
+    uint32_t invoked;                                               /**< number of times this handler has been invoked */
+    int64_t time;                                                   /**< total runtime of this handler across all calls */
 #endif
-    SLIST_ENTRY(esp_event_handler_instance) handler_entry;          /**< next event handler in the list */
+    SLIST_ENTRY(esp_event_handler_instance) next;                   /**< next event handler in the list */
 } esp_event_handler_instance_t;
 
 typedef SLIST_HEAD(esp_event_handler_instances, esp_event_handler_instance) esp_event_handler_instances_t;
 
-typedef struct esp_event_id_instance {
-    int32_t id;
-    esp_event_handler_instances_t handlers;                         /**< list of handlers to be executed when 
+/// Event
+typedef struct esp_event_id_node {
+    int32_t id;                                                     /**< id number of the event */
+    esp_event_handler_instances_t handlers;                         /**< list of handlers to be executed when
                                                                             this event is raised */
-    SLIST_ENTRY(esp_event_id_instance) event_id_entry;              /**< pointer to the next event node on the linked list */
-#ifdef CONFIG_EVENT_LOOP_PROFILING
-    uint32_t handlers_invoked;                                      /**< total number of times the event has been 
-                                                                            raised and processed in the loop */
-    int64_t handlers_runtime;                                       /**< total time spent in executing handlers */
-#endif
-} esp_event_id_instance_t;
+    SLIST_ENTRY(esp_event_id_node) next;                            /**< pointer to the next event node on the linked list */
+} esp_event_id_node_t;
 
-typedef SLIST_HEAD(esp_event_id_instances, esp_event_id_instance) esp_event_id_instances_t;
+typedef SLIST_HEAD(esp_event_id_nodes, esp_event_id_node) esp_event_id_nodes_t;
 
-/// Event
-typedef struct esp_event_base_instance {
+typedef struct esp_event_base_node {
     esp_event_base_t base;                                          /**< base identifier of the event */
-    esp_event_handler_instances_t base_handlers;                    /**< event base level handlers, handlers for 
+    esp_event_handler_instances_t handlers;                         /**< event base level handlers, handlers for
                                                                             all events with this base */
-    esp_event_id_instances_t event_ids;                             /**< list of event ids with this base */
-    SLIST_ENTRY(esp_event_base_instance) event_base_entry;          /**< pointer to the next event node on the linked list */
-#ifdef CONFIG_EVENT_LOOP_PROFILING
-    uint32_t base_handlers_invoked;                                 /**< total number of base-level handlers invoked */
-    int64_t base_handlers_runtime;                                  /**< amount of time processing base-level handlers */
-#endif
-} esp_event_base_instance_t;
+    esp_event_id_nodes_t id_nodes;                                  /**< list of event ids with this base */
+    SLIST_ENTRY(esp_event_base_node) next;                          /**< pointer to the next base node on the linked list */
+} esp_event_base_node_t;
+
+typedef SLIST_HEAD(esp_event_base_nodes, esp_event_base_node) esp_event_base_nodes_t;
+
+typedef struct esp_event_loop_node {
+    esp_event_handler_instances_t handlers;                         /** event loop level handlers */
+    esp_event_base_nodes_t base_nodes;                              /** list of event bases registered to the loop */
+    SLIST_ENTRY(esp_event_loop_node) next;                          /** pointer to the next loop node containing
+                                                                            event loop level handlers and the rest of
+                                                                            event bases registered to the loop */
+} esp_event_loop_node_t;
 
-typedef SLIST_HEAD(esp_event_base_instances, esp_event_base_instance) esp_event_base_instances_t;
+typedef SLIST_HEAD(esp_event_loop_nodes, esp_event_loop_node) esp_event_loop_nodes_t;
 
 /// Event loop
 typedef struct esp_event_loop_instance {
     const char* name;                                               /**< name of this event loop */
     QueueHandle_t queue;                                            /**< event queue */
     TaskHandle_t task;                                              /**< task that consumes the event queue */
-    TaskHandle_t running_task;                                      /**< for loops with no dedicated task, the 
+    TaskHandle_t running_task;                                      /**< for loops with no dedicated task, the
                                                                             task that consumes the queue */
     SemaphoreHandle_t mutex;                                        /**< mutex for updating the events linked list */
-    esp_event_handler_instances_t loop_handlers;                    /**< loop level handlers, handlers for all events 
-                                                                            registered in the loop */
-    esp_event_base_instances_t event_bases;                         /**< events linked list head pointer */
+    esp_event_loop_nodes_t loop_nodes;                              /**< set of linked lists containing the
+                                                                            registered handlers for the loop */
 #ifdef CONFIG_EVENT_LOOP_PROFILING
     uint32_t events_recieved;                                       /**< number of events successfully posted to the loop */
     uint32_t events_dropped;                                        /**< number of events dropped due to queue being full */
-    uint32_t loop_handlers_invoked;                                 /**< total number of loop-level handlers invoked */
-    int64_t loop_handlers_runtime;                                  /**< amount of time processing loop-level handlers */
-    uint32_t total_handlers_invoked;                                /**< total number of handlers invoked */
-    int64_t total_handlers_runtime;                                 /**< total amount of time dedicated to processing this loop */
-    SLIST_ENTRY(esp_event_loop_instance) loop_entry;                /**< next event loop in the list */
-    SemaphoreHandle_t profiling_mutex;
+    SemaphoreHandle_t profiling_mutex;                              /**< mutex used for profiliing */
+    SLIST_ENTRY(esp_event_loop_instance) next;                      /**< next event loop in the list */
 #endif
 } esp_event_loop_instance_t;