]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Use std::shared_mutex in get_fe_by_name().
authorWolfgang Bangerth <bangerth@colostate.edu>
Tue, 24 Oct 2023 21:06:01 +0000 (15:06 -0600)
committerWolfgang Bangerth <bangerth@colostate.edu>
Tue, 24 Oct 2023 21:12:07 +0000 (15:12 -0600)
include/deal.II/fe/fe_tools.templates.h

index f093b1bb6d0a35f29bd31ce84dda85e91a2a986e..82469926cd988f7aaf792b71296720330be58913 100644 (file)
@@ -69,6 +69,7 @@
 #include <cctype>
 #include <iostream>
 #include <memory>
+#include <shared_mutex>
 
 
 DEAL_II_NAMESPACE_OPEN
@@ -1227,7 +1228,7 @@ namespace FETools
       // it belongs to an internal namespace) in order to make icc happy
       // (which otherwise reports a multiply defined symbol when linking
       // libraries for more than one space dimension together)
-      static std::mutex fe_name_map_lock;
+      static std::shared_mutex fe_name_map_lock;
 
       // This is the map used by FETools::get_fe_by_name and
       // FETools::add_fe_name. It is only accessed by functions in this
@@ -2294,25 +2295,32 @@ namespace FETools
       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"));
     if (name_end < name.size())
       name.erase(name_end);
-    // first make sure that no other
-    // thread intercepts the
-    // operation of this function;
-    // for this, acquire the lock
-    // until we quit this function
-    std::lock_guard<std::mutex> lock(
-      internal::FEToolsAddFENameHelper::fe_name_map_lock);
 
-    Assert(
-      internal::FEToolsAddFENameHelper::get_fe_name_map()[dim][spacedim].find(
-        name) ==
-        internal::FEToolsAddFENameHelper::get_fe_name_map()[dim][spacedim]
-          .end(),
-      ExcMessage("Cannot change existing element in finite element name list"));
-
-    // Insert the normalized name into
-    // the map
-    internal::FEToolsAddFENameHelper::get_fe_name_map()[dim][spacedim][name] =
-      std::unique_ptr<const Subscriptor>(factory);
+      // Ensure that the element we are looking for isn't in the map
+      // yet. This only requires us to read the map, so it can happen
+      // in a shared locked state
+#if DEBUG
+    {
+      std::shared_lock<std::shared_mutex> lock(
+        internal::FEToolsAddFENameHelper::fe_name_map_lock);
+
+      Assert(
+        internal::FEToolsAddFENameHelper::get_fe_name_map()[dim][spacedim].find(
+          name) ==
+          internal::FEToolsAddFENameHelper::get_fe_name_map()[dim][spacedim]
+            .end(),
+        ExcMessage(
+          "Cannot change existing element in finite element name list"));
+    }
+#endif
+
+
+    // Insert the normalized name into the map. This changes the map, so it
+    // has to happen under a non-shared (writer) lock:
+    std::unique_lock<std::shared_mutex> lock(
+      internal::FEToolsAddFENameHelper::fe_name_map_lock);
+    internal::FEToolsAddFENameHelper::get_fe_name_map()[dim][spacedim].emplace(
+      name, std::unique_ptr<const Subscriptor>(factory));
   }
 
 
@@ -2456,16 +2464,16 @@ namespace FETools
           }
         else
           {
-            // Make sure no other thread
-            // is just adding an element
-            std::lock_guard<std::mutex> lock(
+            // Lock access to the name map, but do so in a way that allows other
+            // readers to access it concurrently:
+            std::shared_lock<std::shared_mutex> lock(
               internal::FEToolsAddFENameHelper::fe_name_map_lock);
+
             AssertThrow(fe_name_map.find(name_part) != fe_name_map.end(),
                         FETools::ExcInvalidFEName(name));
 
-            // Now, just the (degree)
-            // or (Quadrature<1>(degree+1))
-            // part should be left.
+            // Now, just the (degree) or (Quadrature<1>(degree+1)) part should
+            // be left.
             if (name.empty() || name[0] != '(')
               throw std::string("Invalid first character in ") + name;
             name.erase(0, 1);

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.