mirror of
https://github.com/libretro/parallel-gx1.git
synced 2026-11-07 12:37:59 -10:00
No std::thread, std::async, std::future or std::promise is left. Each
thread is an sthread with a plain entry point: Common::ThreadEntry<&C::F>
turns a member function into one, Common::JoinThread joins and clears a
handle, and Common::StartDetachedThread covers the fire-and-forget users.
Common/ParallelFor.{h,c} (C89) runs fn(ctx, i) for i in [0, count) on a
persistent pool of one worker per extra core plus the caller. Jobs are
claimed with an atomic counter, workers park on an eventcount between
batches, and the batch hand-off is a seq_cst users/active pair, so there
is no lock anywhere. A caller that finds the pool busy runs its batch
serially instead of waiting. retro_deinit joins the pool.
- VolumeWii::HashGroup spawned 64 threads per 2 MiB group and
EncryptGroup another one per core; both are now parallel_for batches
on the pool. The H1/H2 tail is a few small hashes and runs inline.
- VolumeVerifier spawned up to five std::async threads per chunk; the
chunk's tasks now go to one persistent worker that fans them out with
parallel_for, still overlapping the next read. The Redump lookup is an
sthread joined in Finish or the destructor.
- The dual-core "GPU thread" in Core only set a thread_local on itself
and exited, since the frontend runs the GPU loop. It is gone, along
with the non-libretro branches of Core.cpp.
- The emu thread is started through Core::StartEmuThread.
- CPU core counts come from cpu_features_get_core_amount().
76 lines
1.7 KiB
C++
76 lines
1.7 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#ifndef _WIN32
|
|
#include <tuple>
|
|
#endif
|
|
|
|
#include <rthreads/rthreads.h>
|
|
|
|
// Don't include Common.h here as it will break LogManager
|
|
#include "Common/CommonTypes.h"
|
|
|
|
// This may not be defined outside _WIN32
|
|
#ifndef _WIN32
|
|
#ifndef INFINITE
|
|
#define INFINITE 0xffffffff
|
|
#endif
|
|
#endif
|
|
|
|
namespace Common
|
|
{
|
|
int CurrentThreadId();
|
|
|
|
void SleepCurrentThread(int ms);
|
|
|
|
// Use this function during a spin-wait to make the current thread
|
|
// relax while another thread is working. This may be more efficient
|
|
// than using events because event functions use kernel calls.
|
|
void YieldCPU();
|
|
|
|
void SetCurrentThreadName(const char* name);
|
|
|
|
// An sthread entry point that calls F on the object passed as the thread's userdata:
|
|
// m_thread = sthread_create(Common::ThreadEntry<&Foo::Run>, this);
|
|
template <auto F>
|
|
struct ThreadEntryOf;
|
|
template <typename C, void (C::*F)()>
|
|
struct ThreadEntryOf<F>
|
|
{
|
|
static void Run(void* data) { (static_cast<C*>(data)->*F)(); }
|
|
};
|
|
template <auto F>
|
|
inline void ThreadEntry(void* data)
|
|
{
|
|
ThreadEntryOf<F>::Run(data);
|
|
}
|
|
|
|
// Starts a thread nobody joins. Returns false if it couldn't be started.
|
|
inline bool StartDetachedThread(void (*entry)(void*), void* data)
|
|
{
|
|
sthread_t* const thread = sthread_create(entry, data);
|
|
if (!thread)
|
|
return false;
|
|
sthread_detach(thread);
|
|
return true;
|
|
}
|
|
|
|
// Joins and clears an sthread handle; does nothing for a null one.
|
|
inline void JoinThread(sthread_t*& thread)
|
|
{
|
|
if (thread)
|
|
{
|
|
sthread_join(thread);
|
|
thread = nullptr;
|
|
}
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
// Returns the lowest address of the stack and the size of the stack
|
|
std::tuple<void*, size_t> GetCurrentThreadStack();
|
|
#endif
|
|
|
|
} // namespace Common
|