Launder.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*
  2. * Copyright 2017-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <new>
  18. #include <folly/CPortability.h>
  19. #include <folly/Portability.h>
  20. /***
  21. * include or backport:
  22. * * std::launder
  23. */
  24. // Note: libc++ 6+ adds std::launder but does not define __cpp_lib_launder
  25. #if __cpp_lib_launder >= 201606 || (_MSC_VER && _HAS_LAUNDER) || \
  26. (_LIBCPP_VERSION >= 6000 && __cplusplus >= 201703L)
  27. namespace folly {
  28. /* using override */ using std::launder;
  29. } // namespace folly
  30. #else
  31. namespace folly {
  32. /**
  33. * Approximate backport from C++17 of std::launder. It should be `constexpr`
  34. * but that can't be done without specific support from the compiler.
  35. */
  36. template <typename T>
  37. FOLLY_NODISCARD inline T* launder(T* in) noexcept {
  38. #if FOLLY_HAS_BUILTIN(__builtin_launder) || __GNUC__ >= 7
  39. // The builtin has no unwanted side-effects.
  40. return __builtin_launder(in);
  41. #elif __GNUC__
  42. // This inline assembler block declares that `in` is an input and an output,
  43. // so the compiler has to assume that it has been changed inside the block.
  44. __asm__("" : "+r"(in));
  45. return in;
  46. #elif defined(_WIN32)
  47. // MSVC does not currently have optimizations around const members of structs.
  48. // _ReadWriteBarrier() will prevent compiler reordering memory accesses.
  49. _ReadWriteBarrier();
  50. return in;
  51. #else
  52. static_assert(
  53. false, "folly::launder is not implemented for this environment");
  54. #endif
  55. }
  56. /* The standard explicitly forbids laundering these */
  57. void launder(void*) = delete;
  58. void launder(void const*) = delete;
  59. void launder(void volatile*) = delete;
  60. void launder(void const volatile*) = delete;
  61. template <typename T, typename... Args>
  62. void launder(T (*)(Args...)) = delete;
  63. } // namespace folly
  64. #endif