diff --git a/README.md b/README.md
index 15beba9c836ac803dfe2d25559e987b7c541d002..c45ac36ca0010b3b4c2331a3241a4a8bf7e2bc17 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/configure.ac b/configure.ac
index ed4964c18a7d904905a0203d8062372971e44705..e7ce6f8a4ad5e701088c132aca68c8128cf0eef7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/dynare++/integ/cc/Makefile.am b/dynare++/integ/cc/Makefile.am
index 7b2833703bec50c148c7f88414c0085fc47e11ef..03805a2b5c2e15f3a2cee7ffcb1da23229a05316 100644
--- a/dynare++/integ/cc/Makefile.am
+++ b/dynare++/integ/cc/Makefile.am
@@ -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)
diff --git a/dynare++/integ/cc/quadrature.hh b/dynare++/integ/cc/quadrature.hh
index 62890d80f898e25001c9dc4b681fe26efa202c59..ae10ea809155805efdc3ba61249bfbe7d664794a 100644
--- a/dynare++/integ/cc/quadrature.hh
+++ b/dynare++/integ/cc/quadrature.hh
@@ -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));
diff --git a/dynare++/integ/src/Makefile.am b/dynare++/integ/src/Makefile.am
index 8c55df19e3005630f28399b676356993d437bb97..b0088d9be33d47208617af63e6ea1092e8e96476 100644
--- a/dynare++/integ/src/Makefile.am
+++ b/dynare++/integ/src/Makefile.am
@@ -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)
diff --git a/dynare++/integ/testing/Makefile.am b/dynare++/integ/testing/Makefile.am
index 3838bcb888b7fac82bf080bf515337b2a56f5bec..69a47f0ad50cce0b024b595929dbe03b7b5522fe 100644
--- a/dynare++/integ/testing/Makefile.am
+++ b/dynare++/integ/testing/Makefile.am
@@ -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
diff --git a/dynare++/integ/testing/tests.cc b/dynare++/integ/testing/tests.cc
index fdb5bbd0cced2cc191e930b591124d27fd55b2b7..eb52034cd1ae4f67555da17c30346f60bf583cd4 100644
--- a/dynare++/integ/testing/tests.cc
+++ b/dynare++/integ/testing/tests.cc
@@ -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;
diff --git a/dynare++/kord/Makefile.am b/dynare++/kord/Makefile.am
index f804335c516c541dd7b615bdde333e253f4a7bb2..2ee51fafff358e206252822591ebad2312da1344 100644
--- a/dynare++/kord/Makefile.am
+++ b/dynare++/kord/Makefile.am
@@ -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
diff --git a/dynare++/kord/decision_rule.cc b/dynare++/kord/decision_rule.cc
index aade85af6c59ca97c05928fe0ea81dc3c0c2cd9a..5227605606ebe6e2d0109b62a55b73d8de977cf2 100644
--- a/dynare++/kord/decision_rule.cc
+++ b/dynare++/kord/decision_rule.cc
@@ -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)
       {
diff --git a/dynare++/kord/decision_rule.hh b/dynare++/kord/decision_rule.hh
index 72f0081b0f24174dc9e8716e5758e93814a3e018..917fa9fb97cc9e21e7e8ff9c34fb836d8cde2519 100644
--- a/dynare++/kord/decision_rule.hh
+++ b/dynare++/kord/decision_rule.hh
@@ -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;
diff --git a/dynare++/kord/faa_di_bruno.cc b/dynare++/kord/faa_di_bruno.cc
index 45fd5f6134c8cef08dbb86cdaef7356a0b66b90e..d303d2b945ac79c6017defdd85dd3f43775c86f4 100644
--- a/dynare++/kord/faa_di_bruno.cc
+++ b/dynare++/kord/faa_di_bruno.cc
@@ -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;
diff --git a/dynare++/src/Makefile.am b/dynare++/src/Makefile.am
index e3b56ee1e5299eb8320a30e7bb3558679d2a4317..5201a921b0359a3befef664ceade4ca87fd5e8d8 100644
--- a/dynare++/src/Makefile.am
+++ b/dynare++/src/Makefile.am
@@ -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
diff --git a/dynare++/src/main.cc b/dynare++/src/main.cc
index 39dba693c2ac30cbb371e38f3c220ad40281ec8e..cd92a3bda69f2044f305df00989057f3358bb5a5 100644
--- a/dynare++/src/main.cc
+++ b/dynare++/src/main.cc
@@ -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(),
diff --git a/dynare++/tl/cc/Makefile.am b/dynare++/tl/cc/Makefile.am
index d1a4e23866c94ebd6b0f5f8fca300d685b479ebd..544ea0ff6b87a7c3672a3f406fdfdc1673096a9c 100644
--- a/dynare++/tl/cc/Makefile.am
+++ b/dynare++/tl/cc/Makefile.am
@@ -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)
diff --git a/dynare++/tl/cc/stack_container.cc b/dynare++/tl/cc/stack_container.cc
index 6af9f5633105eb0aae6b8f1c75aa9490b887f83f..a79c5bfa92e18c9606e50e56bfe286ba790626df 100644
--- a/dynare++/tl/cc/stack_container.cc
+++ b/dynare++/tl/cc/stack_container.cc
@@ -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);
                       }
                     }
diff --git a/dynare++/tl/cc/stack_container.hh b/dynare++/tl/cc/stack_container.hh
index 074eb69002c905dcb02cffcc7f9031d271d0bb9b..218623bb60e1dcfe14a9dc15a0224ebfcaf78dae 100644
--- a/dynare++/tl/cc/stack_container.hh
+++ b/dynare++/tl/cc/stack_container.hh
@@ -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;
diff --git a/dynare++/tl/cc/sthread.cc b/dynare++/tl/cc/sthread.cc
index b742219289fd7dff430b94921bacd1ae0be94138..c3db848a08a9f9b459979c279df21e91e17680b4 100644
--- a/dynare++/tl/cc/sthread.cc
+++ b/dynare++/tl/cc/sthread.cc
@@ -1,232 +1,70 @@
 // 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
diff --git a/dynare++/tl/cc/sthread.hh b/dynare++/tl/cc/sthread.hh
index e8c223045caa7986b456fabcf651500bda634549..bf979e7ec60ef45e1c712c52a8c8fea986950768 100644
--- a/dynare++/tl/cc/sthread.hh
+++ b/dynare++/tl/cc/sthread.hh
@@ -3,24 +3,18 @@
 // Simple threads.
 
 /* This file defines types making a simple interface to
-   multi-threading. It follows the classical C++ idioms for traits. We
-   have three sorts of traits. The first is a |thread_traits|, which make
-   interface to thread functions (run, exit, create and join), the second
-   is |mutex_traits|, which make interface to mutexes (create, lock,
-   unlock), and third is |cond_traits|, which make interface to
-   conditions (create, wait, broadcast, and destroy). At present, there
-   are two implementations. The first are POSIX threads, mutexes, and
-   conditions, the second is serial (no parallelization).
+   multi-threading.
 
-   The file provides the following interfaces templated by the types
-   implementing the threading (like types |pthread_t|, and |pthread_mutex_t|
-   for POSIX thread and mutex):
+   The file provides the following interfaces:
    \unorderedlist
-   \li |thread| is a pure virtual class, which must be inherited and a
+   \li |detach_thread| is a pure virtual class, which must be inherited and a
    method |operator()()| be implemented as the running code of the
-   thread. This code is run as a new thread by calling |run| method.
-   \li |thread_group| allows insertion of |thread|s and running all of
-   them simultaneously joining them. The number of maximum parallel
+   thread.
+   \li |detach_thread_group| allows insertion of |detach_thread|s and running
+   all of them simultaneously. The threads
+   are not joined, they are synchronized by means of a counter counting
+   running threads. A change of the counter is checked by waiting on an
+   associated condition. The number of maximum parallel
    threads can be controlled. See below.
    \li |synchro| object locks a piece of code to be executed only serially
    for a given data and specified entry-point. It locks the code until it
@@ -28,212 +22,27 @@
    on the stack of a function which is to be synchronized. The
    synchronization can be subjected to specific data (then a pointer can
    be passed to |synchro|'s constructor), and can be subjected to
-   specific entry-point (then |const char*| is passed to the
+   specific entry-point (then |std::string| is passed to the
    constructor).
-   \li |detach_thread| inherits from |thread| and models a detached
-   thread in contrast to |thread| which models the joinable thread.
-   \li |detach_thread_group| groups the detached threads and runs them. They
-   are not joined, they are synchronized by means of a counter counting
-   running threads. A change of the counter is checked by waiting on an
-   associated condition.
    \endunorderedlist
 
-   What implementation is selected is governed (at present) by
-   |HAVE_PTHREAD|. If it is defined, then POSIX threads are linked. If
-   it is not defined, then serial implementation is taken. In accordance
-   with this, the header file defines macros |THREAD|, |THREAD_GROUP|,
-   and |SYNCHRO| as the picked specialization of |thread| (or |detach_thread|),
-   |thread_group| (or |detach_thread_group|), and |synchro|.
-
-   The type of implementation is controlled by |thread_impl| integer
-   template parameter, this can be |posix| or |empty|.
-
    The number of maximum parallel threads is controlled via a static
-   member of |thread_group| and |detach_thread_group| classes. */
+   member of the |detach_thread_group| class. */
 
 #ifndef STHREAD_H
 #define STHREAD_H
 
-#ifdef HAVE_PTHREAD
-# include <pthread.h>
-#else
-/* Give valid types for POSIX thread types, otherwise the templates fail in empty mode.
-   Don't use typedefs because on some systems |pthread_t| and friends are typedefs even
-   without the include. */
-# define pthread_t void *
-# define pthread_mutex_t void *
-# define pthread_cond_t void *
-#endif
-
-#include <cstdio>
-#include <list>
+#include <vector>
 #include <map>
-#include <type_traits>
 #include <memory>
 #include <utility>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
 
 namespace sthread
 {
-  using namespace std;
-
-  class Empty
-  {
-  };
-
-  enum { posix, empty};
-
-  template <int thread_impl>
-  class thread;
-  template <int>
-  class detach_thread;
-
-  /* Clear. We have only |run|, |detach_run|, |exit| and |join|, since
-     this is only a simple interface. */
-
-  template <int thread_impl>
-  struct thread_traits
-  {
-    using _Tthread = std::conditional_t<thread_impl == posix, pthread_t, Empty>;
-    using _Ctype = thread<0>;
-    using _Dtype = detach_thread<0>;
-    static void run(_Ctype *c);
-    static void detach_run(_Dtype *c);
-    static void exit();
-    static void join(_Ctype *c);
-  };
-
-  /* The class of |thread| is clear. The user implements |operator()()|,
-     the method |run| runs the user's code as joinable thread, |exit| kills the
-     execution. */
-  template <int thread_impl>
-  class thread
-  {
-    using _Ttraits = thread_traits<0>;
-    using _Tthread = typename _Ttraits::_Tthread;
-    _Tthread th;
-  public:
-    virtual ~thread()
-    = default;
-    _Tthread &
-    getThreadIden()
-    {
-      return th;
-    }
-    const _Tthread &
-    getThreadIden() const
-    {
-      return th;
-    }
-    virtual void operator()() = 0;
-    void
-    run()
-    {
-      _Ttraits::run(this);
-    }
-    void
-    detach_run()
-    {
-      _Ttraits::detach_run(this);
-    }
-    void
-    exit()
-    {
-      _Ttraits::exit();
-    }
-  };
-
-  /* The |thread_group| is also clear. We allow a user to insert the
-     |thread|s, and then launch |run|, which will run all the threads not
-     allowing more than |max_parallel_threads| joining them at the
-     end. This static member can be set from outside. */
-
-  template <int thread_impl>
-  class thread_group
-  {
-    using _Ttraits = thread_traits<thread_impl>;
-    using _Ctype = thread<thread_impl>;
-    list<_Ctype *> tlist;
-    using iterator = typename list<_Ctype *>::iterator;
-  public:
-    static int max_parallel_threads;
-    void
-    insert(_Ctype *c)
-    {
-      tlist.push_back(c);
-    }
-    /* The thread group class maintains list of pointers to threads. It
-       takes responsibility of deallocating the threads. So we implement the
-       destructor. */
-    ~thread_group()
-    {
-      while (!tlist.empty())
-        {
-          delete tlist.front();
-          tlist.pop_front();
-        }
-    }
-    /* Here we run the threads ensuring that not more than
-       |max_parallel_threads| are run in parallel. More over, we do not want
-       to run a too low number of threads, since it is wasting with resource
-       (if there are). Therefore, we run in parallel |max_parallel_threads|
-       batches as long as the remaining threads are greater than the double
-       number. And then the remaining batch (less than |2*max_parallel_threads|)
-       is run half by half. */
-
-    void
-    run()
-    {
-      int rem = tlist.size();
-      iterator pfirst = tlist.begin();
-      while (rem > 2*max_parallel_threads)
-        {
-          pfirst = run_portion(pfirst, max_parallel_threads);
-          rem -= max_parallel_threads;
-        }
-      if (rem > max_parallel_threads)
-        {
-          pfirst = run_portion(pfirst, rem/2);
-          rem -= rem/2;
-        }
-      run_portion(pfirst, rem);
-    }
-
-  private:
-    /* This runs a given number of threads in parallel starting from the
-       given iterator. It returns the first iterator not run. */
-
-    iterator
-    run_portion(iterator start, int n)
-    {
-      int c = 0;
-      for (iterator i = start; c < n; ++i, c++)
-        {
-          (*i)->run();
-        }
-      iterator ret;
-      c = 0;
-      for (ret = start; c < n; ++ret, c++)
-        {
-          _Ttraits::join(*ret);
-        }
-      return ret;
-    }
-  };
-
-
-  /* Clear. We have only |init|, |lock|, and |unlock|. */
-  struct ltmmkey;
-  using mmkey = pair<const void *, const char *>;
-
-  template <int thread_impl>
-  struct mutex_traits
-  {
-    using _Tmutex = std::conditional_t<thread_impl == posix, pthread_mutex_t, Empty>;
-    using mutex_int_map = map<mmkey, pair<_Tmutex, int>, ltmmkey>;
-    static void init(_Tmutex &m);
-    static void lock(_Tmutex &m);
-    static void unlock(_Tmutex &m);
-  };
+  using mmkey = std::pair<const void *, std::string>;
 
   /* Here we define a map of mutexes keyed by a pair of address, and a
      string. A purpose of the map of mutexes is that, if synchronizing, we
@@ -258,230 +67,77 @@ namespace sthread
     operator()(const mmkey &k1, const mmkey &k2) const
     {
       return k1.first < k2.first
-                        || (k1.first == k2.first && strcmp(k1.second, k2.second) < 0);
+                        || (k1.first == k2.first && k1.second < k2.second);
     }
   };
 
-  template <int thread_impl>
-  class mutex_map :
-    public mutex_traits<thread_impl>::mutex_int_map
+  using mutex_int_map = std::map<mmkey, std::pair<std::mutex, int>, ltmmkey>;
+
+  class mutex_map : public mutex_int_map
   {
-    using _Tmutex = typename mutex_traits<thread_impl>::_Tmutex;
-    using _Mtraits = mutex_traits<thread_impl>;
-    using mmval = pair<_Tmutex, int>;
-    using _Tparent = map<mmkey, mmval, ltmmkey>;
-    using iterator = typename _Tparent::iterator;
-    using _mvtype = typename _Tparent::value_type;
-    _Tmutex m;
+    using mmval = std::pair<std::mutex, int>;
+    std::mutex m;
   public:
-    mutex_map()
-    {
-      _Mtraits::init(m);
-    }
+    mutex_map() = default;
     void
-    insert(const void *c, const char *id, const _Tmutex &m)
+    insert(const void *c, std::string id)
     {
-      _Tparent::insert(_mvtype(mmkey(c, id), mmval(m, 0)));
+      // We cannot use emplace(), because std::mutex is neither copyable nor moveable
+      operator[](mmkey{c, std::move(id)}).second = 0;
     }
     bool
-    check(const void *c, const char *id) const
+    check(const void *c, std::string id) const
     {
-      return _Tparent::find(mmkey(c, id)) != _Tparent::end();
+      return find(mmkey{c, std::move(id)}) != end();
     }
-    /* This returns a pointer to the pair of mutex and count reference number. */
-    mmval *
-    get(const void *c, const char *id)
+    /* This returns the pair of mutex and count reference number. */
+    mmval &
+    get(const void *c, std::string id)
     {
-      auto it = _Tparent::find(mmkey(c, id));
-      if (it == _Tparent::end())
-        return nullptr;
-      return &((*it).second);
+      return operator[](mmkey{c, std::move(id)});
     }
 
     /* This removes unconditionally the mutex from the map regardless its
        number of references. The only user of this class should be |synchro|
        class, it implementation must not remove referenced mutex. */
-
     void
-    remove(const void *c, const char *id)
+    remove(const void *c, std::string id)
     {
-      auto it = _Tparent::find(mmkey(c, id));
-      if (it != _Tparent::end())
-        this->erase(it);
+      auto it = find(mmkey{c, std::string{id}});
+      if (it != end())
+        erase(it);
     }
     void
     lock_map()
     {
-      _Mtraits::lock(m);
+      m.lock();
     }
     void
     unlock_map()
     {
-      _Mtraits::unlock(m);
+      m.unlock();
     }
 
   };
 
+
+  // The global map used by the synchro class
+  static mutex_map mutmap;
+
   /* This is the |synchro| class. The constructor of this class tries to
      lock a mutex for a particular address (identification of data) and
      string (identification of entry-point). If the mutex is already
      locked, it waits until it is unlocked and then returns. The destructor
      releases the lock. The typical use is to construct the object on the
      stacked of the code being synchronized. */
-
-  template <int thread_impl>
   class synchro
   {
-    using _Tmutex = typename mutex_traits<thread_impl>::_Tmutex;
-    using _Mtraits = mutex_traits<0>;
-  public:
-    using mutex_map_t = mutex_map<0>;
   private:
     const void *caller;
-    const char *iden;
-    mutex_map_t &mutmap;
+    const std::string iden;
   public:
-    synchro(const void *c, const char *id, mutex_map_t &mmap)
-      : caller(c), iden(id), mutmap(mmap)
-    {
-      lock();
-    }
-    ~synchro()
-    {
-      unlock();
-    }
-  private:
-    /* The |lock| function 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. */
-
-    void
-    lock()
-    {
-      mutmap.lock_map();
-      if (!mutmap.check(caller, iden))
-        {
-          _Tmutex mut;
-          _Mtraits::init(mut);
-          mutmap.insert(caller, iden, mut);
-        }
-      mutmap.get(caller, iden)->second++;
-      mutmap.unlock_map();
-      _Mtraits::lock(mutmap.get(caller, iden)->first);
-    }
-
-    /* The |unlock| function first locks the map. Then releases the lock,
-       and decreases a number of references. If it is zero, it removes the
-       mutex. */
-
-    void
-    unlock()
-    {
-      mutmap.lock_map();
-      if (mutmap.check(caller, iden))
-        {
-          _Mtraits::unlock(mutmap.get(caller, iden)->first);
-          mutmap.get(caller, iden)->second--;
-          if (mutmap.get(caller, iden)->second == 0)
-            mutmap.remove(caller, iden);
-        }
-      mutmap.unlock_map();
-    }
-  };
-
-  /* These are traits for conditions. We need |init|, |broadcast|, |wait|
-     and |destroy|. */
-
-  template <int thread_impl>
-  struct cond_traits
-  {
-    using _Tcond = std::conditional_t<thread_impl == posix, pthread_cond_t, Empty>;
-    using _Tmutex = typename mutex_traits<thread_impl>::_Tmutex;
-    static void init(_Tcond &cond);
-    static void broadcast(_Tcond &cond);
-    static void wait(_Tcond &cond, _Tmutex &mutex);
-    static void destroy(_Tcond &cond);
-  };
-
-  /* Here is the condition counter. It is a counter which starts at 0,
-     and can be increased and decreased. A thread can wait until the
-     counter is changed, this is implemented by condition. After the wait
-     is done, another (or the same) thread, by calling |waitForChange|
-     waits for another change. This can be dangerous, since it is possible
-     to wait for a change which will not happen, because all the threads
-     which can cause the change (by increase of decrease) might had
-     finished. */
-
-  template <int thread_impl>
-  class condition_counter
-  {
-    using _Tmutex = typename mutex_traits<thread_impl>::_Tmutex;
-    using _Tcond = typename cond_traits<thread_impl>::_Tcond;
-    int counter{0};
-    _Tmutex mut;
-    _Tcond cond;
-    bool changed{true};
-  public:
-    /* We initialize the counter to 0, and |changed| flag to |true|, since
-       the counter was change from undefined value to 0. */
-
-    condition_counter()
-       
-    {
-      mutex_traits<thread_impl>::init(mut);
-      cond_traits<thread_impl>::init(cond);
-    }
-
-    /* In destructor, we only release the resources associated with the
-       condition. */
-
-    ~condition_counter()
-    {
-      cond_traits<thread_impl>::destroy(cond);
-    }
-
-    /* When increasing, we lock the mutex, advance the counter, remember it
-       is changed, broadcast, and release the mutex. */
-
-    void
-    increase()
-    {
-      mutex_traits<thread_impl>::lock(mut);
-      counter++;
-      changed = true;
-      cond_traits<thread_impl>::broadcast(cond);
-      mutex_traits<thread_impl>::unlock(mut);
-    }
-
-    /* Same as increase. */
-    void
-    decrease()
-    {
-      mutex_traits<thread_impl>::lock(mut);
-      counter--;
-      changed = true;
-      cond_traits<thread_impl>::broadcast(cond);
-      mutex_traits<thread_impl>::unlock(mut);
-    }
-
-    /* We lock the mutex, and if there was a change since the last call of
-       |waitForChange|, we return immediately, otherwise we wait for the
-       change. The mutex is released. */
-
-    int
-    waitForChange()
-    {
-      mutex_traits<thread_impl>::lock(mut);
-      if (!changed)
-        {
-          cond_traits<thread_impl>::wait(cond, mut);
-        }
-      changed = false;
-      int res = counter;
-      mutex_traits<thread_impl>::unlock(mut);
-      return res;
-    }
+    synchro(const void *c, std::string id);
+    ~synchro();
   };
 
   /* The detached thread is the same as joinable |thread|. We only
@@ -489,122 +145,36 @@ namespace sthread
      a method which installs a counter. The counter is increased and
      decreased on the body of the new thread. */
 
-  template <int thread_impl>
-  class detach_thread : public thread<thread_impl>
+  class detach_thread
   {
   public:
-    condition_counter<thread_impl> *counter;
-    detach_thread() : counter(nullptr)
-    {
-    }
-    void
-    installCounter(condition_counter<thread_impl> *c)
-    {
-      counter = c;
-    }
-    void
-    run()
-    {
-      thread_traits<thread_impl>::detach_run(this);
-    }
+    virtual ~detach_thread() = default;
+    virtual void operator()() = 0;
   };
 
   /* The detach thread group is (by interface) the same as
      |thread_group|. The extra thing we have here is the |counter|. The
      implementation of |insert| and |run| is different. */
 
-  template<int thread_impl>
   class detach_thread_group
   {
-    using _Ttraits = thread_traits<thread_impl>;
-    using _Ctraits = cond_traits<thread_impl>;
-    using _Ctype = detach_thread<thread_impl>;
-    list<unique_ptr<_Ctype>> tlist;
-    using iterator = typename list<unique_ptr<_Ctype>>::iterator;
-    condition_counter<thread_impl> counter;
+    std::vector<std::unique_ptr<detach_thread>> tlist;
+    std::mutex m; // For the condition variable and the counter
+    std::condition_variable cv;
+    int counter{0};
   public:
     static int max_parallel_threads;
 
-    /* When inserting, the counter is installed to the thread. */
     void
-    insert(unique_ptr<_Ctype> c)
+    insert(std::unique_ptr<detach_thread> c)
     {
-      c->installCounter(&counter);
-      tlist.push_back(move(c));
+      tlist.push_back(std::move(c));
     }
 
     ~detach_thread_group() = default;
 
-    /* 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.
-
-       At the end we have to wait for all thread to finish. */
-
-    void
-    run()
-    {
-      int mpt = max_parallel_threads;
-      auto it = tlist.begin();
-      while (it != tlist.end())
-        {
-          if (counter.waitForChange() < mpt)
-            {
-              counter.increase();
-              (*it)->run();
-              ++it;
-            }
-        }
-      while (counter.waitForChange() > 0)
-        {
-        }
-    }
-  };
-
-#ifdef HAVE_PTHREAD
-  // POSIX thread specializations
-  /* Here we only define the specializations for POSIX threads. Then we
-     define the macros. Note that the |PosixSynchro| class construct itself
-     from the static map defined in {\tt sthreads.cpp}. */
-  using PosixThread = detach_thread<posix>;
-  using PosixThreadGroup = detach_thread_group<posix>;
-  using posix_synchro = synchro<posix>;
-  class PosixSynchro : public posix_synchro
-  {
-  public:
-    PosixSynchro(const void *c, const char *id);
+    void run();
   };
-
-# define THREAD sthread::PosixThread
-# define THREAD_GROUP sthread::PosixThreadGroup
-# define SYNCHRO sthread::PosixSynchro
-
-#else
-  // No threading specializations@>=
-  /* Here we define an empty class and use it as thread and
-     mutex. |NoSynchro| class is also empty, but an empty constructor is
-     declared. The empty destructor is declared only to avoid ``unused
-     variable warning''. */
-  using NoThread = thread<empty>;
-  using NoThreadGroup = thread_group<empty>;
-  using no_synchro = synchro<empty>;
-  class NoSynchro
-  {
-  public:
-    NoSynchro(const void *c, const char *id)
-    {
-    }
-    ~NoSynchro()
-    {
-    }
-  };
-
-# define THREAD sthread::NoThread
-# define THREAD_GROUP sthread::NoThreadGroup
-# define SYNCHRO sthread::NoSynchro
-
-#endif
 };
 
 #endif
diff --git a/dynare++/tl/testing/Makefile.am b/dynare++/tl/testing/Makefile.am
index a30233defd9429d279f7cd2edb180c51e9e30912..815a0da311dae0b2ed9707b6c5fa95a9ab8c9a2b 100644
--- a/dynare++/tl/testing/Makefile.am
+++ b/dynare++/tl/testing/Makefile.am
@@ -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
diff --git a/license.txt b/license.txt
index b90dea083f32050395eb4e3ba18a28550876b5e0..15c08afd165a040236344b46472ac6539bd2e6a5 100644
--- a/license.txt
+++ b/license.txt
@@ -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
diff --git a/m4/ax_cxx11_thread.m4 b/m4/ax_cxx11_thread.m4
new file mode 100644
index 0000000000000000000000000000000000000000..4fa2bb0852ae9fdd449dbf71c9a551d8d6ce7eb4
--- /dev/null
+++ b/m4/ax_cxx11_thread.m4
@@ -0,0 +1,33 @@
+dnl Adds flags needed to compile programs using C++11 threads
+
+dnl Copyright (C) 2019 Dynare Team
+dnl
+dnl This file is part of Dynare.
+dnl
+dnl Dynare is free software: you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation, either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl Dynare is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+
+AC_DEFUN([AX_CXX11_THREAD],
+[
+    AC_REQUIRE([AC_CANONICAL_BUILD])
+    case ${host_os} in
+      *mingw32*)
+        THREAD_CXXFLAGS="-mthreads $THREAD_CXXFLAGS"
+        ;;
+      *)
+        THREAD_CXXFLAGS="-pthread $THREAD_CXXFLAGS"
+        ;;
+    esac
+
+    AC_SUBST(THREAD_CXXFLAGS)
+])
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
deleted file mode 100644
index d383ad5c6d6a5061370800bb1dc89b7a334c0638..0000000000000000000000000000000000000000
--- a/m4/ax_pthread.m4
+++ /dev/null
@@ -1,332 +0,0 @@
-# ===========================================================================
-#        http://www.gnu.org/software/autoconf-archive/ax_pthread.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
-#
-# DESCRIPTION
-#
-#   This macro figures out how to build C programs using POSIX threads. It
-#   sets the PTHREAD_LIBS output variable to the threads library and linker
-#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler
-#   flags that are needed. (The user can also force certain compiler
-#   flags/libs to be tested by setting these environment variables.)
-#
-#   Also sets PTHREAD_CC to any special C compiler that is needed for
-#   multi-threaded programs (defaults to the value of CC otherwise). (This
-#   is necessary on AIX to use the special cc_r compiler alias.)
-#
-#   NOTE: You are assumed to not only compile your program with these flags,
-#   but also link it with them as well. e.g. you should link with
-#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
-#
-#   If you are only building threads programs, you may wish to use these
-#   variables in your default LIBS, CFLAGS, and CC:
-#
-#     LIBS="$PTHREAD_LIBS $LIBS"
-#     CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-#     CC="$PTHREAD_CC"
-#
-#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
-#   has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
-#   (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
-#
-#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
-#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with
-#   PTHREAD_CFLAGS.
-#
-#   ACTION-IF-FOUND is a list of shell commands to run if a threads library
-#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
-#   is not found. If ACTION-IF-FOUND is not specified, the default action
-#   will define HAVE_PTHREAD.
-#
-#   Please let the authors know if this macro fails on any platform, or if
-#   you have any other suggestions or comments. This macro was based on work
-#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
-#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
-#   Alejandro Forero Cuervo to the autoconf macro repository. We are also
-#   grateful for the helpful feedback of numerous users.
-#
-#   Updated for Autoconf 2.68 by Daniel Richard G.
-#
-# LICENSE
-#
-#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
-#   Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
-#
-#   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 <http://www.gnu.org/licenses/>.
-#
-#   As a special exception, the respective Autoconf Macro's copyright owner
-#   gives unlimited permission to copy, distribute and modify the configure
-#   scripts that are the output of Autoconf when processing the Macro. You
-#   need not follow the terms of the GNU General Public License when using
-#   or distributing such scripts, even though portions of the text of the
-#   Macro appear in them. The GNU General Public License (GPL) does govern
-#   all other use of the material that constitutes the Autoconf Macro.
-#
-#   This special exception to the GPL applies to versions of the Autoconf
-#   Macro released by the Autoconf Archive. When you make and distribute a
-#   modified version of the Autoconf Macro, you may extend this special
-#   exception to the GPL to apply to your modified version as well.
-
-#serial 21
-
-AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
-AC_DEFUN([AX_PTHREAD], [
-AC_REQUIRE([AC_CANONICAL_HOST])
-AC_LANG_PUSH([C])
-ax_pthread_ok=no
-
-# We used to check for pthread.h first, but this fails if pthread.h
-# requires special compiler flags (e.g. on True64 or Sequent).
-# It gets checked for in the link test anyway.
-
-# First of all, check if the user has set any of the PTHREAD_LIBS,
-# etcetera environment variables, and if threads linking works using
-# them:
-if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
-        save_CFLAGS="$CFLAGS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-        save_LIBS="$LIBS"
-        LIBS="$PTHREAD_LIBS $LIBS"
-        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
-        AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
-        AC_MSG_RESULT([$ax_pthread_ok])
-        if test x"$ax_pthread_ok" = xno; then
-                PTHREAD_LIBS=""
-                PTHREAD_CFLAGS=""
-        fi
-        LIBS="$save_LIBS"
-        CFLAGS="$save_CFLAGS"
-fi
-
-# We must check for the threads library under a number of different
-# names; the ordering is very important because some systems
-# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
-# libraries is broken (non-POSIX).
-
-# Create a list of thread flags to try.  Items starting with a "-" are
-# C compiler flags, and other items are library names, except for "none"
-# which indicates that we try without any flags at all, and "pthread-config"
-# which is a program returning the flags for the Pth emulation library.
-
-ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
-
-# The ordering *is* (sometimes) important.  Some notes on the
-# individual items follow:
-
-# pthreads: AIX (must check this before -lpthread)
-# none: in case threads are in libc; should be tried before -Kthread and
-#       other compiler flags to prevent continual compiler warnings
-# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
-# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
-# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
-# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
-# -pthreads: Solaris/gcc
-# -mthreads: Mingw32/gcc, Lynx/gcc
-# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
-#      doesn't hurt to check since this sometimes defines pthreads too;
-#      also defines -D_REENTRANT)
-#      ... -mt is also the pthreads flag for HP/aCC
-# pthread: Linux, etcetera
-# --thread-safe: KAI C++
-# pthread-config: use pthread-config program (for GNU Pth library)
-
-case ${host_os} in
-        solaris*)
-
-        # On Solaris (at least, for some versions), libc contains stubbed
-        # (non-functional) versions of the pthreads routines, so link-based
-        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
-        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
-        # a function called by this macro, so we could check for that, but
-        # who knows whether they'll stub that too in a future libc.)  So,
-        # we'll just look for -pthreads and -lpthread first:
-
-        ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
-        ;;
-
-        darwin*)
-        ax_pthread_flags="-pthread $ax_pthread_flags"
-        ;;
-esac
-
-# Clang doesn't consider unrecognized options an error unless we specify
-# -Werror. We throw in some extra Clang-specific options to ensure that
-# this doesn't happen for GCC, which also accepts -Werror.
-
-AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
-save_CFLAGS="$CFLAGS"
-ax_pthread_extra_flags="-Werror"
-CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
-                  [AC_MSG_RESULT([yes])],
-                  [ax_pthread_extra_flags=
-                   AC_MSG_RESULT([no])])
-CFLAGS="$save_CFLAGS"
-
-if test x"$ax_pthread_ok" = xno; then
-for flag in $ax_pthread_flags; do
-
-        case $flag in
-                none)
-                AC_MSG_CHECKING([whether pthreads work without any flags])
-                ;;
-
-                -*)
-                AC_MSG_CHECKING([whether pthreads work with $flag])
-                PTHREAD_CFLAGS="$flag"
-                ;;
-
-                pthread-config)
-                AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
-                if test x"$ax_pthread_config" = xno; then continue; fi
-                PTHREAD_CFLAGS="`pthread-config --cflags`"
-                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
-                ;;
-
-                *)
-                AC_MSG_CHECKING([for the pthreads library -l$flag])
-                PTHREAD_LIBS="-l$flag"
-                ;;
-        esac
-
-        save_LIBS="$LIBS"
-        save_CFLAGS="$CFLAGS"
-        LIBS="$PTHREAD_LIBS $LIBS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
-
-        # Check for various functions.  We must include pthread.h,
-        # since some functions may be macros.  (On the Sequent, we
-        # need a special flag -Kthread to make this header compile.)
-        # We check for pthread_join because it is in -lpthread on IRIX
-        # while pthread_create is in libc.  We check for pthread_attr_init
-        # due to DEC craziness with -lpthreads.  We check for
-        # pthread_cleanup_push because it is one of the few pthread
-        # functions on Solaris that doesn't have a non-functional libc stub.
-        # We try pthread_create on general principles.
-        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
-                        static void routine(void *a) { a = 0; }
-                        static void *start_routine(void *a) { return a; }],
-                       [pthread_t th; pthread_attr_t attr;
-                        pthread_create(&th, 0, start_routine, 0);
-                        pthread_join(th, 0);
-                        pthread_attr_init(&attr);
-                        pthread_cleanup_push(routine, 0);
-                        pthread_cleanup_pop(0) /* ; */])],
-                [ax_pthread_ok=yes],
-                [])
-
-        LIBS="$save_LIBS"
-        CFLAGS="$save_CFLAGS"
-
-        AC_MSG_RESULT([$ax_pthread_ok])
-        if test "x$ax_pthread_ok" = xyes; then
-                break;
-        fi
-
-        PTHREAD_LIBS=""
-        PTHREAD_CFLAGS=""
-done
-fi
-
-# Various other checks:
-if test "x$ax_pthread_ok" = xyes; then
-        save_LIBS="$LIBS"
-        LIBS="$PTHREAD_LIBS $LIBS"
-        save_CFLAGS="$CFLAGS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-
-        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
-        AC_MSG_CHECKING([for joinable pthread attribute])
-        attr_name=unknown
-        for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
-            AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
-                           [int attr = $attr; return attr /* ; */])],
-                [attr_name=$attr; break],
-                [])
-        done
-        AC_MSG_RESULT([$attr_name])
-        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
-            AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
-                               [Define to necessary symbol if this constant
-                                uses a non-standard name on your system.])
-        fi
-
-        AC_MSG_CHECKING([if more special flags are required for pthreads])
-        flag=no
-        case ${host_os} in
-            aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
-            osf* | hpux*) flag="-D_REENTRANT";;
-            solaris*)
-            if test "$GCC" = "yes"; then
-                flag="-D_REENTRANT"
-            else
-                # TODO: What about Clang on Solaris?
-                flag="-mt -D_REENTRANT"
-            fi
-            ;;
-        esac
-        AC_MSG_RESULT([$flag])
-        if test "x$flag" != xno; then
-            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
-        fi
-
-        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
-            [ax_cv_PTHREAD_PRIO_INHERIT], [
-                AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
-                                                [[int i = PTHREAD_PRIO_INHERIT;]])],
-                    [ax_cv_PTHREAD_PRIO_INHERIT=yes],
-                    [ax_cv_PTHREAD_PRIO_INHERIT=no])
-            ])
-        AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
-            [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
-
-        LIBS="$save_LIBS"
-        CFLAGS="$save_CFLAGS"
-
-        # More AIX lossage: compile with *_r variant
-        if test "x$GCC" != xyes; then
-            case $host_os in
-                aix*)
-                AS_CASE(["x/$CC"],
-                  [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
-                  [#handle absolute path differently from PATH based program lookup
-                   AS_CASE(["x$CC"],
-                     [x/*],
-                     [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
-                     [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
-                ;;
-            esac
-        fi
-fi
-
-test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
-
-AC_SUBST([PTHREAD_LIBS])
-AC_SUBST([PTHREAD_CFLAGS])
-AC_SUBST([PTHREAD_CC])
-
-# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
-if test x"$ax_pthread_ok" = xyes; then
-        ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
-        :
-else
-        ax_pthread_ok=no
-        $2
-fi
-AC_LANG_POP
-])dnl AX_PTHREAD
diff --git a/mex/build/dynare_simul_.am b/mex/build/dynare_simul_.am
index 05716b9a26fb10cc80565668beecdbc92740fb36..1416c6d79e3fe0ffb1232b7e60ca027d715e1945 100644
--- a/mex/build/dynare_simul_.am
+++ b/mex/build/dynare_simul_.am
@@ -2,10 +2,9 @@ mex_PROGRAMS = dynare_simul_
 
 dynare_simul__CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/../../../dynare++/sylv/cc -I$(top_srcdir)/../../../dynare++/tl/cc -I$(top_srcdir)/../../../dynare++/kord -I$(top_srcdir)/../../sources $(CPPFLAGS_MATIO)
 
-dynare_simul__CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
+dynare_simul__CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
 
-# libdynare++ must come before pthread
 dynare_simul__LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
-dynare_simul__LDADD = ../libdynare++/libdynare++.a $(PTHREAD_LIBS) $(LIBADD_MATIO)
+dynare_simul__LDADD = ../libdynare++/libdynare++.a $(LIBADD_MATIO)
 
 nodist_dynare_simul__SOURCES = $(top_srcdir)/../../../dynare++/extern/matlab/dynare_simul.cc
diff --git a/mex/build/k_order_perturbation.am b/mex/build/k_order_perturbation.am
index 84655171dd718273f2ad447761e201363a9116f9..0b3e8be840a78cb5f5f00d7fd3d59c8969cffbad 100644
--- a/mex/build/k_order_perturbation.am
+++ b/mex/build/k_order_perturbation.am
@@ -2,11 +2,10 @@ mex_PROGRAMS = k_order_perturbation
 
 k_order_perturbation_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/../../../dynare++/src -I$(top_srcdir)/../../../dynare++/kord -I$(top_srcdir)/../../../dynare++/tl/cc -I$(top_srcdir)/../../../dynare++/utils/cc -I$(top_srcdir)/../../../dynare++/sylv/cc -I$(top_srcdir)/../../../dynare++/integ/cc -I$(top_srcdir)/../../sources $(CPPFLAGS_MATIO)
 
-k_order_perturbation_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
+k_order_perturbation_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
 
-# libdynare++ must come before pthread
 k_order_perturbation_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
-k_order_perturbation_LDADD = ../libdynare++/libdynare++.a $(PTHREAD_LIBS) $(LIBADD_DLOPEN) $(LIBADD_MATIO)
+k_order_perturbation_LDADD = ../libdynare++/libdynare++.a $(LIBADD_DLOPEN) $(LIBADD_MATIO)
 
 TOPDIR = $(top_srcdir)/../../sources/k_order_perturbation
 
diff --git a/mex/build/libdynare++.am b/mex/build/libdynare++.am
index b18dddd06b212cfb999bc1de2031c8b490c6c9da..4dfa0839a77f51ec8e4bdc836279e3d813c74350 100644
--- a/mex/build/libdynare++.am
+++ b/mex/build/libdynare++.am
@@ -2,7 +2,7 @@ noinst_LIBRARIES = libdynare++.a
 
 libdynare___a_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/../../../dynare++/src -I$(top_srcdir)/../../../dynare++/kord -I$(top_srcdir)/../../../dynare++/tl/cc -I$(top_srcdir)/../../../dynare++/utils/cc -I$(top_srcdir)/../../../dynare++/sylv/cc -I$(top_srcdir)/../../../dynare++/integ/cc -I$(top_srcdir)/../../sources $(CPPFLAGS_MATIO)
 
-libdynare___a_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
+libdynare___a_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
 
 TOPDIR = $(top_srcdir)/../../../dynare++
 
diff --git a/mex/build/matlab/configure.ac b/mex/build/matlab/configure.ac
index b95039d758a91ff5cce4edb38cebd83f89aead37..f6ea729583c4c0fa6c067e2f76688219c14df8d4 100644
--- a/mex/build/matlab/configure.ac
+++ b/mex/build/matlab/configure.ac
@@ -75,7 +75,8 @@ case ${host_os} in
     CXXFLAGS="$CXXFLAGS -stdlib=libc++"
     ;;
 esac
-AX_PTHREAD
+
+AX_CXX11_THREAD
 
 # Check for dlopen(), needed by k_order_perturbation DLL
 AC_CHECK_LIB([dl], [dlopen], [LIBADD_DLOPEN="-ldl"], [])
@@ -95,9 +96,6 @@ AM_CONDITIONAL([HAVE_SLICOT], [test "x$has_slicot" = "xyes"])
 # On Windows, we want static linking of the external libraries
 case ${host_os} in
   *mingw32*)
-    # We hardcode -lpthread here, otherwise it is not detected by the
-    # AX_PTHREAD macro and therefore not statically linked
-    PTHREAD_LIBS="-Wl,-Bstatic -lpthread -Wl,-Bdynamic"
     GSL_LIBS="-Wl,-Bstatic $GSL_LIBS -Wl,-Bdynamic"
     LIBADD_MATIO="-Wl,-Bstatic $LIBADD_MATIO -Wl,-Bdynamic"
     LIBADD_SLICOT="-Wl,-Bstatic $LIBADD_SLICOT -Wl,-Bdynamic"
@@ -107,11 +105,7 @@ esac
 AM_CONDITIONAL([DO_SOMETHING], [test "x$ax_enable_matlab" = "xyes" -a "x$ax_matlab_version_ok" = "xyes" -a "x$ax_mexopts_ok" = "xyes"])
 
 if test "x$ax_enable_matlab" = "xyes" -a "x$ax_matlab_version_ok" = "xyes" -a "x$ax_mexopts_ok" = "xyes"; then
-  if test x"$ax_pthread_ok" = "xyes"; then
-     BUILD_MEX_MATLAB="yes"
-  else
-     BUILD_MEX_MATLAB="yes (without POSIX threads)"
-  fi
+  BUILD_MEX_MATLAB="yes"
 else
   BUILD_MEX_MATLAB="no (missing MATLAB, or unknown version, or unknown architecture)"
 fi
diff --git a/mex/build/octave/configure.ac b/mex/build/octave/configure.ac
index c12fc6f11c536e349ec551658b6dea5504152333..1d9ebdb495cd6ca2295db2454640bc3800886fd3 100644
--- a/mex/build/octave/configure.ac
+++ b/mex/build/octave/configure.ac
@@ -48,7 +48,9 @@ AC_PROG_RANLIB
 AX_PROG_LN_S
 AC_PROG_MKDIR_P
 AM_PROG_AR
-AX_PTHREAD
+
+AX_CXX11_THREAD
+
 # Check for dlopen(), needed by k_order_perturbation DLL
 AC_CHECK_LIB([dl], [dlopen], [LIBADD_DLOPEN="-ldl"], [])
 AC_SUBST([LIBADD_DLOPEN])
@@ -78,11 +80,7 @@ AC_SUBST([LIBADD_UMFPACK])
 AM_CONDITIONAL([DO_SOMETHING], [test "x$MKOCTFILE" != "x"])
 
 if test "x$MKOCTFILE" != "x"; then
-  if test x"$ax_pthread_ok" = "xyes"; then
-     BUILD_MEX_OCTAVE="yes"
-  else
-     BUILD_MEX_OCTAVE="yes (without POSIX threads)"
-  fi
+  BUILD_MEX_OCTAVE="yes"
 else
   BUILD_MEX_OCTAVE="no (missing mkoctfile)"
 fi
diff --git a/mex/sources/k_order_perturbation/k_order_perturbation.cc b/mex/sources/k_order_perturbation/k_order_perturbation.cc
index 4d5e5c25f338fa828b8068e2ed9fde85531a46e0..98b3058aaad61fbb0c84b96ec54ee7fa90bac88c 100644
--- a/mex/sources/k_order_perturbation/k_order_perturbation.cc
+++ b/mex/sources/k_order_perturbation/k_order_perturbation.cc
@@ -220,7 +220,7 @@ extern "C" {
     const int nSteps = 0; // Dynare++ solving steps, for time being default to 0 = deterministic steady state
     const double sstol = 1.e-13; //NL solver tolerance from
 
-    THREAD_GROUP::max_parallel_threads = 2; //params.num_threads;
+    sthread::detach_thread_group::max_parallel_threads = 2; //params.num_threads;
 
     try
       {