public static void endThreads ( String check ) { //(error check) if ( currentThread != - 1L ) { throw new IllegalStateException ( "endThreads() called, but thread " + currentThread + " has not finished (exception in thread?)" ) ; } //(end threaded environment) assert ! control . isHeldByCurrentThread ( ) ; isThreaded = false ; //(write remaining threads) boolean cleanPass = false ; while ( ! cleanPass ) { cleanPass = true ; for ( long thread : threadedLogQueue . keySet ( ) ) { assert currentThread < 0L ; if ( threadedLogQueue . get ( thread ) != null && ! threadedLogQueue . get ( thread ) . isEmpty ( ) ) { //(mark queue as unclean) cleanPass = false ; //(variables) Queue < Runnable > backlog = threadedLogQueue . get ( thread ) ; currentThread = thread ; //(clear buffer) while ( currentThread >= 0 ) { if ( currentThread != thread ) { throw new IllegalStateException ( "Redwood control shifted away from flushing thread" ) ; } if ( backlog . isEmpty ( ) ) { throw new IllegalStateException ( "Forgot to call finishThread() on thread " + currentThread ) ; } assert ! control . isHeldByCurrentThread ( ) ; backlog . poll ( ) . run ( ) ; } //(unregister thread) threadsWaiting . remove ( thread ) ; } } } while ( threadsWaiting . size ( ) > 0 ) { assert currentThread < 0L ; assert control . tryLock ( ) ; assert ! threadsWaiting . isEmpty ( ) ; control . lock ( ) ; attemptThreadControlThreadsafe ( - 1 ) ; control . unlock ( ) ; } //(clean up) for ( long threadId : threadedLogQueue . keySet ( ) ) { assert threadedLogQueue . get ( threadId ) . isEmpty ( ) ; } assert threadsWaiting . isEmpty ( ) ; assert currentThread == - 1L ; endTrack ( "Threads( " + check + " )" ) ; }
Signal that all threads have run to completion and the multithreaded environment is over .