Browse Source

Extend the node library to include a Lua implementation of task posting

TerryE 8 years ago
parent
commit
4f8f192cbe
3 changed files with 91 additions and 9 deletions
  1. 4 4
      app/include/task/task.h
  2. 48 5
      app/modules/node.c
  3. 39 0
      docs/en/modules/node.md

+ 4 - 4
app/include/task/task.h

@@ -17,10 +17,10 @@
 * is just a fixed fingerprint and the count is allocated serially by the task get_id()
 * function.
 */
-
-#define task_post_low(handle,param) system_os_post(0, (handle | TASK_PRIORITY_LOW), param)
-#define task_post_medium(handle,param) system_os_post(1, (handle | TASK_PRIORITY_MEDIUM), param)
-#define task_post_high(handle,param) system_os_post(2, (handle | TASK_PRIORITY_HIGH), param)
+#define task_post(priority,handle,param) system_os_post(priority, ((handle) | priority), param)
+#define task_post_low(handle,param)    task_post(TASK_PRIORITY_LOW,    handle, param)
+#define task_post_medium(handle,param) task_post(TASK_PRIORITY_MEDIUM, handle, param)
+#define task_post_high(handle,param)   task_post(TASK_PRIORITY_HIGH,   handle, param)
 
 #define task_handle_t os_signal_t
 #define task_param_t os_param_t

+ 48 - 5
app/modules/node.c

@@ -26,6 +26,7 @@
 #include "flash_fs.h"
 #include "user_version.h"
 #include "rom.h"
+#include "task/task.h"
 
 #define CPU80MHZ 80
 #define CPU160MHZ 160
@@ -448,6 +449,39 @@ static int node_compile( lua_State* L )
   return 0;
 }
 
+// Task callback handler for node.tasknow()
+static task_handle_t do_node_task_handle;
+static void do_node_task (task_param_t task_fn_ref, uint8_t prio)
+{
+  UNUSED(prio);
+  lua_State* L = lua_getstate();
+  lua_rawgeti(L, LUA_REGISTRYINDEX, (int)task_fn_ref);
+	luaL_unref(L, LUA_REGISTRYINDEX, (int)task_fn_ref);
+  lua_pushinteger(L, prio);
+	lua_call(L, 1, 0);
+}
+
+// Lua: node.tasknow(task_cb)) -- schedule a task for execution next
+static int node_task_post( lua_State* L )
+{
+  int n = 1, Ltype = lua_type(L, 1);
+  unsigned priority = TASK_PRIORITY_MEDIUM;
+  if (Ltype == LUA_TNUMBER) {
+    priority = (unsigned) luaL_checkint(L, 1);
+    luaL_argcheck(L, priority <= TASK_PRIORITY_HIGH, 1, "invalid  priority");
+    Ltype = lua_type(L, ++n);
+  }
+  luaL_argcheck(L, Ltype == LUA_TFUNCTION || Ltype == LUA_TLIGHTFUNCTION, n, "invalid function");
+	lua_pushvalue(L, n);
+
+	int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+  if (!do_node_task_handle)  // bind the task handle to do_node_task on 1st call
+    do_node_task_handle = task_get_id(do_node_task);
+
+  task_post(priority, do_node_task_handle, (task_param_t)task_fn_ref);
+}
+
 // Lua: setcpufreq(mhz)
 // mhz is either CPU80MHZ od CPU160MHZ
 static int node_setcpufreq(lua_State* L)
@@ -554,29 +588,37 @@ static int node_stripdebug (lua_State *L) {
 #endif
 
 // Lua: node.egc.setmode( mode, [param])
-// where the mode is one of the node.egc constants  NOT_ACTIVE , ON_ALLOC_FAILURE, 
+// where the mode is one of the node.egc constants  NOT_ACTIVE , ON_ALLOC_FAILURE,
 // ON_MEM_LIMIT, ALWAYS.  In the case of ON_MEM_LIMIT an integer parameter is reqired
 // See legc.h and lecg.c.
 static int node_egc_setmode(lua_State* L) {
   unsigned mode  = luaL_checkinteger(L, 1);
   unsigned limit = luaL_optinteger (L, 2, 0);
-  
+
   luaL_argcheck(L, mode <= (EGC_ON_ALLOC_FAILURE | EGC_ON_MEM_LIMIT | EGC_ALWAYS), 1, "invalid mode");
   luaL_argcheck(L, !(mode & EGC_ON_MEM_LIMIT) || limit>0, 1, "limit must be non-zero");
-  
+
   legc_set_mode( L, mode, limit );
   return 0;
 }
 // Module function map
 
 static const LUA_REG_TYPE node_egc_map[] = {
-  { LSTRKEY( "setmode" ),           LFUNCVAL( node_egc_setmode ) },  
+  { LSTRKEY( "setmode" ),           LFUNCVAL( node_egc_setmode ) },
   { LSTRKEY( "NOT_ACTIVE" ),        LNUMVAL( EGC_NOT_ACTIVE ) },
   { LSTRKEY( "ON_ALLOC_FAILURE" ),  LNUMVAL( EGC_ON_ALLOC_FAILURE ) },
   { LSTRKEY( "ON_MEM_LIMIT" ),      LNUMVAL( EGC_ON_MEM_LIMIT ) },
   { LSTRKEY( "ALWAYS" ),            LNUMVAL( EGC_ALWAYS ) },
   { LNILKEY, LNILVAL }
 };
+static const LUA_REG_TYPE node_task_map[] = {
+  { LSTRKEY( "post" ),            LFUNCVAL( node_task_post ) },
+  { LSTRKEY( "LOW_PRIORITY" ),    LNUMVAL( TASK_PRIORITY_LOW ) },
+  { LSTRKEY( "MEDIUM_PRIORITY" ), LNUMVAL( TASK_PRIORITY_MEDIUM ) },
+  { LSTRKEY( "HIGH_PRIORITY" ),   LNUMVAL( TASK_PRIORITY_HIGH ) },
+  { LNILKEY, LNILVAL }
+};
+
 static const LUA_REG_TYPE node_map[] =
 {
   { LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
@@ -603,7 +645,8 @@ static const LUA_REG_TYPE node_map[] =
 #ifdef LUA_OPTIMIZE_DEBUG
   { LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
 #endif
-  { LSTRKEY( "egc" ), LROVAL( node_egc_map ) },
+  { LSTRKEY( "egc" ),  LROVAL( node_egc_map ) },
+  { LSTRKEY( "task" ), LROVAL( node_task_map ) },
 
 // Combined to dsleep(us, option)
 // { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },

+ 39 - 0
docs/en/modules/node.md

@@ -403,3 +403,42 @@ provides more detailed information on the EGC.
 
 `node.egc.setmode(node.egc.ALWAYS, 4096)  -- This is the default setting at startup.`
 `node.egc.setmode(node.egc.ON_ALLOC_FAILURE) -- This is the fastest activeEGC mode.`
+
+# node.task module
+
+## node.task.post()
+
+Enable a Lua callback or task to post another task request. Note that as per the 
+example multiple tasks can be posted in any task, but the highest priority is 
+always delivered first.
+
+####Syntax
+`node.task.post([task_priority], function)`
+
+#### Parameters
+- `task_priority` (optional)
+	- `node.task.LOW_PRIORITY` = 0
+	- `node.task.MEDIUM_PRIORITY` = 1
+	- `node.task.HIGH_PRIORITY` = 2
+- `function` a callback function to be executed when the task is run. 
+
+If the priority is omitted then  this defaults  to `node.task.MEDIUM_PRIORITY`
+
+####  Returns
+`nil`
+
+#### Example
+```lua
+for i = node.task.LOW_PRIORITY, node.task.HIGH_PRIORITY do 
+  node.task.post(i,function(p2)
+    print("priority is ..p2)
+  end) 
+end      
+``` 
+prints
+```
+priority is 2
+priority is 1
+priority is 0
+```
+