Files
UnrealEngineUWP/Engine/Source/Editor/TaskBrowser/Private/TaskDatabaseThread.cpp
Max Preussner 3aece47882 Docs: Removed file comments and added missing code documentation
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]
2014-06-12 23:22:18 -04:00

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" ) );
}