void ForEach(const C& Enumerable, FUNCTION Function) { auto enumerator = Enumerable.GetEnumerator(); RF_Type::Size elements = enumerator.Size(); RF_Type::UInt32 worker, cport; RF_Pattern::Singleton<RF_Thread::ThreadPool>::GetInstance().GetThreadCount(worker, cport); RF_Type::UInt32 jobsPerWorker = 0; RF_Type::AtomicInt32 overallWork(elements); RF_Type::UInt32 extra = 1; if(elements > worker) { jobsPerWorker = elements / worker; elements -= jobsPerWorker * worker; } else { jobsPerWorker = 1; worker = elements; extra = 0; } for(RF_Type::UInt32 i = 0, offset = 0; i < worker; ++i) { if(elements <= i) extra = 0; auto* task = new ForEachEnumeratorTaskData<C, FUNCTION>(Function); task->Enumeable = enumerator; task->From = offset; task->Steps = jobsPerWorker + extra; task->OverallWork = &overallWork; RF_Pattern::Singleton<RF_Thread::ThreadPool>::GetInstance().QueueUserWorkItem(ForEachEnumeratorTaskFunction<C, FUNCTION>, task); offset += jobsPerWorker + extra; } // Wait for other threads. Sleep(0) will ensure that the thread return if no // other process/thread will work for the rest of the time slice on this core. Time::TimeSpan sleep = Time::TimeSpan::CreateByTicks(0); while(overallWork != 0) { System::Threading::Thread::Sleep(sleep); } }
Memory::AutoPointerArray<RF_Type::Size> FindAll(const C& Enumerable, FUNCTION Function) { auto enumerator = Enumerable.GetConstEnumerator(); RF_Type::Size elements = enumerator.Size(); RF_Type::AtomicInt32 hits; RF_Collect::Array<RF_Type::UInt8> results(elements); if(RF_Pattern::Singleton<RF_Thread::ThreadPool>::GetInstance().CanQueue()) { RF_Type::UInt32 worker; RF_Pattern::Singleton<RF_Thread::ThreadPool>::GetInstance().GetThreadCount( worker); RF_Type::UInt32 jobsPerWorker = 0; RF_Type::AtomicInt32 overallWork(elements); RF_Type::UInt32 extra = 1; if(elements > worker) { jobsPerWorker = elements / worker; elements -= jobsPerWorker * worker; } else { jobsPerWorker = 1; worker = elements; extra = 0; } for(RF_Type::UInt32 i = 0, offset = 0; i < worker; ++i) { if(elements <= i) { extra = 0; } auto* task = new FindAllEnumeratorTaskData<C, FUNCTION>(Function); task->Enumeable = enumerator; task->From = offset; task->Steps = jobsPerWorker + extra; task->OverallWork = &overallWork; task->Results = &results; task->Hits = &hits; RF_Pattern::Singleton<RF_Thread::ThreadPool>::GetInstance() .QueueUserWorkItem(FindAllEnumeratorTaskFunction<C, FUNCTION>, task); offset += jobsPerWorker + extra; } // Wait for other threads. Sleep(0) will ensure that the thread return if no // other process/thread will work for the rest of the time slice on this // core. RF_Time::TimeSpan sleep = RF_Time::TimeSpan::CreateByTicks(0); while(overallWork != 0) { RF_Thread::Thread::Sleep(sleep); } } else { for(RF_Type::Size i = 0; i < elements; ++i, ++enumerator) { if(Function(enumerator)) { hits.Increment(); results(i) = 1; } else { results(i) = 0; } } } RF_Mem::AutoPointerArray<RF_Type::Size> result(hits); for(RF_Type::Size i = 0, ci = 0; i < enumerator.Size(); ++i) { if(results(i) == 1) { result[ci] = i; ++ci; } } return result; }