Commit 752a02a3 authored by Sébastien Villemot's avatar Sébastien Villemot

Dynare++: use C++11 threads (instead of POSIX threads API)

On Windows, this means that a POSIX threads implementation is no longer needed,
since C++11 threads are implemented using native Windows threads.

On GNU/Linux and macOS, POSIX threads are still used under the hood.

A new m4 macro (AX_CXX11_THREAD) is used to add the proper compilation
flags (instead of AX_PTHREAD).
parent 5ea315db
Pipeline #681 failed with stages
in 70 minutes and 17 seconds
......@@ -70,7 +70,6 @@ A number of tools and libraries are needed in order to recompile everything. You
- [Autoconf](http://www.gnu.org/software/autoconf/), version 2.62 or later (only if you get the source through Git) (see [Installing an updated version of Autoconf in your own directory, in GNU/Linux](http://www.dynare.org/DynareWiki/AutoMake))
- [Automake](http://www.gnu.org/software/automake/), version 1.11.2 or later (only if you get the source through Git) (see [Installing an updated version of AutoMake in your own directory, in GNU/Linux](http://www.dynare.org/DynareWiki/AutoMake))
- An implementation of BLAS and LAPACK: either [ATLAS](http://math-atlas.sourceforge.net/), [OpenBLAS](http://xianyi.github.com/OpenBLAS/), Netlib ([BLAS](http://www.netlib.org/blas/), [LAPACK](http://www.netlib.org/lapack/)) or [MKL](http://software.intel.com/en-us/intel-mkl/) (only if you want to build Dynare++)
- An implementation of [POSIX Threads](http://en.wikipedia.org/wiki/POSIX_Threads) (optional, for taking advantage of multi-core)
- [MAT File I/O library](http://sourceforge.net/projects/matio/) (if you want to compile Markov-Switching code, the estimation DLL, k-order DLL and Dynare++)
- [SLICOT](http://www.slicot.org) (if you want to compile the Kalman steady state DLL)
- [GSL library](http://www.gnu.org/software/gsl/) (if you want to compile Markov-Switching code)
......
......@@ -79,6 +79,8 @@ CPPFLAGS="$CPPFLAGS_SAVED"
# Don't use deprecated hash structures
AC_DEFINE([BOOST_NO_HASH], [], [Don't use deprecated STL hash structures])
AX_CXX11_THREAD
# Check for libmatio, needed by Dynare++
AX_MATIO
AM_CONDITIONAL([HAVE_MATIO], [test "x$has_matio" = "xyes"])
......@@ -119,8 +121,6 @@ fi
AM_CONDITIONAL([HAVE_BLAS], [test x"$ax_blas_ok" = "xyes"])
AM_CONDITIONAL([HAVE_LAPACK], [test x"$ax_lapack_ok" = "xyes"])
AX_PTHREAD
AC_CONFIG_FILES([Makefile
VERSION
doc/Makefile
......@@ -181,11 +181,7 @@ AM_CONDITIONAL([ENABLE_ORG_EXPORT], [test "x$enable_org_export" != "x"])
# Construct final output message
if test "x$ax_blas_ok" = "xyes" -a "x$ax_lapack_ok" = "xyes" -a "x$has_matio" = "xyes"; then
if test x"$ax_pthread_ok" = "xyes"; then
BUILD_DYNAREPLUSPLUS="yes"
else
BUILD_DYNAREPLUSPLUS="yes (without POSIX threads)"
fi
BUILD_DYNAREPLUSPLUS="yes"
else
BUILD_DYNAREPLUSPLUS="no (missing one of: BLAS, LAPACK, MatIO)"
fi
......
......@@ -13,4 +13,4 @@ libinteg_a_SOURCES = \
vector_function.hh \
precalc_quadrature.hh
libinteg_a_CPPFLAGS = -I../../sylv/cc -I../../tl/cc -I$(top_srcdir)/mex/sources
libinteg_a_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
libinteg_a_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
......@@ -96,7 +96,7 @@ template <typename _Tpit>
class QuadratureImpl;
template <typename _Tpit>
class IntegrationWorker : public THREAD
class IntegrationWorker : public sthread::detach_thread
{
const QuadratureImpl<_Tpit> &quad;
VectorFunction &func;
......@@ -138,7 +138,7 @@ public:
}
{
SYNCHRO syn(&outvec, "IntegrationWorker");
sthread::synchro syn(&outvec, "IntegrationWorker");
outvec.add(1.0, tmpall);
}
}
......@@ -168,7 +168,7 @@ public:
// todo: out.length()==func.outdim()
// todo: dim == func.indim()
out.zeros();
THREAD_GROUP gr;
sthread::detach_thread_group gr;
for (int ti = 0; ti < fs.getNum(); ti++)
gr.insert(std::make_unique<IntegrationWorker<_Tpit>>(*this, fs.getFunc(ti),
level, ti, fs.getNum(), out));
......
......@@ -2,5 +2,5 @@ noinst_PROGRAMS = quadrature-points
quadrature_points_SOURCES = quadrature-points.cc
quadrature_points_CPPFLAGS = -I../.. -I../../sylv/cc -I../../integ/cc -I../../tl/cc
quadrature_points_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
quadrature_points_LDADD = ../cc/libinteg.a ../../tl/cc/libtl.a ../../parser/cc/libparser.a ../../sylv/cc/libsylv.a ../../utils/cc/libutils.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS)
quadrature_points_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
quadrature_points_LDADD = ../cc/libinteg.a ../../tl/cc/libtl.a ../../parser/cc/libparser.a ../../sylv/cc/libsylv.a ../../utils/cc/libutils.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS)
......@@ -2,9 +2,9 @@ check_PROGRAMS = tests
tests_SOURCES = tests.cc
tests_CPPFLAGS = -I../cc -I../../tl/cc -I../../sylv/cc -I$(top_srcdir)/mex/sources
tests_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
tests_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
tests_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
tests_LDADD = ../../tl/cc/libtl.a ../../sylv/cc/libsylv.a ../cc/libinteg.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS) $(LIBADD_MATIO)
tests_LDADD = ../../tl/cc/libtl.a ../../sylv/cc/libsylv.a ../cc/libinteg.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(LIBADD_MATIO)
check-local:
./tests
......@@ -498,7 +498,7 @@ main()
nvmax = test->nvar;
}
tls.init(dmax, nvmax); // initialize library
THREAD_GROUP::max_parallel_threads = num_threads;
sthread::detach_thread_group::max_parallel_threads = num_threads;
// launch the tests
int success = 0;
......
......@@ -27,15 +27,15 @@ libkord_a_SOURCES = \
random.hh
libkord_a_CPPFLAGS = -I../sylv/cc -I../tl/cc -I../integ/cc -I$(top_srcdir)/mex/sources $(CPPFLAGS_MATIO)
libkord_a_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
libkord_a_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
check_PROGRAMS = tests
tests_SOURCES = tests.cc
tests_CPPFLAGS = -I../sylv/cc -I../tl/cc -I../integ/cc -I$(top_srcdir)/mex/sources
tests_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
tests_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
tests_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
tests_LDADD = libkord.a ../tl/cc/libtl.a ../sylv/cc/libsylv.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS) $(LIBADD_MATIO)
tests_LDADD = libkord.a ../tl/cc/libtl.a ../sylv/cc/libsylv.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(LIBADD_MATIO)
check-local:
./tests
......
......@@ -90,7 +90,7 @@ SimResults::simulate(int num_sim, const DecisionRule &dr, const Vector &start,
std::vector<RandomShockRealization> rsrs;
rsrs.reserve(num_sim);
THREAD_GROUP gr;
sthread::detach_thread_group gr;
for (int i = 0; i < num_sim; i++)
{
RandomShockRealization sr(vcov, system_random_generator.int_uniform());
......@@ -331,7 +331,7 @@ SimResultsIRF::simulate(const DecisionRule &dr, Journal &journal)
void
SimResultsIRF::simulate(const DecisionRule &dr)
{
THREAD_GROUP gr;
sthread::detach_thread_group gr;
for (int idata = 0; idata < control.getNumSets(); idata++)
gr.insert(std::make_unique<SimulationIRFWorker>(*this, dr, DecisionRule::horner,
num_per, idata, ishock, imp));
......@@ -410,7 +410,7 @@ RTSimResultsStats::simulate(int num_sim, const DecisionRule &dr, const Vector &s
std::vector<RandomShockRealization> rsrs;
rsrs.reserve(num_sim);
THREAD_GROUP gr;
sthread::detach_thread_group gr;
for (int i = 0; i < num_sim; i++)
{
RandomShockRealization sr(vcov, system_random_generator.int_uniform());
......@@ -485,7 +485,7 @@ SimulationWorker::operator()()
auto *esr = new ExplicitShockRealization(sr, np);
TwoDMatrix *m = dr.simulate(em, np, st, *esr);
{
SYNCHRO syn(&res, "simulation");
sthread::synchro syn(&res, "simulation");
res.addDataSet(m, esr);
}
}
......@@ -504,7 +504,7 @@ SimulationIRFWorker::operator()()
TwoDMatrix *m = dr.simulate(em, np, st, *esr);
m->add(-1.0, res.control.getData(idata));
{
SYNCHRO syn(&res, "simulation");
sthread::synchro syn(&res, "simulation");
res.addDataSet(m, esr);
}
}
......@@ -546,7 +546,7 @@ RTSimulationWorker::operator()()
nc.update(y);
}
{
SYNCHRO syn(&res, "rtsimulation");
sthread::synchro syn(&res, "rtsimulation");
res.nc.update(nc);
if (res.num_per-ip > 0)
{
......
......@@ -908,7 +908,7 @@ public:
/* This worker simulates the given decision rule and inserts the result
to |SimResults|. */
class SimulationWorker : public THREAD
class SimulationWorker : public sthread::detach_thread
{
protected:
SimResults &res;
......@@ -933,7 +933,7 @@ public:
control simulations are contained in |SimResultsIRF| which is passed
to the constructor. */
class SimulationIRFWorker : public THREAD
class SimulationIRFWorker : public sthread::detach_thread
{
SimResultsIRF &res;
const DecisionRule &dr;
......@@ -960,7 +960,7 @@ public:
Inf is observed, it ends the simulation and adds to the
|thrown_periods| of |RTSimResultsStats|. */
class RTSimulationWorker : public THREAD
class RTSimulationWorker : public sthread::detach_thread
{
protected:
RTSimResultsStats &res;
......
......@@ -120,7 +120,7 @@ int
FaaDiBruno::estimRefinment(const TensorDimens &tdims, int nr, int l,
int &avmem_mb, int &tmpmem_mb)
{
int nthreads = THREAD_GROUP::max_parallel_threads;
int nthreads = sthread::detach_thread_group::max_parallel_threads;
long int per_size1 = tdims.calcUnfoldMaxOffset();
auto per_size2 = (long int) pow((double) tdims.getNVS().getMax(), l);
double lambda = 0.0;
......
......@@ -23,8 +23,8 @@ dynare___SOURCES = \
dynare___CPPFLAGS = -I../sylv/cc -I../tl/cc -I../kord -I../integ/cc -I.. -I$(top_srcdir)/mex/sources -DDYNVERSION=\"$(PACKAGE_VERSION)\" $(BOOST_CPPFLAGS) $(CPPFLAGS_MATIO)
dynare___LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO) $(BOOST_LDFLAGS)
dynare___LDADD = ../kord/libkord.a ../integ/cc/libinteg.a ../tl/cc/libtl.a ../parser/cc/libparser.a ../utils/cc/libutils.a ../sylv/cc/libsylv.a $(LIBADD_MATIO) $(noinst_LIBRARIES) $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS)
dynare___CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
dynare___LDADD = ../kord/libkord.a ../integ/cc/libinteg.a ../tl/cc/libtl.a ../parser/cc/libparser.a ../utils/cc/libutils.a ../sylv/cc/libsylv.a $(LIBADD_MATIO) $(noinst_LIBRARIES) $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS)
dynare___CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
BUILT_SOURCES = $(GENERATED_FILES)
EXTRA_DIST = dynglob.ll dynglob.yy
......
......@@ -31,7 +31,7 @@ main(int argc, char **argv)
printf(" for LGPL see http://www.gnu.org/licenses/lgpl.html\n");
return 0;
}
THREAD_GROUP::max_parallel_threads = params.num_threads;
sthread::detach_thread_group::max_parallel_threads = params.num_threads;
try
{
......@@ -118,7 +118,7 @@ main(int argc, char **argv)
if (params.check_along_path || params.check_along_shocks
|| params.check_on_ellipse)
{
GlobalChecker gcheck(app, THREAD_GROUP::max_parallel_threads, journal);
GlobalChecker gcheck(app, sthread::detach_thread_group::max_parallel_threads, journal);
if (params.check_along_shocks)
gcheck.checkAlongShocksAndSave(matfd, params.prefix,
params.getCheckShockPoints(),
......
......@@ -45,4 +45,4 @@ libtl_a_SOURCES = \
twod_matrix.cc \
twod_matrix.hh
libtl_a_CPPFLAGS = -I../../sylv/cc $(CPPFLAGS_MATIO)
libtl_a_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
libtl_a_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
......@@ -41,7 +41,7 @@ FoldedStackContainer::multAndAdd(int dim, const FGSContainer &c, FGSTensor &out)
TL_RAISE_IF(c.num() != numStacks(),
"Wrong symmetry length of container for FoldedStackContainer::multAndAdd");
THREAD_GROUP gr;
sthread::detach_thread_group gr;
SymmetrySet ss(dim, c.num());
for (symiterator si(ss); !si.isEnd(); ++si)
if (c.check(*si))
......@@ -76,7 +76,7 @@ void
FoldedStackContainer::multAndAddSparse1(const FSSparseTensor &t,
FGSTensor &out) const
{
THREAD_GROUP gr;
sthread::detach_thread_group gr;
UFSTensor dummy(0, numStacks(), t.dimen());
for (Tensor::index ui = dummy.begin(); ui != dummy.end(); ++ui)
gr.insert(std::make_unique<WorkerFoldMAASparse1>(*this, t, out, ui.getCoor()));
......@@ -121,7 +121,7 @@ WorkerFoldMAASparse1::operator()()
{
FPSTensor fps(out.getDims(), it, slice, kp);
{
SYNCHRO syn(&out, "WorkerUnfoldMAASparse1");
sthread::synchro syn(&out, "WorkerUnfoldMAASparse1");
fps.addTo(out);
}
}
......@@ -148,7 +148,7 @@ void
FoldedStackContainer::multAndAddSparse2(const FSSparseTensor &t,
FGSTensor &out) const
{
THREAD_GROUP gr;
sthread::detach_thread_group gr;
FFSTensor dummy_f(0, numStacks(), t.dimen());
for (Tensor::index fi = dummy_f.begin(); fi != dummy_f.end(); ++fi)
gr.insert(std::make_unique<WorkerFoldMAASparse2>(*this, t, out, fi.getCoor()));
......@@ -244,7 +244,7 @@ FoldedStackContainer::multAndAddSparse3(const FSSparseTensor &t,
void
FoldedStackContainer::multAndAddSparse4(const FSSparseTensor &t, FGSTensor &out) const
{
THREAD_GROUP gr;
sthread::detach_thread_group gr;
FFSTensor dummy_f(0, numStacks(), t.dimen());
for (Tensor::index fi = dummy_f.begin(); fi != dummy_f.end(); ++fi)
gr.insert(std::make_unique<WorkerFoldMAASparse4>(*this, t, out, fi.getCoor()));
......@@ -310,7 +310,7 @@ FoldedStackContainer::multAndAddStacks(const IntSequence &coor,
kp.optimizeOrder();
FPSTensor fps(out.getDims(), it, sort_per, ug, kp);
{
SYNCHRO syn(ad, "multAndAddStacks");
sthread::synchro syn(ad, "multAndAddStacks");
fps.addTo(out);
}
}
......@@ -351,7 +351,7 @@ FoldedStackContainer::multAndAddStacks(const IntSequence &coor,
KronProdStack<FGSTensor> kp(sp, coor);
FPSTensor fps(out.getDims(), it, sort_per, g, kp);
{
SYNCHRO syn(ad, "multAndAddStacks");
sthread::synchro syn(ad, "multAndAddStacks");
fps.addTo(out);
}
}
......@@ -394,7 +394,7 @@ UnfoldedStackContainer::multAndAdd(int dim, const UGSContainer &c,
TL_RAISE_IF(c.num() != numStacks(),
"Wrong symmetry length of container for UnfoldedStackContainer::multAndAdd");
THREAD_GROUP gr;
sthread::detach_thread_group gr;
SymmetrySet ss(dim, c.num());
for (symiterator si(ss); !si.isEnd(); ++si)
if (c.check(*si))
......@@ -441,7 +441,7 @@ void
UnfoldedStackContainer::multAndAddSparse1(const FSSparseTensor &t,
UGSTensor &out) const
{
THREAD_GROUP gr;
sthread::detach_thread_group gr;
UFSTensor dummy(0, numStacks(), t.dimen());
for (Tensor::index ui = dummy.begin(); ui != dummy.end(); ++ui)
gr.insert(std::make_unique<WorkerUnfoldMAASparse1>(*this, t, out, ui.getCoor()));
......@@ -503,7 +503,7 @@ WorkerUnfoldMAASparse1::operator()()
{
UPSTensor ups(out.getDims(), it, slice, kp);
{
SYNCHRO syn(&out, "WorkerUnfoldMAASparse1");
sthread::synchro syn(&out, "WorkerUnfoldMAASparse1");
ups.addTo(out);
}
}
......@@ -545,7 +545,7 @@ void
UnfoldedStackContainer::multAndAddSparse2(const FSSparseTensor &t,
UGSTensor &out) const
{
THREAD_GROUP gr;
sthread::detach_thread_group gr;
FFSTensor dummy_f(0, numStacks(), t.dimen());
for (Tensor::index fi = dummy_f.begin(); fi != dummy_f.end(); ++fi)
gr.insert(std::make_unique<WorkerUnfoldMAASparse2>(*this, t, out, fi.getCoor()));
......@@ -629,7 +629,7 @@ UnfoldedStackContainer::multAndAddStacks(const IntSequence &fi,
kp.optimizeOrder();
UPSTensor ups(out.getDims(), it, sort_per, g, kp);
{
SYNCHRO syn(ad, "multAndAddStacks");
sthread::synchro syn(ad, "multAndAddStacks");
ups.addTo(out);
}
}
......
......@@ -645,7 +645,7 @@ public:
}
};
class WorkerFoldMAADense : public THREAD
class WorkerFoldMAADense : public sthread::detach_thread
{
const FoldedStackContainer &cont;
Symmetry sym;
......@@ -659,7 +659,7 @@ public:
void operator()() override;
};
class WorkerFoldMAASparse1 : public THREAD
class WorkerFoldMAASparse1 : public sthread::detach_thread
{
const FoldedStackContainer &cont;
const FSSparseTensor &t;
......@@ -673,7 +673,7 @@ public:
void operator()() override;
};
class WorkerFoldMAASparse2 : public THREAD
class WorkerFoldMAASparse2 : public sthread::detach_thread
{
const FoldedStackContainer &cont;
const FSSparseTensor &t;
......@@ -686,7 +686,7 @@ public:
void operator()() override;
};
class WorkerFoldMAASparse4 : public THREAD
class WorkerFoldMAASparse4 : public sthread::detach_thread
{
const FoldedStackContainer &cont;
const FSSparseTensor &t;
......@@ -699,7 +699,7 @@ public:
void operator()() override;
};
class WorkerUnfoldMAADense : public THREAD
class WorkerUnfoldMAADense : public sthread::detach_thread
{
const UnfoldedStackContainer &cont;
Symmetry sym;
......@@ -713,7 +713,7 @@ public:
void operator()() override;
};
class WorkerUnfoldMAASparse1 : public THREAD
class WorkerUnfoldMAASparse1 : public sthread::detach_thread
{
const UnfoldedStackContainer &cont;
const FSSparseTensor &t;
......@@ -727,7 +727,7 @@ public:
void operator()() override;
};
class WorkerUnfoldMAASparse2 : public THREAD
class WorkerUnfoldMAASparse2 : public sthread::detach_thread
{
const UnfoldedStackContainer &cont;
const FSSparseTensor &t;
......
// Copyright 2004, Ondra Kamenik
/* We set the default values for
|max_parallel_threads| for both |posix| and |empty| implementation and
both joinable and detach group. For |posix| this defaults to
uniprocessor machine with hyper-threading, this is 2. */
#include <cstring>
#include "sthread.hh"
#ifdef HAVE_PTHREAD
namespace sthread
{
template<>
int thread_group<posix>::max_parallel_threads = 2;
template<>
int detach_thread_group<posix>::max_parallel_threads = 2;
// POSIX specializations methods
void *posix_thread_function(void *c);
template <>
void
thread_traits<posix>::run(_Ctype *c)
{
pthread_create(&(c->getThreadIden()), nullptr, posix_thread_function, (void *) c);
}
void *posix_detach_thread_function(void *c);
template <>
void
thread_traits<posix>::detach_run(_Dtype *c)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&(c->getThreadIden()), &attr, posix_detach_thread_function, (void *) c);
pthread_attr_destroy(&attr);
}
template <>
void
thread_traits<posix>::exit()
{
pthread_exit(nullptr);
}
template <>
void
thread_traits<posix>::join(_Ctype *c)
{
pthread_join(c->getThreadIden(), nullptr);
}
template <>
void
mutex_traits<posix>::init(pthread_mutex_t &m)
{
pthread_mutex_init(&m, nullptr);
}
template <>
void
mutex_traits<posix>::lock(pthread_mutex_t &m)
{
pthread_mutex_lock(&m);
}
template <>
void
mutex_traits<posix>::unlock(pthread_mutex_t &m)
{
pthread_mutex_unlock(&m);
}
template <>
void
cond_traits<posix>::init(_Tcond &cond)
{
pthread_cond_init(&cond, nullptr);
}
template <>
void
cond_traits<posix>::broadcast(_Tcond &cond)
{
pthread_cond_broadcast(&cond);
}
template <>
void
cond_traits<posix>::wait(_Tcond &cond, _Tmutex &mutex)
{
pthread_cond_wait(&cond, &mutex);
}
template <>
void
cond_traits<posix>::destroy(_Tcond &cond)
{
pthread_cond_destroy(&cond);
}
/* Here we instantiate the static map, and construct |PosixSynchro|
using that map. */
static posix_synchro::mutex_map_t posix_mm;
PosixSynchro::PosixSynchro(const void *c, const char *id)
: posix_synchro(c, id, posix_mm)
{
}
/* This function is of the type |void* function(void*)| as required by
POSIX, but it typecasts its argument and runs |operator()()|. */
void *
posix_thread_function(void *c)
{
auto *ct
= (thread_traits<posix>::_Ctype *)c;
try
/* We set the default value for |max_parallel_threads| to 2, i.e.
uniprocessor machine with hyper-threading */
int detach_thread_group::max_parallel_threads = 2;
/* The constructor acquires the mutex in the map. First it tries to
get an exclusive access to the map. Then it increases a number of
references of the mutex (if it does not exists, it inserts it). Then
unlocks the map, and finally tries to lock the mutex of the map. */
synchro::synchro(const void *c, std::string id)
: caller{c}, iden{std::move(id)}
{
mutmap.lock_map();
if (!mutmap.check(caller, iden))
mutmap.insert(caller, iden);
mutmap.get(caller, iden).second++;
mutmap.unlock_map();
mutmap.get(caller, iden).first.lock();
}
/* The destructor first locks the map. Then releases the lock,
and decreases a number of references. If it is zero, it removes the
mutex. */
synchro::~synchro()
{
mutmap.lock_map();
if (mutmap.check(caller, iden))
{
ct->operator()();
mutmap.get(caller, iden).first.unlock();
mutmap.get(caller, iden).second--;
if (mutmap.get(caller, iden).second == 0)
mutmap.remove(caller, iden);
}
catch (...)
{
ct->exit();
}
return nullptr;
}
void *
posix_detach_thread_function(void *c)
{
auto *ct
= (thread_traits<posix>::_Dtype *)c;
condition_counter<posix> *counter = ct->counter;
try
{
ct->operator()();
}
catch (...)
{
ct->exit();
}
if (counter)
counter->decrease();
return nullptr;
mutmap.unlock_map();
}
}
#else
namespace sthread
{
template<>
int thread_group<empty>::max_parallel_threads = 1;
template<>
int detach_thread_group<empty>::max_parallel_threads = 1;
// non-threading specialization methods
/* The only trait methods we need to work are |thread_traits::run| and
|thread_traits::detach_run|, which directly call
|operator()()|. Anything other is empty. */
template <>
void
thread_traits<empty>::run(_Ctype *c)
{
c->operator()();
}
template <>
void
thread_traits<empty>::detach_run(_Dtype *c)
{
c->operator()();
}
template <>
void
thread_traits<empty>::exit()
{
}
template <>
void
thread_traits<empty>::join(_Ctype *c)
{
}
/* We cycle through all threads in the group, and in each cycle we wait
for the change in the |counter|. If the counter indicates less than
maximum parallel threads running, then a new thread is run, and the
iterator in the list is moved.
template <>
At the end we have to wait for all thread to finish. */
void
mutex_traits<empty>::init(Empty &m)
{
}
template <>
void
mutex_traits<empty>::lock(Empty &m)
{
}
template <>
void
mutex_traits<empty>::unlock(Empty &m)
{
}
template <>
void
cond_traits<empty>::init(_Tcond &cond)
{
}
template <>
void
cond_traits<empty>::broadcast(_Tcond &cond)
{
}
template <>
void
cond_traits<empty>::wait(_Tcond &cond, _Tmutex &mutex)
{
}
template <>
void
cond_traits<empty>::destroy(_Tcond &cond)
detach_thread_group::run()
{
std::unique_lock<std::mutex> lk{m};
auto it = tlist.begin();
while (it != tlist.end())
{
counter++;
std::thread th{[&, it] {
// The "it" variable is captured by value, because otherwise the iterator may move
(*it)->operator()();
std::unique_lock<std::mutex> lk2{m};
counter--;
std::notify_all_at_thread_exit(cv, std::move(lk2));
}};
th.detach();
++it;
cv.wait(lk, [&] { return counter < max_parallel_threads; });
}
cv.wait(lk, [&] { return counter == 0; });
}
}
#endif
This diff is collapsed.
......@@ -2,9 +2,9 @@ check_PROGRAMS = tests
tests_SOURCES = factory.cc factory.hh monoms.cc monoms.hh tests.cc
tests_CPPFLAGS = -I../cc -I../../sylv/cc
tests_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
tests_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
tests_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
tests_LDADD = ../cc/libtl.a ../../sylv/cc/libsylv.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(PTHREAD_LIBS) $(LIBADD_MATIO)
tests_LDADD = ../cc/libtl.a ../../sylv/cc/libsylv.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) $(LIBADD_MATIO)
check-local:
./tests
......@@ -226,11 +226,6 @@ Files: m4/ax_blas.m4 m4/ax_lapack.m4
Copyright: 2008 Steven G. Johnson <stevenj@alum.mit.edu>
License: GPL-3+ with Autoconf exception
Files: m4/ax_pthread.m4
Copyright: 2008 Steven G. Johnson <stevenj@alum.mit.edu>
2011 Daniel Richard G. <skunk@iSKUNK.ORG>
License: GPL-3+ with Autoconf exception
Files: m4/ax_boost_base.m4
Copyright: 2008 Thomas Porschberg <thomas@randspringer.de>
2009 Peter Adolphs
......