// the lockFile muste be a file separate from any data files. // It is created & deleted by this class, and will always have // size 0. sclass FileBasedLock implements AutoCloseable { File lockFile; double timeout = 60.0; // in seconds. refresh happens twice as often bool verbose; bool haveLock; java.util.Timer touchTimer; *() {} *(File *lockFile) {} *(File *lockFile, double *timeout) {} // returns true iff lock was acquired (or kept) synchronized bool tryToLock() { if (haveLock) true; if (fileExists(lockFile)) { double age = fileAgeInSeconds(lockFile); if (verbose) print("Lock file age: " + lockFile + " = " + iround(age) + " s"); if (age >= timeout) { print("Deleting old lock file (program crashed?): " + lockFile + " (age: " + iround(age) + " seconds)"); deleteFile(lockFile); } } try { mkdirsForFile(lockFile); java.nio.file.Files.createFile(toPath(lockFile)); set haveLock; startTouchTimer(); true; } catch e { printExceptionShort(e); false; } } synchronized void startTouchTimer { if (touchTimer != null) ret; double interval = timeout/2; touchTimer = doEvery(interval, r doTouch); if (verbose) print("Touch timer started for " + lockFile + " (" + interval + "s)"); } synchronized void doTouch { if (haveLock) { if (verbose) print("Touching lock file: " + lockFile); touchExistingFile(lockFile); } } public synchronized void close() pcall { dispose touchTimer; if (haveLock) { haveLock = false; if (verbose) print("Deleting lock file: " + lockFile); deleteFile(lockFile); } } synchronized void _simulateCrash { dispose touchTimer; } }