1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 //                        Kokkos v. 3.0
6 //       Copyright (2020) National Technology & Engineering
7 //               Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44 
45 #include <impl/Kokkos_Utilities.hpp>  // type_list
46 
47 #include <traits/Kokkos_Traits_fwd.hpp>
48 
49 #ifndef KOKKOS_KOKKOS_POLICYTRAITADAPTOR_HPP
50 #define KOKKOS_KOKKOS_POLICYTRAITADAPTOR_HPP
51 
52 namespace Kokkos {
53 namespace Impl {
54 
55 //==============================================================================
56 // <editor-fold desc="Adapter for replacing/adding a trait"> {{{1
57 
58 //------------------------------------------------------------------------------
59 
60 // General strategy: given a TraitSpecification, go through the entries in the
61 // parameter pack of the policy template and find the first one that returns
62 // `true` for the nested `trait_matches_specification` variable template. If
63 // that nested variable template is not found these overloads should be safely
64 // ignored, and the trait can specialize PolicyTraitAdapterImpl to get the
65 // desired behavior.
66 
67 //------------------------------------------------------------------------------
68 
69 //------------------------------------------------------------------------------
70 // <editor-fold desc="PolicyTraitMatcher"> {{{2
71 
72 // To handle the WorkTag case, we need more than just a predicate; we need
73 // something that we can default to in the unspecialized case, just like we
74 // do for AnalyzeExecPolicy
75 template <class TraitSpec, class Trait, class Enable = void>
76 struct PolicyTraitMatcher;
77 
78 template <class TraitSpec, class Trait>
79 struct PolicyTraitMatcher<
80     TraitSpec, Trait,
81     std::enable_if_t<
82         TraitSpec::template trait_matches_specification<Trait>::value>>
83     : std::true_type {};
84 
85 // </editor-fold> end PolicyTraitMatcher }}}2
86 //------------------------------------------------------------------------------
87 
88 //------------------------------------------------------------------------------
89 // <editor-fold desc="PolicyTraitAdaptorImpl specializations"> {{{2
90 
91 // Matching version, replace the trait
92 template <class TraitSpec, template <class...> class PolicyTemplate,
93           class... ProcessedTraits, class MatchingTrait,
94           class... ToProcessTraits, class NewTrait>
95 struct PolicyTraitAdaptorImpl<
96     TraitSpec, PolicyTemplate, type_list<ProcessedTraits...>,
97     type_list<MatchingTrait, ToProcessTraits...>, NewTrait,
98     std::enable_if_t<PolicyTraitMatcher<TraitSpec, MatchingTrait>::value>> {
99   static_assert(PolicyTraitMatcher<TraitSpec, NewTrait>::value, "");
100   using type = PolicyTemplate<ProcessedTraits..., NewTrait, ToProcessTraits...>;
101 };
102 
103 // Non-matching version, check the next option
104 template <class TraitSpec, template <class...> class PolicyTemplate,
105           class... ProcessedTraits, class NonMatchingTrait,
106           class... ToProcessTraits, class NewTrait>
107 struct PolicyTraitAdaptorImpl<
108     TraitSpec, PolicyTemplate, type_list<ProcessedTraits...>,
109     type_list<NonMatchingTrait, ToProcessTraits...>, NewTrait,
110     std::enable_if_t<!PolicyTraitMatcher<TraitSpec, NonMatchingTrait>::value>> {
111   using type = typename PolicyTraitAdaptorImpl<
112       TraitSpec, PolicyTemplate,
113       type_list<ProcessedTraits..., NonMatchingTrait>,
114       type_list<ToProcessTraits...>, NewTrait>::type;
115 };
116 
117 // Base case: no matches found; just add the trait to the end of the list
118 template <class TraitSpec, template <class...> class PolicyTemplate,
119           class... ProcessedTraits, class NewTrait>
120 struct PolicyTraitAdaptorImpl<TraitSpec, PolicyTemplate,
121                               type_list<ProcessedTraits...>, type_list<>,
122                               NewTrait> {
123   static_assert(PolicyTraitMatcher<TraitSpec, NewTrait>::value, "");
124   using type = PolicyTemplate<ProcessedTraits..., NewTrait>;
125 };
126 
127 // </editor-fold> end PolicyTraitAdaptorImpl specializations }}}2
128 //------------------------------------------------------------------------------
129 
130 template <class TraitSpec, template <class...> class PolicyTemplate,
131           class... Traits, class NewTrait>
132 struct PolicyTraitAdaptor<TraitSpec, PolicyTemplate<Traits...>, NewTrait>
133     : PolicyTraitAdaptorImpl<TraitSpec, PolicyTemplate, type_list<>,
134                              type_list<Traits...>, NewTrait> {};
135 
136 // </editor-fold> end Adapter for replacing/adding a trait }}}1
137 //==============================================================================
138 
139 //==============================================================================
140 // <editor-fold desc="CRTP Base class for trait specifications"> {{{1
141 
142 template <class TraitSpec>
143 struct TraitSpecificationBase {
144   using trait_specification = TraitSpec;
145   template <class Policy, class Trait>
146   using policy_with_trait =
147       typename PolicyTraitAdaptor<TraitSpec, Policy, Trait>::type;
148 };
149 
150 // </editor-fold> end CRTP Base class for trait specifications }}}1
151 //==============================================================================
152 
153 }  // end namespace Impl
154 }  // end namespace Kokkos
155 
156 #endif  // KOKKOS_KOKKOS_POLICYTRAITADAPTOR_HPP
157