View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.junitcore.pc;
20  
21  import java.util.concurrent.atomic.AtomicBoolean;
22  
23  import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
24  
25  /**
26   * Specifies the strategy of scheduling whether sequential, or parallel.
27   * The strategy may use a thread pool <b>shared</b> with other strategies.
28   * <br>
29   * One instance of strategy can be used just by one {@link Scheduler}.
30   * <br>
31   * The strategy is scheduling tasks in {@link #schedule(Runnable)} and awaiting them
32   * completed in {@link #finished()}. Both methods should be used in one thread.
33   *
34   * @author Tibor Digana (tibor17)
35   * @since 2.16
36   */
37  public abstract class SchedulingStrategy implements Destroyable {
38  
39      private final AtomicBoolean canSchedule = new AtomicBoolean(true);
40  
41      private final ConsoleLogger logger;
42  
43      protected SchedulingStrategy(ConsoleLogger logger) {
44          this.logger = logger;
45      }
46  
47      /**
48       * Schedules tasks if {@link #canSchedule()}.
49       *
50       * @param task runnable to schedule in a thread pool or invoke
51       * @throws java.util.concurrent.RejectedExecutionException if <code>task</code>
52       *                                    cannot be scheduled for execution
53       * @throws NullPointerException       if <code>task</code> is <code>null</code>
54       * @see org.junit.runners.model.RunnerScheduler#schedule(Runnable)
55       * @see java.util.concurrent.Executor#execute(Runnable)
56       */
57      protected abstract void schedule(Runnable task);
58  
59      /**
60       * Waiting for scheduled tasks to finish.
61       * New tasks will not be scheduled by calling this method.
62       *
63       * @return {@code true} if successfully stopped the scheduler, else
64       *         {@code false} if already stopped (a <b>shared</b> thread
65       *         pool was shutdown externally).
66       * @throws InterruptedException if interrupted while waiting
67       *                              for scheduled tasks to finish
68       * @see org.junit.runners.model.RunnerScheduler#finished()
69       */
70      protected abstract boolean finished() throws InterruptedException;
71  
72      /**
73       * Stops scheduling new tasks (e.g. by {@link java.util.concurrent.ExecutorService#shutdown()}
74       * on a private thread pool which cannot be <b>shared</b> with other strategy).
75       *
76       * @return {@code true} if successfully stopped the scheduler, else
77       *         {@code false} if already stopped (a <b>shared</b> thread
78       *         pool was shutdown externally).
79       * @see java.util.concurrent.ExecutorService#shutdown()
80       */
81      protected abstract boolean stop();
82  
83      /**
84       * Stops scheduling new tasks and {@code interrupts} running tasks
85       * (e.g. by {@link java.util.concurrent.ExecutorService#shutdownNow()} on a private thread pool
86       * which cannot be <b>shared</b> with other strategy).
87       * <br>
88       * This method calls {@link #stop()} by default.
89       *
90       * @return {@code true} if successfully stopped the scheduler, else
91       *         {@code false} if already stopped (a <b>shared</b> thread
92       *         pool was shutdown externally).
93       * @see java.util.concurrent.ExecutorService#shutdownNow()
94       */
95      protected boolean stopNow() {
96          return stop();
97      }
98  
99      /**
100      * Persistently disables this strategy. Atomically ignores {@link Balancer} to acquire a new permit.<br>
101      * The method {@link #canSchedule()} atomically returns {@code false}.
102      * @return {@code true} if {@link #canSchedule()} has return {@code true} on the beginning of this method call.
103      */
104     protected boolean disable() {
105         return canSchedule.getAndSet(false);
106     }
107 
108     protected void setDefaultShutdownHandler(Scheduler.ShutdownHandler handler) {}
109 
110     /**
111      * @return {@code true} if a thread pool associated with this strategy
112      *         can be shared with other strategies.
113      */
114     protected abstract boolean hasSharedThreadPool();
115 
116     /**
117      * @return {@code true} unless stopped, finished or disabled.
118      */
119     protected boolean canSchedule() {
120         return canSchedule.get();
121     }
122 
123     protected void logQuietly(Throwable t) {
124         logger.error(t);
125     }
126 }