Futex.java
/*
* junixsocket
*
* Copyright 2009-2026 Christian Kohlschütter
*
* Licensed 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.newsclub.net.unix.memory;
import java.io.Closeable;
import java.io.IOException;
import java.util.function.Supplier;
/**
* A generic Futex interface.
*
* @author Christian Kohlschütter
*/
interface Futex extends Closeable {
/**
* Tries to wait on the futex, if and as long as it has the value specified in {@code ifValue},
* for the given amount in milliseconds, or, if {@code timeoutMillis} is 0, for as long as the
* condition holds. Sporadic wakeups (with a return value of {@code false}) may occur.
*
* @param ifValue The expected value for this wait.
* @param timeoutMillis The timeout, in milliseconds, or 0 for "undetermined".
* @return {@code true} if the wait was successful (the value changed or {@link #tryWake(boolean)}
* was called), {@code false} otherwise.
* @throws IOException on error.
*/
boolean tryWait(int ifValue, int timeoutMillis) throws IOException;
/**
* Tries to wake waiting threads on the futex. If {@code wakeAll} is true, then all waiting
* threads are woken up, if not, then only one is woken up.
*
* @param wakeAll {@code true} if all waiting threads should be woken.
* @return {@code true} if we definitely woke some; {@code false} may indicate "we don't know".
* @throws IOException on error.
*/
boolean tryWake(boolean wakeAll) throws IOException;
/**
* Tries to wake any/all waiters on the futex for up to the given amount of time (in
* {@code timeoutMillis}), intermittently pausing for {@code pauseMillis}) to give other threads
* time to react, for as long as the timeout is not expired and {@code keepGoing} supplies
* {@code true}.
*
* @param wakeAll {@code true} if all waiting threads should be woken.
* @param timeoutMillis The maximum amount of time (in milliseconds) to try.
* @param pauseMillis While trying, pause this amount of milliseconds to give other threads time
* to react.
* @param keepGoing Keeps going unless this returns {@code true} or the timeout elapses.
* @return {@code false} If the timeout elapsed without either {@link #tryWake(boolean)} returns
* {@code true} or {@code keepGoing} returns {@code false}.
* @throws IOException on error.
* @throws InterruptedException on interrupt.
*/
default boolean tryWakeWithTimeout(boolean wakeAll, int timeoutMillis, int pauseMillis,
Supplier<Boolean> keepGoing) throws IOException, InterruptedException {
long end = System.currentTimeMillis() + timeoutMillis;
while (keepGoing.get() && !tryWake(wakeAll)) {
if (System.currentTimeMillis() >= end) {
return false;
} else {
Thread.sleep(pauseMillis);
}
}
return true;
}
/**
* Returns {@code true} if this {@link Futex} has been closed.
*
* @return {@code true} if closed.
*/
boolean isClosed();
/**
* Reports if this {@link Futex} can safely be accessed from multiple processes, or not. The
* actual way of accessing this {@link Futex} is unspecified, but typically this is coordinated
* via {@link SharedMemory}.
* <p>
* The value returned is constant.
*
* @return {@code true} if inter-process access is permitted.
*/
boolean isInterProcess();
}