8286597: Implement PollerProvider on AIX

Reviewed-by: mdoerr, alanb, vtewari
This commit is contained in:
Tyler Steele 2023-05-25 14:59:11 +00:00
parent e7edf8d145
commit 48d21bd089
6 changed files with 244 additions and 164 deletions

View File

@ -43,11 +43,11 @@ inline intptr_t* ContinuationHelper::frame_align_pointer(intptr_t* p) {
template<typename FKind>
inline void ContinuationHelper::update_register_map(const frame& f, RegisterMap* map) {
Unimplemented();
// Currently all registers are considered to be volatile and saved in the caller (java) frame if needed
}
inline void ContinuationHelper::update_register_map_with_callee(const frame& f, RegisterMap* map) {
Unimplemented();
// Currently all registers are considered to be volatile and saved in the caller (java) frame if needed
}
inline void ContinuationHelper::push_pd(const frame& f) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -27,6 +27,7 @@
package sun.nio.ch;
import java.nio.channels.spi.AsynchronousChannelProvider;
import sun.nio.ch.Pollset;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
@ -34,7 +35,6 @@ import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import jdk.internal.misc.Unsafe;
/**
* AsynchronousChannelGroup implementation based on the AIX pollset framework.
@ -42,33 +42,11 @@ import jdk.internal.misc.Unsafe;
final class AixPollPort
extends Port
{
private static final Unsafe unsafe = Unsafe.getUnsafe();
static {
IOUtil.load();
init();
Pollset.init();
}
/**
* struct pollfd {
* int fd;
* short events;
* short revents;
* }
*/
private static final int SIZEOF_POLLFD = eventSize();
private static final int OFFSETOF_EVENTS = eventsOffset();
private static final int OFFSETOF_REVENTS = reventsOffset();
private static final int OFFSETOF_FD = fdOffset();
// opcodes
private static final int PS_ADD = 0x0;
private static final int PS_MOD = 0x1;
private static final int PS_DELETE = 0x2;
// maximum number of events to poll at a time
private static final int MAX_POLL_EVENTS = 512;
// pollset ID
private final int pollset;
@ -88,6 +66,9 @@ final class AixPollPort
// address of the poll array passed to pollset_poll
private final long address;
// maximum number of events to poll at a time
private static final int MAX_EVENTS_TO_POLL = 512;
// encapsulates an event for a channel
static class Event {
final PollableChannel channel;
@ -142,16 +123,16 @@ final class AixPollPort
super(provider, pool);
// open pollset
this.pollset = pollsetCreate();
this.pollset = Pollset.pollsetCreate();
// create socket pair for wakeup mechanism
int[] sv = new int[2];
try {
socketpair(sv);
Pollset.socketpair(sv);
// register one end with pollset
pollsetCtl(pollset, PS_ADD, sv[0], Net.POLLIN);
Pollset.pollsetCtl(pollset, Pollset.PS_ADD, sv[0], Net.POLLIN);
} catch (IOException x) {
pollsetDestroy(pollset);
Pollset.pollsetDestroy(pollset);
throw x;
}
this.sp = sv;
@ -159,21 +140,21 @@ final class AixPollPort
// create socket pair for pollset control mechanism
sv = new int[2];
try {
socketpair(sv);
Pollset.socketpair(sv);
// register one end with pollset
pollsetCtl(pollset, PS_ADD, sv[0], Net.POLLIN);
Pollset.pollsetCtl(pollset, Pollset.PS_ADD, sv[0], Net.POLLIN);
} catch (IOException x) {
pollsetDestroy(pollset);
Pollset.pollsetDestroy(pollset);
throw x;
}
this.ctlSp = sv;
// allocate the poll array
this.address = allocatePollArray(MAX_POLL_EVENTS);
this.address = Pollset.allocatePollArray(MAX_EVENTS_TO_POLL);
// create the queue and offer the special event to ensure that the first
// threads polls
this.queue = new ArrayBlockingQueue<Event>(MAX_POLL_EVENTS);
this.queue = new ArrayBlockingQueue<Event>(MAX_EVENTS_TO_POLL);
this.queue.offer(NEED_TO_POLL);
}
@ -191,19 +172,19 @@ final class AixPollPort
return;
closed = true;
}
freePollArray(address);
close0(sp[0]);
close0(sp[1]);
close0(ctlSp[0]);
close0(ctlSp[1]);
pollsetDestroy(pollset);
Pollset.freePollArray(address);
Pollset.close0(sp[0]);
Pollset.close0(sp[1]);
Pollset.close0(ctlSp[0]);
Pollset.close0(ctlSp[1]);
Pollset.pollsetDestroy(pollset);
}
private void wakeup() {
void wakeup() {
if (wakeupCount.incrementAndGet() == 1) {
// write byte to socketpair to force wakeup
try {
interrupt(sp[1]);
Pollset.interrupt(sp[1]);
} catch (IOException x) {
throw new AssertionError(x);
}
@ -258,7 +239,7 @@ final class AixPollPort
controlQueue.add(ev);
// write byte to socketpair to force wakeup
try {
interrupt(ctlSp[1]);
Pollset.interrupt(ctlSp[1]);
} catch (IOException x) {
throw new AssertionError(x);
}
@ -299,9 +280,9 @@ final class AixPollPort
Iterator<ControlEvent> iter = controlQueue.iterator();
while (iter.hasNext()) {
ControlEvent ev = iter.next();
pollsetCtl(pollset, PS_DELETE, ev.fd(), 0);
Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, ev.fd(), 0);
if (!ev.removeOnly()) {
ev.setError(pollsetCtl(pollset, PS_MOD, ev.fd(), ev.events()));
ev.setError(Pollset.pollsetCtl(pollset, Pollset.PS_MOD, ev.fd(), ev.events()));
}
iter.remove();
}
@ -325,7 +306,8 @@ final class AixPollPort
int n;
controlLock.lock();
try {
n = pollsetPoll(pollset, address, MAX_POLL_EVENTS);
n = Pollset.pollsetPoll(pollset, address,
MAX_EVENTS_TO_POLL, Pollset.PS_NO_TIMEOUT);
} finally {
controlLock.unlock();
}
@ -338,14 +320,14 @@ final class AixPollPort
fdToChannelLock.readLock().lock();
try {
while (n-- > 0) {
long eventAddress = getEvent(address, n);
int fd = getDescriptor(eventAddress);
long eventAddress = Pollset.getEvent(address, n);
int fd = Pollset.getDescriptor(eventAddress);
// To emulate one shot semantic we need to remove
// the file descriptor here.
if (fd != sp[0] && fd != ctlSp[0]) {
synchronized (controlQueue) {
pollsetCtl(pollset, PS_DELETE, fd, 0);
Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, fd, 0);
}
}
@ -353,7 +335,7 @@ final class AixPollPort
if (fd == sp[0]) {
if (wakeupCount.decrementAndGet() == 0) {
// no more wakeups so drain pipe
drain1(sp[0]);
Pollset.drain1(sp[0]);
}
// queue special event if there are more events
@ -368,7 +350,7 @@ final class AixPollPort
// wakeup to process control event
if (fd == ctlSp[0]) {
synchronized (controlQueue) {
drain1(ctlSp[0]);
Pollset.drain1(ctlSp[0]);
processControlQueue();
}
if (n > 0) {
@ -379,7 +361,7 @@ final class AixPollPort
PollableChannel channel = fdToChannel.get(fd);
if (channel != null) {
int events = getRevents(eventAddress);
int events = Pollset.getRevents(eventAddress);
Event ev = new Event(channel, events);
// n-1 events are queued; This thread handles
@ -467,75 +449,4 @@ final class AixPollPort
}
}
}
/**
* Allocates a poll array to handle up to {@code count} events.
*/
private static long allocatePollArray(int count) {
return unsafe.allocateMemory(count * SIZEOF_POLLFD);
}
/**
* Free a poll array
*/
private static void freePollArray(long address) {
unsafe.freeMemory(address);
}
/**
* Returns event[i];
*/
private static long getEvent(long address, int i) {
return address + (SIZEOF_POLLFD*i);
}
/**
* Returns event->fd
*/
private static int getDescriptor(long eventAddress) {
return unsafe.getInt(eventAddress + OFFSETOF_FD);
}
/**
* Returns event->events
*/
private static int getEvents(long eventAddress) {
return unsafe.getChar(eventAddress + OFFSETOF_EVENTS);
}
/**
* Returns event->revents
*/
private static int getRevents(long eventAddress) {
return unsafe.getChar(eventAddress + OFFSETOF_REVENTS);
}
// -- Native methods --
private static native void init();
private static native int eventSize();
private static native int eventsOffset();
private static native int reventsOffset();
private static native int fdOffset();
private static native int pollsetCreate() throws IOException;
private static native int pollsetCtl(int pollset, int opcode, int fd, int events);
private static native int pollsetPoll(int pollset, long pollAddress, int numfds)
throws IOException;
private static native void pollsetDestroy(int pollset);
private static native void socketpair(int[] sv) throws IOException;
private static native void interrupt(int fd) throws IOException;
private static native void drain1(int fd) throws IOException;
private static native void close0(int fd);
}

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.ch;
import java.io.IOException;
import jdk.internal.misc.Unsafe;
public class Pollset {
private static final Unsafe unsafe = Unsafe.getUnsafe();
/**
* struct pollfd {
* int fd;
* short events;
* short revents;
* }
*/
public static final int SIZEOF_POLLFD = eventSize();
public static final int OFFSETOF_EVENTS = eventsOffset();
public static final int OFFSETOF_REVENTS = reventsOffset();
public static final int OFFSETOF_FD = fdOffset();
// opcodes
public static final int PS_ADD = 0x0;
public static final int PS_MOD = 0x1;
public static final int PS_DELETE = 0x2;
// event
public static final int PS_POLLPRI = 0x4;
// revent errcodes
public static final char PS_POLLNVAL = 0x8000;
public static final char PS_POLLERR = 0x4000;
public static final int PS_NO_TIMEOUT = -1;
/**
* Allocates a poll array to handle up to {@code count} events.
*/
public static long allocatePollArray(int count) {
return unsafe.allocateMemory(count * SIZEOF_POLLFD);
}
/**
* Free a poll array
*/
public static void freePollArray(long address) {
unsafe.freeMemory(address);
}
/**
* Returns event[i];
*/
public static long getEvent(long address, int i) {
return address + (SIZEOF_POLLFD * i);
}
/**
* Returns event->fd
*/
public static int getDescriptor(long eventAddress) {
return unsafe.getInt(eventAddress + OFFSETOF_FD);
}
/**
* Returns event->events
*/
public static int getEvents(long eventAddress) {
return unsafe.getChar(eventAddress + OFFSETOF_EVENTS);
}
/**
* Returns event->revents
*/
public static char getRevents(long eventAddress) {
return unsafe.getChar(eventAddress + OFFSETOF_REVENTS);
}
public static boolean isReventsError(long eventAddress) {
char revents = getRevents(eventAddress);
return (revents & PS_POLLNVAL) != 0 || (revents & PS_POLLERR) != 0;
}
// -- Native methods --
public static native int pollsetCreate() throws IOException;
public static native int pollsetCtl(int pollset, int opcode, int fd, int events);
public static native int pollsetPoll(int pollset, long pollAddress, int numfds, int timeout)
throws IOException;
public static native void pollsetDestroy(int pollset);
public static native void init();
public static native int eventSize();
public static native int eventsOffset();
public static native int reventsOffset();
public static native int fdOffset();
public static native void socketpair(int[] sv) throws IOException;
public static native void interrupt(int fd) throws IOException;
public static native void drain1(int fd) throws IOException;
public static native void close0(int fd);
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +26,8 @@
package sun.nio.ch;
import java.io.IOException;
import java.time.Instant;
import sun.nio.ch.Pollset;
/**
* Poller implementation based on the AIX Pollset library.
@ -32,32 +35,74 @@ import java.io.IOException;
class PollsetPoller extends Poller {
private static final int MAX_EVENTS_TO_POLL;
static {
Pollset.init(); /* Dynamically loads pollset C functions */
MAX_EVENTS_TO_POLL = 512;
}
private final int setid;
private final long pollBuffer;
PollsetPoller(boolean read) throws IOException {
super(read);
this.setid = Pollset.pollsetCreate();
this.pollBuffer = Pollset.allocatePollArray(MAX_EVENTS_TO_POLL);
}
@Override
int fdVal() {
// Stub
throw new UnsupportedOperationException("Unimplemented on AIX");
return setid;
}
@Override
void implRegister(int fdVal) throws IOException {
// Stub
throw new UnsupportedOperationException("Unimplemented on AIX");
void implRegister(int fd) throws IOException {
int ret = Pollset.pollsetCtl(setid, Pollset.PS_MOD, fd,
Pollset.PS_POLLPRI | (this.reading() ? Net.POLLIN : Net.POLLOUT));
if (ret != 0) {
throw new IOException("Unable to register fd " + fd);
}
}
@Override
void implDeregister(int fdVal) {
// Stub
throw new UnsupportedOperationException("Unimplemented on AIX");
void implDeregister(int fd) {
int ret = Pollset.pollsetCtl(setid, Pollset.PS_DELETE, fd, 0);
assert ret == 0;
}
/**
* Main poll method. The AIX Pollset library does not appear to pick up changes to the pollset
* (the set of fds being polled) while blocked on a call to this method. These changes happen
* regularly in the poll-loop thread and update thread from Poller.java.
* To address this difficulty, we break poll calls into 100ms sub-calls and emulate the timout.
*/
@Override
int poll(int timeout) throws IOException {
// Stub
throw new UnsupportedOperationException("Unimplemented on AIX");
int n;
switch (timeout) {
case 0:
n = pollInner(0);
break;
case Pollset.PS_NO_TIMEOUT:
do { n = pollInner(100); } while (n == 0);
break;
default:
Instant end = Instant.now().plusMillis(timeout);
do { n = pollInner(100); } while (n == 0 && Instant.now().isBefore(end));
break;
}
return n;
}
int pollInner(int subInterval) throws IOException {
int n = Pollset.pollsetPoll(setid, pollBuffer, MAX_EVENTS_TO_POLL, subInterval);
for (int i=0; i<n; i++) {
long eventAddress = Pollset.getEvent(pollBuffer, i);
int fd = Pollset.getDescriptor(eventAddress);
polled(fd);
}
return n;
}
}

View File

@ -29,17 +29,16 @@
#include "jvm.h"
#include "jlong.h"
#include "sun_nio_ch_AixPollPort.h"
#include "sun_nio_ch_Pollset.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>
#include <sys/pollset.h>
#include <fcntl.h>
#include <stddef.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <sys/pollset.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
/* Initially copied from src/solaris/native/sun/nio/ch/nio_util.h */
#define RESTARTABLE(_cmd, _result) do { \
@ -58,7 +57,7 @@ static pollset_ctl_func* _pollset_ctl = NULL;
static pollset_poll_func* _pollset_poll = NULL;
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_init(JNIEnv* env, jclass this) {
Java_sun_nio_ch_Pollset_init(JNIEnv* env, jclass this) {
_pollset_create = (pollset_create_func*) dlsym(RTLD_DEFAULT, "pollset_create");
_pollset_destroy = (pollset_destroy_func*) dlsym(RTLD_DEFAULT, "pollset_destroy");
_pollset_ctl = (pollset_ctl_func*) dlsym(RTLD_DEFAULT, "pollset_ctl");
@ -70,27 +69,27 @@ Java_sun_nio_ch_AixPollPort_init(JNIEnv* env, jclass this) {
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_eventSize(JNIEnv* env, jclass this) {
Java_sun_nio_ch_Pollset_eventSize(JNIEnv* env, jclass this) {
return sizeof(struct pollfd);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_eventsOffset(JNIEnv* env, jclass this) {
Java_sun_nio_ch_Pollset_eventsOffset(JNIEnv* env, jclass this) {
return offsetof(struct pollfd, events);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_reventsOffset(JNIEnv* env, jclass this) {
Java_sun_nio_ch_Pollset_reventsOffset(JNIEnv* env, jclass this) {
return offsetof(struct pollfd, revents);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_fdOffset(JNIEnv* env, jclass this) {
Java_sun_nio_ch_Pollset_fdOffset(JNIEnv* env, jclass this) {
return offsetof(struct pollfd, fd);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_pollsetCreate(JNIEnv *env, jclass c) {
Java_sun_nio_ch_Pollset_pollsetCreate(JNIEnv *env, jclass c) {
/* pollset_create can take the maximum number of fds, but we
* cannot predict this number so we leave it at OPEN_MAX. */
pollset_t ps = _pollset_create(-1);
@ -101,7 +100,7 @@ Java_sun_nio_ch_AixPollPort_pollsetCreate(JNIEnv *env, jclass c) {
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_pollsetCtl(JNIEnv *env, jclass c, jint ps,
Java_sun_nio_ch_Pollset_pollsetCtl(JNIEnv *env, jclass c, jint ps,
jint opcode, jint fd, jint events) {
struct poll_ctl event;
int res;
@ -116,26 +115,27 @@ Java_sun_nio_ch_AixPollPort_pollsetCtl(JNIEnv *env, jclass c, jint ps,
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_AixPollPort_pollsetPoll(JNIEnv *env, jclass c,
jint ps, jlong address, jint numfds) {
Java_sun_nio_ch_Pollset_pollsetPoll(JNIEnv *env, jclass c,
jint ps, jlong address, jint numfds, jint timeout) {
struct pollfd *events = jlong_to_ptr(address);
int res;
RESTARTABLE(_pollset_poll(ps, events, numfds, -1), res);
RESTARTABLE(_pollset_poll(ps, events, numfds, timeout), res);
if (res < 0) {
perror("pollset_poll failed");
JNU_ThrowIOExceptionWithLastError(env, "pollset_poll failed");
}
return res;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_pollsetDestroy(JNIEnv *env, jclass c, jint ps) {
Java_sun_nio_ch_Pollset_pollsetDestroy(JNIEnv *env, jclass c, jint ps) {
int res;
RESTARTABLE(_pollset_destroy((pollset_t)ps), res);
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
Java_sun_nio_ch_Pollset_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
int sp[2];
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
@ -148,7 +148,7 @@ Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv)
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
Java_sun_nio_ch_Pollset_interrupt(JNIEnv *env, jclass c, jint fd) {
int res;
int buf[1];
buf[0] = 1;
@ -159,7 +159,7 @@ Java_sun_nio_ch_AixPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
Java_sun_nio_ch_Pollset_drain1(JNIEnv *env, jclass cl, jint fd) {
int res;
char buf[1];
RESTARTABLE(read(fd, buf, 1), res);
@ -169,7 +169,7 @@ Java_sun_nio_ch_AixPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_AixPollPort_close0(JNIEnv *env, jclass c, jint fd) {
Java_sun_nio_ch_Pollset_close0(JNIEnv *env, jclass c, jint fd) {
int res;
RESTARTABLE(close(fd), res);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -97,9 +97,9 @@ public abstract class Poller {
*/
private void poll(int fdVal, long nanos, BooleanSupplier supplier) throws IOException {
if (USE_DIRECT_REGISTER) {
poll1(fdVal, nanos, supplier);
pollDirect(fdVal, nanos, supplier);
} else {
poll2(fdVal, nanos, supplier);
pollIndirect(fdVal, nanos, supplier);
}
}
@ -107,7 +107,7 @@ public abstract class Poller {
* Parks the current thread until a file descriptor is ready. This implementation
* registers the file descriptor, then parks until the file descriptor is polled.
*/
private void poll1(int fdVal, long nanos, BooleanSupplier supplier) throws IOException {
private void pollDirect(int fdVal, long nanos, BooleanSupplier supplier) throws IOException {
register(fdVal);
try {
boolean isOpen = supplier.getAsBoolean();
@ -128,7 +128,7 @@ public abstract class Poller {
* queues the file descriptor to the update thread, then parks until the file
* descriptor is polled.
*/
private void poll2(int fdVal, long nanos, BooleanSupplier supplier) {
private void pollIndirect(int fdVal, long nanos, BooleanSupplier supplier) {
Request request = registerAsync(fdVal);
try {
boolean isOpen = supplier.getAsBoolean();