mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-03 06:35:31 +00:00
Merge branch 'master' of https://github.com/openjdk/jdk into feature/class-is-class-or-interface-1
This commit is contained in:
commit
8240dea2de
@ -2671,14 +2671,6 @@ LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
static inline void report_error(Thread* t, DWORD exception_code,
|
||||
address addr, void* siginfo, void* context) {
|
||||
VMError::report_and_die(t, exception_code, addr, siginfo, context);
|
||||
|
||||
// If UseOSErrorReporting, this will return here and save the error file
|
||||
// somewhere where we can find it in the minidump.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
JNIEXPORT
|
||||
LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
@ -2750,9 +2742,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
// Fatal red zone violation.
|
||||
overflow_state->disable_stack_red_zone();
|
||||
tty->print_raw_cr("An unrecoverable stack overflow has occurred.");
|
||||
report_error(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
VMError::report_and_die(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
}
|
||||
} else if (exception_code == EXCEPTION_ACCESS_VIOLATION) {
|
||||
if (in_java) {
|
||||
@ -2789,9 +2780,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
|
||||
if (stub != nullptr) return Handle_Exception(exceptionInfo, stub);
|
||||
}
|
||||
report_error(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
VMError::report_and_die(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
}
|
||||
|
||||
// Special care for fast JNI field accessors.
|
||||
@ -2803,9 +2793,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
}
|
||||
|
||||
// Stack overflow or null pointer exception in native code.
|
||||
report_error(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
VMError::report_and_die(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
} // /EXCEPTION_ACCESS_VIOLATION
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
@ -2873,8 +2862,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
#endif
|
||||
|
||||
if (should_report_error) {
|
||||
report_error(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
VMError::report_and_die(t, exception_code, pc, exception_record,
|
||||
exceptionInfo->ContextRecord);
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
@ -2894,8 +2883,8 @@ LONG WINAPI topLevelUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* excepti
|
||||
Thread* thread = Thread::current_or_null_safe();
|
||||
|
||||
if (exceptionCode != EXCEPTION_BREAKPOINT) {
|
||||
report_error(thread, exceptionCode, pc, exceptionInfo->ExceptionRecord,
|
||||
exceptionInfo->ContextRecord);
|
||||
VMError::report_and_die(thread, exceptionCode, pc, exceptionInfo->ExceptionRecord,
|
||||
exceptionInfo->ContextRecord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -240,10 +240,6 @@ void report_vm_out_of_memory(const char* file, int line, size_t size,
|
||||
|
||||
VMError::report_and_die(Thread::current_or_null(), file, line, size, vm_err_type, detail_fmt, detail_args);
|
||||
va_end(detail_args);
|
||||
|
||||
// The UseOSErrorReporting option in report_and_die() may allow a return
|
||||
// to here. If so then we'll have to figure out how to handle it.
|
||||
guarantee(false, "report_and_die() should not return here");
|
||||
}
|
||||
|
||||
void report_should_not_call(const char* file, int line) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, 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
|
||||
@ -183,7 +183,7 @@ public class BufferingSubscriber<T> implements TrustedSubscriber<T>
|
||||
}
|
||||
|
||||
private final SequentialScheduler pushDemandedScheduler =
|
||||
new SequentialScheduler(new PushDemandedTask());
|
||||
SequentialScheduler.lockingScheduler(new PushDemandedTask());
|
||||
|
||||
void pushDemanded() {
|
||||
if (cancelled.get())
|
||||
@ -191,7 +191,7 @@ public class BufferingSubscriber<T> implements TrustedSubscriber<T>
|
||||
pushDemandedScheduler.runOrSchedule();
|
||||
}
|
||||
|
||||
class PushDemandedTask extends SequentialScheduler.CompleteRestartableTask {
|
||||
class PushDemandedTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2026, 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
|
||||
@ -52,7 +52,6 @@ import jdk.internal.net.http.common.Demand;
|
||||
import jdk.internal.net.http.common.FlowTube;
|
||||
import jdk.internal.net.http.common.Logger;
|
||||
import jdk.internal.net.http.common.SequentialScheduler;
|
||||
import jdk.internal.net.http.common.SequentialScheduler.DeferredCompleter;
|
||||
import jdk.internal.net.http.common.Log;
|
||||
import jdk.internal.net.http.common.Utils;
|
||||
|
||||
@ -554,7 +553,7 @@ abstract class HttpConnection implements Closeable {
|
||||
volatile Flow.Subscriber<? super List<ByteBuffer>> subscriber;
|
||||
volatile HttpWriteSubscription subscription;
|
||||
final SequentialScheduler writeScheduler =
|
||||
new SequentialScheduler(this::flushTask);
|
||||
SequentialScheduler.lockingScheduler(this::flushTask);
|
||||
@Override
|
||||
public void subscribe(Flow.Subscriber<? super List<ByteBuffer>> subscriber) {
|
||||
synchronized (reading) {
|
||||
@ -570,13 +569,9 @@ abstract class HttpConnection implements Closeable {
|
||||
signal();
|
||||
}
|
||||
|
||||
void flushTask(DeferredCompleter completer) {
|
||||
try {
|
||||
HttpWriteSubscription sub = subscription;
|
||||
if (sub != null) sub.flush();
|
||||
} finally {
|
||||
completer.complete();
|
||||
}
|
||||
void flushTask() {
|
||||
HttpWriteSubscription sub = subscription;
|
||||
if (sub != null) sub.flush();
|
||||
}
|
||||
|
||||
void signal() {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2026, 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
|
||||
@ -85,7 +85,7 @@ class PullPublisher<T> implements Flow.Publisher<T> {
|
||||
private volatile boolean completed;
|
||||
private volatile boolean cancelled;
|
||||
private volatile Throwable error;
|
||||
final SequentialScheduler pullScheduler = new SequentialScheduler(new PullTask());
|
||||
final SequentialScheduler pullScheduler = SequentialScheduler.lockingScheduler(new PullTask());
|
||||
private final Demand demand = new Demand();
|
||||
|
||||
Subscription(Flow.Subscriber<? super T> subscriber,
|
||||
@ -96,9 +96,9 @@ class PullPublisher<T> implements Flow.Publisher<T> {
|
||||
this.error = throwable;
|
||||
}
|
||||
|
||||
final class PullTask extends SequentialScheduler.CompleteRestartableTask {
|
||||
final class PullTask implements Runnable {
|
||||
@Override
|
||||
protected void run() {
|
||||
public void run() {
|
||||
if (completed || cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, 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
|
||||
@ -29,15 +29,12 @@ import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import jdk.internal.net.http.common.BufferSupplier;
|
||||
@ -46,8 +43,6 @@ import jdk.internal.net.http.common.FlowTube;
|
||||
import jdk.internal.net.http.common.Log;
|
||||
import jdk.internal.net.http.common.Logger;
|
||||
import jdk.internal.net.http.common.SequentialScheduler;
|
||||
import jdk.internal.net.http.common.SequentialScheduler.DeferredCompleter;
|
||||
import jdk.internal.net.http.common.SequentialScheduler.RestartableTask;
|
||||
import jdk.internal.net.http.common.Utils;
|
||||
|
||||
/**
|
||||
@ -160,34 +155,6 @@ final class SocketTube implements FlowTube {
|
||||
new IOException("connection closed locally", cause));
|
||||
}
|
||||
|
||||
/**
|
||||
* A restartable task used to process tasks in sequence.
|
||||
*/
|
||||
private static class SocketFlowTask implements RestartableTask {
|
||||
final Runnable task;
|
||||
private final Lock lock = new ReentrantLock();
|
||||
SocketFlowTask(Runnable task) {
|
||||
this.task = task;
|
||||
}
|
||||
@Override
|
||||
public final void run(DeferredCompleter taskCompleter) {
|
||||
try {
|
||||
// The logics of the sequential scheduler should ensure that
|
||||
// the restartable task is running in only one thread at
|
||||
// a given time: there should never be contention.
|
||||
boolean locked = lock.tryLock();
|
||||
assert locked : "contention detected in SequentialScheduler";
|
||||
try {
|
||||
task.run();
|
||||
} finally {
|
||||
if (locked) lock.unlock();
|
||||
}
|
||||
} finally {
|
||||
taskCompleter.complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is best effort - there's no guarantee that the printed set of values
|
||||
// is consistent. It should only be considered as weakly accurate - in
|
||||
// particular in what concerns the events states, especially when displaying
|
||||
@ -682,7 +649,7 @@ final class SocketTube implements FlowTube {
|
||||
private final AsyncEvent subscribeEvent;
|
||||
|
||||
InternalReadSubscription() {
|
||||
readScheduler = new SequentialScheduler(new SocketFlowTask(this::read));
|
||||
readScheduler = SequentialScheduler.lockingScheduler(this::read);
|
||||
subscribeEvent = new AsyncTriggerEvent(this::signalError,
|
||||
this::handleSubscribeEvent);
|
||||
readEvent = new ReadEvent(channel, this);
|
||||
|
||||
@ -244,17 +244,10 @@ public class SSLFlowDelegate {
|
||||
final ReentrantLock readBufferLock = new ReentrantLock();
|
||||
final Logger debugr = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
|
||||
|
||||
private final class ReaderDownstreamPusher implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
processData();
|
||||
}
|
||||
}
|
||||
|
||||
Reader() {
|
||||
super();
|
||||
scheduler = SequentialScheduler.lockingScheduler(
|
||||
new ReaderDownstreamPusher());
|
||||
this::processData);
|
||||
this.readBuf = ByteBuffer.allocate(1024);
|
||||
readBuf.limit(0); // keep in read mode
|
||||
}
|
||||
@ -588,14 +581,10 @@ public class SSLFlowDelegate {
|
||||
volatile boolean completing;
|
||||
boolean completed; // only accessed in processData
|
||||
|
||||
class WriterDownstreamPusher extends SequentialScheduler.CompleteRestartableTask {
|
||||
@Override public void run() { processData(); }
|
||||
}
|
||||
|
||||
Writer() {
|
||||
super();
|
||||
writeList = Collections.synchronizedList(new LinkedList<>());
|
||||
scheduler = new SequentialScheduler(new WriterDownstreamPusher());
|
||||
scheduler = SequentialScheduler.lockingScheduler(this::processData);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2026, 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
|
||||
@ -111,7 +111,7 @@ public final class SequentialScheduler {
|
||||
* later time, and maybe in different thread. This type exists for
|
||||
* readability purposes at use-sites only.
|
||||
*/
|
||||
public abstract static class DeferredCompleter {
|
||||
private abstract static class DeferredCompleter {
|
||||
|
||||
/** Extensible from this (outer) class ONLY. */
|
||||
private DeferredCompleter() { }
|
||||
@ -124,7 +124,7 @@ public final class SequentialScheduler {
|
||||
* A restartable task.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface RestartableTask {
|
||||
private interface RestartableTask {
|
||||
|
||||
/**
|
||||
* The body of the task.
|
||||
@ -140,7 +140,7 @@ public final class SequentialScheduler {
|
||||
* A simple and self-contained task that completes once its {@code run}
|
||||
* method returns.
|
||||
*/
|
||||
public abstract static class CompleteRestartableTask
|
||||
private abstract static class CompleteRestartableTask
|
||||
implements RestartableTask
|
||||
{
|
||||
@Override
|
||||
@ -161,7 +161,7 @@ public final class SequentialScheduler {
|
||||
* memory visibility between runs. Since the main loop can't run concurrently,
|
||||
* the lock shouldn't be contended and no deadlock should ever be possible.
|
||||
*/
|
||||
public static final class LockingRestartableTask
|
||||
private static final class LockingRestartableTask
|
||||
extends CompleteRestartableTask {
|
||||
|
||||
private final Runnable mainLoop;
|
||||
@ -208,7 +208,7 @@ public final class SequentialScheduler {
|
||||
}
|
||||
}
|
||||
|
||||
public SequentialScheduler(RestartableTask restartableTask) {
|
||||
private SequentialScheduler(RestartableTask restartableTask) {
|
||||
this.restartableTask = requireNonNull(restartableTask);
|
||||
this.completer = new TryEndDeferredCompleter();
|
||||
this.schedulableTask = new SchedulableTask();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, 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
|
||||
@ -29,7 +29,6 @@ import jdk.internal.net.http.common.Demand;
|
||||
import jdk.internal.net.http.common.Logger;
|
||||
import jdk.internal.net.http.common.MinimalFuture;
|
||||
import jdk.internal.net.http.common.SequentialScheduler;
|
||||
import jdk.internal.net.http.common.SequentialScheduler.CompleteRestartableTask;
|
||||
import jdk.internal.net.http.common.Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -58,7 +57,7 @@ public class TransportImpl implements Transport {
|
||||
/* Used for correlating enters to and exists from a method */
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
|
||||
private final SequentialScheduler sendScheduler = new SequentialScheduler(new SendTask());
|
||||
private final SequentialScheduler sendScheduler = SequentialScheduler.lockingScheduler(new SendTask());
|
||||
|
||||
private final MessageQueue queue;
|
||||
private final MessageEncoder encoder = new MessageEncoder();
|
||||
@ -93,7 +92,7 @@ public class TransportImpl implements Transport {
|
||||
// To ensure the initial non-final `data` will be visible
|
||||
// (happens-before) when `readEvent.handle()` invokes `receiveScheduler`
|
||||
// the following assignment is done last:
|
||||
receiveScheduler = new SequentialScheduler(new ReceiveTask());
|
||||
receiveScheduler = SequentialScheduler.lockingScheduler(new ReceiveTask());
|
||||
}
|
||||
|
||||
private ByteBuffer createWriteBuffer() {
|
||||
@ -361,7 +360,7 @@ public class TransportImpl implements Transport {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
private class SendTask extends CompleteRestartableTask {
|
||||
private class SendTask implements Runnable {
|
||||
|
||||
private final MessageQueue.QueueCallback<Boolean, IOException>
|
||||
encodingCallback = new MessageQueue.QueueCallback<>() {
|
||||
@ -654,7 +653,7 @@ public class TransportImpl implements Transport {
|
||||
}
|
||||
}
|
||||
|
||||
private class ReceiveTask extends CompleteRestartableTask {
|
||||
private class ReceiveTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2026, 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
|
||||
@ -116,7 +116,7 @@ public final class WebSocketImpl implements WebSocket {
|
||||
private final AtomicBoolean pendingPingOrPong = new AtomicBoolean();
|
||||
private final Transport transport;
|
||||
private final SequentialScheduler receiveScheduler
|
||||
= new SequentialScheduler(new ReceiveTask());
|
||||
= SequentialScheduler.lockingScheduler(new ReceiveTask());
|
||||
private final Demand demand = new Demand();
|
||||
private final Executor clientExecutor;
|
||||
|
||||
@ -416,7 +416,7 @@ public final class WebSocketImpl implements WebSocket {
|
||||
* - after the state has been observed as CLOSE/ERROR, the scheduler
|
||||
* is stopped
|
||||
*/
|
||||
private class ReceiveTask extends SequentialScheduler.CompleteRestartableTask {
|
||||
private class ReceiveTask implements Runnable {
|
||||
|
||||
// Transport only asked here and nowhere else because we must make sure
|
||||
// onOpen is invoked first and no messages become pending before onOpen
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
grant {
|
||||
permission javax.security.auth.AuthPermission "modifyPrincipals";
|
||||
permission javax.security.auth.AuthPermission "doAsPrivileged";
|
||||
permission java.util.PropertyPermission "*", "read,write";
|
||||
};
|
||||
|
||||
grant Principal MyPrincipal "test" {
|
||||
permission java.net.SocketPermission "${host.name}", "resolve";
|
||||
};
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
grant {
|
||||
|
||||
};
|
||||
@ -1,4 +0,0 @@
|
||||
grant {
|
||||
permission java.lang.RuntimePermission "setFactory";
|
||||
};
|
||||
|
||||
@ -74,7 +74,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
* @build jdk.test.lib.net.SimpleSSLContext jdk.test.lib.RandomFactory jdk.test.lib.net.URIBuilder
|
||||
* @comment An arbitrary high value for idle connection timeout to prevent idle
|
||||
* connection management from closing the HTTP/2 connection
|
||||
* @run junit/othervm -Djdk.httpclient.keepalive.timeout.h2=36000 ${test.main.class}
|
||||
* @run junit/othervm -Djdk.httpclient.keepalive.timeout.h2=36000
|
||||
* -Djdk.internal.httpclient.debug=true
|
||||
* ${test.main.class}
|
||||
*/
|
||||
class H2GoAwayPromptConnectionClose {
|
||||
|
||||
|
||||
@ -265,7 +265,7 @@ public class SSLEchoTubeTest extends AbstractSSLTubeTest {
|
||||
private final Queue<Object> queue = new ConcurrentLinkedQueue<>();
|
||||
private final int maxQueueSize;
|
||||
private final SequentialScheduler processingScheduler =
|
||||
new SequentialScheduler(createProcessingTask());
|
||||
SequentialScheduler.lockingScheduler(createProcessingTask());
|
||||
|
||||
/* Writing into this tube */
|
||||
private volatile long requested;
|
||||
@ -360,11 +360,11 @@ public class SSLEchoTubeTest extends AbstractSSLTubeTest {
|
||||
}
|
||||
|
||||
int transmitted = 0;
|
||||
private SequentialScheduler.RestartableTask createProcessingTask() {
|
||||
return new SequentialScheduler.CompleteRestartableTask() {
|
||||
private Runnable createProcessingTask() {
|
||||
return new Runnable() {
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
public void run() {
|
||||
try {
|
||||
while (!cancelled.get()) {
|
||||
Object item = queue.peek();
|
||||
@ -374,39 +374,36 @@ public class SSLEchoTubeTest extends AbstractSSLTubeTest {
|
||||
requestMore();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
System.out.printf("EchoTube processing item, requested=%s, demand=%s, transmitted=%s%n",
|
||||
requested, demand.get(), transmitted);
|
||||
if (item instanceof List) {
|
||||
if (!demand.tryDecrement()) {
|
||||
System.out.println("EchoTube no demand");
|
||||
return;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ByteBuffer> bytes = (List<ByteBuffer>) item;
|
||||
Object removed = queue.remove();
|
||||
assert removed == item;
|
||||
System.out.println("EchoTube processing "
|
||||
+ Utils.remaining(bytes));
|
||||
transmitted++;
|
||||
subscriber.onNext(bytes);
|
||||
requestMore();
|
||||
} else if (item instanceof Throwable) {
|
||||
cancelled.set(true);
|
||||
Object removed = queue.remove();
|
||||
assert removed == item;
|
||||
System.out.println("EchoTube processing " + item);
|
||||
subscriber.onError((Throwable) item);
|
||||
} else if (item == EOF) {
|
||||
cancelled.set(true);
|
||||
Object removed = queue.remove();
|
||||
assert removed == item;
|
||||
System.out.println("EchoTube processing EOF");
|
||||
subscriber.onComplete();
|
||||
} else {
|
||||
throw new InternalError(String.valueOf(item));
|
||||
System.out.printf("EchoTube processing item, requested=%s, demand=%s, transmitted=%s%n",
|
||||
requested, demand.get(), transmitted);
|
||||
if (item instanceof List) {
|
||||
if (!demand.tryDecrement()) {
|
||||
System.out.println("EchoTube no demand");
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ByteBuffer> bytes = (List<ByteBuffer>) item;
|
||||
Object removed = queue.remove();
|
||||
assert removed == item;
|
||||
System.out.println("EchoTube processing "
|
||||
+ Utils.remaining(bytes));
|
||||
transmitted++;
|
||||
subscriber.onNext(bytes);
|
||||
requestMore();
|
||||
} else if (item instanceof Throwable) {
|
||||
cancelled.set(true);
|
||||
Object removed = queue.remove();
|
||||
assert removed == item;
|
||||
System.out.println("EchoTube processing " + item);
|
||||
subscriber.onError((Throwable) item);
|
||||
} else if (item == EOF) {
|
||||
cancelled.set(true);
|
||||
Object removed = queue.remove();
|
||||
assert removed == item;
|
||||
System.out.println("EchoTube processing EOF");
|
||||
subscriber.onComplete();
|
||||
} else {
|
||||
throw new InternalError(String.valueOf(item));
|
||||
}
|
||||
}
|
||||
} catch(Throwable t) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user