@@ -12,11 +12,11 @@ A copy of this license is included in the COPYING file of this distribution.
1212Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
1313-------------------------------------------------------------------------- */
1414
15+ # include < mutex>
16+ # include < shared_mutex>
1517# include < set>
1618# include < cppad/core/cppad_assert.hpp>
1719# include < cppad/local/sparse_internal.hpp>
18- // needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
19- # include < cppad/utility/thread_alloc.hpp>
2020
2121namespace CppAD { // BEGIN_CPPAD_NAMESPACE
2222/* !
@@ -38,7 +38,7 @@ class atomic_base {
3838 // constants
3939 //
4040 // / index of this object in class_object
41- const size_t index_;
41+ size_t index_;
4242
4343 // -----------------------------------------------------
4444 // variables
@@ -79,15 +79,17 @@ class atomic_base {
7979 // -----------------------------------------------------
8080 // static member functions
8181 //
82+ // this can become a shared_mutex when moving up to C++17
83+ static std::shared_timed_mutex vector_mutex;
8284 // / List of all the object in this class
8385 static std::vector<atomic_base *>& class_object (void )
84- { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
86+ {
8587 static std::vector<atomic_base *> list_;
8688 return list_;
8789 }
8890 // / List of names for each object in this class
8991 static std::vector<std::string>& class_name (void )
90- { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
92+ {
9193 static std::vector<std::string> list_;
9294 return list_;
9395 }
@@ -102,7 +104,10 @@ class atomic_base {
102104
103105 // / Name corresponding to a base_atomic object
104106 const std::string& afun_name (void ) const
105- { return class_name ()[index_]; }
107+ {
108+ std::shared_lock<std::shared_timed_mutex> vector_lock (vector_mutex);
109+ return class_name ()[index_];
110+ }
106111/*
107112$begin atomic_ctor$$
108113$spell
@@ -159,10 +164,6 @@ all the virtual functions that have their
159164
160165$head atomic_base$$
161166
162- $subhead Restrictions$$
163- The $code atomic_base$$ constructor cannot be called in
164- $cref/parallel/ta_in_parallel/$$ mode.
165-
166167$subhead Base$$
167168The template parameter determines the
168169$icode Base$$ type for this $codei%AD<%Base%>%$$ atomic operation.
@@ -237,15 +238,15 @@ atomic_base(
237238 const std::string& name,
238239 option_enum sparsity = bool_sparsity_enum
239240) :
240- index_ ( class_object().size() ) ,
241241sparsity_ ( sparsity )
242- { CPPAD_ASSERT_KNOWN (
243- ! thread_alloc::in_parallel () ,
244- " atomic_base: constructor cannot be called in parallel mode."
245- );
246- class_object ().push_back (this );
247- class_name ().push_back (name);
248- CPPAD_ASSERT_UNKNOWN ( class_object ().size () == class_name ().size () );
242+ {
243+ {
244+ std::unique_lock<std::shared_timed_mutex> vector_lock (vector_mutex);
245+ index_ = class_object ().size ();
246+ class_object ().push_back (this );
247+ class_name ().push_back (name);
248+ CPPAD_ASSERT_UNKNOWN ( class_object ().size () == class_name ().size () );
249+ }
249250 //
250251 // initialize work pointers as null;
251252 for (size_t thread = 0 ; thread < CPPAD_MAX_NUM_THREADS; thread++)
@@ -254,9 +255,13 @@ sparsity_( sparsity )
254255// / destructor informs CppAD that this atomic function with this index
255256// / has dropped out of scope by setting its pointer to null
256257virtual ~atomic_base (void )
257- { CPPAD_ASSERT_UNKNOWN ( class_object ().size () > index_ );
258- // change object pointer to null, but leave name for error reporting
259- class_object ()[index_] = CPPAD_NULL;
258+ {
259+ {
260+ std::unique_lock<std::shared_timed_mutex> vector_lock (vector_mutex);
261+ CPPAD_ASSERT_UNKNOWN ( class_object ().size () > index_ );
262+ // change object pointer to null, but leave name for error reporting
263+ class_object ()[index_] = CPPAD_NULL;
264+ }
260265 //
261266 // free temporary work memory
262267 for (size_t thread = 0 ; thread < CPPAD_MAX_NUM_THREADS; thread++)
@@ -290,12 +295,16 @@ void free_work(size_t thread)
290295}
291296// / atomic_base function object corresponding to a certain index
292297static atomic_base* class_object (size_t index)
293- { CPPAD_ASSERT_UNKNOWN ( class_object ().size () > index );
298+ {
299+ std::shared_lock<std::shared_timed_mutex> vector_lock (vector_mutex);
300+ CPPAD_ASSERT_UNKNOWN ( class_object ().size () > index );
294301 return class_object ()[index];
295302}
296303// / atomic_base function name corresponding to a certain index
297304static const std::string& class_name (size_t index)
298- { CPPAD_ASSERT_UNKNOWN ( class_name ().size () > index );
305+ {
306+ std::shared_lock<std::shared_timed_mutex> vector_lock (vector_mutex);
307+ CPPAD_ASSERT_UNKNOWN ( class_name ().size () > index );
299308 return class_name ()[index];
300309}
301310/*
@@ -2381,10 +2390,6 @@ If there is future use of an $code atomic_base$$ object,
23812390after a call to $code clear$$,
23822391the work space will be reallocated and held onto.
23832392
2384- $head Restriction$$
2385- This routine cannot be called
2386- while in $cref/parallel/ta_in_parallel/$$ execution mode.
2387-
23882393$end
23892394------------------------------------------------------------------------------
23902395*/
@@ -2394,10 +2399,8 @@ Free all thread_alloc static memory held by atomic_base (avoids reallocations).
23942399*/
23952400// / Free vector memory used by this class (work space)
23962401static void clear (void )
2397- { CPPAD_ASSERT_KNOWN (
2398- ! thread_alloc::in_parallel () ,
2399- " cannot use atomic_base clear during parallel execution"
2400- );
2402+ {
2403+ std::unique_lock<std::shared_timed_mutex> vector_lock (vector_mutex);
24012404 size_t i = class_object ().size ();
24022405 while (i--)
24032406 { atomic_base* op = class_object ()[i];
@@ -2419,5 +2422,7 @@ virtual void set_old(size_t id)
24192422{ }
24202423// ---------------------------------------------------------------------------
24212424};
2425+
2426+ template <class Base > std::shared_timed_mutex atomic_base<Base>::vector_mutex;
24222427} // END_CPPAD_NAMESPACE
24232428# endif
0 commit comments