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