KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mchange > v2 > async > RoundRobinAsynchronousRunner


1 /*
2  * Distributed as part of c3p0 v.0.9.1
3  *
4  * Copyright (C) 2005 Machinery For Change, Inc.
5  *
6  * Author: Steve Waldman <swaldman@mchange.com>
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License version 2.1, as
10  * published by the Free Software Foundation.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this software; see the file LICENSE. If not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */

22
23
24 package com.mchange.v2.async;
25
26 import com.mchange.v2.log.*;
27 import com.mchange.v2.util.ResourceClosedException;
28
29 /**
30  * A class that provides for effecient asynchronous execution
31  * of multiple tasks that may block, but that do not contend
32  * for the same locks. The order in which tasks will be executed
33  * is not guaranteed.
34  */

35 public class RoundRobinAsynchronousRunner implements AsynchronousRunner, Queuable
36 {
37     private final static MLogger logger = MLog.getLogger( RoundRobinAsynchronousRunner.class );
38
39     //MT: unchanging, individual elements are thread-safe
40
final RunnableQueue[] rqs;
41
42     //MT: protected by this' lock
43
int task_turn = 0;
44
45     //MT: protected by this' lock
46
int view_turn = 0;
47
48     public RoundRobinAsynchronousRunner( int num_threads, boolean daemon )
49     {
50     this.rqs = new RunnableQueue[ num_threads ];
51     for(int i = 0; i < num_threads; ++i)
52         rqs[i] = new CarefulRunnableQueue( daemon, false );
53     }
54
55     public synchronized void postRunnable(Runnable JavaDoc r)
56     {
57     try
58         {
59         int index = task_turn;
60         task_turn = (task_turn + 1) % rqs.length;
61         rqs[index].postRunnable( r );
62
63         /* we do this "long-hand" to avoid bad fragility if an exception */
64         /* occurs in postRunnable, causing the mod step of the original */
65         /* concise code to get skipped, and leading (if */
66         /* task_turn == rqs.length - 1 when the exception occurs) to an */
67         /* endless cascade of ArrayIndexOutOfBoundsExceptions. */
68         /* we might alternatively have just put the mod step into a */
69         /* finally block, but that's too fancy. */
70         /* thanks to Travis Reeder for reporting this problem. */
71
72         //rqs[task_turn++].postRunnable( r );
73
//task_turn %= rqs.length;
74
}
75     catch ( NullPointerException JavaDoc e )
76         {
77         //e.printStackTrace();
78
if ( Debug.DEBUG )
79             {
80             if ( logger.isLoggable( MLevel.FINE ) )
81                 logger.log( MLevel.FINE, "NullPointerException while posting Runnable -- Probably we're closed.", e );
82             }
83         this.close( true );
84         throw new ResourceClosedException("Attempted to use a RoundRobinAsynchronousRunner in a closed or broken state.");
85         }
86     }
87
88     public synchronized RunnableQueue asRunnableQueue()
89     {
90     try
91         {
92         int index = view_turn;
93         view_turn = (view_turn + 1) % rqs.length;
94         return new RunnableQueueView( index );
95         
96         /* same explanation as above */
97         
98         //RunnableQueue out = new RunnableQueueView( view_turn++ );
99
//view_turn %= rqs.length;
100
//return out;
101
}
102     catch ( NullPointerException JavaDoc e )
103         {
104         //e.printStackTrace();
105
if ( Debug.DEBUG )
106             {
107             if ( logger.isLoggable( MLevel.FINE ) )
108                 logger.log( MLevel.FINE, "NullPointerException in asRunnableQueue() -- Probably we're closed.", e );
109             }
110         this.close( true );
111         throw new ResourceClosedException("Attempted to use a RoundRobinAsynchronousRunner in a closed or broken state.");
112         }
113     }
114
115     public synchronized void close( boolean skip_remaining_tasks )
116     {
117     for (int i = 0, len = rqs.length; i < len; ++i)
118         {
119         attemptClose( rqs[i], skip_remaining_tasks );
120         rqs[i] = null;
121         }
122     }
123
124     public void close()
125     { close( true ); }
126
127     static void attemptClose(RunnableQueue rq, boolean skip_remaining_tasks)
128     {
129     try { rq.close( skip_remaining_tasks ); }
130     catch ( Exception JavaDoc e )
131         {
132         //e.printStackTrace();
133
if ( logger.isLoggable( MLevel.WARNING ) )
134             logger.log( MLevel.WARNING, "RunnableQueue close FAILED.", e );
135         }
136     }
137
138     class RunnableQueueView implements RunnableQueue
139     {
140     final int rq_num;
141
142     RunnableQueueView( int rq_num )
143     { this.rq_num = rq_num; }
144
145     public void postRunnable(Runnable JavaDoc r)
146     { rqs[ rq_num ].postRunnable( r ); }
147     
148     public void close( boolean skip_remaining_tasks )
149     { }
150     
151     public void close()
152     { /* ignore */ }
153     }
154 }
155
Popular Tags