diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index e7db35b4e..5cd4d83d9 100644 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -1695,9 +1695,7 @@ public final class ChronicleMapBuilder implements final AtomicBoolean newFile = new AtomicBoolean(); final FileChannel fileChannel = raf.getChannel(); - FileLockUtil.acquireExclusiveFileLock(canonicalFile, fileChannel); - - try { + FileLockUtil.runExclusively(canonicalFile, fileChannel, () -> { if (raf.length() == 0) { map.set(newMap()); headerBuffer.set(writeHeader(fileChannel, map.get())); @@ -1705,10 +1703,7 @@ public final class ChronicleMapBuilder implements } else { newFile.set(false); } - } - finally { - FileLockUtil.releaseFileLock(canonicalFile); - } + }); if (newFile.get()) { final int headerSize = headerBuffer.get().remaining(); diff --git a/src/main/java/net/openhft/chronicle/map/FileLockUtil.java b/src/main/java/net/openhft/chronicle/map/FileLockUtil.java index f8237ccc8..161877f77 100644 --- a/src/main/java/net/openhft/chronicle/map/FileLockUtil.java +++ b/src/main/java/net/openhft/chronicle/map/FileLockUtil.java @@ -90,36 +90,34 @@ public final class FileLockUtil { printWarningTheFirstTime(); } + /** + * Executes a closure under exclusive file lock. + * If USE_LOCKING is false, provides synchronization only within local JVM. + * + * @param fileIOAction Closure to run, can throw {@link IOException}s. + */ public static void runExclusively(@NotNull final File canonicalFile, @NotNull final FileChannel fileChannel, - @NotNull final Runnable fileIOAction) { - - // This method runs regardless of the USE_LOCKING flag since it is only used - // for initial map creation. This works on all platforms - - // Atomically acquire a FileLockReference - final FileLockReference fileLockRef = FILE_LOCKS.compute(canonicalFile, (f, flr) -> - { + @NotNull final FileIOAction fileIOAction) { + FILE_LOCKS.compute(canonicalFile, (f, flr) -> { if (flr != null) throw new ChronicleFileLockException("A file lock instance already exists for the file " + canonicalFile); + try { - return new FileLockReference(fileChannel.lock()); - } catch (IOException e) { - throw new ChronicleFileLockException(e); + if (USE_LOCKING) { + try (FileLock ignored = fileChannel.lock()) { + fileIOAction.fileIOAction(); + } + } else { + fileIOAction.fileIOAction(); + } + + return null; + } catch (Exception e) { + throw Jvm.rethrow(e); } } ); - - try { - fileIOAction.run(); - } finally { - try { - fileLockRef.release(); - } catch (Exception ignore) { - } finally { - FILE_LOCKS.remove(canonicalFile); - } - } } static void dump() { @@ -183,4 +181,9 @@ public final class FileLockUtil { '}'; } } + + @FunctionalInterface + interface FileIOAction { + void fileIOAction() throws IOException; + } } \ No newline at end of file