From 92832c355c45de79ffd56aa70f3108c98745abc3 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Tue, 20 Dec 2016 09:00:01 -0700 Subject: [PATCH] Add a mutex to IndexSet and use it to make IndexSet::do_compress() thread-safe. IndexSet has a number of 'mutable' member variables. The only function that modifies them is 'do_compress', which is called by 'compress', which is in turn called by all of the 'const' member functions. To make all of these 'const' member functions thread-safe, we need to use a mutex in 'do_compress'. This patch does this. I have verified that no other 'const' function actually modifies any of the 'mutable' member variables, so only guarding 'do_compress' by the mutex is sufficient. --- doc/news/changes/minor/20161220Bangerth | 6 ++++++ include/deal.II/base/index_set.h | 9 ++++++++- source/base/index_set.cc | 10 +++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 doc/news/changes/minor/20161220Bangerth diff --git a/doc/news/changes/minor/20161220Bangerth b/doc/news/changes/minor/20161220Bangerth new file mode 100644 index 0000000000..7985bf1d8d --- /dev/null +++ b/doc/news/changes/minor/20161220Bangerth @@ -0,0 +1,6 @@ +
  • Changed: IndexSet::compress() and, by extension, all of the + "const" member functions of the IndexSet class, are now thread-safe. +
    + (Wolfgang Bangerth, 2016/12/20) +
  • + diff --git a/include/deal.II/base/index_set.h b/include/deal.II/base/index_set.h index 67dd11a99c..c1e3472c33 100644 --- a/include/deal.II/base/index_set.h +++ b/include/deal.II/base/index_set.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -853,6 +854,12 @@ private: */ mutable size_type largest_range; + /** + * A mutex that is used to synchronize operations of the do_compress() function + * that is called from many 'const' functions via compress(). + */ + mutable Threads::Mutex compress_mutex; + /** * Actually perform the compress() operation. */ @@ -1751,7 +1758,7 @@ IndexSet::print (StreamType &out) const else out << "[" << p->begin << "," << p->end-1 << "]"; - if (p !=--ranges.end()) + if (p != --ranges.end()) out << ", "; } out << "}" << std::endl; diff --git a/source/base/index_set.cc b/source/base/index_set.cc index c6f78e3ea4..c8efcf2489 100644 --- a/source/base/index_set.cc +++ b/source/base/index_set.cc @@ -119,6 +119,13 @@ IndexSet::add_range (const size_type begin, void IndexSet::do_compress () const { + // we will, in the following, modify mutable variables. this can only + // work in multithreaded applications if we lock the data structures + // via a mutex, so that users can call 'const' functions from threads + // in parallel (and these 'const' functions can then call compress() + // which itself calls the current function) + Threads::Mutex::ScopedLock lock (compress_mutex); + // see if any of the contiguous ranges can be merged. do not use // std::vector::erase in-place as it is quadratic in the number of // ranges. since the ranges are sorted by their first index, determining @@ -660,7 +667,8 @@ IndexSet::memory_consumption () const { return (MemoryConsumption::memory_consumption (ranges) + MemoryConsumption::memory_consumption (is_compressed) + - MemoryConsumption::memory_consumption (index_space_size)); + MemoryConsumption::memory_consumption (index_space_size) + + sizeof (compress_mutex)); } -- 2.39.5