FileDocCategorySizeDatePackage
ConcurrentHasher.javaAPI DocAzureus 3.0.3.47102Tue May 29 14:07:24 BST 2007org.gudy.azureus2.core3.util

ConcurrentHasher

public class ConcurrentHasher extends Object
author
parg

Fields Summary
protected static ConcurrentHasher
singleton
protected int
processor_num
protected List
requests
protected List
hashers
protected AESemaphore
request_sem
protected AESemaphore
scheduler_sem
protected AEMonitor
requests_mon
private static boolean
friendly_hashing
private static int
realtime_task_count
Constructors Summary
protected ConcurrentHasher()

			// TODO: number of processors can apparently change....
			// so periodically grab num + reserve/release as necessary
		
		processor_num = Runtime.getRuntime().availableProcessors();
		
			// just in case :P
		
		if ( processor_num <= 0 ){
			
			processor_num	= 1;
		}
			
			// one more that proc num seems to improve performance ;)
		
		for (int i=0;i<processor_num + 1;i++){
			
			scheduler_sem.release();
		}
	
		final ThreadPool pool	= new ThreadPool( "ConcurrentHasher", 64 );
		
		AEThread	scheduler = 
			new AEThread("CuncurrentHasher:scheduler")
			{
				public void
				runSupport()
				{
					while(true){
						
							// get a request to run
						
						request_sem.reserve();
						
							// now extract the request
						
						final ConcurrentHasherRequest	req;
						final SHA1Hasher				hasher;
						
						try{
							requests_mon.enter();
							
							req	= (ConcurrentHasherRequest)requests.remove(0);
							
							if ( hashers.size() == 0 ){
								
								hasher = new SHA1Hasher();
								
							}else{
								
								hasher	= (SHA1Hasher)hashers.remove( hashers.size()-1 );
							}
						}finally{
							
							requests_mon.exit();
						}
						
						pool.run( 
								new AERunnable()
								{
									public void
									runSupport()
									{
										try{											
											req.run( hasher );
											
										}finally{
											try{
												requests_mon.enter();

												hashers.add( hasher );
											
											}finally{
												
												requests_mon.exit();
											}

											if ( friendly_hashing && req.isLowPriority()){
					
												try{  
													int	size = req.getSize();
													
														// pieces can be several MB so delay based on size
													
													final int max = 250;
													final int min = 50;
													
													size = size/1024;	// in K
													
													size = size/8;
													
														// 4MB -> 500
														// 1MB -> 125
													
													size = Math.min( size, max );
													size = Math.max( size, min );
													
													Thread.sleep( size );
						
												}catch( Throwable e ){ 
						
													Debug.printStackTrace( e ); 
												}
											}
										       		
											scheduler_sem.release();
										}
									}
								});
													
					}
				}
			};
	
		scheduler.setDaemon( true );
		
		scheduler.start();
	
Methods Summary
public voidaddRealTimeTask()

		synchronized( this ){
			
			realtime_task_count++;
		}
	
public ConcurrentHasherRequestaddRequest(java.nio.ByteBuffer buffer)
add a synchronous request - on return it will have run (or been cancelled)

		return( addRequest( buffer, null, false ));
	
public ConcurrentHasherRequestaddRequest(java.nio.ByteBuffer buffer, ConcurrentHasherRequestListener listener, boolean low_priorty)
Add an asynchronous request if listener supplied, sync otherwise

param
buffer
param
priority
param
listener
param
low_priorty low priority checks will cause the "friendly hashing" setting to be taken into account
return

		final ConcurrentHasherRequest	req = new ConcurrentHasherRequest( this, buffer, listener, low_priorty );
			
			// get permission to run a request
		

		// test code to force synchronous checking
		//SHA1Hasher	hasher = new SHA1Hasher();
		//req.run( hasher );
		
		scheduler_sem.reserve();
		
		try{
			requests_mon.enter();
			
			requests.add( req );
		
		}finally{
			
			requests_mon.exit();
		}
		
		request_sem.release();
		
		return( req );
	
public static booleanconcurrentHashingAvailable()

		return( getSingleton().processor_num > 1 );
	
public static org.gudy.azureus2.core3.util.ConcurrentHashergetSingleton()

		return( singleton );
	
public booleanisRealTimeTaskActive()

		return( realtime_task_count > 0 );
	
public static voidmain(java.lang.String[] args)

		/*
		final ConcurrentHasher	hasher = ConcurrentHasher.getSingleton();
		
		int		threads			= 1;
		
		final long	buffer_size		= 128*1024;
		final long	loop			= 1024;
		
		for (int i=0;i<threads;i++){
						
			new Thread()
			{
				public void
				run()
				{
					// SHA1Hasher sha1_hasher = new SHA1Hasher();
					
					long	start = System.currentTimeMillis();
					//ByteBuffer	buffer = ByteBuffer.allocate((int)buffer_size);
					
					for (int j=0;j<loop;j++){
						
												
						//sha1_hasher.calculateHash( buffer );
						//ConcurrentHasherRequest req = hasher.addRequest( buffer );
					}
					
					long	elapsed = System.currentTimeMillis() - start;
					
					System.out.println( 
							"elapsed = " + elapsed + ", " + 
							((loop*buffer_size*1000)/elapsed) + " B/sec" );
				}
			}.start();
		}
		*/
	
public voidremoveRealTimeTask()

		synchronized( this ){
			
			realtime_task_count--;
		}