src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/common/SequentialScheduler.java
branchhttp-client-branch
changeset 56040 f8eabb9a5c0f
parent 55973 4d9b002587db
equal deleted inserted replaced
56039:01739771e48b 56040:f8eabb9a5c0f
     1 /*
     1 /*
     2  * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   133          */
   133          */
   134         void run(DeferredCompleter taskCompleter);
   134         void run(DeferredCompleter taskCompleter);
   135     }
   135     }
   136 
   136 
   137     /**
   137     /**
   138      * A complete restartable task is one which is simple and self-contained.
   138      * A simple and self-contained task that completes once its {@code run}
   139      * It completes once its {@code run} method returns.
   139      * method returns.
   140      */
   140      */
   141     public static abstract class CompleteRestartableTask
   141     public static abstract class CompleteRestartableTask
   142         implements RestartableTask
   142         implements RestartableTask
   143     {
   143     {
   144         @Override
   144         @Override
   153         /** The body of the task. */
   153         /** The body of the task. */
   154         protected abstract void run();
   154         protected abstract void run();
   155     }
   155     }
   156 
   156 
   157     /**
   157     /**
   158      * A RestartableTask that runs its main loop within a
   158      * A task that runs its main loop within a synchronized block to provide
   159      * synchronized block to place a memory barrier around it.
   159      * memory visibility between runs. Since the main loop can't run concurrently,
   160      * Because the main loop can't run concurrently in two treads,
   160      * the lock shouldn't be contended and no deadlock should ever be possible.
   161      * then the lock shouldn't be contended and no deadlock should
       
   162      * ever be possible.
       
   163      */
   161      */
   164     public static final class SynchronizedRestartableTask
   162     public static final class SynchronizedRestartableTask
   165             extends CompleteRestartableTask {
   163             extends CompleteRestartableTask {
       
   164 
   166         private final Runnable mainLoop;
   165         private final Runnable mainLoop;
   167         private final Object lock = new Object();
   166         private final Object lock = new Object();
       
   167 
   168         public SynchronizedRestartableTask(Runnable mainLoop) {
   168         public SynchronizedRestartableTask(Runnable mainLoop) {
   169             this.mainLoop = mainLoop;
   169             this.mainLoop = mainLoop;
   170         }
   170         }
   171 
   171 
   172         @Override
   172         @Override
   187     private final RestartableTask restartableTask;
   187     private final RestartableTask restartableTask;
   188     private final DeferredCompleter completer;
   188     private final DeferredCompleter completer;
   189     private final SchedulableTask schedulableTask;
   189     private final SchedulableTask schedulableTask;
   190 
   190 
   191     /**
   191     /**
   192      * A simple task that can be pushed on an executor to execute
   192      * An auxiliary task that starts the restartable task:
   193      * {@code restartableTask.run(completer)}.
   193      * {@code restartableTask.run(completer)}.
   194      */
   194      */
   195     private final class SchedulableTask implements Runnable {
   195     private final class SchedulableTask implements Runnable {
   196         @Override
   196         @Override
   197         public void run() {
   197         public void run() {
   223     public void runOrSchedule() {
   223     public void runOrSchedule() {
   224         runOrSchedule(schedulableTask, null);
   224         runOrSchedule(schedulableTask, null);
   225     }
   225     }
   226 
   226 
   227     /**
   227     /**
   228      * Runs or schedules the task to be run in the provided executor.
   228      * Executes or schedules the task to be executed in the provided executor.
   229      *
   229      *
   230      * <p> This method can be used when potential executing from a calling
   230      * <p> This method can be used when potential executing from a calling
   231      * thread is not desirable.
   231      * thread is not desirable.
   232      *
   232      *
   233      * @param executor
   233      * @param executor
   234      *         An executor in which to execute the task, if the task needs
   234      *         An executor in which to execute the task, if the task needs
   235      *         to be executed.
   235      *         to be executed.
   236      *
   236      *
   237      * @apiNote The given executor can be {@code null} in which case calling
   237      * @apiNote The given executor can be {@code null} in which case calling
   238      * {@code deferOrSchedule(null)} is strictly equivalent to calling
   238      * {@code runOrSchedule(null)} is strictly equivalent to calling
   239      * {@code runOrSchedule()}.
   239      * {@code runOrSchedule()}.
   240      */
   240      */
   241     public void deferOrSchedule(Executor executor) { // TODO: why this name? why not runOrSchedule?
   241     public void runOrSchedule(Executor executor) {
   242         runOrSchedule(schedulableTask, executor);
   242         runOrSchedule(schedulableTask, executor);
   243     }
   243     }
   244 
   244 
   245     private void runOrSchedule(SchedulableTask task, Executor executor) {
   245     private void runOrSchedule(SchedulableTask task, Executor executor) {
   246         while (true) {
   246         while (true) {
   346 
   346 
   347     /**
   347     /**
   348      * Returns a new {@code SequentialScheduler} that executes the provided
   348      * Returns a new {@code SequentialScheduler} that executes the provided
   349      * {@code mainLoop} from within a {@link SynchronizedRestartableTask}.
   349      * {@code mainLoop} from within a {@link SynchronizedRestartableTask}.
   350      *
   350      *
   351      * @apiNote
   351      * @apiNote This is equivalent to calling
   352      * This is equivalent to calling
   352      * {@code new SequentialScheduler(new SynchronizedRestartableTask(mainLoop))}
   353      * {@code new SequentialScheduler(new SynchronizedRestartableTask(mainloop));}
   353      * The main loop must not perform any blocking operation.
   354      * The main loop must not do any blocking operation.
   354      *
   355      *
   355      * @param mainLoop The main loop of the new sequential scheduler
   356      * @param mainloop The main loop of the new sequential scheduler.
       
   357      * @return a new {@code SequentialScheduler} that executes the provided
   356      * @return a new {@code SequentialScheduler} that executes the provided
   358      * {@code mainLoop} from within a {@link SynchronizedRestartableTask}.
   357      * {@code mainLoop} from within a {@link SynchronizedRestartableTask}.
   359      */
   358      */
   360     public static SequentialScheduler synchronizedScheduler(Runnable mainloop) {
   359     public static SequentialScheduler synchronizedScheduler(Runnable mainLoop) {
   361         return new SequentialScheduler(new SynchronizedRestartableTask(mainloop));
   360         return new SequentialScheduler(new SynchronizedRestartableTask(mainLoop));
   362     }
   361     }
   363 
       
   364 }
   362 }