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 }