diff options
Diffstat (limited to 'src/lanes.lua')
-rw-r--r-- | src/lanes.lua | 142 |
1 files changed, 87 insertions, 55 deletions
diff --git a/src/lanes.lua b/src/lanes.lua index e6400df..c9ab07d 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -40,55 +40,93 @@ THE SOFTWARE. | |||
40 | ]]-- | 40 | ]]-- |
41 | 41 | ||
42 | -- Lua 5.1: module() creates a global variable | 42 | -- Lua 5.1: module() creates a global variable |
43 | -- Lua 5.2: module() might go away | 43 | -- Lua 5.2: module() is gone |
44 | -- almost everything module() does is done by require() | 44 | -- almost everything module() does is done by require() anyway |
45 | -- -> simply create a table, populate it, return it, and be done | 45 | -- -> simply create a table, populate it, return it, and be done |
46 | local lanes = {} | 46 | local lanes = {} |
47 | 47 | ||
48 | lanes.configure = function( _params) | 48 | lanes.configure = function( _params) |
49 | _params = _params or { nb_keepers = 1, with_timers = true, on_state_create = nil} | ||
50 | if type( _params) ~= "table" then | ||
51 | error( "Bad parameter #1 to lanes.configure(), should be a table") | ||
52 | end | ||
53 | -- on_state_create may be nil or a function | ||
54 | if _params.on_state_create and (type( _params.on_state_create) ~= "function") then | ||
55 | error( "Bad on_state_create: " .. tostring( _params.on_state_create), 2) | ||
56 | end | ||
57 | 49 | ||
58 | local mm = require "lanes.core" | 50 | -- This check is for sublanes requiring Lanes |
59 | assert( type(mm)=="table" ) | 51 | -- |
52 | -- TBD: We could also have the C level expose 'string.gmatch' for us. But this is simpler. | ||
53 | -- | ||
54 | if not string then | ||
55 | error( "To use 'lanes', you will also need to have 'string' available.", 2) | ||
56 | end | ||
60 | 57 | ||
61 | -- configure() is available only the first time lanes.core is required process-wide, and we *must* call it to have the other functions in the interface | 58 | -- |
62 | if mm.configure then mm.configure( _params.nb_keepers, _params.on_state_create) end | 59 | -- Cache globals for code that might run under sandboxing |
60 | -- | ||
61 | local assert = assert | ||
62 | local string_gmatch = assert( string.gmatch) | ||
63 | local select = assert( select) | ||
64 | local type = assert( type) | ||
65 | local pairs = assert( pairs) | ||
66 | local tostring = assert( tostring) | ||
67 | local error = assert( error) | ||
68 | |||
69 | local default_params = { nb_keepers = 1, on_state_create = nil, shutdown_timeout = 0.25, with_timers = true} | ||
70 | local param_checkers = | ||
71 | { | ||
72 | nb_keepers = function( _val) | ||
73 | -- nb_keepers should be a number > 0 | ||
74 | return type( _val) == "number" and _val > 0 | ||
75 | end, | ||
76 | with_timers = function( _val) | ||
77 | -- with_timers may be nil or boolean | ||
78 | return _val and type( _val) == "boolean" or true | ||
79 | end, | ||
80 | on_state_create = function( _val) | ||
81 | -- on_state_create may be nil or a function | ||
82 | return _val and type( _val) == "function" or true | ||
83 | end, | ||
84 | shutdown_timeout = function( _val) | ||
85 | -- nb_keepers should be a number >= 0 | ||
86 | return type( _val) == "number" and _val >= 0 | ||
87 | end | ||
88 | } | ||
63 | 89 | ||
64 | local thread_new = assert(mm.thread_new) | 90 | local params_checker = function( _params) |
91 | if not _params then | ||
92 | return default_params | ||
93 | end | ||
94 | if type( _params) ~= "table" then | ||
95 | error( "Bad parameter #1 to lanes.configure(), should be a table") | ||
96 | end | ||
97 | -- any setting not present in the provided parameters takes the default value | ||
98 | for key, value in pairs( default_params) do | ||
99 | local my_param = _params[key] | ||
100 | local param | ||
101 | if my_param ~= nil then | ||
102 | param = my_param | ||
103 | else | ||
104 | param = default_params[key] | ||
105 | end | ||
106 | if not param_checkers[key]( param) then | ||
107 | error( "Bad " .. key .. ": " .. tostring( param), 2) | ||
108 | end | ||
109 | _params[key] = param | ||
110 | end | ||
111 | return _params | ||
112 | end | ||
65 | 113 | ||
66 | local _single= assert(mm._single) | 114 | _params = params_checker( _params) |
67 | local _version= assert(mm._version) | ||
68 | 115 | ||
69 | local now_secs= assert( mm.now_secs ) | 116 | local core = require "lanes.core" |
70 | local wakeup_conv= assert( mm.wakeup_conv ) | 117 | assert( type( core)=="table") |
71 | 118 | ||
72 | local max_prio= assert( mm.max_prio ) | 119 | -- configure() is available only the first time lanes.core is required process-wide, and we *must* call it to have the other functions in the interface |
120 | if core.configure then core.configure( _params.nb_keepers, _params.on_state_create, _params.shutdown_timeout) end | ||
73 | 121 | ||
74 | -- This check is for sublanes requiring Lanes | 122 | local thread_new = assert( core.thread_new) |
75 | -- | ||
76 | -- TBD: We could also have the C level expose 'string.gmatch' for us. But this is simpler. | ||
77 | -- | ||
78 | if not string then | ||
79 | error( "To use 'lanes', you will also need to have 'string' available.", 2 ) | ||
80 | end | ||
81 | 123 | ||
82 | -- | 124 | local set_singlethreaded = assert( core.set_singlethreaded) |
83 | -- Cache globals for code that might run under sandboxing | 125 | |
84 | -- | 126 | local now_secs = assert( core.now_secs) |
85 | local assert= assert | 127 | local wakeup_conv = assert( core.wakeup_conv) |
86 | local string_gmatch= assert( string.gmatch ) | 128 | |
87 | local select= assert( select ) | 129 | local max_prio = assert( core.max_prio) |
88 | local type= assert( type ) | ||
89 | local pairs= assert( pairs ) | ||
90 | local tostring= assert( tostring ) | ||
91 | local error= assert( error ) | ||
92 | 130 | ||
93 | lanes.ABOUT= | 131 | lanes.ABOUT= |
94 | { | 132 | { |
@@ -96,7 +134,7 @@ lanes.ABOUT= | |||
96 | description= "Running multiple Lua states in parallel", | 134 | description= "Running multiple Lua states in parallel", |
97 | license= "MIT/X11", | 135 | license= "MIT/X11", |
98 | copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-12, Benoit Germain", | 136 | copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-12, Benoit Germain", |
99 | version= _version, | 137 | version = assert( core.version) |
100 | } | 138 | } |
101 | 139 | ||
102 | 140 | ||
@@ -258,7 +296,7 @@ end | |||
258 | -- lanes.linda(["name"]) -> linda_ud | 296 | -- lanes.linda(["name"]) -> linda_ud |
259 | -- | 297 | -- |
260 | -- PUBLIC LANES API | 298 | -- PUBLIC LANES API |
261 | local linda = mm.linda | 299 | local linda = core.linda |
262 | 300 | ||
263 | 301 | ||
264 | ---=== Timers ===--- | 302 | ---=== Timers ===--- |
@@ -268,7 +306,7 @@ local timer = function() error "timers are not active" end | |||
268 | 306 | ||
269 | if _params.with_timers ~= false then | 307 | if _params.with_timers ~= false then |
270 | 308 | ||
271 | local timer_gateway= assert( mm.timer_gateway ) | 309 | local timer_gateway = assert( core.timer_gateway) |
272 | -- | 310 | -- |
273 | -- On first 'require "lanes"', a timer lane is spawned that will maintain | 311 | -- On first 'require "lanes"', a timer lane is spawned that will maintain |
274 | -- timer tables and sleep in between the timer events. All interaction with | 312 | -- timer tables and sleep in between the timer events. All interaction with |
@@ -558,28 +596,23 @@ local function genatomic( linda, key, initial_val ) | |||
558 | end | 596 | end |
559 | end | 597 | end |
560 | 598 | ||
561 | -- newuserdata = mm.newuserdata | ||
562 | |||
563 | -- activate full interface | 599 | -- activate full interface |
564 | lanes.gen = gen | 600 | lanes.gen = gen |
565 | lanes.linda = mm.linda | 601 | lanes.linda = core.linda |
566 | lanes.cancel_error = mm.cancel_error | 602 | lanes.cancel_error = core.cancel_error |
567 | lanes.nameof = mm.nameof | 603 | lanes.nameof = core.nameof |
568 | lanes.timer = timer | 604 | lanes.timer = timer |
569 | lanes.genlock = genlock | 605 | lanes.genlock = genlock |
570 | lanes.now_secs = now_secs | 606 | lanes.now_secs = now_secs |
571 | lanes.genatomic = genatomic | 607 | lanes.genatomic = genatomic |
572 | -- from now on, calling configure does nothing but checking that we don't call it with parameters that changed compared to the first invocation | 608 | -- from now on, calling configure does nothing but checking that we don't call it with parameters that changed compared to the first invocation |
573 | lanes.configure = function( _params2) | 609 | lanes.configure = function( _params2) |
574 | _params2 = _params2 or _params | 610 | _params2 = params_checker( _params2 or _params) |
575 | if _params2.nb_keepers ~= _params.nb_keepers then | 611 | for key, value2 in pairs( _params2) do |
576 | error( "mismatched configuration: " .. tostring( _params2.nb_keepers) .. " keepers instead of " .. tostring( _params.nb_keepers)) | 612 | local value = _params[key] |
577 | end | 613 | if value2 ~= value then |
578 | if _params2.with_timers ~= _params.with_timers then | 614 | error( "mismatched configuration: " .. key .. " is " .. tostring( value2) .. " instead of " .. tostring( value)) |
579 | error( "mismatched configuration: " .. tostring( _params2.with_timers) .. " timer activity instead of " .. tostring( _params.with_timers)) | 615 | end |
580 | end | ||
581 | if _params2.on_create_state and _params2.on_create_state ~= _params.on_create_state then | ||
582 | error( "mismatched configuration: " .. tostring( _params2.on_create_state) .. " timer activity instead of " .. tostring( _params.on_create_state)) | ||
583 | end | 616 | end |
584 | return lanes | 617 | return lanes |
585 | end | 618 | end |
@@ -588,4 +621,3 @@ end -- lanes.configure | |||
588 | 621 | ||
589 | --the end | 622 | --the end |
590 | return lanes | 623 | return lanes |
591 | |||