Kyty/source/emulator/include/Emulator/Graphics/AsyncJob.h

94 lines
1.9 KiB
C
Raw Normal View History

2021-12-01 09:29:27 +00:00
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Threads.h"
#include "Emulator/Common.h"
#include "Emulator/Profiler.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
class AsyncJob
{
public:
using func_t = std::function<void(void*)>;
2022-05-25 10:07:51 +00:00
explicit AsyncJob(const char* name): m_name(name), m_thread(new Core::Thread(ThreadRun, this)) {}
2021-12-01 09:29:27 +00:00
virtual ~AsyncJob()
{
EXIT_IF(m_thread == nullptr);
Core::LockGuard lock(m_mutex);
m_need_exit = true;
m_cond_var1.Signal();
m_thread->Join();
delete m_thread;
}
KYTY_CLASS_NO_COPY(AsyncJob);
void Execute(func_t func, void* arg = nullptr)
{
Core::LockGuard lock(m_mutex);
while (m_func != nullptr)
{
m_cond_var2.Wait(&m_mutex);
}
m_func = std::move(func);
m_arg = arg;
m_cond_var1.Signal();
}
void Wait()
{
Core::LockGuard lock(m_mutex);
while (m_func != nullptr)
{
m_cond_var2.Wait(&m_mutex);
}
}
private:
Core::Mutex m_mutex;
Core::CondVar m_cond_var1;
Core::CondVar m_cond_var2;
2022-05-25 10:07:51 +00:00
const char* m_name = nullptr;
func_t m_func = nullptr;
void* m_arg = nullptr;
bool m_need_exit = false;
Core::Thread* m_thread = nullptr;
2021-12-01 09:29:27 +00:00
static void ThreadRun(void* data)
{
// printf("Start AsyncJob Thread: 0x%" PRIx64 "\n", static_cast<uint64_t>(GetCurrentThreadId()));
auto* aj = static_cast<AsyncJob*>(data);
if (aj->m_name != nullptr)
{
KYTY_PROFILER_THREAD(aj->m_name);
}
for (;;)
{
Core::LockGuard lock(aj->m_mutex);
while (aj->m_func == nullptr && !aj->m_need_exit)
{
aj->m_cond_var1.Wait(&aj->m_mutex);
}
if (aj->m_need_exit)
{
break;
}
aj->m_func(aj->m_arg);
aj->m_func = nullptr;
aj->m_cond_var2.Signal();
}
}
};
} // namespace Kyty::Libs::Graphics
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_ */