11local class = require (' jls.lang.class' )
2+ local system = require (' jls.lang.system' )
3+
4+ local function read (file , offset )
5+ file :seek (' set' , offset )
6+ local s = file :read (1 )
7+ if s then
8+ return (string.byte (s ))
9+ end
10+ return 0
11+ end
12+
13+ local function write (file , offset , value )
14+ file :seek (' set' , offset )
15+ file :write (string.char (value ))
16+ file :flush ()
17+ end
18+
19+ local MAX_ID = 2
20+
21+ local function getId (self )
22+ return self .initialized and 0 or 1
23+ end
24+
25+ local function softUnlock (file , id )
26+ write (file , MAX_ID + id , 0 )
27+ end
28+
29+ -- From Lamport's bakery algorithm
30+ local function softLock (file , id , try )
31+ local max = 0
32+ write (file , id , 1 )
33+ for j = MAX_ID , MAX_ID * 2 - 1 do
34+ max = math.max (max , read (file , j ))
35+ end
36+ local tic = 1 + max ;
37+ write (file , MAX_ID + id , tic )
38+ write (file , id , 0 )
39+ -- print(string.format("mutex_soft_init(%s, %s) max: %d", id, try, max));
40+ if try and max ~= 0 then
41+ softUnlock (file , id )
42+ return false
43+ end
44+ for i = 0 , MAX_ID - 1 do
45+ if i ~= id then
46+ while read (file , i ) == 1 do
47+ system .sleep (0 )
48+ end
49+ local j = MAX_ID + i
50+ while true do
51+ local cur = read (file , j )
52+ if cur ~= 0 and (cur < tic or (cur == tic and i < id )) then
53+ system .sleep (0 )
54+ else
55+ break
56+ end
57+ end
58+ end
59+ end
60+ return true
61+ end
262
363return class .create (function (lock )
464
565 function lock :initialize ()
666 self .name = string.format (' .%s-%p.tmp' , ' jls.lang.Lock' , self )
767 self .file = io.open (self .name , ' w+' )
868 self .initialized = true
69+ self .file :write (string.rep (' \0 ' , MAX_ID * 2 ))
70+ self .file :flush ()
971 end
1072
1173 function lock :finalize ()
@@ -17,33 +79,15 @@ return class.create(function(lock)
1779 end
1880
1981 function lock :lock ()
20- local b
21- repeat
22- self .file :seek (' set' )
23- b = self .file :read (1 )
24- -- we may want to sleep in case of multiple failures
25- until b ~= ' l'
26- self .file :seek (' set' )
27- self .file :write (' l' )
28- self .file :flush ()
82+ softLock (self .file , getId (self ), false )
2983 end
3084
3185 function lock :unlock ()
32- self .file :seek (' set' )
33- self .file :write (' ' )
34- self .file :flush ()
86+ softUnlock (self .file , getId (self ))
3587 end
3688
3789 function lock :tryLock ()
38- self .file :seek (' set' )
39- local b = self .file :read (1 )
40- if b == ' l' then
41- return false
42- end
43- self .file :seek (' set' )
44- self .file :write (' l' )
45- self .file :flush ()
46- return true
90+ return softLock (self .file , getId (self ), true )
4791 end
4892
4993 function lock :toReference ()
0 commit comments