rpuch commented on code in PR #4233:
URL: https://github.com/apache/ignite-3/pull/4233#discussion_r1718668058


##########
modules/core/src/main/java/org/apache/ignite/internal/util/VersatileReadWriteLock.java:
##########
@@ -0,0 +1,498 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+import org.apache.ignite.internal.tostring.S;
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * A versatile read-write lock that can be used both in synchronous and 
asynchronous contexts.
+ * Its blocking methods use the spinwait strategy. When they do so, they are 
not interruptible (that is, they do not break their loop on
+ * interruption signal).
+ *
+ * <p>The locks are NOT reentrant (that is, the same thread can NOT acquire 
the same lock a few times without releasing it).
+ *
+ * <p>Write lock acquire requests are prioritized over read lock acquire 
requests. That is, if both read and write lock
+ * acquire requests are received when the write lock is held by someone else, 
then, on its release, the write lock attempt will be served
+ * first.
+ *
+ * <p>Lock owners are not tracked.
+ *
+ * <p>Asynchronous locking methods may complete the futures either in the 
calling thread (if they were able to immediately acquire
+ * the requested lock) or in the supplied pool (if they had to wait for a 
release to happen before being able to satisfy the request).
+ *
+ * <p>Asynchronous locking methods never use spin loops. They do use CAS 
loops, but these are mostly very short.
+ */
+public class VersatileReadWriteLock {
+    /** The highest bit of the state signals that the write lock is acquired. 
*/
+    private static final int WRITE_LOCK_BITS = 1 << 31;
+
+    /** 31 lower bits represent a counter of read locks that qre acquired. */
+    private static final int READ_LOCK_BITS = ~WRITE_LOCK_BITS;
+
+    /**
+     * State 0 means that both read and write locks are available for 
acquiring (as no locks are acquired).
+     *
+     * @see #state
+     */
+    private static final int AVAILABLE = 0;
+
+    /** How much time to sleep on each iteration of a spin loop 
(milliseconds). */
+    private static final int SLEEP_MILLIS = 10;
+
+    /** {@link VarHandle} used to access the {@code pendingWLocks} field. */
+    private static final VarHandle PENDING_WLOCKS_VH;
+
+    /** {@link VarHandle} used to access the {@code state} field. */
+    private static final VarHandle STATE_VH;
+
+    static {
+        try {
+            STATE_VH = MethodHandles.lookup()
+                .findVarHandle(VersatileReadWriteLock.class, "state", 
int.class);
+
+            PENDING_WLOCKS_VH = MethodHandles.lookup()
+                .findVarHandle(VersatileReadWriteLock.class, 
"pendingWriteLocks", int.class);
+        } catch (ReflectiveOperationException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    /**
+     * Main state of the lock.
+     * <ul>
+     *     <li>The highest bit is for whether the write lock is acquired or 
not.</li>
+     *     <li>The remaining bits store a counter representing the acquired 
read locks.</li>
+     * </ul>
+     */
+    @SuppressWarnings("unused")
+    private volatile int state;
+
+    /**
+     * Number of pending write attempts to acquire the write lock. It is used 
to prioritize write lock attempts over read
+     * lock attempts when the write lock has been released (so, if both an 
attempt to acquire the write lock and an attempt to acquire the
+     * read lock are waiting for write lock to be released, a write lock 
attempt will be served first when the release happens).
+     */
+    @SuppressWarnings("unused")
+    private volatile int pendingWriteLocks;

Review Comment:
   Are you asking about `state` and `pendingWriteChecks`? They don't always get 
CASed together, so I don't see why we would want to merge them together.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to