// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Threading/IRunnable.h"
class Asset;
class LoadingThread;
class ContentLoadTask;
///
/// Resources loading thread
///
class LoadingThread : public IRunnable
{
protected:
volatile int64 _exitFlag;
Thread* _thread;
int32 _totalTasksDoneCount;
public:
///
/// Init
///
LoadingThread();
///
/// Destructor
///
~LoadingThread();
public:
///
/// Gets the thread identifier.
///
/// Thread ID
uint64 GetID() const;
public:
///
/// Returns true if thread has empty exit flag, so it can continue it's work
///
/// True if exit flag is empty, otherwise false
FORCE_INLINE bool HasExitFlagClear()
{
return Platform::AtomicRead(&_exitFlag) == 0;
}
///
/// Set exit flag to true so thread must exit
///
void NotifyExit();
///
/// Stops the calling thread execution until the loading thread ends its execution.
///
void Join();
public:
///
/// Starts thread execution.
///
/// The thread name.
/// True if cannot start, otherwise false
bool Start(const String& name);
///
/// Runs the specified task.
///
/// The task.
void Run(ContentLoadTask* task);
public:
// [IRunnable]
String ToString() const override;
int32 Run() override;
void Exit() override;
};
///
/// Content loading manager.
///
class ContentLoadingManager
{
friend ContentLoadTask;
friend LoadingThread;
friend Asset;
public:
///
/// Checks if current execution context is thread used to load assets.
///
/// True if execution is in Load Thread, otherwise false.
FORCE_INLINE static bool IsInLoadThread()
{
return GetCurrentLoadThread() != nullptr;
}
///
/// Gets content loading thread handle if current thread is one of them.
///
/// Current load thread or null if current thread is different.
static LoadingThread* GetCurrentLoadThread();
public:
///
/// Gets amount of enqueued tasks to perform.
///
/// The tasks count.
static int32 GetTasksCount();
};