#include <thread>
#include <random>
#include <condition_variable>
#include <cstdlib>
#include <list>
#include <mutex>
#include <vector>
#include <hpc/matvec/gematrix.h>
#include <hpc/matvec/apply.h>
#include <hpc/matvec/print.h>
#include <hpc/aux/slices.h>
template<typename T>
struct RandomEnginePool {
using EngineType = T;
RandomEnginePool(std::size_t size) :
size(size), nof_free_engines(size),
inuse(size), engines(size) {
std::random_device r;
for (std::size_t i = 0; i < size; ++i) {
engines[i].seed(r()); inuse[i] = false;
}
}
T& get() {
std::unique_lock<std::mutex> lock(mutex);
if (nof_free_engines == 0) {
cv.wait(lock);
}
for (std::size_t i = 0; i < size; ++i) {
if (!inuse[i]) {
inuse[i] = true; --nof_free_engines;
return engines[i];
}
}
assert(false);
}
void free(T& engine) {
{
std::unique_lock<std::mutex> lock(mutex);
bool found = false;
for (std::size_t i = 0; i < size; ++i) {
if (&engine == &engines[i]) {
inuse[i] = false; ++nof_free_engines;
found = true; break;
}
}
assert(found);
}
cv.notify_one();
}
private:
std::mutex mutex;
std::condition_variable cv;
std::size_t size;
std::size_t nof_free_engines;
std::vector<bool> inuse;
std::vector<T> engines;
};
template<typename T>
struct RandomEngineGuard {
using EngineType = T;
RandomEngineGuard(RandomEnginePool<T>& pool) : pool(pool), engine(pool.get()) {
}
~RandomEngineGuard() {
pool.free(engine);
}
T& get() {
return engine;
}
RandomEnginePool<T>& pool;
T& engine;
};
template<typename MA, typename Pool>
typename std::enable_if<hpc::matvec::IsRealGeMatrix<MA>::value, void>::type
randomInit(MA& A, Pool& pool) {
using ElementType = typename MA::ElementType;
using Index = typename MA::Index;
using EngineType = typename Pool::EngineType;
std::uniform_real_distribution<double> uniform(-100, 100);
RandomEngineGuard<EngineType> guard(pool);
auto& engine(guard.get());
hpc::matvec::apply(A, [&](ElementType& val, Index i, Index j) -> void {
val = uniform(engine);
});
}
int main() {
using namespace hpc::matvec;
using namespace hpc::aux;
RandomEnginePool<std::mt19937> pool(2);
GeMatrix<double> A(51, 7);
unsigned int nof_threads = std::thread::hardware_concurrency();
std::vector<std::thread> threads(nof_threads);
Slices<GeMatrix<double>::Index> slices(nof_threads, A.numRows);
for (int index = 0; index < nof_threads; ++index) {
auto firstRow = slices.offset(index);
auto numRows = slices.size(index);
auto A_ = A(firstRow, 0, numRows, A.numCols);
threads[index] = std::thread([=,&pool]() mutable { randomInit(A_, pool); });
}
for (int index = 0; index < nof_threads; ++index) {
threads[index].join();
}
print(A, "A");
}