/**
	 * The real thread entry point. It waits for work events to be queued. Once
	 * an event is queued, it executes it and goes back to waiting.
	 */
	virtual uint32 Run() override
	{
		while (!TimeToDie)
		{
			// This will force sending the stats packet from the previous frame.
			SET_DWORD_STAT( STAT_ThreadPoolDummyCounter, 0 );
			// We need to wait for shorter amount of time
			bool bContinueWaiting = true;
			while( bContinueWaiting )
			{				
				DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FQueuedThread::Run.WaitForWork" ), STAT_FQueuedThread_Run_WaitForWork, STATGROUP_ThreadPoolAsyncTasks );
				// Wait for some work to do
				bContinueWaiting = !DoWorkEvent->Wait( 10 );
			}

			IQueuedWork* LocalQueuedWork = QueuedWork;
			QueuedWork = nullptr;
			FPlatformMisc::MemoryBarrier();
			check(LocalQueuedWork || TimeToDie); // well you woke me up, where is the job or termination request?
			while (LocalQueuedWork)
			{
				// Tell the object to do the work
				LocalQueuedWork->DoThreadedWork();
				// Let the object cleanup before we remove our ref to it
				LocalQueuedWork = OwningThreadPool->ReturnToPoolOrGetNextJob(this);
			} 
		}
		return 0;
	}
Beispiel #2
0
	void FManifestBuilderImpl::AddDataScanner(FDataScannerRef Scanner)
	{
		DataScannersCS.Lock();
		DataScanners.Add(MoveTemp(Scanner));
		DataScannersCS.Unlock();
		CheckForWork->Trigger();
	}
Beispiel #3
0
void FEditPanel::ApplyModif(FEvent& oEvent)
{
    oEvent.SetParent(m_pNameRef->GetValue());

    m_pTagControl->ApplyModif(oEvent);
    m_pRoleControl->ApplyModif(oEvent);
}
Beispiel #4
0
	/**
	 * Tells the thread there is work to be done. Upon completion, the thread
	 * is responsible for adding itself back into the available pool.
	 *
	 * @param InQueuedWork The queued work to perform
	 */
	void DoWork(IQueuedWork* InQueuedWork)
	{
		check(QueuedWork == nullptr && "Can't do more than one task at a time");
		// Tell the thread the work to be done
		QueuedWork = InQueuedWork;
		FPlatformMisc::MemoryBarrier();
		// Tell the thread to wake up and do its job
		DoWorkEvent->Trigger();
	}
	/**
	 * Tells the thread there is work to be done. Upon completion, the thread
	 * is responsible for adding itself back into the available pool.
	 *
	 * @param InQueuedWork The queued work to perform
	 */
	void DoWork(IQueuedWork* InQueuedWork)
	{
		DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FQueuedThread::DoWork" ), STAT_FQueuedThread_DoWork, STATGROUP_ThreadPoolAsyncTasks );

		check(QueuedWork == nullptr && "Can't do more than one task at a time");
		// Tell the thread the work to be done
		QueuedWork = InQueuedWork;
		FPlatformMisc::MemoryBarrier();
		// Tell the thread to wake up and do its job
		DoWorkEvent->Trigger();
	}
FEvent* FWindowsPlatformProcess::CreateSynchEvent(bool bIsManualReset)
{
	// Allocate the new object
	FEvent* Event = NULL;	
	if (FPlatformProcess::SupportsMultithreading())
	{
		Event = new FEventWin();
	}
	else
	{
		// Fake event object.
		Event = new FSingleThreadEvent();
	}
	// If the internal create fails, delete the instance and return NULL
	if (!Event->Create(bIsManualReset))
	{
		delete Event;
		Event = NULL;
	}
	return Event;
}
Beispiel #7
0
	/**
	 * Tells the thread to exit. If the caller needs to know when the thread
	 * has exited, it should use the bShouldWait value and tell it how long
	 * to wait before deciding that it is deadlocked and needs to be destroyed.
	 * NOTE: having a thread forcibly destroyed can cause leaks in TLS, etc.
	 *
	 * @return True if the thread exited graceful, false otherwise
	 */
	virtual bool KillThread()
	{
		bool bDidExitOK = true;
		// Tell the thread it needs to die
		FPlatformAtomics::InterlockedExchange(&TimeToDie,1);
		// Trigger the thread so that it will come out of the wait state if
		// it isn't actively doing work
		DoWorkEvent->Trigger();
		// If waiting was specified, wait the amount of time. If that fails,
		// brute force kill that thread. Very bad as that might leak.
		Thread->WaitForCompletion();
		// Clean up the event
		FPlatformProcess::ReturnSynchEventToPool(DoWorkEvent);
		DoWorkEvent = nullptr;
		delete Thread;
		return bDidExitOK;
	}
Beispiel #8
0
	/**
	 * The real thread entry point. It waits for work events to be queued. Once
	 * an event is queued, it executes it and goes back to waiting.
	 */
	virtual uint32 Run() override
	{
		while (!TimeToDie)
		{
			// Wait for some work to do
			DoWorkEvent->Wait();
			IQueuedWork* LocalQueuedWork = QueuedWork;
			QueuedWork = nullptr;
			FPlatformMisc::MemoryBarrier();
			check(LocalQueuedWork || TimeToDie); // well you woke me up, where is the job or termination request?
			while (LocalQueuedWork)
			{
				// Tell the object to do the work
				LocalQueuedWork->DoThreadedWork();
				// Let the object cleanup before we remove our ref to it
				LocalQueuedWork = OwningThreadPool->ReturnToPoolOrGetNextJob(this);
			} 
		}
		return 0;
	}
int32 UFileServerCommandlet::Main( const FString& Params )
{
	GIsRequestingExit = false;
	GIsRunning = true;

	//@todo abstract properly or delete
#if PLATFORM_WINDOWS// Windows only
	// Used by the .com wrapper to notify that the Ctrl-C handler was triggered.
	// This shared event is checked each tick so that the log file can be cleanly flushed.
	FEvent* ComWrapperShutdownEvent = FPlatformProcess::CreateSynchEvent(true);
#endif

	// parse instance identifier
	FString InstanceIdString;

	if (FParse::Value(*Params, TEXT("InstanceId="), InstanceIdString))
	{
		if (!FGuid::Parse(InstanceIdString, InstanceId))
		{
			UE_LOG(LogFileServerCommandlet, Warning, TEXT("Invalid InstanceId on command line: %s"), *InstanceIdString);
		}
	}

	// start the listening thread
	INetworkFileServer* NetworkFileServer = FModuleManager::LoadModuleChecked<INetworkFileSystemModule>("NetworkFileSystem")
		.CreateNetworkFileServer(true, InstanceId.IsValid() ? 0 : -1);

	TArray<TSharedPtr<FInternetAddr> > AddressList;

	if ((NetworkFileServer == NULL) || !NetworkFileServer->GetAddressList(AddressList))
	{
		UE_LOG(LogFileServerCommandlet, Error, TEXT("Failed to create network file server"));

		return -1;
	}

	// broadcast our presence
	if (InstanceId.IsValid())
	{
		TArray<FString> AddressStringList;

		for (int32 AddressIndex = 0; AddressIndex < AddressList.Num(); ++AddressIndex)
		{
			AddressStringList.Add(AddressList[AddressIndex]->ToString(true));
		}

		FMessageEndpointPtr MessageEndpoint = FMessageEndpoint::Builder("UFileServerCommandlet").Build();

		if (MessageEndpoint.IsValid())
		{
			MessageEndpoint->Publish(new FFileServerReady(AddressStringList, InstanceId), EMessageScope::Network);
		}		
	}

	// main loop
	FDateTime LastConnectionTime = FDateTime::UtcNow();

	while (GIsRunning && !GIsRequestingExit)
	{
		GEngine->UpdateTimeAndHandleMaxTickRate();
		GEngine->Tick(FApp::GetDeltaTime(), false);

		// tick the directory watcher
		FDirectoryWatcherModule& DirectoryWatcherModule = FModuleManager::Get().LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher"));
		DirectoryWatcherModule.Get()->Tick(FApp::GetDeltaTime());

		// update task graph
		FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread);

		// execute deferred commands
		for (int32 DeferredCommandsIndex=0; DeferredCommandsIndex<GEngine->DeferredCommands.Num(); DeferredCommandsIndex++)
		{
			GEngine->Exec( GWorld, *GEngine->DeferredCommands[DeferredCommandsIndex], *GLog);
		}

		GEngine->DeferredCommands.Empty();

		// handle server timeout
		if (InstanceId.IsValid())
		{
			if (NetworkFileServer->NumConnections() > 0)
			{
				LastConnectionTime = FDateTime::UtcNow();
			}

			if ((FDateTime::UtcNow() - LastConnectionTime) > FTimespan::FromMinutes(3.0))
			{
				uint32 Result = FMessageDialog::Open(EAppMsgType::YesNo, NSLOCTEXT("UnrealEd", "FileServerIdle", "The file server did not receive any connections in the past 3 minutes. Would you like to shut it down?"));

				if (Result == EAppReturnType::No)
				{
					LastConnectionTime = FDateTime::UtcNow();
				}
				else
				{
					break;
				}
			}
		}

		// flush log
		GLog->FlushThreadedLogs();

#if PLATFORM_WINDOWS
		if (ComWrapperShutdownEvent->Wait(0))
		{
			GIsRequestingExit = true;
		}
#endif
	}

	// shutdown the server
	NetworkFileServer->Shutdown();
	delete NetworkFileServer;

	//@todo abstract properly or delete 
#if PLATFORM_WINDOWS
	delete ComWrapperShutdownEvent;
#endif

	GIsRunning = false;

	return 0;
}
Beispiel #10
0
	void FManifestBuilderImpl::BuildManifest()
	{
		TMap<FGuid, FChunkInfo> ChunkInfoLookup;
		bool Running = true;
		while (Running)
		{
			FDataScannerPtr NextScanner = GetNextScanner();
			if (NextScanner.IsValid())
			{
				FDataScanResult ScanResult = NextScanner->GetResultWhenComplete();
				ChunkInfoLookup.Append(ScanResult.ChunkInfo);

				// Always reverse for now
				if (ScanResult.DataStructure.Num() > 0)
				{
					FChunkPart& ChunkPart = ScanResult.DataStructure[0];
					if (ChunkPart.DataOffset != FileBuilder.CurrentDataPos)
					{
						check(ChunkPart.DataOffset < FileBuilder.CurrentDataPos); // Missing data!

						bool FoundPosition = false;
						uint64 DataCount = 0;
						for (int32 FileIdx = 0; FileIdx < Manifest->Data->FileManifestList.Num() && !FoundPosition; ++FileIdx)
						{
							FFileManifestData& FileManifest = Manifest->Data->FileManifestList[FileIdx];
							FileManifest.Init();
							uint64 FileStartIdx = DataCount;
							uint64 FileEndIdx = FileStartIdx + FileManifest.GetFileSize();
							if (FileEndIdx > ChunkPart.DataOffset)
							{
								for (int32 ChunkIdx = 0; ChunkIdx < FileManifest.FileChunkParts.Num() && !FoundPosition; ++ChunkIdx)
								{
									FChunkPartData& ChunkPartData = FileManifest.FileChunkParts[ChunkIdx];
									uint64 ChunkPartEndIdx = DataCount + ChunkPartData.Size;
									if (ChunkPartEndIdx < ChunkPart.DataOffset)
									{
										DataCount += ChunkPartData.Size;
									}
									else if (ChunkPartEndIdx > ChunkPart.DataOffset)
									{
										ChunkPartData.Size = ChunkPart.DataOffset - DataCount;
										FileBuilder.CurrentDataPos = DataCount + ChunkPartData.Size;
										FileManifest.FileChunkParts.SetNum(ChunkIdx + 1, false);
										FileManifest.FileChunkParts.Emplace();
										Manifest->Data->FileManifestList.SetNum(FileIdx + 1, false);
										FileBuilder.FileManifest = &Manifest->Data->FileManifestList.Last();
										bool FoundFile = BuildStreamer->GetFileSpan(FileStartIdx, FileBuilder.FileSpan);
										check(FoundFile); // Incorrect positional tracking
										FoundPosition = true;
									}
									else
									{
										FileBuilder.CurrentDataPos = DataCount + ChunkPartData.Size;
										FileManifest.FileChunkParts.SetNum(ChunkIdx + 1, false);
										FileManifest.FileChunkParts.Emplace();
										Manifest->Data->FileManifestList.SetNum(FileIdx + 1, false);
										FileBuilder.FileManifest = &Manifest->Data->FileManifestList.Last();
										bool FoundFile = BuildStreamer->GetFileSpan(FileStartIdx, FileBuilder.FileSpan);
										check(FoundFile); // Incorrect positional tracking
										FoundPosition = true;
									}
								}
							}
							else if (FileEndIdx < ChunkPart.DataOffset)
							{
								DataCount += FileManifest.GetFileSize();
							}
							else
							{
								FileBuilder.FileManifest = nullptr;
								FileBuilder.CurrentDataPos = DataCount + FileManifest.GetFileSize();
								Manifest->Data->FileManifestList.SetNum(FileIdx + 1, false);
								FoundPosition = true;
							}
						}

						check(ChunkPart.DataOffset == FileBuilder.CurrentDataPos);
						check(FileBuilder.FileManifest == nullptr || FileBuilder.FileSpan.Filename == Manifest->Data->FileManifestList.Last().Filename);
					}
				}

				for (int32 idx = 0; idx < ScanResult.DataStructure.Num(); ++idx)
				{
					FChunkPart& ChunkPart = ScanResult.DataStructure[idx];
					// Starting new file?
					if (FileBuilder.FileManifest == nullptr)
					{
						Manifest->Data->FileManifestList.Emplace();
						FileBuilder.FileManifest = &Manifest->Data->FileManifestList.Last();

						bool FoundFile = BuildStreamer->GetFileSpan(FileBuilder.CurrentDataPos, FileBuilder.FileSpan);
						check(FoundFile); // Incorrect positional tracking

						FileBuilder.FileManifest->Filename = FileBuilder.FileSpan.Filename;
						FileBuilder.FileManifest->FileChunkParts.Emplace();
					}

					FChunkPartData& FileChunkPartData = FileBuilder.FileManifest->FileChunkParts.Last();
					FileChunkPartData.Guid = ChunkPart.ChunkGuid;
					FileChunkPartData.Offset = (FileBuilder.CurrentDataPos - ChunkPart.DataOffset) + ChunkPart.ChunkOffset;

					// Process data into file manifests
					int64 FileDataLeft = (FileBuilder.FileSpan.StartIdx + FileBuilder.FileSpan.Size) - FileBuilder.CurrentDataPos;
					int64 ChunkDataLeft = (ChunkPart.DataOffset + ChunkPart.PartSize) - FileBuilder.CurrentDataPos;
					check(FileDataLeft > 0);
					check(ChunkDataLeft > 0);

					if (ChunkDataLeft >= FileDataLeft)
					{
						FileBuilder.CurrentDataPos += FileDataLeft;
						FileChunkPartData.Size = FileDataLeft;
					}
					else
					{
						FileBuilder.CurrentDataPos += ChunkDataLeft;
						FileChunkPartData.Size = ChunkDataLeft;
					}

					FileDataLeft = (FileBuilder.FileSpan.StartIdx + FileBuilder.FileSpan.Size) - FileBuilder.CurrentDataPos;
					ChunkDataLeft = (ChunkPart.DataOffset + ChunkPart.PartSize) - FileBuilder.CurrentDataPos;
					check(FileDataLeft == 0 || ChunkDataLeft == 0);
					// End of file?
					if (FileDataLeft == 0)
					{
						// Fill out rest of data??
						FFileSpan FileSpan;
						bool FoundFile = BuildStreamer->GetFileSpan(FileBuilder.FileSpan.StartIdx, FileSpan);
						check(FoundFile); // Incorrect positional tracking
						check(FileSpan.Filename == FileBuilder.FileManifest->Filename);
						FMemory::Memcpy(FileBuilder.FileManifest->FileHash.Hash, FileSpan.SHAHash.Hash, FSHA1::DigestSize);
						FFileAttributes Attributes = FileAttributesMap.FindRef(FileSpan.Filename);
						FileBuilder.FileManifest->bIsUnixExecutable = Attributes.bUnixExecutable || FileSpan.IsUnixExecutable;
						FileBuilder.FileManifest->SymlinkTarget = FileSpan.SymlinkTarget;
						FileBuilder.FileManifest->bIsReadOnly = Attributes.bReadOnly;
						FileBuilder.FileManifest->bIsCompressed = Attributes.bCompressed;
						FileBuilder.FileManifest->InstallTags = Attributes.InstallTags.Array();
						FileBuilder.FileManifest->Init();
						check(FileBuilder.FileManifest->GetFileSize() == FileBuilder.FileSpan.Size);
						FileBuilder.FileManifest = nullptr;
					}
					else if (ChunkDataLeft == 0)
					{
						FileBuilder.FileManifest->FileChunkParts.Emplace();
					}

					// Continue with this chunk?
					if (ChunkDataLeft > 0)
					{
						--idx;
					}
				}
			}
			else
			{
				if (EndOfData)
				{
					Running = false;
				}
				else
				{
					CheckForWork->Wait();
					CheckForWork->Reset();
				}
			}
		}

		// Fill out chunk list from only chunks that remain referenced
		TSet<FGuid> ReferencedChunks;
		for (const auto& FileManifest : Manifest->Data->FileManifestList)
		{
			for (const auto& ChunkPart : FileManifest.FileChunkParts)
			{
				if (ReferencedChunks.Contains(ChunkPart.Guid) == false)
				{
					auto& ChunkInfo = ChunkInfoLookup[ChunkPart.Guid];
					ReferencedChunks.Add(ChunkPart.Guid);
					Manifest->Data->ChunkList.Emplace();
					auto& ChunkInfoData = Manifest->Data->ChunkList.Last();
					ChunkInfoData.Guid = ChunkPart.Guid;
					ChunkInfoData.Hash = ChunkInfo.Hash;
					FMemory::Memcpy(ChunkInfoData.ShaHash.Hash, ChunkInfo.ShaHash.Hash, FSHA1::DigestSize);
					ChunkInfoData.FileSize = ChunkInfo.ChunkFileSize;
					ChunkInfoData.GroupNumber = FCrc::MemCrc32(&ChunkPart.Guid, sizeof(FGuid)) % 100;
				}
			}
		}

		// Get empty files
		FSHA1 EmptyHasher;
		EmptyHasher.Final();
		const TArray< FString >& EmptyFileList = BuildStreamer->GetEmptyFiles();
		for (const auto& EmptyFile : EmptyFileList)
		{
			Manifest->Data->FileManifestList.Emplace();
			FFileManifestData& EmptyFileManifest = Manifest->Data->FileManifestList.Last();
			EmptyFileManifest.Filename = EmptyFile;
			EmptyHasher.GetHash(EmptyFileManifest.FileHash.Hash);
		}

		// Fill out lookups
		Manifest->InitLookups();
	}
Beispiel #11
-1
	void FManifestBuilderImpl::SaveToFile(const FString& Filename)
	{
		// Wait for builder to complete
		EndOfData = true;
		CheckForWork->Trigger();
		Future.Wait();

		Manifest->Data->ManifestFileVersion = EBuildPatchAppManifestVersion::GetLatestJsonVersion();
		Manifest->SaveToFile(Filename, false);
	}