From 704fbe74b6a8497b5bddf003fbb3637981d967eb Mon Sep 17 00:00:00 2001 From: pull-vert <5107035+pull-vert@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:32:59 +0100 Subject: [PATCH] BasicLock --- .../java/jayo/internal/RealBasicLock.java | 47 +++++++++++++++++++ .../main/java/jayo/internal/SegmentQueue.java | 4 +- .../main/java/jayo/internal/SimpleLock.java | 45 ------------------ core/src/main/java/jayo/tools/BasicLock.java | 44 +++++++++++++++++ 4 files changed, 93 insertions(+), 47 deletions(-) create mode 100644 core/src/main/java/jayo/internal/RealBasicLock.java delete mode 100644 core/src/main/java/jayo/internal/SimpleLock.java create mode 100644 core/src/main/java/jayo/tools/BasicLock.java diff --git a/core/src/main/java/jayo/internal/RealBasicLock.java b/core/src/main/java/jayo/internal/RealBasicLock.java new file mode 100644 index 0000000..7000284 --- /dev/null +++ b/core/src/main/java/jayo/internal/RealBasicLock.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025-present, pull-vert and Jayo contributors. + * Use of this source code is governed by the Apache 2.0 license. + */ + +package jayo.internal; + +import jayo.tools.BasicLock; +import org.jspecify.annotations.Nullable; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.concurrent.locks.LockSupport; + +public final class RealBasicLock implements BasicLock { + @SuppressWarnings("FieldMayBeFinal") + private volatile @Nullable Thread lockingThread = null; + + // VarHandle mechanics + private static final VarHandle LOCKING_THREAD; + + static { + try { + final var l = MethodHandles.lookup(); + LOCKING_THREAD = l.findVarHandle(RealBasicLock.class, "lockingThread", Thread.class); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } + + @Override + public void lock() { + final var lockingThread = (Thread) LOCKING_THREAD.getAndSetRelease(this, Thread.currentThread()); + if (lockingThread != null) { + LockSupport.park(); + } + } + + @Override + public void unlock() { + final var currentThread = Thread.currentThread(); + final var lockingThread = (Thread) LOCKING_THREAD.compareAndExchangeRelease(this, currentThread, null); + if (lockingThread != currentThread) { + LockSupport.unpark(lockingThread); + } + } +} diff --git a/core/src/main/java/jayo/internal/SegmentQueue.java b/core/src/main/java/jayo/internal/SegmentQueue.java index 2d50378..f88b815 100644 --- a/core/src/main/java/jayo/internal/SegmentQueue.java +++ b/core/src/main/java/jayo/internal/SegmentQueue.java @@ -5,6 +5,7 @@ package jayo.internal; +import jayo.tools.BasicLock; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; @@ -13,7 +14,6 @@ import java.util.Objects; import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.ToIntFunction; @@ -29,7 +29,7 @@ sealed class SegmentQueue implements AutoCloseable permits WriterSegmentQueue, R Segment head = null; @Nullable Segment tail = null; - final @NonNull Lock lock = new ReentrantLock(); + final @NonNull Lock lock = BasicLock.create(); private final @NonNull LongAdder size = new LongAdder(); diff --git a/core/src/main/java/jayo/internal/SimpleLock.java b/core/src/main/java/jayo/internal/SimpleLock.java deleted file mode 100644 index 37eee28..0000000 --- a/core/src/main/java/jayo/internal/SimpleLock.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2025-present, pull-vert and Jayo contributors. - * Use of this source code is governed by the Apache 2.0 license. - */ - -package jayo.internal; - -import org.jspecify.annotations.NonNull; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -final class SimpleLock implements Lock { - @Override - public void lock() { - - } - - @Override - public void unlock() { - - } - - @Override - public void lockInterruptibly() { - - } - - @Override - public boolean tryLock() { - return false; - } - - @Override - public boolean tryLock(long time, @NonNull TimeUnit unit) { - return false; - } - - @NonNull - @Override - public Condition newCondition() { - return null; - } -} diff --git a/core/src/main/java/jayo/tools/BasicLock.java b/core/src/main/java/jayo/tools/BasicLock.java new file mode 100644 index 0000000..32c4a5e --- /dev/null +++ b/core/src/main/java/jayo/tools/BasicLock.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025-present, pull-vert and Jayo contributors. + * Use of this source code is governed by the Apache 2.0 license. + */ + +package jayo.tools; + +import jayo.internal.RealBasicLock; +import org.jspecify.annotations.NonNull; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; + +/** + * A basic lock that only supports {@link #lock()} and {@link #unlock()}. It is not reentrant and only support 2 + * concurrent threads. + */ +public interface BasicLock extends Lock { + static BasicLock create() { + return new RealBasicLock(); + } + + @Override + default void lockInterruptibly() { + throw new UnsupportedOperationException(); + } + + @Override + default boolean tryLock() { + throw new UnsupportedOperationException(); + } + + @Override + default boolean tryLock(long time, @NonNull TimeUnit unit) { + throw new UnsupportedOperationException(); + } + + @NonNull + @Override + default Condition newCondition() { + throw new UnsupportedOperationException(); + } +}