From a29d1da57ba224e7ea1186d9dfffceb85ba28592 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Mon, 14 Aug 2017 11:57:19 -0230 Subject: [PATCH] Threaded Blargg + phosphor improvements: - Handle case of only 1 or zero (!) reported cores - Fix memory leak by using smart pointers --- src/common/tv_filters/AtariNTSC.cxx | 51 ++++++++++++++++------------- src/common/tv_filters/AtariNTSC.hxx | 10 +++--- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/common/tv_filters/AtariNTSC.cxx b/src/common/tv_filters/AtariNTSC.cxx index 0df5a6513..743bceebe 100644 --- a/src/common/tv_filters/AtariNTSC.cxx +++ b/src/common/tv_filters/AtariNTSC.cxx @@ -36,8 +36,21 @@ void AtariNTSC::initialize(const Setup& setup, const uInt8* palette) init(myImpl, setup); initializePalette(palette); - myNumThreads = std::min(4u, std::thread::hardware_concurrency()); - myThreads = new std::thread[myNumThreads]; + uInt32 systemThreads = std::thread::hardware_concurrency(); + if(systemThreads <= 1) + { + myWorkerThreads = 0; + myTotalThreads = 1; + } + else + { + systemThreads = std::min(4u, systemThreads); + + myWorkerThreads = systemThreads - 1; + myTotalThreads = systemThreads; + + myThreads = make_unique(myWorkerThreads); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -69,36 +82,30 @@ void AtariNTSC::initializePalette(const uInt8* palette) } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AtariNTSC::render(const uInt8* atari_in, const uInt32 in_width, - const uInt32 in_height, void* rgb_out, const uInt32 out_pitch) -{ - // Spawn the threads... - for(uInt8 i = 0; i < myNumThreads; i++) - myThreads[i] = std::thread([=] { - renderThread(atari_in, in_width, in_height, myNumThreads, i, rgb_out, out_pitch); - }); - // ...and make them join again - for(uInt8 i = 0; i < myNumThreads; i++) - myThreads[i].join(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AtariNTSC::render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height, void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in) { // Spawn the threads... - for(uInt8 i = 0; i < myNumThreads; i++) + for(uInt32 i = 0; i < myWorkerThreads; ++i) + { myThreads[i] = std::thread([=] { - renderWithPhosphorThread(atari_in, in_width, in_height, myNumThreads, i, - rgb_in, rgb_out, out_pitch); - }); + rgb_in == nullptr ? + renderThread(atari_in, in_width, in_height, myTotalThreads, i+1, rgb_out, out_pitch) : + renderWithPhosphorThread(atari_in, in_width, in_height, myTotalThreads, i+1, rgb_in, rgb_out, out_pitch); + }); + } + // Make the main thread busy too + rgb_in == nullptr ? + renderThread(atari_in, in_width, in_height, myTotalThreads, 0, rgb_out, out_pitch) : + renderWithPhosphorThread(atari_in, in_width, in_height, myTotalThreads, 0, rgb_in, rgb_out, out_pitch); // ...and make them join again - for(uInt8 i = 0; i < myNumThreads; i++) + for(uInt32 i = 0; i < myWorkerThreads; ++i) myThreads[i].join(); // Copy phosphor values into out buffer - memcpy(rgb_out, rgb_in, in_height * out_pitch); + if(rgb_in != nullptr) + memcpy(rgb_out, rgb_in, in_height * out_pitch); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/tv_filters/AtariNTSC.hxx b/src/common/tv_filters/AtariNTSC.hxx index 8bbea345e..44ffc294c 100644 --- a/src/common/tv_filters/AtariNTSC.hxx +++ b/src/common/tv_filters/AtariNTSC.hxx @@ -90,9 +90,7 @@ class AtariNTSC // In_row_width is the number of pixels to get to the next input row. // Out_pitch is the number of *bytes* to get to the next output row. void render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height, - void* rgb_out, const uInt32 out_pitch); - void render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height, - void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in); + void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in = nullptr); // Number of input pixels that will fit within given output width. // Might be rounded down slightly; use outWidth() on result to find @@ -165,9 +163,9 @@ class AtariNTSC uInt8 myPhosphorPalette[256][256]; // Rendering threads - std::thread* myThreads; - // Number of rendering threads - uInt8 myNumThreads; + unique_ptr myThreads; + // Number of rendering and total threads + uInt32 myWorkerThreads, myTotalThreads; struct init_t {