StaticSingletonManager.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * Copyright 2016-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 <typeinfo>
  18. #include <folly/CPortability.h>
  19. namespace folly {
  20. namespace detail {
  21. // This internal-use-only class is used to create all leaked Meyers singletons.
  22. // It guarantees that only one instance of every such singleton will ever be
  23. // created, even when requested from different compilation units linked
  24. // dynamically.
  25. class StaticSingletonManager {
  26. public:
  27. template <typename T, typename Tag, typename F>
  28. FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN static T* create(
  29. F&& creator) {
  30. return static_cast<T*>(create_<T, Tag>(creator));
  31. }
  32. private:
  33. template <typename A, typename B>
  34. struct TypePair {};
  35. using Key = std::type_info;
  36. using Make = void*(void*);
  37. template <typename F>
  38. struct Creator {
  39. static void* create(void* f) {
  40. return static_cast<void*>((*static_cast<F*>(f))());
  41. }
  42. };
  43. template <typename T, typename Tag, typename F>
  44. FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN static void* create_(
  45. F& creator) {
  46. auto const& key = typeid(TypePair<T, Tag>);
  47. return create_(key, &Creator<F>::create, &creator);
  48. }
  49. template <typename T, typename Tag, typename F>
  50. FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN static void* create_(
  51. F const& creator) {
  52. auto const& key = typeid(TypePair<T, Tag>);
  53. return create_(key, &Creator<F const>::create, const_cast<F*>(&creator));
  54. }
  55. FOLLY_NOINLINE static void* create_(Key const& key, Make* make, void* ctx);
  56. };
  57. template <typename T, typename Tag, typename F>
  58. FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T* createGlobal(F&& creator) {
  59. return StaticSingletonManager::create<T, Tag>(static_cast<F&&>(creator));
  60. }
  61. template <typename T, typename Tag>
  62. FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T* createGlobal() {
  63. return StaticSingletonManager::create<T, Tag>([]() { return new T(); });
  64. }
  65. } // namespace detail
  66. } // namespace folly