1 //
2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.util.thread;
20
21 import java.lang.reflect.Constructor;
22 import java.util.concurrent.Executor;
23 import java.util.concurrent.RejectedExecutionException;
24
25 import org.eclipse.jetty.util.Loader;
26 import org.eclipse.jetty.util.log.Log;
27 import org.eclipse.jetty.util.log.Logger;
28 import org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume;
29
30 /**
31 * <p>An {@link ExecutionStrategy} executes {@link Runnable} tasks produced by a {@link Producer}.
32 * The strategy to execute the task may vary depending on the implementation; the task may be
33 * run in the calling thread, or in a new thread, etc.</p>
34 * <p>The strategy delegates the production of tasks to a {@link Producer}, and continues to
35 * execute tasks until the producer continues to produce them.</p>
36 */
37 public interface ExecutionStrategy
38 {
39 /**
40 * <p>Initiates (or resumes) the task production and execution.</p>
41 * <p>This method guarantees that the task is never run by the
42 * thread that called this method.</p>
43 *
44 * @see #execute()
45 */
46 public void dispatch();
47
48 /**
49 * <p>Initiates (or resumes) the task production and execution.</p>
50 * <p>The produced task may be run by the same thread that called
51 * this method.</p>
52 *
53 * @see #dispatch()
54 */
55 public void execute();
56
57
58 /**
59 * A task that can handle {@link RejectedExecutionException}
60 */
61 public interface Rejectable
62 {
63 public void reject();
64 }
65
66 /**
67 * <p>A producer of {@link Runnable} tasks to run.</p>
68 * <p>The {@link ExecutionStrategy} will repeatedly invoke {@link #produce()} until
69 * the producer returns null, indicating that it has nothing more to produce.</p>
70 * <p>When no more tasks can be produced, implementations should arrange for the
71 * {@link ExecutionStrategy} to be invoked again in case an external event resumes
72 * the tasks production.</p>
73 */
74 public interface Producer
75 {
76 /**
77 * <p>Produces a task to be executed.</p>
78 *
79 * @return a task to executed or null if there are no more tasks to execute
80 */
81 Runnable produce();
82 }
83
84 public static class Factory
85 {
86 private static final Logger LOG = Log.getLogger(Factory.class);
87
88 public static ExecutionStrategy instanceFor(Producer producer, Executor executor)
89 {
90 // TODO remove this mechanism before release
91 String strategy = System.getProperty(producer.getClass().getName()+".ExecutionStrategy");
92 if (strategy!=null)
93 {
94 try
95 {
96 Class<? extends ExecutionStrategy> c = Loader.loadClass(producer.getClass(),strategy);
97 Constructor<? extends ExecutionStrategy> m = c.getConstructor(Producer.class,Executor.class);
98 LOG.info("Use {} for {}",c.getSimpleName(),producer.getClass().getName());
99 return m.newInstance(producer,executor);
100 }
101 catch(Exception e)
102 {
103 LOG.warn(e);
104 }
105 }
106
107 return new ExecuteProduceConsume(producer,executor);
108 }
109 }
110 }