2018-09-28 17:54:21 +02:00
|
|
|
// OpenSTA, Static Timing Analyzer
|
2019-01-01 21:26:11 +01:00
|
|
|
// Copyright (c) 2019, Parallax Software, Inc.
|
2018-09-28 17:54:21 +02:00
|
|
|
//
|
|
|
|
|
// 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 <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
#ifndef STA_THREAD_FOR_EACH_H
|
|
|
|
|
#define STA_THREAD_FOR_EACH_H
|
|
|
|
|
|
2019-03-13 01:25:53 +01:00
|
|
|
#include <mutex>
|
|
|
|
|
#include <thread>
|
|
|
|
|
#include <vector>
|
2018-09-28 17:54:21 +02:00
|
|
|
#include "Iterator.hh"
|
|
|
|
|
|
|
|
|
|
namespace sta {
|
|
|
|
|
|
|
|
|
|
template<class Iterator, class Func>
|
|
|
|
|
class ForEachArg {
|
|
|
|
|
public:
|
2019-02-16 21:07:59 +01:00
|
|
|
ForEachArg(Iterator *iter,
|
2019-03-13 01:25:53 +01:00
|
|
|
std::mutex &lock,
|
2019-02-16 21:07:59 +01:00
|
|
|
Func *func) :
|
2018-09-28 17:54:21 +02:00
|
|
|
iter_(iter),
|
|
|
|
|
lock_(lock),
|
|
|
|
|
func_(func)
|
|
|
|
|
{}
|
|
|
|
|
|
2019-03-13 01:25:53 +01:00
|
|
|
~ForEachArg()
|
|
|
|
|
{
|
|
|
|
|
delete func_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy constructor.
|
|
|
|
|
ForEachArg(const ForEachArg &arg) :
|
|
|
|
|
iter_(arg.iter_),
|
|
|
|
|
lock_(arg.lock_),
|
|
|
|
|
func_(arg.func_->copy())
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
// Move constructor.
|
|
|
|
|
ForEachArg(ForEachArg &&arg) :
|
|
|
|
|
iter_(arg.iter_),
|
|
|
|
|
lock_(arg.lock_),
|
|
|
|
|
func_(arg.func_)
|
|
|
|
|
{
|
|
|
|
|
arg.func_ = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
Iterator *iter_;
|
2019-03-13 01:25:53 +01:00
|
|
|
std::mutex &lock_;
|
2018-09-28 17:54:21 +02:00
|
|
|
Func *func_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class Iterator, class Func, class FuncArg>
|
|
|
|
|
void
|
2019-03-13 01:25:53 +01:00
|
|
|
forEachBegin(ForEachArg<Iterator, Func> arg1)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
Iterator *iter = arg1.iter_;
|
|
|
|
|
std::mutex &lock = arg1.lock_;
|
|
|
|
|
Func *func = arg1.func_;
|
2018-09-28 17:54:21 +02:00
|
|
|
while (true) {
|
2019-03-13 01:25:53 +01:00
|
|
|
lock.lock();
|
2018-09-28 17:54:21 +02:00
|
|
|
if (iter->hasNext()) {
|
|
|
|
|
FuncArg arg = iter->next();
|
2019-03-13 01:25:53 +01:00
|
|
|
lock.unlock();
|
2018-09-28 17:54:21 +02:00
|
|
|
(*func)(arg);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2019-03-13 01:25:53 +01:00
|
|
|
lock.unlock();
|
2018-09-28 17:54:21 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parallel version of STL for_each.
|
2019-03-13 01:25:53 +01:00
|
|
|
// Each thread has its own functor.
|
|
|
|
|
// Func::copy() must be defined.
|
2018-09-28 17:54:21 +02:00
|
|
|
template<class Iterator, class Func, class FuncArg>
|
|
|
|
|
void
|
2019-02-16 21:07:59 +01:00
|
|
|
forEach(Iterator *iter,
|
|
|
|
|
Func *func,
|
|
|
|
|
int thread_count)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
if (thread_count <= 1) {
|
|
|
|
|
while (iter->hasNext())
|
|
|
|
|
(*func)(iter->next());
|
|
|
|
|
}
|
|
|
|
|
else {
|
2019-03-13 01:25:53 +01:00
|
|
|
std::vector<std::thread> threads;
|
|
|
|
|
std::mutex lock;
|
2018-09-28 17:54:21 +02:00
|
|
|
for (int i = 0; i < thread_count; i++) {
|
2019-03-13 01:25:53 +01:00
|
|
|
ForEachArg<Iterator,Func> arg(iter, lock, func->copy());
|
|
|
|
|
threads.push_back(std::thread(forEachBegin<Iterator,Func,FuncArg>, arg));
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
2019-03-13 01:25:53 +01:00
|
|
|
for (auto &thread : threads)
|
|
|
|
|
thread.join();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
#endif
|