diff options
Diffstat (limited to 'src/lanes.lua')
-rw-r--r-- | src/lanes.lua | 79 |
1 files changed, 62 insertions, 17 deletions
diff --git a/src/lanes.lua b/src/lanes.lua index 252d151..8837e4b 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -39,11 +39,19 @@ THE SOFTWARE. | |||
39 | =============================================================================== | 39 | =============================================================================== |
40 | ]]-- | 40 | ]]-- |
41 | 41 | ||
42 | module( "lanes", package.seeall ) | 42 | -- Lua 5.1: module() creates a global variable |
43 | -- Lua 5.2: module() might go away | ||
44 | -- almost everything module() does is done by require() | ||
45 | -- -> simply create a table, populate it, return it, and be done | ||
46 | local lanes = {} | ||
47 | |||
48 | lanes.configure = function( _nb_keepers, _timers) | ||
43 | 49 | ||
44 | local mm = require "lua51-lanes" | 50 | local mm = require "lua51-lanes" |
45 | assert( type(mm)=="table" ) | 51 | assert( type(mm)=="table" ) |
46 | 52 | ||
53 | -- configure() is available only the first time lua51-lanes is required process-wide, and we *must* call it to have the other functions in the interface | ||
54 | if mm.configure then mm.configure( _nb_keepers) end | ||
47 | 55 | ||
48 | local thread_new = assert(mm.thread_new) | 56 | local thread_new = assert(mm.thread_new) |
49 | 57 | ||
@@ -140,6 +148,7 @@ end | |||
140 | -- | 148 | -- |
141 | -- .globals: table of globals to set for a new thread (passed by value) | 149 | -- .globals: table of globals to set for a new thread (passed by value) |
142 | -- | 150 | -- |
151 | -- .required: table of packages to require | ||
143 | -- ... (more options may be introduced later) ... | 152 | -- ... (more options may be introduced later) ... |
144 | -- | 153 | -- |
145 | -- Calling with a function parameter ('lane_func') ends the string/table | 154 | -- Calling with a function parameter ('lane_func') ends the string/table |
@@ -161,7 +170,8 @@ local valid_libs= { | |||
161 | ["*"]= true | 170 | ["*"]= true |
162 | } | 171 | } |
163 | 172 | ||
164 | function gen( ... ) | 173 | -- PUBLIC LANES API |
174 | local function gen( ... ) | ||
165 | local opt= {} | 175 | local opt= {} |
166 | local libs= nil | 176 | local libs= nil |
167 | local lev= 2 -- level for errors | 177 | local lev= 2 -- level for errors |
@@ -204,27 +214,34 @@ function gen( ... ) | |||
204 | end | 214 | end |
205 | end | 215 | end |
206 | 216 | ||
207 | local prio, cs, g_tbl, packagepath, packagecpath | 217 | local prio, cs, g_tbl, packagepath, packagecpath, required |
208 | 218 | ||
209 | for k,v in pairs(opt) do | 219 | for k,v in pairs(opt) do |
210 | if k=="priority" then prio= v | 220 | if k=="priority" then prio= v |
211 | elseif k=="cancelstep" then cs= (v==true) and 100 or | 221 | elseif k=="cancelstep" then |
212 | (v==false) and 0 or | 222 | cs = (v==true) and 100 or |
213 | type(v)=="number" and v or | 223 | (v==false) and 0 or |
214 | error( "Bad cancelstep: "..tostring(v), lev ) | 224 | type(v)=="number" and v or |
225 | error( "Bad cancelstep: "..tostring(v), lev ) | ||
215 | elseif k=="globals" then g_tbl= v | 226 | elseif k=="globals" then g_tbl= v |
216 | elseif k=="packagepath" then packagepath= v | 227 | elseif k=="packagepath" then |
217 | elseif k=="packagecpath" then packagecpath= v | 228 | packagepath = (type( v) == "string") and v or error( "Bad packagepath: " .. tostring( v), lev) |
229 | elseif k=="packagecpath" then | ||
230 | packagecpath = (type( v) == "string") and v or error( "Bad packagecpath: " .. tostring( v), lev) | ||
231 | elseif k=="required" then | ||
232 | required= (type( v) == "table") and v or error( "Bad required: " .. tostring( v), lev) | ||
218 | --.. | 233 | --.. |
219 | elseif k==1 then error( "unkeyed option: ".. tostring(v), lev ) | 234 | elseif k==1 then error( "unkeyed option: ".. tostring(v), lev ) |
220 | else error( "Bad option: ".. tostring(k), lev ) | 235 | else error( "Bad option: ".. tostring(k), lev ) |
221 | end | 236 | end |
222 | end | 237 | end |
223 | 238 | ||
239 | if not packagepath then packagepath = package.path end | ||
240 | if not packagecpath then packagecpath = package.cpath end | ||
224 | -- Lane generator | 241 | -- Lane generator |
225 | -- | 242 | -- |
226 | return function(...) | 243 | return function(...) |
227 | return thread_new( func, libs, cs, prio, g_tbl, packagepath, packagecpath, ...) -- args | 244 | return thread_new( func, libs, cs, prio, g_tbl, packagepath, packagecpath, required, ...) -- args |
228 | end | 245 | end |
229 | end | 246 | end |
230 | 247 | ||
@@ -235,12 +252,16 @@ end | |||
235 | ----- | 252 | ----- |
236 | -- lanes.linda() -> linda_ud | 253 | -- lanes.linda() -> linda_ud |
237 | -- | 254 | -- |
238 | linda = mm.linda | 255 | -- PUBLIC LANES API |
256 | local linda = mm.linda | ||
239 | 257 | ||
240 | 258 | ||
241 | ---=== Timers ===--- | 259 | ---=== Timers ===--- |
242 | local want_timers = true | 260 | |
243 | if want_timers then | 261 | -- PUBLIC LANES API |
262 | local timer = function() error "timers are not active" end | ||
263 | |||
264 | if _timers ~= "NO_TIMERS" then | ||
244 | 265 | ||
245 | local timer_gateway= assert( mm.timer_gateway ) | 266 | local timer_gateway= assert( mm.timer_gateway ) |
246 | -- | 267 | -- |
@@ -424,6 +445,8 @@ if first_time then | |||
424 | assert( key and wakeup_at and period ) | 445 | assert( key and wakeup_at and period ) |
425 | 446 | ||
426 | set_timer( linda, key, wakeup_at, period>0 and period or nil ) | 447 | set_timer( linda, key, wakeup_at, period>0 and period or nil ) |
448 | elseif secs == 0 then -- got no value while block-waiting? | ||
449 | WR( "timer lane: no linda, aborted?") | ||
427 | end | 450 | end |
428 | end | 451 | end |
429 | end )() | 452 | end )() |
@@ -432,7 +455,8 @@ end | |||
432 | ----- | 455 | ----- |
433 | -- = timer( linda_h, key_val, date_tbl|first_secs [,period_secs] ) | 456 | -- = timer( linda_h, key_val, date_tbl|first_secs [,period_secs] ) |
434 | -- | 457 | -- |
435 | function timer( linda, key, a, period ) | 458 | -- PUBLIC LANES API |
459 | timer = function( linda, key, a, period ) | ||
436 | 460 | ||
437 | if a==0.0 then | 461 | if a==0.0 then |
438 | -- Caller expects to get current time stamp in Linda, on return | 462 | -- Caller expects to get current time stamp in Linda, on return |
@@ -456,7 +480,7 @@ function timer( linda, key, a, period ) | |||
456 | timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period ) | 480 | timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period ) |
457 | end | 481 | end |
458 | 482 | ||
459 | end -- want_timers | 483 | end -- _timers |
460 | 484 | ||
461 | ---=== Lock & atomic generators ===--- | 485 | ---=== Lock & atomic generators ===--- |
462 | 486 | ||
@@ -473,7 +497,8 @@ end -- want_timers | |||
473 | -- Returns an access function that allows 'N' simultaneous entries between | 497 | -- Returns an access function that allows 'N' simultaneous entries between |
474 | -- acquire (+M) and release (-M). For binary locks, use M==1. | 498 | -- acquire (+M) and release (-M). For binary locks, use M==1. |
475 | -- | 499 | -- |
476 | function genlock( linda, key, N ) | 500 | -- PUBLIC LANES API |
501 | local function genlock( linda, key, N ) | ||
477 | linda:limit(key,N) | 502 | linda:limit(key,N) |
478 | linda:set(key,nil) -- clears existing data | 503 | linda:set(key,nil) -- clears existing data |
479 | 504 | ||
@@ -506,7 +531,8 @@ end | |||
506 | -- Returns an access function that allows atomic increment/decrement of the | 531 | -- Returns an access function that allows atomic increment/decrement of the |
507 | -- number in 'key'. | 532 | -- number in 'key'. |
508 | -- | 533 | -- |
509 | function genatomic( linda, key, initial_val ) | 534 | -- PUBLIC LANES API |
535 | local function genatomic( linda, key, initial_val ) | ||
510 | linda:limit(key,2) -- value [,true] | 536 | linda:limit(key,2) -- value [,true] |
511 | linda:set(key,initial_val or 0.0) -- clears existing data (also queue) | 537 | linda:set(key,initial_val or 0.0) -- clears existing data (also queue) |
512 | 538 | ||
@@ -522,4 +548,23 @@ end | |||
522 | 548 | ||
523 | -- newuserdata = mm.newuserdata | 549 | -- newuserdata = mm.newuserdata |
524 | 550 | ||
551 | -- activate full interface | ||
552 | lanes.gen = gen | ||
553 | lanes.linda = mm.linda | ||
554 | lanes.timer = timer | ||
555 | lanes.genlock = genlock | ||
556 | lanes.genatomic = genatomic | ||
557 | -- from now on, calling configure does nothing but checking that we don't call it with parameters that changed compared to the first invocation | ||
558 | lanes.configure = function( _nk, _t) | ||
559 | if _nk ~= _nb_keepers then | ||
560 | error( "mismatched configuration: " .. tostring( _nk) .. " keepers instead of " .. tostring( _nb_keepers)) | ||
561 | end | ||
562 | if _t ~= _timers then | ||
563 | error( "mismatched configuration: " .. tostring( _t) .. " timer activity instead of " .. tostring( _timers)) | ||
564 | end | ||
565 | end | ||
566 | end -- lanes.configure | ||
567 | |||
525 | --the end | 568 | --the end |
569 | return lanes | ||
570 | |||