capture
[rrq/gorite.git] / com / intendico / gorite / PoolExecutor.java
1 /*********************************************************************
2 Copyright 2012, Ralph Ronnquist.
3
4 This file is part of GORITE.
5
6 GORITE is free software: you can redistribute it and/or modify it
7 under the terms of the Lesser GNU General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GORITE is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14 License for more details.
15
16 You should have received a copy of the Lesser GNU General Public
17 License along with GORITE.  If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
19
20 package com.intendico.gorite;
21
22 /**
23  * This is an Executor extension intended for applications containing
24  * multiple models (i.e., Executors), and multiple threads to execute
25  * them. The PoolExecutor is tied to a {@link
26  * java.util.concurrent.Executor} on concstruction. It adds itself for
27  * running whenever it gets runnable by signalling, or any performer
28  * ended in STOPPED rather than BLOCKED. This approach allows an
29  * execution pool of many threads, where one thread at a time is used
30  * for executing all each Executor's performers once, then
31  * interleaving the models in between these one-shot runs.
32  */
33 public class PoolExecutor extends Executor {
34
35     /**
36      * Cache of the execution queue interface.
37      */
38     private java.util.concurrent.Executor runner;
39
40     /**
41      * Control flag for capturing signal calls during performer
42      * execution. This is reset by the {@link #run()} method before it
43      * executes performers, and set by the {@link #signal()} method
44      * whenever called.
45      */
46     private boolean signaled = false;
47
48     /**
49      * Constructor with a given {@link java.util.concurrent.Executor}.
50      */
51     public PoolExecutor(java.util.concurrent.Executor x) {
52         super( "PoolExecutor" );
53         runner = x;
54         x.execute( this );
55     }
56
57     /**
58      * Utility method to "tickle" the executor with, just in case it
59      * is idle. Unless marked as running, this Executor is entered
60      * into the execution queue (and marked as running).
61      */
62     synchronized public void signal() {
63         signaled = true;
64         if ( ! running ) {
65             running = true;
66             runner.execute( this );
67             notifyAll();
68         }
69     }
70
71     /**
72      * Overrides {@link Executor#run()} for a one-shot execution of
73      * all performers. If any performer ends in STOPPED rather than
74      * BLOCKED, or there is a {@link #signal()} while the execution is
75      * in progress, then this Executor is re-entered into the
76      * execution pool.
77      */
78     public void run() {
79         signaled = false;
80         if ( runPerformersOnce() != Goal.States.BLOCKED ) {
81             runner.execute( this ); // continue asap
82             return;
83         }
84         boolean b;
85         synchronized ( this ) {
86             b = running = signaled;
87         }
88         if ( b ) {
89             runner.execute( this ); // continue asap
90         }
91     }
92 }