Skip to content

Commit ab7676e

Browse files
committed
Merge remote-tracking branch 'origin/v10-minor'
2 parents 528f2a4 + 4e3a3b1 commit ab7676e

File tree

3 files changed

+42
-35
lines changed

3 files changed

+42
-35
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@ Fixed bugs
519519
- aggregate integer variable to not in clique variable in cliquePresolve() of xor constraints to avoid infeasible solutions
520520
- fixed memory leak in dynamic partition search primal heuristic
521521
- fixed issue with file existence check in XML parser when SCIP was build with ZLIB support on Windows
522+
- fixed thread-safety issue when using CppAD and user-defined expression handler
523+
- fixed typo in `#pragma` directive of redistributed nauty.h
522524

523525
Miscellaneous
524526
-------------

src/cppad/core/atomic_base.hpp

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ A copy of this license is included in the COPYING file of this distribution.
1212
Please 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

2121
namespace 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$$
167168
The 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() ) ,
241241
sparsity_( 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
256257
virtual ~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
292297
static 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
297304
static 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,
23812390
after a call to $code clear$$,
23822391
the 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)
23962401
static 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

src/nauty/nauty.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,17 +1043,17 @@ static int msc_bsr_16(setword x) \
10431043
#include <x86intrin.h>
10441044
#endif
10451045
#if WORDSIZE==128
1046-
#pragma instrinsic(_mm_popcnt_u64)
1046+
#pragma intrinsic(_mm_popcnt_u64)
10471047
#define POPCOUNT(x) ((int)_mm_popcnt_u64((unsigned long long)((x)>>64)) \
10481048
+ (int)_mm_popcnt_u64((unsigned long long)((x)&MASK128R)))
10491049
#elif WORDSIZE==64
1050-
#pragma instrinsic(_mm_popcnt_u64)
1050+
#pragma intrinsic(_mm_popcnt_u64)
10511051
#define POPCOUNT(x) ((int)_mm_popcnt_u64(x))
10521052
#elif WORDSIZE==32
1053-
#pragma instrinsic(_mm_popcnt_u32)
1053+
#pragma intrinsic(_mm_popcnt_u32)
10541054
#define POPCOUNT(x) _mm_popcnt_u32(x)
10551055
#elif WORDSIZE==16
1056-
#pragma instrinsic(_mm_popcnt_u32)
1056+
#pragma intrinsic(_mm_popcnt_u32)
10571057
#define POPCOUNT(x) _mm_popcnt_u32((unsigned int)(x))
10581058
#endif
10591059

0 commit comments

Comments
 (0)