Organized under this project.
NB.* mutex.ijs: implement mutual exclusion via file locking.
coclass 'mutex'
require 'task' NB. Only for "spawn" in "whoami" - not necessary.
fopen=: [:1!:21< NB. Open file named by y.
fclose=: [:1!:22< NB. Close file name or number y.
flock=: 1!:31 NB. File number, index, length of region to lock
funlock=: 1!:32 NB. File number, index, length of region to unlock
whlocks=: 1!:30 NB. Which locks - 3-cols: file #, index, and length
whfiles=: 1!:20 NB. Which files - 2-cols: file #; name
getpid=: 2!:6 NB. Current process ID
qts=: 6!:0 NB. Timestamp -integers: Y M D h m s.s (millisec?)
fwrix=: 1!:12 NB. Write to position (1{y) for file-id 0{y.
LOCKFL=: 'Lock.fl' NB. Central hold file
LFINFO=: (i.0);'' NB. Hold file details while holding
NB.* getMyInfo: nice to have info identifying who has the lock and when.
getMyInfo=: 3 : '100{.(;'' '',~&.>whoami''''),":(getpid,qts)'''''
NB.* getHold: put hold on lock file.
getHold=: 3 : 0
fid=. fopen LOCKFL [ myinfo=. getMyInfo ''
if. -. fid e. ;0{"1 whlocks '' do.
while. -.flock fid,0,100 do. wait 1 end.
myinfo fwrix fid;0
LFINFO=: fid (]{~[i.~[:;0{"1]) whfiles ''
end.
fid;myinfo
NB.EG 'fid myinfo'=. getHold '' NB. File ID, my ID info.
)
NB. funlock (>0{LFINFO) (]{~[i.~[:;0{"1]) whlocks ''
releaseHold=: 3 : 0
if. 0~:#>0{LFINFO do. 0*./ . =#&>LFINFO=: (i.0);'' [ fclose >0{LFINFO end.
)
NB.* getMUP: get Machine name, User ID, Process ID from my info string.
getMUP=: 13 : '3{.<;._1 '' '',y'
NB.* dsp: Despace - remove leading, trailing and redundant spaces.
dsp=: [:(#~(+.(1:|.(></\)))@(' '&~:))"1 (#~([:(+./\*. +./\.)' '&~:))"1
NB.* whoami: get machine and user ID - Windows only. This could be simply hard-coded as an alternative.
whoami=: 3 : 0
assert. 6-:9!:12 '' NB. Fail if not Windows
sess=. spawn 'net config workstation'
sess=. dsp&.><;._1 LF,sess-.CR NB. Vec of lines
sess=. ><;._1&.> ' ',&.>,sess NB. Mat of words
strs=. 'COMPUTER';<'USER' NB. Strings to key on
wh=. (<toupper&.>0{"1 sess)e.&.> <&.>strs NB. Which lines start w/ strings?
wh=. ;I.&.>(<(toupper&.>1{"1 sess)e. <'NAME')*.&.>wh
wh{2{"1 sess
NB.EG 'machine userid'=. whoami ''
)