1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and 2 // other Axom Project Developers. See the top-level LICENSE file for details. 3 // 4 // SPDX-License-Identifier: (BSD-3-Clause) 5 6 /*! 7 * 8 * \file AxomMacros.hpp 9 * 10 * \brief Contains several useful macros for the axom project 11 * 12 */ 13 14 #ifndef AXOM_MACROS_HPP_ 15 #define AXOM_MACROS_HPP_ 16 17 #include "axom/config.hpp" 18 #include <cassert> // for assert() 19 20 /*! 21 * \def AXOM_DEVICE 22 * \def AXOM_HOST_DEVICE 23 * 24 * \brief CUDA host/device macros for decorating functions/lambdas 25 * 26 * \note These will expand to the corresponding CUDA decorations when 27 * compiled with -DAXOM_USE_CUDA 28 */ 29 #if defined(__CUDACC__) 30 #define AXOM_DEVICE __device__ 31 #define AXOM_HOST_DEVICE __host__ __device__ 32 #define AXOM_HOST __host__ 33 #else 34 #define AXOM_DEVICE 35 #define AXOM_HOST_DEVICE 36 #define AXOM_HOST 37 #endif 38 39 /* 40 * \def AXOM_STRINGIFY 41 * 42 * \brief Helper Macro to specify strings inside pragmas. 43 */ 44 #define AXOM_STRINGIFY(x) AXOM_DO_STRINGIFY(x) 45 #define AXOM_DO_STRINGIFY(x) #x 46 47 /* 48 * \def AXOM_PRAGMA 49 * 50 * \brief Macro used to specify pragma directive 51 */ 52 #ifdef _WIN32 53 #define AXOM_PRAGMA(x) __pragma(x) 54 #else 55 #define AXOM_PRAGMA(x) _Pragma(AXOM_STRINGIFY(x)) 56 #endif 57 58 /* 59 * \def AXOM_SUPPRESS_HD_WARN 60 * 61 * \brief Macro used to silence __host__ __device__ compiler warnings 62 * when calling __host__ function from __host__ __device__ function. 63 */ 64 #if defined(__CUDACC__) 65 #define AXOM_SUPPRESS_HD_WARN AXOM_PRAGMA(nv_exec_check_disable) 66 #else 67 #define AXOM_SUPPRESS_HD_WARN 68 #endif 69 70 /*! 71 * \def AXOM_LAMBDA 72 * 73 * \brief Convenience macro used for lambda capture by value. 74 * \note When CUDA is used, the macro always expands to a host/device lambda. 75 * 76 * \warning When compiling with CUDA, host/device lambdas incur a significant 77 * penalty on the CPU code. The way NVCC implements host/device lambdas 78 * prevents the compiler from proper in-lining them. When CUDA is enabled use 79 * the parallel_gpu execution policy or opt to turn off CUDA if the application 80 * is making more use of the parallel_cpu and serial execution policies. 81 */ 82 #ifdef AXOM_USE_CUDA 83 #define AXOM_LAMBDA [=] AXOM_HOST_DEVICE 84 #define AXOM_DEVICE_LAMBDA [=] AXOM_DEVICE 85 #define AXOM_HOST_LAMBDA [=] AXOM_HOST 86 #else 87 #define AXOM_LAMBDA [=] 88 #define AXOM_DEVICE_LAMBDA [=] 89 #define AXOM_HOST_LAMBDA [=] 90 #endif 91 92 /*! 93 * \def AXOM_CUDA_TEST 94 * 95 * \brief Convenience macro used for a gtest that uses cuda. 96 */ 97 #if defined(AXOM_USE_CUDA) 98 #define AXOM_CUDA_TEST(X, Y) \ 99 static void cuda_test_##X##Y(); \ 100 TEST(X, Y) { cuda_test_##X##Y(); } \ 101 static void cuda_test_##X##Y() 102 #else 103 #define AXOM_CUDA_TEST(X, Y) TEST(X, Y) 104 #endif 105 106 /*! 107 * \def AXOM_DEVICE_CODE 108 * 109 * \brief Convenience macro used for kernel code 110 */ 111 #if defined(__CUDA_ARCH__) 112 #define AXOM_DEVICE_CODE 113 #endif 114 115 /*! 116 * 117 * \def AXOM_UNUSED_PARAM(x) 118 * \brief Macro used to silence compiler warnings in methods with unused arguments. 119 * \note The intent is to use this macro in the function signature. For example: 120 * \code 121 * 122 * void my_function(int x, int AXOM_UNUSED_PARAM(y)) 123 * { 124 * // my implementation 125 * } 126 * 127 * \endcode 128 */ 129 #define AXOM_UNUSED_PARAM(x) 130 131 /*! 132 * 133 * \def AXOM_STATIC_ASSERT(cond) 134 * \def AXOM_STATIC_ASSERT_MSG(cond, MSG) 135 * 136 * \brief This macro wraps the compile time static_assert functionality 137 * so you don't have to provide a message. 138 */ 139 #define AXOM_STATIC_ASSERT(cond) static_assert(cond, #cond) 140 #define AXOM_STATIC_ASSERT_MSG(cond, MSG) static_assert(cond, MSG) 141 142 /*! 143 * 144 * \def AXOM_UNUSED_VAR(x) 145 * \brief Macro used to silence compiler warnings about variables 146 * that are defined but not used. 147 * \note The intent is to use this macro for variables that are only used 148 * within compiler defines (e.g. in debug assertions). For example: 149 * \code 150 * 151 * double myVar = ... 152 * AXOM_UNUSED_VAR(myVar); 153 * 154 * // code emits the following warning in release builds 155 * // if extra warnings are enabled and this macro is not called 156 * // warning: unused variable 'myVar' [-Wunused-variable] 157 * 158 * SLIC_ASSERT(myVar > 0) 159 * 160 * \endcode 161 */ 162 #define AXOM_UNUSED_VAR(_x) static_cast<void>(_x) 163 164 /*! 165 * \def AXOM_DEBUG_PARAM(x) 166 * \brief Macro used to silence compiler warnings about parameters 167 * that are only used when AXOM_DEBUG is defined 168 * \note Default values are ok 169 * \code 170 * 171 * void my_function(int x, int AXOM_DEBUG_PARAM(y)) 172 * { 173 * // my implementation 174 * SLIC_ASSERT(y > 0) 175 * } 176 * 177 * \endcode 178 */ 179 #ifdef AXOM_DEBUG 180 #define AXOM_DEBUG_PARAM(_x) _x 181 #else 182 #define AXOM_DEBUG_PARAM(_x) 183 #endif 184 185 /*! 186 * \def DISABLE_DEFAULT_CTOR(className) 187 * \brief Macro to disable default constructor for the given class. 188 * \note This macro should only be used within the private section of a class, 189 * as indicated in the example below. 190 * 191 * \code 192 * 193 * class Foo 194 * { 195 * public: 196 * 197 * // Public methods here 198 * 199 * private: 200 * DISABLE_DEFAULT_CTOR(Foo); 201 * }; 202 * 203 * \endcode 204 */ 205 #define DISABLE_DEFAULT_CTOR(className) className() = delete 206 207 /*! 208 * \def DISABLE_COPY_AND_ASSIGNMENT(className) 209 * \brief Macro to disable copy and assignment operations for the given class. 210 * \note This macro should only be used within the private section of a class, 211 * as indicated in the example below. 212 * 213 * \code 214 * 215 * class Foo 216 * { 217 * public: 218 * Foo(); 219 * ~Foo(); 220 * 221 * // Other methods here 222 * 223 * private: 224 * DISABLE_COPY_AND_ASSIGNMENT(Foo); 225 * }; 226 * 227 * \endcode 228 */ 229 #define DISABLE_COPY_AND_ASSIGNMENT(className) \ 230 className(const className&) = delete; \ 231 className& operator=(const className&) = delete 232 233 /*! 234 * \def DISABLE_MOVE_AND_ASSIGNMENT(className) 235 * \brief Macro to disable move constructor and move assignment operations for 236 * the given class. 237 * \note This macro should only be used within the private section of a class, 238 * as indicated in the example below. 239 * 240 * \code 241 * 242 * class Foo 243 * { 244 * public: 245 * Foo(); 246 * ~Foo(); 247 * 248 * // Other methods here 249 * 250 * private: 251 * DISABLE_MOVE_AND_ASSIGNMENT(Foo); 252 * }; 253 * 254 * \endcode 255 */ 256 #define DISABLE_MOVE_AND_ASSIGNMENT(className) \ 257 className(className&&) = delete; \ 258 className& operator=(className&&) = delete 259 260 #endif /* AXOM_MACROS_HPP_ */ 261