<s> package org . eclipse . jdt . internal . compiler ; import java . lang . reflect . InvocationTargetException ; import org . eclipse . jdt . internal . compiler . env . ICompilationUnit ; public class ReadManager implements Runnable { ICompilationUnit [ ] units ; int nextFileToRead ; ICompilationUnit [ ] filesRead ; char [ ] [ ] contentsRead ; int readyToReadPosition ; int nextAvailablePosition ; Thread [ ] readingThreads ; char [ ] readInProcessMarker = new char [ 0 ] ; int sleepingThreadCount ; private Throwable caughtException ; static final int START_CUSHION = 5 ; public static final int THRESHOLD = 10 ; static final int CACHE_SIZE = 15 ; public ReadManager ( ICompilationUnit [ ] files , int length ) { int threadCount = 0 ; try { Class runtime = Class . forName ( "" ) ; java . lang . reflect . Method m = runtime . getDeclaredMethod ( "" , new Class [ 0 ] ) ; if ( m != null ) { Integer result = ( Integer ) m . invoke ( Runtime . getRuntime ( ) , null ) ; threadCount = result . intValue ( ) + 1 ; if ( threadCount < 2 ) threadCount = 0 ; else if ( threadCount > CACHE_SIZE ) threadCount = CACHE_SIZE ; } } catch ( IllegalAccessException ignored ) { } catch ( ClassNotFoundException e ) { } catch ( SecurityException e ) { } catch ( NoSuchMethodException e ) { } catch ( IllegalArgumentException e ) { } catch ( InvocationTargetException e ) { } if ( threadCount > 0 ) { synchronized ( this ) { this . units = new ICompilationUnit [ length ] ; System . arraycopy ( files , 0 , this . units , 0 , length ) ; this . nextFileToRead = START_CUSHION ; this . filesRead = new ICompilationUnit [ CACHE_SIZE ] ; this . contentsRead = new char [ CACHE_SIZE ] [ ] ; this . readyToReadPosition = 0 ; this . nextAvailablePosition = 0 ; this . sleepingThreadCount = 0 ; this . readingThreads = new Thread [ threadCount ] ; for ( int i = threadCount ; -- i >= 0 ; ) { this . readingThreads [ i ] = new Thread ( this , "" ) ; this . readingThreads [ i ] . setDaemon ( true ) ; this . readingThreads [ i ] . start ( ) ; } } } } public char [ ] getContents ( ICompilationUnit unit ) throws Error { if ( this . readingThreads == null || this . units . length == 0 ) { if ( this . caughtException != null ) { if ( this . caughtException instanceof Error ) throw ( Error ) this . caughtException ; throw ( RuntimeException ) this . caughtException ; } return unit . getContents ( ) ; } boolean yield = false ; char [ ] result = null ; synchronized ( this ) { if ( unit == this . filesRead [ this . readyToReadPosition ] ) { result = this . contentsRead [ this . readyToReadPosition ] ; while ( result == this . readInProcessMarker || result == null ) { this . contentsRead [ this . readyToReadPosition ] = null ; try { wait ( 250 ) ; } catch ( InterruptedException ignore ) { } if ( this . caughtException != null ) { if ( this . caughtException instanceof Error ) throw ( Error ) this . caughtException ; throw ( RuntimeException ) this . caughtException ; } result = this . contentsRead [ this . readyToReadPosition ] ; } this . filesRead [ this . readyToReadPosition ] = null ; this . contentsRead [ this . readyToReadPosition ] = null ; if ( ++ this . readyToReadPosition >= this . contentsRead . length ) this . readyToReadPosition = 0 ; if ( this . sleepingThreadCount > 0 ) { notify ( ) ; yield = this . sleepingThreadCount == this . readingThreads . length ; } } else { int unitIndex = 0 ; for ( int l = this . units . length ; unitIndex < l ; unitIndex ++ ) if ( this . units [ unitIndex ] == unit ) break ; if ( unitIndex == this . units . length ) { this . units = new ICompilationUnit [ 0 ] ; } else if ( unitIndex >= this . nextFileToRead ) { this . nextFileToRead = unitIndex + START_CUSHION ; this . readyToReadPosition = 0 ; this . nextAvailablePosition = 0 ; this . filesRead = new ICompilationUnit [ CACHE_SIZE ] ; this . contentsRead = new char [ CACHE_SIZE ] [ ] ; notifyAll ( ) ; } } } if ( yield ) Thread . yield ( ) ; if ( result != null ) return result ; return unit . getContents ( ) ; } public void run ( ) { try { while ( this . readingThreads != null && this . nextFileToRead < this . units . length ) { ICompilationUnit unit = null ; int position = - 1 ; synchronized ( this ) { if ( this . readingThreads == null ) return ; while ( this . filesRead [ this . nextAvailablePosition ] != null ) { this . sleepingThreadCount ++ ; try { wait ( 250 ) ; } catch ( InterruptedException e ) { } this . sleepingThreadCount -- ; if ( this . readingThreads == null ) return ; } if ( this . nextFileToRead >= this . units . length ) return ; unit = this . units [ this . nextFileToRead ++ ] ; position = this . nextAvailablePosition ; if ( ++ this . nextAvailablePosition >= this . contentsRead . length ) this . nextAvailablePosition = 0 ; this . filesRead [ position ] = unit ; this . contentsRead [ position ] = this . readInProcessMarker ; } char [ ] result = unit . getContents ( ) ; synchronized ( this ) { if ( this . filesRead [ position ] == unit ) { if ( this . contentsRead [ position ] == null ) notifyAll ( ) ; this . contentsRead [ position ] = result ; } } } } catch ( Error e ) { synchronized ( this ) { this . caughtException = e ; shutdown ( ) ; } return ; } catch ( RuntimeException e ) { synchronized ( this ) { this . caughtException = e ; shutdown ( ) ; } return ; } } public synchronized void shutdown ( ) { this . readingThreads = null ; notifyAll ( ) ; } } </s>