Skip to content

Commit

Permalink
Enhance soft lock
Browse files Browse the repository at this point in the history
  • Loading branch information
javalikescript committed Sep 7, 2024
1 parent 0ca3f09 commit 38c5a60
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 21 deletions.
86 changes: 65 additions & 21 deletions jls/lang/Lock-.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,73 @@
local class = require('jls.lang.class')
local system = require('jls.lang.system')

local function read(file, offset)
file:seek('set', offset)
local s = file:read(1)
if s then
return (string.byte(s))
end
return 0
end

local function write(file, offset, value)
file:seek('set', offset)
file:write(string.char(value))
file:flush()
end

local MAX_ID = 2

local function getId(self)
return self.initialized and 0 or 1
end

local function softUnlock(file, id)
write(file, MAX_ID + id, 0)
end

-- From Lamport's bakery algorithm
local function softLock(file, id, try)
local max = 0
write(file, id, 1)
for j = MAX_ID, MAX_ID * 2 - 1 do
max = math.max(max, read(file, j))
end
local tic = 1 + max;
write(file, MAX_ID + id, tic)
write(file, id, 0)
--print(string.format("mutex_soft_init(%s, %s) max: %d", id, try, max));
if try and max ~= 0 then
softUnlock(file, id)
return false
end
for i = 0, MAX_ID - 1 do
if i ~= id then
while read(file, i) == 1 do
system.sleep(0)
end
local j = MAX_ID + i
while true do
local cur = read(file, j)
if cur ~= 0 and (cur < tic or (cur == tic and i < id)) then
system.sleep(0)
else
break
end
end
end
end
return true
end

return class.create(function(lock)

function lock:initialize()
self.name = string.format('.%s-%p.tmp', 'jls.lang.Lock', self)
self.file = io.open(self.name, 'w+')
self.initialized = true
self.file:write(string.rep('\0', MAX_ID * 2))
self.file:flush()
end

function lock:finalize()
Expand All @@ -17,33 +79,15 @@ return class.create(function(lock)
end

function lock:lock()
local b
repeat
self.file:seek('set')
b = self.file:read(1)
-- we may want to sleep in case of multiple failures
until b ~= 'l'
self.file:seek('set')
self.file:write('l')
self.file:flush()
softLock(self.file, getId(self), false)
end

function lock:unlock()
self.file:seek('set')
self.file:write(' ')
self.file:flush()
softUnlock(self.file, getId(self))
end

function lock:tryLock()
self.file:seek('set')
local b = self.file:read(1)
if b == 'l' then
return false
end
self.file:seek('set')
self.file:write('l')
self.file:flush()
return true
return softLock(self.file, getId(self), true)
end

function lock:toReference()
Expand Down
18 changes: 18 additions & 0 deletions jls/lang/Lock-buffer.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
--- Provides mutual exclusion for the threads in the current process.
-- @module jls.lang.Lock
-- @pragma nostrip

local class = require('jls.lang.class')

local bufferLib = require('buffer')
assert(type(bufferLib.initmutex) == 'function', 'bad buffer lib version '..tostring(bufferLib._VERSION))

--- The Lock class.
-- @type Lock
return class.create(function(lock)

--- Creates a new Lock.
-- @function Lock:new
function lock:initialize()
self.mutex = bufferLib.newmutex()
bufferLib.initmutex(self.mutex)
Expand All @@ -18,24 +27,33 @@ return class.create(function(lock)
end
end

--- Acquires the lock, blocking if necessary.
function lock:lock()
bufferLib.lock(self.mutex)
end

--- Releases the lock.
function lock:unlock()
bufferLib.unlock(self.mutex)
end

--- Returns true if the lock has been acquired without blocking.
-- @treturn boolean true if the lock has been acquired
function lock:tryLock()
return bufferLib.trylock(self.mutex)
end

--- Returns a reference for this lock.
-- @treturn string a reference for this lock
function lock:toReference()
return bufferLib.toreference(self.mutex, nil, 'jls.lang.Lock')
end

end, function(Lock)

--- Returns a lock shared by the specified reference.
-- @tparam string reference the reference
-- @return The shared lock
function Lock.fromReference(reference)
local m = bufferLib.fromreference(reference, nil, 'jls.lang.Lock')
if type(m) ~= 'userdata' then
Expand Down

0 comments on commit 38c5a60

Please sign in to comment.