diff options
Diffstat (limited to 'src/lanes.lua')
-rw-r--r-- | src/lanes.lua | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/src/lanes.lua b/src/lanes.lua index 98f8c20..c5b3315 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -96,6 +96,7 @@ local default_params = | |||
96 | -- it looks also like LuaJIT allocator may not appreciate direct use of its allocator for other purposes than the VM operation | 96 | -- it looks also like LuaJIT allocator may not appreciate direct use of its allocator for other purposes than the VM operation |
97 | internal_allocator = isLuaJIT and "libc" or "allocator", | 97 | internal_allocator = isLuaJIT and "libc" or "allocator", |
98 | keepers_gc_threshold = -1, | 98 | keepers_gc_threshold = -1, |
99 | linda_wake_period = 'never', | ||
99 | nb_user_keepers = 0, | 100 | nb_user_keepers = 0, |
100 | on_state_create = nil, | 101 | on_state_create = nil, |
101 | shutdown_timeout = 0.25, | 102 | shutdown_timeout = 0.25, |
@@ -141,6 +142,19 @@ local param_checkers = | |||
141 | end | 142 | end |
142 | return true | 143 | return true |
143 | end, | 144 | end, |
145 | linda_wake_period = function(val_) | ||
146 | -- linda_wake_period should be a number > 0, or the string 'never' | ||
147 | if val_ == 'never' then | ||
148 | return true | ||
149 | end | ||
150 | if type(val_) ~= "number" then | ||
151 | return nil, "not a number" | ||
152 | end | ||
153 | if val_ <= 0 then | ||
154 | return nil, "value out of range" | ||
155 | end | ||
156 | return true | ||
157 | end, | ||
144 | nb_user_keepers = function(val_) | 158 | nb_user_keepers = function(val_) |
145 | -- nb_user_keepers should be a number in [0,100] (so that nobody tries to run OOM by specifying a huge amount) | 159 | -- nb_user_keepers should be a number in [0,100] (so that nobody tries to run OOM by specifying a huge amount) |
146 | if type(val_) ~= "number" then | 160 | if type(val_) ~= "number" then |
@@ -266,6 +280,10 @@ local opt_validators = | |||
266 | local tv = type(v_) | 280 | local tv = type(v_) |
267 | return (tv == "string") and v_ or raise_option_error("name", tv, v_) | 281 | return (tv == "string") and v_ or raise_option_error("name", tv, v_) |
268 | end, | 282 | end, |
283 | native_priority = function(v_) | ||
284 | local tv = type(v_) | ||
285 | return (tv == "number") and v_ or raise_option_error("native_priority", tv, v_) | ||
286 | end, | ||
269 | package = function(v_) | 287 | package = function(v_) |
270 | local tv = type(v_) | 288 | local tv = type(v_) |
271 | return (tv == "table") and v_ or raise_option_error("package", tv, v_) | 289 | return (tv == "table") and v_ or raise_option_error("package", tv, v_) |
@@ -281,7 +299,7 @@ local opt_validators = | |||
281 | } | 299 | } |
282 | 300 | ||
283 | -- ############################################################################################# | 301 | -- ############################################################################################# |
284 | -- ##################################### lanes.gen() ########################################### | 302 | -- ################################### lanes.gen/coro() ######################################## |
285 | -- ############################################################################################# | 303 | -- ############################################################################################# |
286 | 304 | ||
287 | local process_gen_opt = function(...) | 305 | local process_gen_opt = function(...) |
@@ -353,9 +371,16 @@ local process_gen_opt = function(...) | |||
353 | opt[k] = validator(v) | 371 | opt[k] = validator(v) |
354 | end | 372 | end |
355 | end | 373 | end |
374 | |||
375 | -- special case: can't have priority and native_priority at the same time | ||
376 | if opt.priority and opt.native_priority then | ||
377 | error "priority and native_priority cannot be specified together" | ||
378 | end | ||
356 | return func, libs, opt | 379 | return func, libs, opt |
357 | end -- process_gen_opt | 380 | end -- process_gen_opt |
358 | 381 | ||
382 | -- ################################################################################################# | ||
383 | |||
359 | -- lane_h[1..n]: lane results, same as via 'lane_h:join()' | 384 | -- 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 (gives the number of available results) | 385 | -- lane_h[0]: can be read to make sure a thread has finished (gives the number of available results) |
361 | -- lane_h[negative]: error message, without propagating the error | 386 | -- lane_h[negative]: error message, without propagating the error |
@@ -394,25 +419,28 @@ end -- process_gen_opt | |||
394 | -- Calling with a function argument ('lane_func') ends the string/table | 419 | -- Calling with a function argument ('lane_func') ends the string/table |
395 | -- modifiers, and prepares a lane generator. | 420 | -- modifiers, and prepares a lane generator. |
396 | 421 | ||
397 | -- receives a sequence of strings and tables, plus a function | 422 | local make_generator = function(is_coro_, ...) |
398 | local gen = function(...) | ||
399 | local func, libs, opt = process_gen_opt(...) | 423 | local func, libs, opt = process_gen_opt(...) |
400 | local core_lane_new = assert(core.lane_new) | 424 | local core_lane_new = assert(core.lane_new) |
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] | 425 | local prio_is_native = opt.native_priority and true or false |
426 | local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority or opt.native_priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] | ||
402 | return function(...) | 427 | return function(...) |
403 | -- must pass functions args last else they will be truncated to the first one | 428 | -- must pass functions args last else they will be truncated to the first one |
404 | return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, false, ...) | 429 | return core_lane_new(func, libs, prio_is_native, priority, globals, package, required, gc_cb, name, error_trace_level, is_coro_, ...) |
405 | end | 430 | end |
431 | end -- make_generator | ||
432 | |||
433 | -- ################################################################################################# | ||
434 | |||
435 | -- receives a sequence of strings and tables, plus a function | ||
436 | local gen = function(...) | ||
437 | return make_generator(false, ...) | ||
406 | end -- gen() | 438 | end -- gen() |
407 | 439 | ||
440 | -- ################################################################################################# | ||
441 | |||
408 | local coro = function(...) | 442 | local coro = function(...) |
409 | local func, libs, opt = process_gen_opt(...) | 443 | return make_generator(true, ...) |
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() | 444 | end -- coro() |
417 | 445 | ||
418 | -- ################################################################################################# | 446 | -- ################################################################################################# |
@@ -603,7 +631,6 @@ local configure_timers = function() | |||
603 | return next_wakeup -- may be 'nil' | 631 | return next_wakeup -- may be 'nil' |
604 | end -- check_timers() | 632 | end -- check_timers() |
605 | 633 | ||
606 | local timer_gateway_batched = timerLinda.batched | ||
607 | set_finalizer(function(err, stk) | 634 | set_finalizer(function(err, stk) |
608 | if err and type(err) ~= "userdata" then | 635 | if err and type(err) ~= "userdata" then |
609 | error("LanesTimer error: "..tostring(err)) | 636 | error("LanesTimer error: "..tostring(err)) |
@@ -628,7 +655,7 @@ local configure_timers = function() | |||
628 | 655 | ||
629 | if _timerKey == TGW_KEY then | 656 | if _timerKey == TGW_KEY then |
630 | assert(getmetatable(_what) == "Linda") -- '_what' should be a linda on which the client sets a timer | 657 | assert(getmetatable(_what) == "Linda") -- '_what' should be a linda on which the client sets a timer |
631 | local _, key, wakeup_at, period = timerLinda:receive(0, timer_gateway_batched, TGW_KEY, 3) | 658 | local _, key, wakeup_at, period = timerLinda:receive_batched(0, TGW_KEY, 3) |
632 | assert(key) | 659 | assert(key) |
633 | set_timer(_what, key, wakeup_at, period and period > 0 and period or nil) | 660 | set_timer(_what, key, wakeup_at, period and period > 0 and period or nil) |
634 | elseif _timerKey == TGW_QUERY then | 661 | elseif _timerKey == TGW_QUERY then |
@@ -643,7 +670,8 @@ local configure_timers = function() | |||
643 | end | 670 | end |
644 | end | 671 | end |
645 | end -- timer_body() | 672 | end -- timer_body() |
646 | timer_lane = gen("lanes_core,table", { name = "LanesTimer", package = {}, priority = core.max_prio }, timer_body)() | 673 | local min_prio, max_prio = core.thread_priority_range() |
674 | timer_lane = gen("lanes_core,table", { name = "LanesTimer", package = {}, priority = max_prio }, timer_body)() | ||
647 | end -- first_time | 675 | end -- first_time |
648 | 676 | ||
649 | ----- | 677 | ----- |
@@ -758,7 +786,7 @@ local genlock = function(linda_, key_, N) | |||
758 | -- 'nil' timeout allows 'key_' to be numeric | 786 | -- 'nil' timeout allows 'key_' to be numeric |
759 | return linda_:send(timeout, key_, trues(M_)) -- suspends until been able to push them | 787 | return linda_:send(timeout, key_, trues(M_)) -- suspends until been able to push them |
760 | else | 788 | else |
761 | local _k, _v = linda_:receive(nil, linda_.batched, key_, -M_) | 789 | local _k, _v = linda_:receive_batched(nil, key_, -M_) |
762 | -- propagate cancel_error if we got it, else return true or false | 790 | -- propagate cancel_error if we got it, else return true or false |
763 | return (_v == cancel_error and _v) or (_k and true or false) | 791 | return (_v == cancel_error and _v) or (_k and true or false) |
764 | end | 792 | end |
@@ -863,6 +891,7 @@ local configure = function(settings_) | |||
863 | lanes.set_thread_affinity = core.set_thread_affinity | 891 | lanes.set_thread_affinity = core.set_thread_affinity |
864 | lanes.set_thread_priority = core.set_thread_priority | 892 | lanes.set_thread_priority = core.set_thread_priority |
865 | lanes.sleep = core.sleep | 893 | lanes.sleep = core.sleep |
894 | lanes.thread_priority_range = core.thread_priority_range | ||
866 | lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false | 895 | lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false |
867 | 896 | ||
868 | lanes.gen = gen | 897 | lanes.gen = gen |