import java.util.concurrent.*;

public class Main {
    public static void main(String... args) throws InterruptedException {
        ExecutorService pool = Executors.newSingleThreadExecutor();
        try {
            // Ensure that putFirst(), putLast(), takeFirst(), and takeLast()
            // immediately throw an InterruptedException if the thread is
            // interrupted, to be consistent with other blocking queues such as
            // ArrayBlockingQueue and LinkedBlockingQueue
            Future<Void> success = pool.submit(() -> {
                var queue = new LinkedBlockingDeque<>();
                Thread.currentThread().interrupt();
                try {
                    queue.putFirst(42);
                    fail("Expected InterruptedException in putFirst()");
                } catch (InterruptedException expected) {
                    // good that's what we want
                }

                Thread.currentThread().interrupt();
                try {
                    queue.putLast(42);
                    fail("Expected InterruptedException in putLast()");
                } catch (InterruptedException expected) {
                    // good that's what we want
                }

                queue.add(42);
                Thread.currentThread().interrupt();
                try {
                    queue.takeFirst();
                    fail("Expected InterruptedException in takeFirst()");
                } catch (InterruptedException expected) {
                    // good that's what we want
                }

                queue.add(42);
                Thread.currentThread().interrupt();
                try {
                    queue.takeLast();
                    fail("Expected InterruptedException in takeLast()");
                } catch (InterruptedException expected) {
                    // good that's what we want
                }
                return null;
            });
            try {
                success.get();
            } catch (ExecutionException e) {
                try {
                    throw e.getCause();
                } catch (Error | RuntimeException unchecked) {
                    throw unchecked;
                } catch (Throwable cause) {
                    throw new AssertionError(cause);
                }
            }
        } finally {
            pool.shutdown();
        }
    }

    private static void fail(String message) {
        throw new AssertionError(message);
    }
}