From 4276ffe6f0f1f28217eb6f8f064f5b86d7b89862 Mon Sep 17 00:00:00 2001
From: Tobias Leibner <tobias.leibner@googlemail.com>
Date: Wed, 31 Oct 2018 10:48:23 +0100
Subject: [PATCH] [walker] make usable with new PerThreadValue

---
 .gitsuper                   |   8 +-
 dune/xt/grid/test/walker.cc |  26 +++--
 dune/xt/grid/walker.hh      | 187 +++++++++++++++++++++---------------
 3 files changed, 132 insertions(+), 89 deletions(-)

diff --git a/.gitsuper b/.gitsuper
index e65b22659..60ad864fd 100644
--- a/.gitsuper
+++ b/.gitsuper
@@ -14,10 +14,10 @@ status = 1a3bcab04b011a5d6e44f9983cae6ff89fa695e8 bin (heads/master)
 	 741e4f8e53bdd3e1b6e19d84eb22b6e3dc48526c dune-python (remotes/origin/releases/2.5)
 	 26cc8cb4161a3a51002ab2a81b8c81d2c951ee79 dune-testtools (remotes/origin/p/renemilk/testname_listing_hack_no-skiptest)
 	 0a74e7dd0b2115778a5d490dab08a2ed07fcaa1e dune-uggrid (v2.5.2)
-	+effefc7695eba0c0ca94fff0f93026b86501027e dune-xt-common (heads/master)
+	+7d4cb994b3aad0e0ff73172b187e35bbf191bf29 dune-xt-common (heads/dailywork_tleibner)
 	+3e3f3bf06e21cbbf3c0a559891b44c6f5d987d0f dune-xt-data (heads/master)
 	+f05aa7470ead4150ca7a91894cd2ad77dfcedc46 dune-xt-functions (heads/new-master)
-	+be11e17850621da0847812f667c650cd008ae281 dune-xt-grid (heads/new-master)
+	+5be0c7c0e69d6364022421b866016d6443280cf2 dune-xt-grid (heads/new-master)
 	+f6904b69f9a3ee5d45ee824d3b244e59cfed7ff4 dune-xt-la (heads/master)
 	 09d0378f616b94d68bcdd9fc6114813181849ec0 scripts (heads/master)
 commit = 5f5841ee7a2dff290b98845c46262151752189c1
@@ -95,7 +95,7 @@ commit = 0a74e7dd0b2115778a5d490dab08a2ed07fcaa1e
 [submodule.dune-xt-common]
 remote = git@github.com:dune-community/dune-xt-common.git
 status = 2424627f0ad5de7e4aaa5e7f48bc2a02414d95a1 .vcsetup (heads/master)
-commit = effefc7695eba0c0ca94fff0f93026b86501027e
+commit = 7d4cb994b3aad0e0ff73172b187e35bbf191bf29
 
 [submodule.dune-xt-data]
 remote = git@github.com:dune-community/dune-xt-data
@@ -110,7 +110,7 @@ commit = f05aa7470ead4150ca7a91894cd2ad77dfcedc46
 [submodule.dune-xt-grid]
 remote = git@github.com:dune-community/dune-xt-grid.git
 status = 2424627f0ad5de7e4aaa5e7f48bc2a02414d95a1 .vcsetup (heads/master)
-commit = be11e17850621da0847812f667c650cd008ae281
+commit = 5be0c7c0e69d6364022421b866016d6443280cf2
 
 [submodule.dune-xt-la]
 remote = git@github.com:dune-community/dune-xt-la.git
diff --git a/dune/xt/grid/test/walker.cc b/dune/xt/grid/test/walker.cc
index cbf6f4524..e30a80c1d 100644
--- a/dune/xt/grid/test/walker.cc
+++ b/dune/xt/grid/test/walker.cc
@@ -48,7 +48,7 @@ struct GridWalkerTest : public ::testing::Test
   {
     const auto gv = grid_prv.grid().leafGridView();
     Walker<GridLayerType> walker(gv);
-    const auto correct_size = gv.size(0);
+    const auto num_elements = gv.size(0);
     atomic<size_t> count(0);
     atomic<size_t> intersection_count(0);
     auto counter = GenericElementFunctor<GridLayerType>([] {}, [&count](const EntityType&) { count++; }, [] {});
@@ -66,7 +66,8 @@ struct GridWalkerTest : public ::testing::Test
     auto test4 = [&] { walker.append(intersection_counter).walk(false); };
     auto test5 = [&] { walker.append(intersection_counter).walk(true); };
 
-    list<function<void()>> tests({test1, test2, test3, test4, test5});
+    list<function<void()>> element_tests({test1, test2, test3});
+    list<function<void()>> intersection_tests({test4, test5});
 #if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) && HAVE_TBB // EXADUNE
     // exadune guard for SeedListPartitioning
     auto test0 = [&] {
@@ -80,10 +81,16 @@ struct GridWalkerTest : public ::testing::Test
     tests.push_back(test0);
 #endif // DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) && HAVE_TBB
 
-    for (const auto& test : tests) {
+    for (const auto& test : element_tests) {
       count = 0;
       test();
-      EXPECT_EQ(count, correct_size);
+      EXPECT_EQ(num_elements, count);
+    }
+    const auto faces_per_element = 2 * griddim; // only for cube grids
+    for (const auto& test : intersection_tests) {
+      intersection_count = 0;
+      test();
+      EXPECT_EQ(num_elements * faces_per_element, intersection_count);
     }
   }
 
@@ -113,9 +120,10 @@ struct GridWalkerTest : public ::testing::Test
     Walker<GridLayerType> walker(gv);
 
     size_t filter_count = 0, all_count = 0, inner_count = 0, inner_set_count = 0;
-    auto filter_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { filter_count++; }, [] {});
-    auto inner_filter_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { inner_set_count++; }, [] {});
-    auto all_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { all_count++; }, [] {});
+    auto filter_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { filter_count++; }, [] {});
+    auto inner_filter_counter =
+        GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { inner_set_count++; }, [] {});
+    auto all_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { all_count++; }, [] {});
     auto inner_counter = GenericElementFunctor<GridLayerType>(
         [] {}, [&](const auto& e) { inner_count += e.partitionType() == Dune::PartitionType::InteriorEntity; }, [] {});
 
@@ -137,8 +145,8 @@ struct GridWalkerTest : public ::testing::Test
     Walker<GridLayerType> walker(gv);
 
     size_t all_count = 0, inner_count = 0;
-    auto all_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { all_count++; }, [] {});
-    auto inner_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](...) { inner_count++; }, [] {});
+    auto all_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { all_count++; }, [] {});
+    auto inner_set_counter = GenericElementFunctor<GridLayerType>([] {}, [&](const auto&) { inner_count++; }, [] {});
     ApplyOn::PartitionSetElements<GridLayerType, Dune::Partitions::Interior> on_interior_partitionset{};
     ApplyOn::PartitionSetElements<GridLayerType, Dune::Partitions::All> on_all_partitionset{};
     walker.append(inner_set_counter, on_interior_partitionset);
diff --git a/dune/xt/grid/walker.hh b/dune/xt/grid/walker.hh
index e09f4ac44..667cbc9b3 100644
--- a/dune/xt/grid/walker.hh
+++ b/dune/xt/grid/walker.hh
@@ -79,6 +79,12 @@ public:
   {
   }
 
+  ElementFunctorWrapper(const ThisType& other)
+    : functor_(other.functor_->copy())
+    , filter_(other.filter_->copy())
+  {
+  }
+
   const FilterType& filter() const
   {
     return *filter_;
@@ -116,6 +122,12 @@ public:
   {
   }
 
+  IntersectionFunctorWrapper(const ThisType& other)
+    : functor_(other.functor_->copy())
+    , filter_(other.filter_->copy())
+  {
+  }
+
   const FilterType& filter() const
   {
     return *filter_;
@@ -157,6 +169,13 @@ public:
   {
   }
 
+  ElementAndIntersectionFunctorWrapper(const ThisType& other)
+    : functor_(other.functor_->copy())
+    , element_filter_(other.element_filter_->copy())
+    , intersection_filter_(other.intersection_filter_->copy())
+  {
+  }
+
   const ElementFilterType& element_filter() const
   {
     return *element_filter_;
@@ -202,11 +221,12 @@ private:
   using VoidFunctionType = std::function<void()>;
 
   template <typename WrapperType, class... Args>
-  void emplace_all(Common::PerThreadValue<std::list<std::shared_ptr<WrapperType>>>& thread_storage, Args&&... args)
+  void emplace_all(std::list<WrapperType>& storage,
+                   Common::PerThreadValue<std::list<WrapperType>>& thread_storage,
+                   Args&&... args)
   {
-    for (auto&& local_list : thread_storage) {
-      local_list.emplace_back(new WrapperType(std::forward<Args>(args)...));
-    }
+    storage.emplace_back(std::forward<Args>(args)...);
+    thread_storage = Common::PerThreadValue<std::list<WrapperType>>(storage);
   }
 
 public:
@@ -216,36 +236,20 @@ public:
   }
 
   Walker(const ThisType& other)
-    : BaseType()
-    , grid_view_(other.grid_view_)
-  {
-    // Since all Common::PerThreadValue are created with the same size given by the global singleton threadManager(),
-    // we just assume they are of the same size!
-    // Copy the element functors ...
-    auto zip_emplace = [](auto& target_thread_ctr, const auto& source_thread_ctr, auto& gen_function) {
-      auto target_wrappers_it = target_thread_ctr.begin();
-      auto source_wrappers_it = source_thread_ctr.begin();
-      for (; target_wrappers_it != target_thread_ctr.end() && source_wrappers_it != source_thread_ctr.end();
-           ++target_wrappers_it, ++source_wrappers_it) {
-        auto& target__wrappers = *target_wrappers_it;
-        for (auto&& source_wrapper : *source_wrappers_it) {
-          target__wrappers.emplace_back(gen_function(*source_wrapper));
-        }
-      }
-    };
-    auto el_wrapper = [](auto&& wrapper) {
-      return new typename std::decay<decltype(wrapper)>::type(wrapper.functor(), wrapper.filter());
-    };
-    zip_emplace(element_functor_wrappers_, other.element_functor_wrappers_, el_wrapper);
-    zip_emplace(intersection_functor_wrappers_, other.intersection_functor_wrappers_, el_wrapper);
-
-    auto elint_wrapper = [](auto&& wrapper) {
-      return new typename std::decay<decltype(wrapper)>::type(
-          wrapper.functor(), wrapper.element_filter(), wrapper.intersection_filter());
-    };
-    zip_emplace(
-        element_and_intersection_functor_wrappers_, other.element_and_intersection_functor_wrappers_, elint_wrapper);
-  } // Walker(...)
+    : grid_view_(other.grid_view_)
+    , stored_element_functor_wrappers_(other.stored_element_functor_wrappers_)
+    , stored_intersection_functor_wrappers_(other.stored_intersection_functor_wrappers_)
+    , stored_element_and_intersection_functor_wrappers_(other.stored_element_and_intersection_functor_wrappers_)
+  {
+    element_functor_wrappers_ = Common::PerThreadValue<std::list<internal::ElementFunctorWrapper<GridViewType>>>(
+        stored_element_functor_wrappers_);
+    intersection_functor_wrappers_ =
+        Common::PerThreadValue<std::list<internal::IntersectionFunctorWrapper<GridViewType>>>(
+            stored_intersection_functor_wrappers_);
+    element_and_intersection_functor_wrappers_ =
+        Common::PerThreadValue<std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>>(
+            stored_element_and_intersection_functor_wrappers_);
+  }
 
   Walker(ThisType&& source) = default;
 
@@ -268,26 +272,32 @@ public:
 
   ThisType& append(ElementFunctor<GV>& functor, const ElementFilter<GV>& filter = ApplyOn::AllElements<GV>())
   {
-    emplace_all(element_functor_wrappers_, functor, filter);
+    emplace_all(stored_element_functor_wrappers_, element_functor_wrappers_, functor, filter);
     return *this;
   }
 
   ThisType& append(ElementFunctor<GV>*&& functor, const ElementFilter<GV>& filter = ApplyOn::AllElements<GV>())
   {
-    emplace_all(element_functor_wrappers_, *functor, filter);
+    emplace_all(stored_element_functor_wrappers_, element_functor_wrappers_, *functor, filter);
     delete functor;
     return *this;
   }
 
   ThisType& append(ElementFunctor<GV>& functor, GenericElementFilterFunctionType filter)
   {
-    emplace_all(element_functor_wrappers_, functor, ApplyOn::GenericFilteredElements<GV>(filter));
+    emplace_all(stored_element_functor_wrappers_,
+                element_functor_wrappers_,
+                functor,
+                ApplyOn::GenericFilteredElements<GV>(filter));
     return *this;
   }
 
   ThisType& append(ElementFunctor<GV>*&& functor, GenericElementFilterFunctionType filter)
   {
-    emplace_all(element_functor_wrappers_, *functor, ApplyOn::GenericFilteredElements<GV>(filter));
+    emplace_all(stored_element_functor_wrappers_,
+                element_functor_wrappers_,
+                *functor,
+                ApplyOn::GenericFilteredElements<GV>(filter));
     delete functor;
     return *this;
   }
@@ -324,27 +334,33 @@ public:
   ThisType& append(IntersectionFunctor<GV>& functor,
                    const IntersectionFilter<GV>& filter = ApplyOn::AllIntersections<GV>())
   {
-    emplace_all(intersection_functor_wrappers_, functor, filter);
+    emplace_all(stored_intersection_functor_wrappers_, intersection_functor_wrappers_, functor, filter);
     return *this;
   }
 
   ThisType& append(IntersectionFunctor<GV>*&& functor,
                    const IntersectionFilter<GV>& filter = ApplyOn::AllIntersections<GV>())
   {
-    emplace_all(intersection_functor_wrappers_, *functor, filter);
+    emplace_all(stored_intersection_functor_wrappers_, intersection_functor_wrappers_, *functor, filter);
     delete functor;
     return *this;
   }
 
   ThisType& append(IntersectionFunctor<GV>& functor, GenericIntersectionFilterFunctionType filter)
   {
-    emplace_all(intersection_functor_wrappers_, functor, ApplyOn::GenericFilteredIntersections<GV>(filter));
+    emplace_all(stored_intersection_functor_wrappers_,
+                intersection_functor_wrappers_,
+                functor,
+                ApplyOn::GenericFilteredIntersections<GV>(filter));
     return *this;
   }
 
   ThisType& append(IntersectionFunctor<GV>*&& functor, GenericIntersectionFilterFunctionType filter)
   {
-    emplace_all(intersection_functor_wrappers_, *functor, ApplyOn::GenericFilteredIntersections<GV>(filter));
+    emplace_all(stored_intersection_functor_wrappers_,
+                intersection_functor_wrappers_,
+                *functor,
+                ApplyOn::GenericFilteredIntersections<GV>(filter));
     delete functor;
     return *this;
   }
@@ -384,7 +400,11 @@ public:
   {
     if (&functor == this)
       DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!");
-    emplace_all(element_and_intersection_functor_wrappers_, functor, element_filter, intersection_filter);
+    emplace_all(stored_element_and_intersection_functor_wrappers_,
+                element_and_intersection_functor_wrappers_,
+                functor,
+                element_filter,
+                intersection_filter);
     return *this;
   }
 
@@ -394,7 +414,11 @@ public:
   {
     if (functor == this)
       DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!");
-    emplace_all(element_and_intersection_functor_wrappers_, *functor, element_filter, intersection_filter);
+    emplace_all(stored_element_and_intersection_functor_wrappers_,
+                element_and_intersection_functor_wrappers_,
+                *functor,
+                element_filter,
+                intersection_filter);
     delete functor;
     return *this;
   }
@@ -405,7 +429,8 @@ public:
   {
     if (&functor == this)
       DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!");
-    emplace_all(element_and_intersection_functor_wrappers_,
+    emplace_all(stored_element_and_intersection_functor_wrappers_,
+                element_and_intersection_functor_wrappers_,
                 functor,
                 ApplyOn::GenericFilteredElements<GV>(element_filter),
                 ApplyOn::GenericFilteredIntersections<GV>(intersection_filter));
@@ -418,7 +443,8 @@ public:
   {
     if (functor == this)
       DUNE_THROW(Common::Exceptions::you_are_using_this_wrong, "Do not append a Walker to itself!");
-    emplace_all(element_and_intersection_functor_wrappers_,
+    emplace_all(stored_element_and_intersection_functor_wrappers_,
+                element_and_intersection_functor_wrappers_,
                 *functor,
                 ApplyOn::GenericFilteredElements<GV>(element_filter),
                 ApplyOn::GenericFilteredIntersections<GV>(intersection_filter));
@@ -466,10 +492,10 @@ public:
 
   virtual void prepare() override
   {
-    auto prep = [](auto& pt) {
-      for (auto&& list : pt) {
-        for (auto&& wrapper : list)
-          wrapper->functor().prepare();
+    auto prep = [](auto& functor_list) {
+      for (auto&& pt_wrapper : functor_list) {
+        for (auto&& wrapper : pt_wrapper)
+          wrapper.functor().prepare();
       }
     };
     prep(element_functor_wrappers_);
@@ -480,12 +506,12 @@ public:
   virtual void apply_local(const ElementType& element) override
   {
     for (auto&& wrapper : *element_functor_wrappers_) {
-      if (wrapper->filter().contains(grid_view_, element))
-        wrapper->functor().apply_local(element);
+      if (wrapper.filter().contains(grid_view_, element))
+        wrapper.functor().apply_local(element);
     }
     for (auto&& wrapper : *element_and_intersection_functor_wrappers_) {
-      if (wrapper->element_filter().contains(grid_view_, element))
-        wrapper->functor().apply_local(element);
+      if (wrapper.element_filter().contains(grid_view_, element))
+        wrapper.functor().apply_local(element);
     }
   } // ... apply_local(...)
 
@@ -494,21 +520,21 @@ public:
                            const ElementType& outside_element) override
   {
     for (auto&& wrapper : *intersection_functor_wrappers_) {
-      if (wrapper->filter().contains(grid_view_, intersection))
-        wrapper->functor().apply_local(intersection, inside_element, outside_element);
+      if (wrapper.filter().contains(grid_view_, intersection))
+        wrapper.functor().apply_local(intersection, inside_element, outside_element);
     }
     for (auto&& wrapper : *element_and_intersection_functor_wrappers_) {
-      if (wrapper->intersection_filter().contains(grid_view_, intersection))
-        wrapper->functor().apply_local(intersection, inside_element, outside_element);
+      if (wrapper.intersection_filter().contains(grid_view_, intersection))
+        wrapper.functor().apply_local(intersection, inside_element, outside_element);
     }
   } // ... apply_local(...)
 
   virtual void finalize() override
   {
-    auto fin = [](auto& pt) {
-      for (auto&& list : pt) {
-        for (auto&& wrapper : list)
-          wrapper->functor().finalize();
+    auto fin = [](auto& list) {
+      for (auto&& pt : list) {
+        for (auto&& wrapper : pt)
+          wrapper.functor().finalize();
       }
     };
     fin(element_and_intersection_functor_wrappers_);
@@ -552,14 +578,17 @@ public:
 
   void clear()
   {
-    auto clr = [](auto& pt) {
-      for (auto&& list : pt) {
-        list.clear();
-      }
-    };
-    clr(element_functor_wrappers_);
-    clr(intersection_functor_wrappers_);
-    clr(element_and_intersection_functor_wrappers_);
+    stored_element_functor_wrappers_.clear();
+    stored_intersection_functor_wrappers_.clear();
+    stored_element_and_intersection_functor_wrappers_.clear();
+    element_functor_wrappers_ = Common::PerThreadValue<std::list<internal::ElementFunctorWrapper<GridViewType>>>(
+        stored_element_functor_wrappers_);
+    intersection_functor_wrappers_ =
+        Common::PerThreadValue<std::list<internal::IntersectionFunctorWrapper<GridViewType>>>(
+            stored_intersection_functor_wrappers_);
+    element_and_intersection_functor_wrappers_ =
+        Common::PerThreadValue<std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>>(
+            stored_element_and_intersection_functor_wrappers_);
   }
 
   BaseType* copy() override
@@ -679,15 +708,21 @@ private:
   } // ... walk_range(...)
 
   GridViewType grid_view_;
-  Common::PerThreadValue<std::list<std::shared_ptr<internal::ElementFunctorWrapper<GridViewType>>>>
-      element_functor_wrappers_;
-  Common::PerThreadValue<std::list<std::shared_ptr<internal::IntersectionFunctorWrapper<GridViewType>>>>
-      intersection_functor_wrappers_;
-  Common::PerThreadValue<std::list<std::shared_ptr<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>>>
+  // We want each thread to have its own copy of each functor. However, as we do not know in advance how many different
+  // threads we will have (even if DXTC_CONFIG["threading.max_count"] is set, there may be only max_threads at a time,
+  // but we cannot guarantee that there will only be max_threads over the whole runtime of our program), we store the
+  // wrappers in a list that is shared by all threads and copy that list to the thread once a new thread tries to access
+  // the functors.
+  std::list<internal::ElementFunctorWrapper<GridViewType>> stored_element_functor_wrappers_;
+  std::list<internal::IntersectionFunctorWrapper<GridViewType>> stored_intersection_functor_wrappers_;
+  std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>
+      stored_element_and_intersection_functor_wrappers_;
+  Common::PerThreadValue<std::list<internal::ElementFunctorWrapper<GridViewType>>> element_functor_wrappers_;
+  Common::PerThreadValue<std::list<internal::IntersectionFunctorWrapper<GridViewType>>> intersection_functor_wrappers_;
+  Common::PerThreadValue<std::list<internal::ElementAndIntersectionFunctorWrapper<GridViewType>>>
       element_and_intersection_functor_wrappers_;
 }; // class Walker
 
-
 template <class GV>
 Walker<GV> make_walker(GV grid_view)
 {
-- 
GitLab