Sample solution

Content

The wanted RAII class can be formulated quite simply:

struct Guard {
   Guard(std::mutex& mutex) : mutex(mutex) {
      mutex.lock();
   }
   ~Guard() {
      mutex.unlock();
   }
   std::mutex& mutex;
};

This allows to simplify the gen method:

double gen() {
   Guard guard(mutex);
   return uniform(mt);
}

It shouldn't be surprising that a similar class is present in the standard C++ library. It is named std::lock_guard and gets the mutex class as template parameter:

double gen() {
   std::lock_guard<std::mutex> guard(mutex);
   return uniform(mt);
}
#include <cstdlib>
#include <mutex>
#include <random>
#include <thread>
#include <vector>
#include <hpc/aux/slices.hpp>
#include <hpc/matvec/gematrix.hpp>
#include <hpc/matvec/iterators.hpp>
#include <hpc/matvec/print.hpp>
#include <hpc/matvec/views.hpp>

using namespace hpc;
using namespace hpc::aux;
using namespace hpc::matvec;

struct Guard {
   Guard(std::mutex& mutex) : mutex(mutex) {
      mutex.lock();
   }
   ~Guard() {
      mutex.unlock();
   }
   std::mutex& mutex;
};

struct MyRandomGenerator {
      MyRandomGenerator() : mt(std::random_device()()), uniform(-100, 100) {
      }
      double gen() {
	 Guard guard(mutex);
	 return uniform(mt);
      }
   private:
      std::mutex mutex;
      std::mt19937 mt;
      std::uniform_real_distribution<double> uniform;
};

template <
   template<typename> class MatrixA, typename T,
   typename RNG,
   Require< Ge<MatrixA<T>> > = true
>
void randomInit(MatrixA<T>& A, RNG& rng) {
   for (auto [i, j, Aij]: A) {
      Aij = rng.gen();
      (void) i; (void) j; // suppress gcc warning
   }
}

int main() {
   MyRandomGenerator rng;
   GeMatrix<double> A(51, 7);
   std::size_t nof_threads = std::thread::hardware_concurrency();

   std::vector<std::thread> threads(nof_threads);
   UniformSlices<std::size_t> slices(nof_threads, A.numRows());
   for (std::size_t index = 0; index < nof_threads; ++index) {
      auto firstRow = slices.offset(index);
      auto numRows = slices.size(index);
      threads[index] = std::thread([
	       A_ = A.view(firstRow, 0, numRows, A.numCols()),
	       &rng
	    ]() mutable {
	 randomInit(A_, rng);
      });
   }
   for (std::size_t index = 0; index < nof_threads; ++index) {
      threads[index].join();
   }
   print(A, " %7.2f");
}
theon$ g++ -O3 -g -I/home/numerik/pub/hpc/ws18/session16 -std=c++17 -o random_init9 random_init9.cpp
theon$ ./random_init9
    2.14  -16.66  -30.52  -59.51  -54.84   50.94   18.47
   97.60   81.93   66.43   80.94  -19.75  -32.74  -30.35
  -48.32   -2.27   33.39   63.60   69.51   63.03  -80.12
   53.40  -93.69   13.84   -0.89  -46.15   18.21   80.63
  -99.47  -82.29  -99.81   83.60   81.04  -67.13  -28.37
  -65.56  -66.86  -70.72   39.80   33.18  -33.67   64.92
   92.12   88.46   12.60   22.39  -42.37   22.88   96.79
   60.29   83.21   40.00  -39.72   66.07    3.49   97.29
   56.82   46.69   20.54   31.65   -0.25  -14.46   66.04
  -34.16  -27.55  -67.03  -72.45   82.19   84.03  -86.33
  -83.77  -35.66  -12.15   14.16  -30.09   -2.84   -5.55
  -88.26  -76.79   85.32  -55.87   97.51   69.40  -37.35
  -84.02  -74.92  -70.91  -72.01   31.57  -45.09   -3.58
  -41.75   99.41  -15.71  -34.43   41.03   91.97  -42.47
  -32.14  -61.15   87.01  -91.85  -11.52   95.41  -75.91
  -76.89   75.73  -15.34  -98.65   12.63   81.87    3.43
   92.15   87.41  -39.26   98.12  -90.28   -2.55   16.87
   65.20  -45.22  -40.87  -57.50  -59.38  -63.99   77.12
   89.25   20.18   69.50   43.04  -60.29  -24.75   47.01
  -47.04   93.82  -51.61  -89.33   35.03  -92.95   -0.36
   -1.87  -90.12  -79.87  -56.49   39.67   -1.92   64.39
  -22.16  -86.80   -8.89   86.60   54.01   51.52    5.84
   91.42   56.68    2.15   13.06  -54.15  -29.54  -15.78
   14.96   39.29   89.97  -47.18   70.49  -35.01   60.53
   79.31  -37.15   88.00  -94.42  -13.73   93.72  -24.10
   50.57  -49.15  -98.03  -74.45  -84.24  -77.64   66.33
   10.89   33.57  -53.76  -22.15  -56.44  -86.32  -41.51
   32.72  -54.13   96.05   86.06   13.28  -29.47   14.98
   -5.05   15.56   71.89  -66.75   64.28   72.51    6.65
  -40.47  -89.15  -16.15  -34.53    3.38   77.68  -54.12
   48.71  -65.30  -21.56   -6.80  -55.80  -48.40  -22.03
  -35.28  -10.38  -66.58   21.27   21.48  -15.27  -68.09
   52.20  -22.16  -40.13   47.84  -56.58    7.18   47.13
   49.69   91.75   -8.73  -95.79  -93.10  -93.50  -73.73
   63.80  -97.12   73.47   -7.85   47.64   77.59   -5.51
  -16.58  -12.49  -75.71  -18.79   34.11  -41.47  -76.42
   18.33   57.40  -20.57   16.88   32.54  -18.45   80.14
    5.31  -26.32  -41.78    4.71   92.34  -15.57  -13.98
   -2.54   62.72   69.98  -34.82   31.31  -91.76  -31.19
    8.61  -61.70  -39.48    1.98  -26.94   86.03   65.03
  -57.61   82.16    4.53   71.05  -56.47   42.03   -7.28
  -12.56   -3.18  -50.43   20.67   11.13  -35.79   70.33
    1.56  -86.69   71.12   23.59   29.46   36.95  -58.52
  -45.25   90.89  -64.57  -15.02  -18.43   96.71   50.82
  -15.49    4.88  -14.64   31.97  -19.20   37.54  -90.82
  -53.15  -30.75   79.37   66.25    0.30   61.98  -90.05
  -13.03    5.49  -50.54   57.11   87.01   95.84  -28.28
  -77.46   78.65  -17.99   -9.42   53.25  -34.46   42.90
   24.26  -83.25    2.74   -8.37  -16.36  -62.78  -20.23
   72.27   49.57   75.16    9.23  -56.92   16.82  -14.28
  -68.80  -82.97   86.77  -86.03   79.50   89.44  -59.49
theon$