DenseMapExtras.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright (c) 2019 Apple Inc. All Rights Reserved.
  3. *
  4. * @APPLE_LICENSE_HEADER_START@
  5. *
  6. * This file contains Original Code and/or Modifications of Original Code
  7. * as defined in and that are subject to the Apple Public Source License
  8. * Version 2.0 (the 'License'). You may not use this file except in
  9. * compliance with the License. Please obtain a copy of the License at
  10. * http://www.opensource.apple.com/apsl/ and read it before using this
  11. * file.
  12. *
  13. * The Original Code and all software distributed under the License are
  14. * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  15. * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  16. * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  18. * Please see the License for the specific language governing rights and
  19. * limitations under the License.
  20. *
  21. * @APPLE_LICENSE_HEADER_END@
  22. */
  23. #ifndef DENSEMAPEXTRAS_H
  24. #define DENSEMAPEXTRAS_H
  25. #include "llvm-DenseMap.h"
  26. #include "llvm-DenseSet.h"
  27. namespace objc {
  28. // We cannot use a C++ static initializer to initialize certain globals because
  29. // libc calls us before our C++ initializers run. We also don't want a global
  30. // pointer to some globals because of the extra indirection.
  31. //
  32. // ExplicitInit / LazyInit wrap doing it the hard way.
  33. template <typename Type>
  34. class ExplicitInit {
  35. alignas(Type) uint8_t _storage[sizeof(Type)];
  36. public:
  37. template <typename... Ts>
  38. void init(Ts &&... Args) {
  39. new (_storage) Type(std::forward<Ts>(Args)...);
  40. }
  41. Type &get() {
  42. return *reinterpret_cast<Type *>(_storage);
  43. }
  44. };
  45. template <typename Type>
  46. class LazyInit {
  47. alignas(Type) uint8_t _storage[sizeof(Type)];
  48. bool _didInit;
  49. public:
  50. template <typename... Ts>
  51. Type *get(bool allowCreate, Ts &&... Args) {
  52. if (!_didInit) {
  53. if (!allowCreate) {
  54. return nullptr;
  55. }
  56. new (_storage) Type(std::forward<Ts>(Args)...);
  57. _didInit = true;
  58. }
  59. return reinterpret_cast<Type *>(_storage);
  60. }
  61. };
  62. // Convenience class for Dense Maps & Sets
  63. template <typename Key, typename Value>
  64. class ExplicitInitDenseMap : public ExplicitInit<DenseMap<Key, Value>> { };
  65. template <typename Key, typename Value>
  66. class LazyInitDenseMap : public LazyInit<DenseMap<Key, Value>> { };
  67. template <typename Value>
  68. class ExplicitInitDenseSet : public ExplicitInit<DenseSet<Value>> { };
  69. template <typename Value>
  70. class LazyInitDenseSet : public LazyInit<DenseSet<Value>> { };
  71. } // namespace objc
  72. #endif /* DENSEMAPEXTRAS_H */