diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.cpp | 4 | ||||
-rw-r--r-- | src/lanes.lua | 97 |
2 files changed, 59 insertions, 42 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index a5e4236..473e150 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -242,6 +242,7 @@ LUAG_FUNC(register) | |||
242 | // , [gc_cb_func] | 242 | // , [gc_cb_func] |
243 | // , [name] | 243 | // , [name] |
244 | // , error_trace_level | 244 | // , error_trace_level |
245 | // , as_coroutine | ||
245 | // [, ... args ...]) | 246 | // [, ... args ...]) |
246 | // | 247 | // |
247 | // Upvalues: metatable to use for 'lane_ud' | 248 | // Upvalues: metatable to use for 'lane_ud' |
@@ -257,7 +258,8 @@ LUAG_FUNC(lane_new) | |||
257 | static constexpr int kGcCbIdx{ 7 }; | 258 | static constexpr int kGcCbIdx{ 7 }; |
258 | static constexpr int kNameIdx{ 8 }; | 259 | static constexpr int kNameIdx{ 8 }; |
259 | static constexpr int kErTlIdx{ 9 }; | 260 | static constexpr int kErTlIdx{ 9 }; |
260 | static constexpr int kFixedArgsIdx{ 9 }; | 261 | static constexpr int kAsCoro{ 10 }; |
262 | static constexpr int kFixedArgsIdx{ 10 }; | ||
261 | 263 | ||
262 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; | 264 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; |
263 | LUA_ASSERT(L_, _nargs >= 0); | 265 | LUA_ASSERT(L_, _nargs >= 0); |
diff --git a/src/lanes.lua b/src/lanes.lua index d28fcf4..57183e9 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -284,46 +284,7 @@ local opt_validators = | |||
284 | -- ##################################### lanes.gen() ########################################### | 284 | -- ##################################### lanes.gen() ########################################### |
285 | -- ############################################################################################# | 285 | -- ############################################################################################# |
286 | 286 | ||
287 | -- lane_h[1..n]: lane results, same as via 'lane_h:join()' | 287 | local process_gen_opt = function(...) |
288 | -- lane_h[0]: can be read to make sure a thread has finished (always gives 'true') | ||
289 | -- lane_h[-1]: error message, without propagating the error | ||
290 | -- | ||
291 | -- Reading a Lane result (or [0]) propagates a possible error in the lane | ||
292 | -- (and execution does not return). Cancelled lanes give 'nil' values. | ||
293 | -- | ||
294 | -- lane_h.state: "pending"/"running"/"waiting"/"done"/"error"/"cancelled" | ||
295 | -- | ||
296 | -- Note: Would be great to be able to have '__ipairs' metamethod, that gets | ||
297 | -- called by 'ipairs()' function to custom iterate objects. We'd use it | ||
298 | -- for making sure a lane has ended (results are available); not requiring | ||
299 | -- the user to precede a loop by explicit 'h[0]' or 'h:join()'. | ||
300 | -- | ||
301 | -- Or, even better, 'ipairs()' should start valuing '__index' instead | ||
302 | -- of using raw reads that bypass it. | ||
303 | -- | ||
304 | ----- | ||
305 | -- lanes.gen([libs_str|opt_tbl [, ...],] lane_func ) ([...]) -> h | ||
306 | -- | ||
307 | -- 'libs': nil: no libraries available (default) | ||
308 | -- "": only base library ('assert', 'print', 'unpack' etc.) | ||
309 | -- "math,os": math + os + base libraries (named ones + base) | ||
310 | -- "*": all standard libraries available | ||
311 | -- | ||
312 | -- 'opt': .priority: int (-3..+3) smaller is lower priority (0 = default) | ||
313 | -- | ||
314 | -- .globals: table of globals to set for a new thread (passed by value) | ||
315 | -- | ||
316 | -- .required: table of packages to require | ||
317 | -- | ||
318 | -- .gc_cb: function called when the lane handle is collected | ||
319 | -- | ||
320 | -- ... (more options may be introduced later) ... | ||
321 | -- | ||
322 | -- Calling with a function argument ('lane_func') ends the string/table | ||
323 | -- modifiers, and prepares a lane generator. | ||
324 | |||
325 | -- receives a sequence of strings and tables, plus a function | ||
326 | local gen = function(...) | ||
327 | -- aggregrate all strings together, separated by "," as well as tables | 288 | -- aggregrate all strings together, separated by "," as well as tables |
328 | -- the strings are a list of libraries to open | 289 | -- the strings are a list of libraries to open |
329 | -- the tables contain the lane options | 290 | -- the tables contain the lane options |
@@ -392,15 +353,68 @@ local gen = function(...) | |||
392 | opt[k] = validator(v) | 353 | opt[k] = validator(v) |
393 | end | 354 | end |
394 | end | 355 | end |
356 | return func, libs, opt | ||
357 | end -- process_gen_opt | ||
358 | |||
359 | -- lane_h[1..n]: lane results, same as via 'lane_h:join()' | ||
360 | -- lane_h[0]: can be read to make sure a thread has finished (always gives 'true') | ||
361 | -- lane_h[-1]: error message, without propagating the error | ||
362 | -- | ||
363 | -- Reading a Lane result (or [0]) propagates a possible error in the lane | ||
364 | -- (and execution does not return). Cancelled lanes give 'nil' values. | ||
365 | -- | ||
366 | -- lane_h.state: "pending"/"running"/"waiting"/"done"/"error"/"cancelled" | ||
367 | -- | ||
368 | -- Note: Would be great to be able to have '__ipairs' metamethod, that gets | ||
369 | -- called by 'ipairs()' function to custom iterate objects. We'd use it | ||
370 | -- for making sure a lane has ended (results are available); not requiring | ||
371 | -- the user to precede a loop by explicit 'h[0]' or 'h:join()'. | ||
372 | -- | ||
373 | -- Or, even better, 'ipairs()' should start valuing '__index' instead | ||
374 | -- of using raw reads that bypass it. | ||
375 | -- | ||
376 | ----- | ||
377 | -- lanes.gen([libs_str|opt_tbl [, ...],] lane_func ) ([...]) -> h | ||
378 | -- | ||
379 | -- 'libs': nil: no libraries available (default) | ||
380 | -- "": only base library ('assert', 'print', 'unpack' etc.) | ||
381 | -- "math,os": math + os + base libraries (named ones + base) | ||
382 | -- "*": all standard libraries available | ||
383 | -- | ||
384 | -- 'opt': .priority: int (-3..+3) smaller is lower priority (0 = default) | ||
385 | -- | ||
386 | -- .globals: table of globals to set for a new thread (passed by value) | ||
387 | -- | ||
388 | -- .required: table of packages to require | ||
389 | -- | ||
390 | -- .gc_cb: function called when the lane handle is collected | ||
391 | -- | ||
392 | -- ... (more options may be introduced later) ... | ||
393 | -- | ||
394 | -- Calling with a function argument ('lane_func') ends the string/table | ||
395 | -- modifiers, and prepares a lane generator. | ||
395 | 396 | ||
397 | -- receives a sequence of strings and tables, plus a function | ||
398 | local gen = function(...) | ||
399 | local func, libs, opt = process_gen_opt(...) | ||
396 | local core_lane_new = assert(core.lane_new) | 400 | local core_lane_new = assert(core.lane_new) |
397 | local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] | 401 | local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] |
398 | return function(...) | 402 | return function(...) |
399 | -- must pass functions args last else they will be truncated to the first one | 403 | -- must pass functions args last else they will be truncated to the first one |
400 | return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, ...) | 404 | return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, false, ...) |
401 | end | 405 | end |
402 | end -- gen() | 406 | end -- gen() |
403 | 407 | ||
408 | local coro = function(...) | ||
409 | local func, libs, opt = process_gen_opt(...) | ||
410 | local core_lane_new = assert(core.lane_new) | ||
411 | local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] | ||
412 | return function(...) | ||
413 | -- must pass functions args last else they will be truncated to the first one | ||
414 | return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, true, ...) | ||
415 | end | ||
416 | end -- coro() | ||
417 | |||
404 | -- ################################################################################################# | 418 | -- ################################################################################################# |
405 | -- ####################################### Timers ################################################## | 419 | -- ####################################### Timers ################################################## |
406 | -- ################################################################################################# | 420 | -- ################################################################################################# |
@@ -850,6 +864,7 @@ local configure = function(settings_) | |||
850 | lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false | 864 | lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false |
851 | 865 | ||
852 | lanes.gen = gen | 866 | lanes.gen = gen |
867 | lanes.coro = coro | ||
853 | lanes.genatomic = genatomic | 868 | lanes.genatomic = genatomic |
854 | lanes.genlock = genlock | 869 | lanes.genlock = genlock |
855 | lanes.timer = timer | 870 | lanes.timer = timer |