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().
38 lines
1.2 KiB
C
38 lines
1.2 KiB
C
/* Copyright 2026 Dolphin Emulator Project
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#ifndef DOLPHIN_COMMON_PARALLEL_FOR_H
|
|
#define DOLPHIN_COMMON_PARALLEL_FOR_H
|
|
|
|
#include <stddef.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef void (*parallel_for_fn)(void *ctx, size_t index);
|
|
|
|
/* Runs fn(ctx, i) for every i in [0, count) and returns once all of them
|
|
* have run. The calls are spread over a pool of persistent worker threads
|
|
* (one per extra core, started on first use) and the calling thread, which
|
|
* takes jobs too. No locks: jobs are claimed with an atomic counter and the
|
|
* workers park on an eventcount between batches.
|
|
*
|
|
* Calls may come from any thread. While one batch runs, a call from another
|
|
* thread runs its jobs serially on that thread instead of waiting. A job must
|
|
* not call parallel_for itself unless it accepts that serial fallback. */
|
|
void parallel_for(size_t count, parallel_for_fn fn, void *ctx);
|
|
|
|
/* Number of threads parallel_for may run jobs on, the caller included. */
|
|
unsigned parallel_for_threads(void);
|
|
|
|
/* Joins the worker threads. Call when no batch can be running (the core's
|
|
* retro_deinit); the next parallel_for starts the pool again. */
|
|
void parallel_for_deinit(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|