objectifying queues

This commit is contained in:
Axel Kittenberger 2016-12-14 16:29:33 +01:00
parent d8b565ae02
commit 9e647f8113
1 changed files with 184 additions and 70 deletions

View File

@ -295,163 +295,275 @@ end )( )
-- A queue is optimized for pushing and poping. -- A queue is optimized for pushing and poping.
-- TODO: make this an object -- TODO: make this an object
-- --
Queue = ( function( ) Queue = ( function
( )
--
-- Metatable
--
local mt = { }
-- --
-- Creates a new queue. -- Key to native table
-- --
local function new local k_nt = { }
( )
return {
first = 1, --
last = 0, -- On accessing a nil index.
size = 0 --
}; mt.__index = function
(
t, -- table being accessed
k -- key used to access
)
if type( k ) ~= 'number'
then
error( 'Key "' .. k .. '" invalid for Queue', 2 )
end
return t[ k_nt ][ k ]
end end
--
-- On assigning a new index.
--
mt.__newindex = function
(
t, -- table getting a new index assigned
k, -- key value to assign to
v -- value to assign
)
error( 'Queues are not directly assignable.', 2 )
end
--
-- Returns the first item of the Queue.
--
local function first
(
self
)
local nt = self[ k_nt ]
return nt[ nt.first ]
end
--
-- Returns the last item of the Queue.
--
local function last
(
self
)
local nt = self[ k_nt ]
return nt[ nt.last ]
end
--
-- Returns the size of the queue.
--
local function size
(
self
)
return self[ k_nt ].size
end
-- --
-- Pushes a value on the queue. -- Pushes a value on the queue.
-- Returns the last value -- Returns the last value
-- --
local function push local function push
( (
list, -- list to push to self, -- queue to push to
value -- value to push value -- value to push
) )
if not value if not value
then then
error('Queue pushing nil value', 2) error( 'Queue pushing nil value', 2 )
end end
local last = list.last + 1 local nt = self[ k_nt ]
list.last = last local last = nt.last + 1
list[ last ] = value nt.last = last
list.size = list.size + 1 nt[ last ] = value
nt.size = nt.size + 1
return last return last
end end
-- --
-- Removes an item at pos from the Queue. -- Removes an item at pos from the Queue.
-- --
local function remove local function remove
( (
list, -- the queue self, -- the queue
pos pos -- position to remove
) )
if list[ pos ] == nil local nt = self[ k_nt ]
if nt[ pos ] == nil
then then
error( 'Removing nonexisting item in Queue', 2 ) error( 'Removing nonexisting item in Queue', 2 )
end end
list[ pos ] = nil nt[ pos ] = nil
-- if removing first or last element, -- if removing first or last element,
-- the queue limits are adjusted. -- the queue limits are adjusted.
if pos == list.first if pos == nt.first
then then
local last = list.last local last = nt.last
while list[ pos ] == nil and pos <= list.last while nt[ pos ] == nil and pos <= last
do do
pos = pos + 1 pos = pos + 1
end end
list.first = pos nt.first = pos
elseif pos == list.last elseif pos == nt.last
then then
while list[ pos ] == nil and pos >= list.first local first = nt.firt
while nt[ pos ] == nil and pos >= first
do do
pos = pos - 1 pos = pos - 1
end end
list.last = pos nt.last = pos
end end
-- reset the indizies if the queue is empty -- reset the indizies if the queue is empty
if list.last < list.first if nt.last < nt.first
then then
list.first = 1 nt.first = 1
list.last = 0 nt.last = 0
end end
list.size = list.size - 1 nt.size = nt.size - 1
end end
-- --
-- Queue iterator ( stateless ) -- Queue iterator ( stateless )
-- TODO rename next
-- --
local function iter local function iter
( (
list, -- list to iterate self, -- queue to iterate
pos -- position in the list pos -- current position
) )
local nt = self[ k_nt ]
pos = pos + 1 pos = pos + 1
while list[ pos ] == nil and pos <= list.last while nt[ pos ] == nil and pos <= nt.last
do do
pos = pos + 1 pos = pos + 1
end end
if pos > list.last if pos > nt.last
then then
return nil return nil
end end
return pos, list[ pos ] return pos, nt[ pos ]
end end
-- --
-- Reverse queue iterator (stateless) -- Reverse queue iterator (stateless)
-- TODO rename prev
-- --
local function iterReverse local function iterReverse
( (
list, -- list to iterate self, -- queue to iterate
pos -- position in the list pos -- current position
) )
local nt = self[ k_nt ]
pos = pos - 1 pos = pos - 1
while list[pos] == nil and pos >= list.first while nt[ pos ] == nil and pos >= nt.first
do do
pos = pos - 1 pos = pos - 1
end end
if pos < list.first if pos < nt.first
then then
return nil return nil
end end
return pos, list[ pos ] return pos, nt[ pos ]
end end
-- --
-- Iteraters through the queue -- Iteraters through the queue
-- returning all non-nil pos-value entries. -- returning all non-nil pos-value entries.
-- --
local function qpairs( list ) local function qpairs
return iter, list, list.first - 1 (
self
)
return iter, self, self[ k_nt ].first - 1
end end
-- --
-- Iteraters backwards through the queue -- Iteraters backwards through the queue
-- returning all non-nil pos-value entries. -- returning all non-nil pos-value entries.
-- --
local function qpairsReverse( list ) local function qpairsReverse
return iterReverse, list, list.last + 1 (
self
)
return iterReverse, self, self[ k_nt ].last + 1
end
--
-- Creates a new queue.
--
local function new
( )
local q = {
first = first,
last = last,
push = push,
qpairs = qpairs,
qpairsReverse = qpairsReverse,
remove = remove,
size = size,
[ k_nt ] =
{
first = 1,
last = 0,
size = 0
}
}
setmetatable( q, mt )
return q
end end
return { --
new = new, -- Public interface
push = push, --
remove = remove, return { new = new }
qpairs = qpairs,
qpairsReverse = qpairsReverse
}
end )( ) end )( )
@ -1886,10 +1998,10 @@ local Sync = ( function
) )
if self.delays[ delay.dpos ] ~= delay if self.delays[ delay.dpos ] ~= delay
then then
error( 'Queue is broken, delay not a dpos' ) error( 'Queue is broken, delay not at dpos' )
end end
Queue.remove( self.delays, delay.dpos ) self.delays:remove( delay.dpos )
-- frees all delays blocked by this one. -- frees all delays blocked by this one.
if delay.blocks if delay.blocks
@ -2237,12 +2349,12 @@ local Sync = ( function
' event.' ' event.'
) )
if self.delays.size > 0 if self.delays:size( ) > 0
then then
stack( self.delays[ self.delays.last ], nd ) stack( self.delays:last( ), nd )
end end
nd.dpos = Queue.push( self.delays, nd ) nd.dpos = self.delays:push( nd )
recurse( ) recurse( )
@ -2251,7 +2363,7 @@ local Sync = ( function
-- detects blocks and combos by working from back until -- detects blocks and combos by working from back until
-- front through the fifo -- front through the fifo
for il, od in Queue.qpairsReverse( self.delays ) for il, od in self.delays:qpairsReverse( )
do do
-- asks Combiner what to do -- asks Combiner what to do
local ac = Combiner.combine( od, nd ) local ac = Combiner.combine( od, nd )
@ -2260,17 +2372,18 @@ local Sync = ( function
then then
if ac == 'remove' if ac == 'remove'
then then
Queue.remove( self.delays, il ) self.delays:remove( il )
elseif ac == 'stack' elseif ac == 'stack'
then then
stack( od, nd ) stack( od, nd )
nd.dpos = Queue.push( self.delays, nd ) nd.dpos = self.delays:push( nd )
elseif ac == 'absorb' elseif ac == 'absorb'
then then
-- nada -- nada
elseif ac == 'replace' elseif ac == 'replace'
then then
-- TODO make this more elegant
od.etype = nd.etype od.etype = nd.etype
od.path = nd.path od.path = nd.path
od.path2 = nd.path2 od.path2 = nd.path2
@ -2299,7 +2412,7 @@ local Sync = ( function
end end
-- no block or combo -- no block or combo
nd.dpos = Queue.push( self.delays, nd ) nd.dpos = self.delays:push( nd )
recurse( ) recurse( )
end end
@ -2320,7 +2433,7 @@ local Sync = ( function
if self.processes:size( ) < self.config.maxProcesses if self.processes:size( ) < self.config.maxProcesses
then then
-- finds the nearest delay waiting to be spawned -- finds the nearest delay waiting to be spawned
for _, d in Queue.qpairs( self.delays ) for _, d in self.delays:qpairs( )
do do
if d.status == 'wait' if d.status == 'wait'
then then
@ -2365,7 +2478,7 @@ local Sync = ( function
end end
end end
for _, d in Queue.qpairs( self.delays ) for _, d in self.delays:qpairs( )
do do
if d.status == 'active' if d.status == 'active'
or ( test and not test( InletFactory.d2e( d ) ) ) or ( test and not test( InletFactory.d2e( d ) ) )
@ -2404,7 +2517,7 @@ local Sync = ( function
return return
end end
for _, d in Queue.qpairs( self.delays ) for _, d in self.delays:qpairs( )
do do
-- if reached the global limit return -- if reached the global limit return
if uSettings.maxProcesses if uSettings.maxProcesses
@ -2415,7 +2528,7 @@ local Sync = ( function
return return
end end
if self.delays.size < self.config.maxDelays if self.delays:size( ) < self.config.maxDelays
then then
-- time constrains are only concerned if not maxed -- time constrains are only concerned if not maxed
-- the delay FIFO already. -- the delay FIFO already.
@ -2453,9 +2566,9 @@ local Sync = ( function
self, self,
timestamp timestamp
) )
for i, d in Queue.qpairs( self.delays ) for i, d in self.delays:qpairs( )
do do
if self.delays.size < self.config.maxDelays if self.delays:size( ) < self.config.maxDelays
then then
-- time constrains are only concerned if not maxed -- time constrains are only concerned if not maxed
-- the delay FIFO already. -- the delay FIFO already.
@ -2485,7 +2598,7 @@ local Sync = ( function
) )
local newd = Delay.new( 'Blanket', self, true, '' ) local newd = Delay.new( 'Blanket', self, true, '' )
newd.dpos = Queue.push( self.delays, newd ) newd.dpos = self.delays:push( newd )
return newd return newd
end end
@ -2500,7 +2613,7 @@ local Sync = ( function
) )
local newd = Delay.new( 'Init', self, true, '' ) local newd = Delay.new( 'Init', self, true, '' )
newd.dpos = Queue.push( self.delays, newd ) newd.dpos = self.delays:push( newd )
return newd return newd
end end
@ -2517,11 +2630,12 @@ local Sync = ( function
f:write( self.config.name, ' source=', self.source, '\n' ) f:write( self.config.name, ' source=', self.source, '\n' )
f:write( 'There are ', self.delays.size, ' delays\n') f:write( 'There are ', self.delays:size( ), ' delays\n')
for i, vd in Queue.qpairs( self.delays ) for i, vd in self.delays:qpairs( )
do do
local st = vd.status local st = vd.status
f:write( st, string.sub( spaces, 1, 7 - #st ) ) f:write( st, string.sub( spaces, 1, 7 - #st ) )
f:write( vd.etype, ' ' ) f:write( vd.etype, ' ' )
f:write( vd.path ) f:write( vd.path )