You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Please note that file comments had no purpose in nearly all cases and just added visual clutter. The two files that had meaningful file comments had their comments moved into the corresponding classes. There are still hundreds of file comments left in other files that will be removed over time. Also cleaned up some random stuff along the way: - relative paths to public headers within the same module are no longer necessary (automatically discovered by UBT now) - header guards are deprecated, use #pragma once instead (all compilers support it now) - space between multiple template brackets is no longer required (all compilers support >> now) - NULL to nullptr, OVERRIDE to override - spelling errors, whitespace, line breaks [CL 2104067 by Max Preussner in Main branch]
312 lines
9.2 KiB
C++
312 lines
9.2 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "TaskBrowserPrivatePCH.h"
|
|
#include "TaskDatabaseThread.h"
|
|
|
|
|
|
/**
|
|
* FTaskDatabaseThreadRunnable constructor
|
|
*
|
|
* @param InTaskDatabaseProvider The task database provider to bind to
|
|
*/
|
|
FTaskDatabaseThreadRunnable::FTaskDatabaseThreadRunnable( FTaskDatabaseProviderInterface* InTaskDatabaseProvider )
|
|
: bThreadSafeShouldSuspend( false ),
|
|
ThreadSafeCurrentRequest( NULL ),
|
|
ThreadSafeResponse( NULL ),
|
|
TaskDatabaseProvider( InTaskDatabaseProvider ),
|
|
bAskedToStop( false )
|
|
{
|
|
// NOTE: This code always runs on the main thread, not the task database thread
|
|
// NOTE: This code runs after the task database thread has shut down
|
|
}
|
|
|
|
|
|
/** FTaskDatabaseThreadRunnable destructor */
|
|
FTaskDatabaseThreadRunnable::~FTaskDatabaseThreadRunnable()
|
|
{
|
|
// NOTE: This code always runs on the main thread, not the task database thread
|
|
// NOTE: This code runs before the the task database thread is started
|
|
|
|
// Task database thread should have cleaned everything up by now
|
|
check( TaskDatabaseProvider == NULL );
|
|
|
|
// Clean up left over request/response memory if we need to
|
|
if( ThreadSafeCurrentRequest != NULL )
|
|
{
|
|
delete ThreadSafeCurrentRequest;
|
|
ThreadSafeCurrentRequest = NULL;
|
|
}
|
|
if( ThreadSafeResponse != NULL )
|
|
{
|
|
delete ThreadSafeResponse;
|
|
ThreadSafeResponse = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Allows per runnable object initialization. NOTE: This is called in the
|
|
* context of the thread object that aggregates this, not the thread that
|
|
* passes this runnable to a new thread.
|
|
*
|
|
* @return True if initialization was successful, false otherwise
|
|
*/
|
|
bool FTaskDatabaseThreadRunnable::Init()
|
|
{
|
|
// Make sure that a task database provider was assigned at construction
|
|
check( TaskDatabaseProvider != NULL );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* This is where all per object thread work is done. This is only called
|
|
* if the initialization was successful.
|
|
*
|
|
* @return The exit code of the runnable object
|
|
*/
|
|
uint32 FTaskDatabaseThreadRunnable::Run()
|
|
{
|
|
TDLOG( TEXT( "TDThread: Run() started" ) );
|
|
|
|
while( !bAskedToStop )
|
|
{
|
|
const FTaskDatabaseRequest* GenericRequestCopy = NULL;
|
|
{
|
|
// @todo: Make sure we really need crit sects in all cases. A lot of operations should be atomic
|
|
FScopeLock ScopeLock( &CriticalSection );
|
|
GenericRequestCopy = ThreadSafeCurrentRequest;
|
|
}
|
|
|
|
if( GenericRequestCopy != NULL )
|
|
{
|
|
// Polymorphic response data. We'll allocate an event-specific instance of this.
|
|
FTaskDatabaseResponse* GenericResponse = NULL;
|
|
|
|
TDLOG( TEXT( "TDThread: Starting work on request (Type: %i)" ), ( int32 )GenericRequestCopy->RequestType );
|
|
|
|
// We have work to do!
|
|
switch( GenericRequestCopy->RequestType )
|
|
{
|
|
case ETaskDatabaseRequestType::QueryAvailableDatabases:
|
|
{
|
|
const FTaskDatabaseRequest_QueryAvailableDatabases* Request =
|
|
static_cast< const FTaskDatabaseRequest_QueryAvailableDatabases* >( GenericRequestCopy );
|
|
FTaskDatabaseResponse_QueryAvailableDatabases* Response =
|
|
new FTaskDatabaseResponse_QueryAvailableDatabases();
|
|
GenericResponse = Response;
|
|
|
|
// Query available databases and store whether or not we succeeded
|
|
GenericResponse->bSucceeded =
|
|
TaskDatabaseProvider->QueryAvailableDatabases(
|
|
Request->ServerURL,
|
|
Request->LoginUserName,
|
|
Request->LoginPassword,
|
|
Response->DatabaseNames ); // Out
|
|
}
|
|
break;
|
|
|
|
|
|
case ETaskDatabaseRequestType::ConnectToDatabase:
|
|
{
|
|
const FTaskDatabaseRequest_ConnectToDatabase* Request =
|
|
static_cast< const FTaskDatabaseRequest_ConnectToDatabase* >( GenericRequestCopy );
|
|
FTaskDatabaseResponse_ConnectToDatabase* Response =
|
|
new FTaskDatabaseResponse_ConnectToDatabase();
|
|
GenericResponse = Response;
|
|
|
|
// Query available databases and store whether or not we succeeded
|
|
GenericResponse->bSucceeded =
|
|
TaskDatabaseProvider->ConnectToDatabase(
|
|
Request->ServerURL,
|
|
Request->LoginUserName,
|
|
Request->LoginPassword,
|
|
Request->DatabaseName,
|
|
Response->UserRealName, // Out
|
|
Response->ResolutionValues, // Out
|
|
Response->OpenTaskStatusPrefix ); // Out
|
|
}
|
|
break;
|
|
|
|
|
|
case ETaskDatabaseRequestType::DisconnectFromDatabase:
|
|
{
|
|
const FTaskDatabaseRequest* Request =
|
|
static_cast< const FTaskDatabaseRequest* >( GenericRequestCopy );
|
|
FTaskDatabaseResponse* Response = new FTaskDatabaseResponse();
|
|
GenericResponse = Response;
|
|
|
|
// Query available databases and store whether or not we succeeded
|
|
GenericResponse->bSucceeded =
|
|
TaskDatabaseProvider->DisconnectFromDatabase();
|
|
}
|
|
break;
|
|
|
|
|
|
case ETaskDatabaseRequestType::QueryFilters:
|
|
{
|
|
const FTaskDatabaseRequest* Request =
|
|
static_cast< const FTaskDatabaseRequest* >( GenericRequestCopy );
|
|
FTaskDatabaseResponse_QueryFilters* Response = new FTaskDatabaseResponse_QueryFilters();
|
|
GenericResponse = Response;
|
|
|
|
// Query list of filters
|
|
GenericResponse->bSucceeded =
|
|
TaskDatabaseProvider->QueryFilters(
|
|
Response->FilterNames ); // Out
|
|
}
|
|
break;
|
|
|
|
|
|
case ETaskDatabaseRequestType::QueryTasks:
|
|
{
|
|
const FTaskDatabaseRequest_QueryTasks* Request =
|
|
static_cast< const FTaskDatabaseRequest_QueryTasks* >( GenericRequestCopy );
|
|
FTaskDatabaseResponse_QueryTasks* Response = new FTaskDatabaseResponse_QueryTasks();
|
|
GenericResponse = Response;
|
|
|
|
// Query list of tasks
|
|
GenericResponse->bSucceeded =
|
|
TaskDatabaseProvider->QueryTasks(
|
|
Request->FilterName,
|
|
Response->TaskEntries ); // Out
|
|
}
|
|
break;
|
|
|
|
|
|
case ETaskDatabaseRequestType::QueryTaskDetails:
|
|
{
|
|
const FTaskDatabaseRequest_QueryTaskDetails* Request =
|
|
static_cast< const FTaskDatabaseRequest_QueryTaskDetails* >( GenericRequestCopy );
|
|
FTaskDatabaseResponse_QueryTaskDetails* Response = new FTaskDatabaseResponse_QueryTaskDetails();
|
|
GenericResponse = Response;
|
|
|
|
// Query details about a specific task
|
|
GenericResponse->bSucceeded =
|
|
TaskDatabaseProvider->QueryTaskDetails(
|
|
Request->TaskNumber,
|
|
Response->TaskEntryDetails ); // Out
|
|
}
|
|
break;
|
|
|
|
|
|
case ETaskDatabaseRequestType::MarkTaskComplete:
|
|
{
|
|
const FTaskDatabaseRequest_MarkTaskComplete* Request =
|
|
static_cast< const FTaskDatabaseRequest_MarkTaskComplete* >( GenericRequestCopy );
|
|
FTaskDatabaseResponse* Response = new FTaskDatabaseResponse();
|
|
GenericResponse = Response;
|
|
|
|
// Mark the specified task as complete
|
|
GenericResponse->bSucceeded =
|
|
TaskDatabaseProvider->MarkTaskComplete(
|
|
Request->TaskNumber,
|
|
Request->ResolutionData );
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
{
|
|
// Unknown request
|
|
check( 0 );
|
|
}
|
|
break;
|
|
}
|
|
|
|
// There should really always be a response, otherwise it's a code error
|
|
check( GenericResponse != NULL );
|
|
if( GenericResponse != NULL )
|
|
{
|
|
if( GenericResponse->bSucceeded )
|
|
{
|
|
TDLOG( TEXT( "TDThread: Completed SUCCESSFUL request (Type: %i)" ), ( int32 )GenericRequestCopy->RequestType );
|
|
|
|
GenericResponse->bFailedBecauseOfDisconnection = false;
|
|
}
|
|
else
|
|
{
|
|
TDLOG( TEXT( "TDThread: Completed FAILED request (Type: %i)" ), ( int32 )GenericRequestCopy->RequestType );
|
|
|
|
// Set the error message string
|
|
GenericResponse->ErrorMessage = TaskDatabaseProvider->GetLastErrorMessage();
|
|
|
|
// Did we fail because we were disconnected from the server?
|
|
GenericResponse->bFailedBecauseOfDisconnection =
|
|
TaskDatabaseProvider->LastErrorWasCausedByDisconnection();
|
|
|
|
if( GenericResponse->bFailedBecauseOfDisconnection )
|
|
{
|
|
TDLOG( TEXT( "TDThread: We were disconnected from the server due to this error" ) );
|
|
}
|
|
}
|
|
|
|
// Store the request type in the response payload
|
|
GenericResponse->RequestType = GenericRequestCopy->RequestType;
|
|
|
|
// Request completed, so we'll report back to the main thread
|
|
{
|
|
FScopeLock ScopeLock( &CriticalSection );
|
|
|
|
// The main thread will check this response data frequently, and before issuing
|
|
// any new requests to us. We simply need to set it safely.
|
|
ThreadSafeResponse = GenericResponse;
|
|
|
|
// We can delete the original request data now
|
|
delete ThreadSafeCurrentRequest;
|
|
ThreadSafeCurrentRequest = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if( bThreadSafeShouldSuspend )
|
|
{
|
|
// We've been asked to suspend, so sleep for a long time
|
|
FPlatformProcess::Sleep( 1.0f );
|
|
}
|
|
else
|
|
{
|
|
// Give a time slice between tasks. We're don't want to use a lot of CPU on this thread.
|
|
FPlatformProcess::Sleep( 0.01f );
|
|
}
|
|
}
|
|
|
|
TDLOG( TEXT( "TDThread: Run() finished" ) );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* This is called if a thread is requested to terminate early
|
|
*/
|
|
void FTaskDatabaseThreadRunnable::Stop()
|
|
{
|
|
TDLOG( TEXT( "TDThread: Stop() started" ) );
|
|
|
|
// Ask the thread to stop after it's current operation
|
|
bAskedToStop = true;
|
|
|
|
TDLOG( TEXT( "TDThread: Stop() finished" ) );
|
|
}
|
|
|
|
|
|
/**
|
|
* Called in the context of the aggregating thread to perform any cleanup.
|
|
*/
|
|
void FTaskDatabaseThreadRunnable::Exit()
|
|
{
|
|
TDLOG( TEXT( "TDThread: Exit() started" ) );
|
|
|
|
// Cleanup task database provider
|
|
if( TaskDatabaseProvider != NULL )
|
|
{
|
|
delete TaskDatabaseProvider;
|
|
TaskDatabaseProvider = NULL;
|
|
}
|
|
|
|
TDLOG( TEXT( "TDThread: Exit() finished" ) );
|
|
}
|