// OpenSTA, Static Timing Analyzer // Copyright (c) 2019, Parallax Software, Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #ifndef STA_THREAD_FOR_EACH_H #define STA_THREAD_FOR_EACH_H #include "Iterator.hh" #include "Thread.hh" #include "Mutex.hh" namespace sta { template class ForEachArg { public: ForEachArg() {} ForEachArg(Iterator *iter, Mutex *lock, Func *func) : iter_(iter), lock_(lock), func_(func) {} Iterator *iter_; Mutex *lock_; Func *func_; }; template void forEachBegin(void *arg) { ForEachArg *arg1 = reinterpret_cast*>(arg); Iterator *iter = arg1->iter_; Mutex *lock = arg1->lock_; Func *func = arg1->func_; while (true) { lock->lock(); if (iter->hasNext()) { FuncArg arg = iter->next(); lock->unlock(); (*func)(arg); } else { lock->unlock(); break; } } } // Parallel version of STL for_each. template void forEach(Iterator *iter, Func *func, int thread_count) { if (thread_count <= 1) { while (iter->hasNext()) (*func)(iter->next()); } else { Mutex lock; ForEachArg arg(iter, &lock, func); Thread *threads = new Thread[thread_count]; for (int i = 0; i < thread_count; i++) threads[i].beginTask(forEachBegin, reinterpret_cast(&arg)); for (int i = 0; i < thread_count; i++) threads[i].wait(); delete [] threads; } } // forEach2 is similar to forEach, except that each thread has // its own functor. // Func::copy() must be defined. template void forEach2(Iterator *iter, Func *func, int thread_count) { if (thread_count <= 1) { while (iter->hasNext()) (*func)(iter->next()); } else { ForEachArg *args = new ForEachArg[thread_count]; Thread *threads = new Thread[thread_count]; Mutex lock; for (int i = 0; i < thread_count; i++) { ForEachArg *arg = &args[i]; arg->iter_ = iter; arg->lock_ = &lock; arg->func_ = func->copy(); threads[i].beginTask(forEachBegin, reinterpret_cast(arg)); } for (int i = 0; i < thread_count; i++) { threads[i].wait(); ForEachArg *arg = &args[i]; delete arg->func_; } delete [] threads; delete [] args; } } } // namespace #endif