diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-07-01 15:45:22 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-07-01 15:45:22 +0200 |
| commit | 7c3400f46aa7b341cab557c734326a6a0d8907a8 (patch) | |
| tree | ac932e9e1b4f34faa31d37250b9539d3ed5f2e05 /src | |
| parent | a29b16db27c0cd3c6cf1d1a4d8551174282bd296 (diff) | |
| download | lanes-7c3400f46aa7b341cab557c734326a6a0d8907a8.tar.gz lanes-7c3400f46aa7b341cab557c734326a6a0d8907a8.tar.bz2 lanes-7c3400f46aa7b341cab557c734326a6a0d8907a8.zip | |
A small step toward coroutine-based lanes
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 |
