aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/lanes.lua')
-rw-r--r--src/lanes.lua187
1 files changed, 104 insertions, 83 deletions
diff --git a/src/lanes.lua b/src/lanes.lua
index 5dfe41d..57aa0fe 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -56,8 +56,9 @@ lanes.configure = function( settings_)
56 -- 56 --
57 -- Cache globals for code that might run under sandboxing 57 -- Cache globals for code that might run under sandboxing
58 -- 58 --
59 local assert = assert 59 local assert = assert( assert)
60 local string_gmatch = assert( string.gmatch) 60 local string_gmatch = assert( string.gmatch)
61 local string_format = assert( string.format)
61 local select = assert( select) 62 local select = assert( select)
62 local type = assert( type) 63 local type = assert( type)
63 local pairs = assert( pairs) 64 local pairs = assert( pairs)
@@ -127,7 +128,7 @@ lanes.configure = function( settings_)
127 return settings 128 return settings
128 end 129 end
129 local settings = core.configure and core.configure( params_checker( settings_)) or core.settings 130 local settings = core.configure and core.configure( params_checker( settings_)) or core.settings
130 local thread_new = assert( core.thread_new) 131 local core_lane_new = assert( core.lane_new)
131 local max_prio = assert( core.max_prio) 132 local max_prio = assert( core.max_prio)
132 133
133lanes.ABOUT = 134lanes.ABOUT =
@@ -203,11 +204,9 @@ end
203-- ... (more options may be introduced later) ... 204-- ... (more options may be introduced later) ...
204-- 205--
205-- Calling with a function parameter ('lane_func') ends the string/table 206-- Calling with a function parameter ('lane_func') ends the string/table
206-- modifiers, and prepares a lane generator. One can either finish here, 207-- modifiers, and prepares a lane generator.
207-- and call the generator later (maybe multiple times, with different parameters)
208-- or add on actual thread arguments to also ignite the thread on the same call.
209 208
210local valid_libs= 209local valid_libs =
211{ 210{
212 ["package"] = true, 211 ["package"] = true,
213 ["table"] = true, 212 ["table"] = true,
@@ -223,88 +222,110 @@ local valid_libs=
223 ["lanes.core"] = true 222 ["lanes.core"] = true
224} 223}
225 224
225local raise_option_error = function( name_, tv_, v_)
226 error( "Bad '" .. name_ .. "' option: " .. tv_ .. " " .. string_format( "%q", tostring( v_)), 4)
227end
228
229local opt_validators =
230{
231 priority = function( v_)
232 local tv = type( v_)
233 return (tv == "number") and v_ or raise_option_error( "priority", tv, v_)
234 end,
235 cancelstep = function( v_)
236 local tv = type( v_)
237 return (tv == "number") and v_ or (v_ == true) and 100 or (v_ == false) and 0 or raise_option_error( "cancelstep", tv, v_)
238 end,
239 globals = function( v_)
240 local tv = type( v_)
241 return (tv == "table") and v_ or raise_option_error( "globals", tv, v_)
242 end,
243 package = function( v_)
244 local tv = type( v_)
245 return (tv == "table") and v_ or raise_option_error( "package", tv, v_)
246 end,
247 required = function( v_)
248 local tv = type( v_)
249 return (tv == "table") and v_ or raise_option_error( "required", tv, v_)
250 end,
251 gc_cb = function( v_)
252 local tv = type( v_)
253 return (tv == "function") and v_ or raise_option_error( "gc_cb", tv, v_)
254 end
255}
256
226-- PUBLIC LANES API 257-- PUBLIC LANES API
227local function gen( ... ) 258-- receives a sequence of strings and tables, plus a function
228 local opt= {} 259local gen = function( ...)
229 local libs= nil 260 -- aggregrate all strings together, separated by "," as well as tables
230 local lev= 2 -- level for errors 261 -- the strings are a list of libraries to open
231 262 -- the tables contain the lane options
232 local n= select('#',...) 263 local opt = {}
233 264 local libs = nil
234 if n==0 then 265
235 error( "No parameters!" ) 266 local n = select( '#', ...)
236 end 267
268 -- we need at least a function
269 if n == 0 then
270 error( "No parameters!", 2)
271 end
237 272
238 for i=1,n-1 do 273 -- all arguments but the last must be nil, strings, or tables
239 local v= select(i,...) 274 for i = 1, n - 1 do
240 if type(v)=="string" then 275 local v = select( i, ...)
241 libs= libs and libs..","..v or v 276 local tv = type( v)
242 elseif type(v)=="table" then 277 if tv == "string" then
243 for k,vv in pairs(v) do 278 libs = libs and libs .. "," .. v or v
244 opt[k]= vv 279 elseif tv == "table" then
245 end 280 for k, vv in pairs( v) do
246 elseif v==nil then 281 opt[k]= vv
247 -- skip 282 end
248 else 283 elseif v == nil then
249 error( "Bad parameter: "..tostring(v) ) 284 -- skip
250 end 285 else
251 end 286 error( "Bad parameter " .. i .. ": " .. tv .. " " .. string_format( "%q", tostring( v)), 2)
287 end
288 end
252 289
253 local func= select(n,...) 290 -- the last argument should be a function or a string
254 local functype = type(func) 291 local func = select( n, ...)
255 if functype ~= "function" and functype ~= "string" then 292 local functype = type( func)
256 error( "Last parameter not function or string: "..tostring(func)) 293 if functype ~= "function" and functype ~= "string" then
257 end 294 error( "Last parameter not function or string: " .. functype .. " " .. string_format( "%q", tostring( func)), 2)
295 end
258 296
259 -- Check 'libs' already here, so the error goes in the right place 297 -- check that the caller only provides reserved library names, and those only once
260 -- (otherwise will be noticed only once the generator is called) 298 -- "*" is a special case that doesn't require individual checking
261 -- "*" is a special case that doesn't require individual checking 299 if libs and libs ~= "*" then
262 -- 300 local found = {}
263 if libs and libs ~= "*" then 301 for s in string_gmatch(libs, "[%a%d.]+") do
264 local found = {} 302 if not valid_libs[s] then
265 -- check that the caller only provides reserved library names 303 error( "Bad library name: " .. s, 2)
266 for s in string_gmatch(libs, "[%a%d.]+") do 304 else
267 if not valid_libs[s] then 305 found[s] = (found[s] or 0) + 1
268 error( "Bad library name: " .. s) 306 if found[s] > 1 then
269 else 307 error( "libs specification contains '" .. s .. "' more than once", 2)
270 found[s] = (found[s] or 0) + 1 308 end
271 if found[s] > 1 then 309 end
272 error( "libs specification contains '" .. s .. "' more than once") 310 end
273 end 311 end
274 end
275 end
276 end
277
278 local prio, cs, g_tbl, package_tbl, required, gc_cb
279
280 for k,v in pairs(opt) do
281 if k == "priority" then
282 prio = (type( v) == "number") and v or error( "Bad 'prio' option: expecting number, got " .. type( v), lev)
283 elseif k=="cancelstep" then
284 cs = (v==true) and 100 or
285 (v==false) and 0 or
286 type(v)=="number" and v or
287 error( "Bad cancelstep: "..tostring(v), lev )
288 elseif k=="globals" then g_tbl= v
289 elseif k=="package" then
290 package_tbl = (type( v) == "table") and v or error( "Bad package: " .. tostring( v), lev)
291 elseif k=="required" then
292 required= (type( v) == "table") and v or error( "Bad 'required' option: expecting table, got " .. type( v), lev)
293 elseif k == "gc_cb" then
294 gc_cb = (type( v) == "function") and v or error( "Bad 'gc_cb' option: expecting function, got " .. type( v), lev)
295 --..
296 elseif k==1 then error( "unkeyed option: ".. tostring(v), lev )
297 else error( "Bad option: ".. tostring(k), lev )
298 end
299 end
300 312
301 if not package_tbl then package_tbl = package end 313 -- validate that each option is known and properly valued
302 -- Lane generator 314 for k, v in pairs( opt) do
303 -- 315 local validator = opt_validators[k]
304 return function(...) 316 if not validator then
305 return thread_new( func, libs, cs, prio, g_tbl, package_tbl, required, gc_cb, ...) -- args 317 error( (type( k) == "number" and "Unkeyed option: " .. type( v) .. " " .. string_format( "%q", tostring( v)) or "Bad '" .. tostring( k) .. "' option"), 2)
306 end 318 else
307end 319 opt[k] = validator( v)
320 end
321 end
322
323 local cancelstep, priority, globals, package, required, gc_cb = opt.cancelstep, opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb
324 return function( ...)
325 -- must pass functions args last else they will be truncated to the first one
326 return core_lane_new( func, libs, cancelstep, priority, globals, package, required, gc_cb, ...)
327 end
328end -- gen()
308 329
309---=== Timers ===--- 330---=== Timers ===---
310 331