1 /*
2  * Created on 17 Jul 2006
3  * Created by Paul Gardner
4  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  */
19 
20 package org.gudy.azureus2.core3.util;
21 
22 import java.util.LinkedList;
23 
24 public class
25 AsyncDispatcher
26 {
27 	private String					name;
28 	private AEThread2				thread;
29 	private int						priority	= Thread.NORM_PRIORITY;
30 	private AERunnable				queue_head;
31 	private LinkedList<AERunnable>	queue_tail;
32 	private AESemaphore				queue_sem 	= new AESemaphore( "AsyncDispatcher" );
33 
34 	private int						num_priority;
35 
36 	private int quiesce_after_millis;
37 
38 	public
AsyncDispatcher()39 	AsyncDispatcher()
40 	{
41 		this( "AsyncDispatcher: " + Debug.getLastCallerShort(), 10000 );
42 	}
43 
44 	public
AsyncDispatcher( String name )45 	AsyncDispatcher(
46 		String		name )
47 	{
48 		this( name, 10000 );
49 	}
50 
51 	public
AsyncDispatcher( int quiesce_after_millis )52 	AsyncDispatcher(
53 		int		quiesce_after_millis )
54 	{
55 		this( "AsyncDispatcher: " + Debug.getLastCallerShort(), quiesce_after_millis );
56 	}
57 
58 	public
AsyncDispatcher( String _name, int _quiesce_after_millis )59 	AsyncDispatcher(
60 		String		_name,
61 		int			_quiesce_after_millis )
62 	{
63 		name					= _name;
64 		quiesce_after_millis	= _quiesce_after_millis;
65 	}
66 
67 	public void
dispatch( AERunnable target )68 	dispatch(
69 		AERunnable	target )
70 	{
71 		dispatch( target, false );
72 	}
73 
74 	public void
dispatch( AERunnable target, boolean is_priority )75 	dispatch(
76 		AERunnable	target,
77 		boolean		is_priority )
78 	{
79 		synchronized( this ){
80 
81 			if ( queue_head == null ){
82 
83 				queue_head = target;
84 
85 				if ( is_priority ){
86 
87 					num_priority++;
88 				}
89 			}else{
90 
91 				if ( queue_tail == null ){
92 
93 					queue_tail = new LinkedList<AERunnable>();
94 				}
95 
96 				if ( is_priority ){
97 
98 					if ( num_priority == 0 ){
99 
100 						queue_tail.add( 0, queue_head );
101 
102 						queue_head = target;
103 
104 					}else{
105 
106 						queue_tail.add( num_priority-1, target );
107 					}
108 
109 					num_priority++;
110 
111 				}else{
112 
113 					queue_tail.add( target );
114 				}
115 			}
116 
117 			if ( thread == null ){
118 
119 				thread =
120 					new AEThread2( name, true )
121 					{
122 						public void
123 						run()
124 						{
125 							while( true ){
126 
127 								queue_sem.reserve( quiesce_after_millis );
128 
129 								AERunnable	to_run = null;
130 
131 								synchronized( AsyncDispatcher.this ){
132 
133 									if ( queue_head == null){
134 
135 										queue_tail = null;
136 
137 										thread = null;
138 
139 										break;
140 									}
141 
142 									to_run = queue_head;
143 
144 									if ( queue_tail != null && !queue_tail.isEmpty()){
145 
146 										queue_head = queue_tail.removeFirst();
147 
148 									}else{
149 
150 										queue_head = null;
151 									}
152 
153 									if ( num_priority > 0 ){
154 
155 										num_priority--;
156 									}
157 								}
158 
159 								try{
160 									to_run.runSupport();
161 
162 								}catch( Throwable e ){
163 
164 									Debug.printStackTrace(e);
165 								}
166 							}
167 						}
168 					};
169 
170 				thread.setPriority( priority );
171 
172 				thread.start();
173 			}
174 		}
175 
176 		queue_sem.release();
177 	}
178 
179 	public boolean
isQuiescent()180 	isQuiescent()
181 	{
182 		synchronized( this ){
183 
184 			return( thread == null );
185 		}
186 	}
187 
188 	public int
getQueueSize()189 	getQueueSize()
190 	{
191 		synchronized( this ){
192 
193 			int	result = queue_head == null?0:1;
194 
195 			if ( queue_tail != null ){
196 
197 				result += queue_tail.size();
198 			}
199 
200 			return( result );
201 		}
202 	}
203 
204 	public void
setPriority( int p )205 	setPriority(
206 		int		p )
207 	{
208 		priority = p;
209 	}
210 
211 	public boolean
isDispatchThread()212 	isDispatchThread()
213 	{
214 		synchronized( this ){
215 
216 			return( thread != null && thread.isCurrentThread());
217 		}
218 	}
219 }
220