You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Sandbox/Editor/Include/IBackgroundTaskManager.h

231 lines
6.7 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
//
// IBackgroundTaskManager runs background tasks in worker thread.
//
// Tasks are derived from IBackgroundTask. Each task is split in two parts for:
// Work - done in background thread.
// Finalize - called afterward in main thread to apply results.
//
// Task objects are reference counted. Task manager will hold its own reference to the task object
// for as long as the task is pending or being executed. If you want to keep the task object around
// in your code you will have to call AddRef() and Release() on the task object by yourself so there
// will be an extra reference to the task object held by your code.
//
// Work returns the state of the task. Task can be resumed, then the Work
// method will be called again. Other tasks can work between calls to Work.
// It is possible to Cancel task. Work method is not invoked any more for
// Canceled tasks.
//
#ifndef CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDTASKMANAGER_H
#define CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDTASKMANAGER_H
#pragma once
enum ETaskPriority
{
eTaskPriority_FileUpdateFinal,
eTaskPriority_BackgroundScan,
eTaskPriority_FileUpdate,
eTaskPriority_RealtimePreview
};
// Result code returned by task Work() function
enum ETaskResult
{
// Task has not yet completed, add it back to the task queue with the same parameters (priority and thread mask)
eTaskResult_Resume,
// Task has completed without errors (it's assumed that the result the task was supposed to achieve was achieved)
eTaskResult_Completed,
// Task was canceled
eTaskResult_Canceled,
// Task has failed to complete it's work
eTaskResult_Failed,
};
// Internal task tracking state
enum ETaskState
{
// Task was just created.
eTaskState_Created,
// Task was scheduled to be executed in the future.
eTaskState_Scheduled,
// Task was added to the task queue and is waiting for it's time to be executed.
eTaskState_Pending,
// Task is being processed right now.
eTaskState_Working,
// Task was canceled before it has finished (indication that TaskManager has seen the Cancel() call).
eTaskState_Canceled,
// Task Work() function was called but it ended with an error code.
eTaskState_Failed,
// Task has completed it's Work() function without errors.
eTaskState_Completed,
};
// Thread mask controls which on which threads given task can be executed.
enum ETaskThreadMask
{
// Task can run only on the IO thread (default)
// There is only one IO thread so all task with this flag are run in a sequence.
eTaskThreadMask_IO,
// Task can run on any thread (concurrent tasks allowed)
// There can be many threads with this mask so there's no limit on the concurrent task count.
eTaskThreadMask_Any,
eTaskThreadMask_COUNT,
};
struct IBackgroundTask
{
public:
IBackgroundTask()
: m_bCanceled(false)
, m_state(eTaskState_Created)
, m_progress(-1.0f)
, m_refCount(0)
, m_bFailReported(false)
{}
void Cancel()
{
m_bCanceled = true;
}
bool IsCanceled() const
{
return m_bCanceled;
}
bool HasFinished() const
{
return (m_state == eTaskState_Canceled) ||
(m_state == eTaskState_Completed) ||
(m_state == eTaskState_Failed);
}
bool HasFinishedWithoutError() const
{
return (m_state == eTaskState_Completed);
}
ETaskState GetState() const
{
return m_state;
}
void SetState(ETaskState state)
{
m_state = state;
}
float GetProgress() const
{
return m_progress;
}
int AddRef()
{
return CryInterlockedIncrement(&m_refCount);
}
int Release()
{
const int nCount = CryInterlockedDecrement(&m_refCount);
assert(nCount >= 0);
if (nCount == 0)
{
Delete();
}
else if (nCount < 0)
{
assert(0);
CryFatalError("Deleting Reference Counted Object Twice");
}
return nCount;
}
bool FailReported() const{ return m_bFailReported; }
// Get the user readable description (name) of this task, used for logging
virtual const char* Description() const { return ""; }
// Get the user readable error message (in case when the task fails), used for logging the errors
virtual const char* ErrorMessage() const { return ""; }
// Called from main thread after task is completed just before the task gets destroyed
virtual void Finalize() {}
// Since there's a possibility that task object were created using different allocator
// we need a way to delete the task object once we are done with it
virtual void Delete() = 0;
// Invoked from worker thread, actual work is done here
virtual ETaskResult Work() = 0;
protected:
void SetProgress(float progress) { m_progress = progress; }
void SetFailReported() { m_bFailReported = true; }
// destructor is hidden to indicate that we should use Release() method
virtual ~IBackgroundTask() {}
private:
volatile int m_refCount;
ETaskState m_state;
float m_progress;
bool m_bCanceled;
bool m_bFailReported;
};
struct IBackgroundTaskManagerListener
{
virtual ~IBackgroundTaskManagerListener() {}
virtual void OnBackgroundTaskAdded(const char* description) = 0;
virtual void OnBackgroundTaskCompleted(ETaskResult taskResult, const char* description) = 0;
};
struct IBackgroundTaskManager
{
enum
{
BACKGROUND_TASK_ID_INVALID = 0
};
virtual ~IBackgroundTaskManager() {}
// Add task to the queue with given priority and thread mask
virtual void AddTask(IBackgroundTask* pTask, ETaskPriority priority, ETaskThreadMask threadMask) = 0;
// Schedule task to be executed in the future
virtual void ScheduleTask(IBackgroundTask* pTask, ETaskPriority priority, int delayMilliseconds, ETaskThreadMask threadMask) = 0;
virtual void AddListener(IBackgroundTaskManagerListener* pListener, const char* name) = 0;
virtual void RemoveListener(IBackgroundTaskManagerListener* pListener) = 0;
};
#endif // CRYINCLUDE_EDITOR_INCLUDE_IBACKGROUNDTASKMANAGER_H