/**
 * The unsynchronized version of FlushThreadedLogs.
 * Assumes that the caller holds a lock on SynchronizationObject.
 */
void FOutputDeviceRedirector::UnsynchronizedFlushThreadedLogs( bool bUseAllDevices )
{
	for(int32 LineIndex = 0;LineIndex < BufferedLines.Num();LineIndex++)
	{
		FBufferedLine BufferedLine = BufferedLines[LineIndex];

		for( int32 OutputDeviceIndex=0; OutputDeviceIndex<OutputDevices.Num(); OutputDeviceIndex++ )
		{
			FOutputDevice* OutputDevice = OutputDevices[OutputDeviceIndex];
			if( OutputDevice->CanBeUsedOnAnyThread() || bUseAllDevices )
			{
				OutputDevice->Serialize( *BufferedLine.Data, BufferedLine.Verbosity, BufferedLine.Category, BufferedLine.Time );
			}
		}
	}

	BufferedLines.Empty();
}
void FOutputDeviceRedirector::PanicFlushThreadedLogs()
{
	SCOPE_CYCLE_COUNTER(STAT_FlushThreadedLogs);
	// Acquire a lock on SynchronizationObject and call the unsynchronized worker function.
	FScopeLock ScopeLock( &SynchronizationObject );
	
	// Flush threaded logs, but use the safe version.
	UnsynchronizedFlushThreadedLogs( false );

	// Flush devices.
	for (int32 OutputDeviceIndex = 0; OutputDeviceIndex<OutputDevices.Num(); OutputDeviceIndex++)
	{
		FOutputDevice* OutputDevice = OutputDevices[OutputDeviceIndex];
		if (OutputDevice->CanBeUsedOnAnyThread())
		{
			OutputDevice->Flush();
		}
	}

	BufferedLines.Empty();
}