react-native-windows 0.85.0-preview.1 → 0.85.0-preview.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (910) hide show
  1. package/Directory.Build.props +1 -1
  2. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +28 -46
  3. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +0 -3
  4. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +19 -13
  5. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +107 -0
  6. package/Microsoft.ReactNative/Fabric/Composition/SelectionItemAutomationEvent.h +73 -0
  7. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +105 -32
  8. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +7 -2
  9. package/PropertySheets/CIBuildOptimizations.props +2 -2
  10. package/PropertySheets/Generated/PackageVersion.g.props +2 -2
  11. package/PropertySheets/JSEngine.props +1 -1
  12. package/PropertySheets/NuGet.LockFile.props +2 -9
  13. package/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 +54 -5
  14. package/Scripts/UpdateNightlyDependencies.ps1 +47 -0
  15. package/Scripts/creaternwapp.cmd +29 -9
  16. package/Scripts/creaternwlib.cmd +31 -15
  17. package/external/.clang-format +1 -0
  18. package/external/External.vcxitems +10 -0
  19. package/external/fast-float/.syncignore +10 -0
  20. package/external/fast-float/LICENSE-APACHE +190 -0
  21. package/external/fast-float/LICENSE-BOOST +23 -0
  22. package/external/fast-float/LICENSE-MIT +27 -0
  23. package/external/fast-float/README.md +545 -0
  24. package/external/fast-float/cgmanifest.json +15 -0
  25. package/external/fast-float/fast-float.vcxitems +14 -0
  26. package/external/fast-float/include/fast_float/ascii_number.h +588 -0
  27. package/external/fast-float/include/fast_float/bigint.h +638 -0
  28. package/external/fast-float/include/fast_float/constexpr_feature_detect.h +46 -0
  29. package/external/fast-float/include/fast_float/decimal_to_binary.h +212 -0
  30. package/external/fast-float/include/fast_float/digit_comparison.h +457 -0
  31. package/external/fast-float/include/fast_float/fast_float.h +59 -0
  32. package/external/fast-float/include/fast_float/fast_table.h +708 -0
  33. package/external/fast-float/include/fast_float/float_common.h +1240 -0
  34. package/external/fast-float/include/fast_float/parse_number.h +399 -0
  35. package/external/fast-float/sync-config.json +8 -0
  36. package/external/fmt/.syncignore +10 -0
  37. package/external/fmt/CONTRIBUTING.md +20 -0
  38. package/external/fmt/LICENSE +27 -0
  39. package/external/fmt/README.md +484 -0
  40. package/external/fmt/cgmanifest.json +15 -0
  41. package/external/fmt/doc/ChangeLog-old.md +3290 -0
  42. package/external/fmt/doc/api.md +650 -0
  43. package/external/fmt/doc/fmt.css +61 -0
  44. package/external/fmt/doc/fmt.js +4 -0
  45. package/external/fmt/doc/get-started.md +222 -0
  46. package/external/fmt/doc/index.md +151 -0
  47. package/external/fmt/doc/perf.svg +1 -0
  48. package/external/fmt/doc/python-license.txt +290 -0
  49. package/external/fmt/doc/syntax.md +887 -0
  50. package/external/fmt/fmt.vcxitems +28 -0
  51. package/external/fmt/include/fmt/args.h +228 -0
  52. package/external/fmt/include/fmt/base.h +3077 -0
  53. package/external/fmt/include/fmt/chrono.h +2432 -0
  54. package/external/fmt/include/fmt/color.h +612 -0
  55. package/external/fmt/include/fmt/compile.h +529 -0
  56. package/external/fmt/include/fmt/core.h +5 -0
  57. package/external/fmt/include/fmt/format-inl.h +1928 -0
  58. package/external/fmt/include/fmt/format.h +4427 -0
  59. package/external/fmt/include/fmt/os.h +439 -0
  60. package/external/fmt/include/fmt/ostream.h +211 -0
  61. package/external/fmt/include/fmt/printf.h +656 -0
  62. package/external/fmt/include/fmt/ranges.h +882 -0
  63. package/external/fmt/include/fmt/std.h +699 -0
  64. package/external/fmt/include/fmt/xchar.h +322 -0
  65. package/external/fmt/src/fmt.cc +135 -0
  66. package/external/fmt/src/format.cc +43 -0
  67. package/external/fmt/src/os.cc +403 -0
  68. package/external/fmt/sync-config.json +8 -0
  69. package/external/folly/.syncignore +60 -0
  70. package/external/folly/Folly.natvis +25 -0
  71. package/external/folly/LICENSE +200 -0
  72. package/external/folly/README.md +263 -0
  73. package/external/folly/cgmanifest.json +25 -0
  74. package/external/folly/folly/.clang-format +1 -0
  75. package/external/folly/folly/AtomicHashArray-inl.h +546 -0
  76. package/external/folly/folly/AtomicHashArray.h +431 -0
  77. package/external/folly/folly/AtomicHashMap-inl.h +653 -0
  78. package/external/folly/folly/AtomicHashMap.h +484 -0
  79. package/external/folly/folly/AtomicIntrusiveLinkedList.h +206 -0
  80. package/external/folly/folly/AtomicLinkedList.h +110 -0
  81. package/external/folly/folly/AtomicUnorderedMap.h +522 -0
  82. package/external/folly/folly/BUCK +1631 -0
  83. package/external/folly/folly/BUILD_MODE.bzl +72 -0
  84. package/external/folly/folly/Benchmark.cpp +986 -0
  85. package/external/folly/folly/Benchmark.h +680 -0
  86. package/external/folly/folly/BenchmarkUtil.h +47 -0
  87. package/external/folly/folly/Bits.h +17 -0
  88. package/external/folly/folly/CMakeLists.txt +110 -0
  89. package/external/folly/folly/CPortability.h +338 -0
  90. package/external/folly/folly/CancellationToken-inl.h +449 -0
  91. package/external/folly/folly/CancellationToken.cpp +250 -0
  92. package/external/folly/folly/CancellationToken.h +365 -0
  93. package/external/folly/folly/Chrono.h +132 -0
  94. package/external/folly/folly/ClockGettimeWrappers.cpp +93 -0
  95. package/external/folly/folly/ClockGettimeWrappers.h +29 -0
  96. package/external/folly/folly/ConcurrentBitSet.h +157 -0
  97. package/external/folly/folly/ConcurrentLazy.h +74 -0
  98. package/external/folly/folly/ConcurrentSkipList-inl.h +341 -0
  99. package/external/folly/folly/ConcurrentSkipList.h +824 -0
  100. package/external/folly/folly/ConstexprMath.h +978 -0
  101. package/external/folly/folly/ConstructorCallbackList.h +158 -0
  102. package/external/folly/folly/Conv.cpp +1205 -0
  103. package/external/folly/folly/Conv.h +2026 -0
  104. package/external/folly/folly/CppAttributes.h +170 -0
  105. package/external/folly/folly/CpuId.h +297 -0
  106. package/external/folly/folly/DefaultKeepAliveExecutor.h +172 -0
  107. package/external/folly/folly/Demangle.cpp +255 -0
  108. package/external/folly/folly/Demangle.h +73 -0
  109. package/external/folly/folly/DiscriminatedPtr.h +236 -0
  110. package/external/folly/folly/DynamicConverter.h +17 -0
  111. package/external/folly/folly/Exception.h +150 -0
  112. package/external/folly/folly/ExceptionString.cpp +51 -0
  113. package/external/folly/folly/ExceptionString.h +33 -0
  114. package/external/folly/folly/ExceptionWrapper-inl.h +264 -0
  115. package/external/folly/folly/ExceptionWrapper.cpp +37 -0
  116. package/external/folly/folly/ExceptionWrapper.h +377 -0
  117. package/external/folly/folly/Executor.cpp +111 -0
  118. package/external/folly/folly/Executor.h +351 -0
  119. package/external/folly/folly/Expected.h +1725 -0
  120. package/external/folly/folly/FBString.h +2888 -0
  121. package/external/folly/folly/FBVector.h +17 -0
  122. package/external/folly/folly/File.cpp +180 -0
  123. package/external/folly/folly/File.h +177 -0
  124. package/external/folly/folly/FileUtil.cpp +378 -0
  125. package/external/folly/folly/FileUtil.h +332 -0
  126. package/external/folly/folly/Fingerprint.cpp +135 -0
  127. package/external/folly/folly/Fingerprint.h +289 -0
  128. package/external/folly/folly/FixedString.h +2965 -0
  129. package/external/folly/folly/FollyMemcpy.cpp +30 -0
  130. package/external/folly/folly/FollyMemcpy.h +23 -0
  131. package/external/folly/folly/FollyMemset.cpp +29 -0
  132. package/external/folly/folly/FollyMemset.h +25 -0
  133. package/external/folly/folly/Format-inl.h +1152 -0
  134. package/external/folly/folly/Format.cpp +429 -0
  135. package/external/folly/folly/Format.h +463 -0
  136. package/external/folly/folly/FormatArg.h +285 -0
  137. package/external/folly/folly/FormatTraits.h +65 -0
  138. package/external/folly/folly/Function.h +1159 -0
  139. package/external/folly/folly/GLog.h +85 -0
  140. package/external/folly/folly/GroupVarint.cpp +153 -0
  141. package/external/folly/folly/GroupVarint.h +630 -0
  142. package/external/folly/folly/Hash.h +20 -0
  143. package/external/folly/folly/IPAddress.cpp +490 -0
  144. package/external/folly/folly/IPAddress.h +667 -0
  145. package/external/folly/folly/IPAddressException.h +82 -0
  146. package/external/folly/folly/IPAddressV4.cpp +305 -0
  147. package/external/folly/folly/IPAddressV4.h +495 -0
  148. package/external/folly/folly/IPAddressV6.cpp +541 -0
  149. package/external/folly/folly/IPAddressV6.h +627 -0
  150. package/external/folly/folly/Indestructible.h +164 -0
  151. package/external/folly/folly/IndexedMemPool.h +550 -0
  152. package/external/folly/folly/IntrusiveList.h +17 -0
  153. package/external/folly/folly/Lazy.h +142 -0
  154. package/external/folly/folly/Likely.h +76 -0
  155. package/external/folly/folly/MPMCPipeline.h +280 -0
  156. package/external/folly/folly/MPMCQueue.h +1556 -0
  157. package/external/folly/folly/MacAddress.cpp +188 -0
  158. package/external/folly/folly/MacAddress.h +260 -0
  159. package/external/folly/folly/MapUtil.h +17 -0
  160. package/external/folly/folly/Math.h +258 -0
  161. package/external/folly/folly/MaybeManagedPtr.h +120 -0
  162. package/external/folly/folly/Memory.h +900 -0
  163. package/external/folly/folly/MicroLock.cpp +76 -0
  164. package/external/folly/folly/MicroLock.h +354 -0
  165. package/external/folly/folly/MicroSpinLock.h +17 -0
  166. package/external/folly/folly/MoveWrapper.h +76 -0
  167. package/external/folly/folly/ObserverContainer.h +1026 -0
  168. package/external/folly/folly/Optional.h +743 -0
  169. package/external/folly/folly/Overload.h +325 -0
  170. package/external/folly/folly/PackedSyncPtr.h +147 -0
  171. package/external/folly/folly/Padded.h +464 -0
  172. package/external/folly/folly/Poly-inl.h +230 -0
  173. package/external/folly/folly/Poly.h +1095 -0
  174. package/external/folly/folly/PolyException.h +43 -0
  175. package/external/folly/folly/Portability.h +644 -0
  176. package/external/folly/folly/Preprocessor.h +236 -0
  177. package/external/folly/folly/ProducerConsumerQueue.h +182 -0
  178. package/external/folly/folly/RWSpinLock.h +17 -0
  179. package/external/folly/folly/Random-inl.h +86 -0
  180. package/external/folly/folly/Random.cpp +184 -0
  181. package/external/folly/folly/Random.h +434 -0
  182. package/external/folly/folly/Range.h +1772 -0
  183. package/external/folly/folly/Replaceable.h +636 -0
  184. package/external/folly/folly/ScopeGuard.cpp +29 -0
  185. package/external/folly/folly/ScopeGuard.h +420 -0
  186. package/external/folly/folly/SharedMutex.cpp +81 -0
  187. package/external/folly/folly/SharedMutex.h +1751 -0
  188. package/external/folly/folly/Singleton-inl.h +332 -0
  189. package/external/folly/folly/Singleton.cpp +512 -0
  190. package/external/folly/folly/Singleton.h +891 -0
  191. package/external/folly/folly/SingletonThreadLocal.cpp +53 -0
  192. package/external/folly/folly/SingletonThreadLocal.h +263 -0
  193. package/external/folly/folly/SocketAddress.cpp +786 -0
  194. package/external/folly/folly/SocketAddress.h +768 -0
  195. package/external/folly/folly/SpinLock.h +55 -0
  196. package/external/folly/folly/String-inl.h +668 -0
  197. package/external/folly/folly/String.cpp +777 -0
  198. package/external/folly/folly/String.h +767 -0
  199. package/external/folly/folly/Subprocess.cpp +1142 -0
  200. package/external/folly/folly/Subprocess.h +1055 -0
  201. package/external/folly/folly/Synchronized.h +1833 -0
  202. package/external/folly/folly/SynchronizedPtr.h +106 -0
  203. package/external/folly/folly/ThreadCachedInt.h +175 -0
  204. package/external/folly/folly/ThreadLocal.h +478 -0
  205. package/external/folly/folly/TimeoutQueue.cpp +78 -0
  206. package/external/folly/folly/TimeoutQueue.h +123 -0
  207. package/external/folly/folly/TokenBucket.h +673 -0
  208. package/external/folly/folly/Traits.h +1442 -0
  209. package/external/folly/folly/Try-inl.h +372 -0
  210. package/external/folly/folly/Try.cpp +23 -0
  211. package/external/folly/folly/Try.h +728 -0
  212. package/external/folly/folly/UTF8String.h +56 -0
  213. package/external/folly/folly/Unicode.cpp +201 -0
  214. package/external/folly/folly/Unicode.h +94 -0
  215. package/external/folly/folly/Unit.h +65 -0
  216. package/external/folly/folly/Uri-inl.h +101 -0
  217. package/external/folly/folly/Uri.cpp +190 -0
  218. package/external/folly/folly/Uri.h +142 -0
  219. package/external/folly/folly/Utility.h +932 -0
  220. package/external/folly/folly/VERSION +1 -0
  221. package/external/folly/folly/Varint.h +230 -0
  222. package/external/folly/folly/VirtualExecutor.h +17 -0
  223. package/external/folly/folly/algorithm/simd/BUCK +47 -0
  224. package/external/folly/folly/algorithm/simd/Contains.cpp +42 -0
  225. package/external/folly/folly/algorithm/simd/Contains.h +116 -0
  226. package/external/folly/folly/algorithm/simd/FindFixed.h +301 -0
  227. package/external/folly/folly/algorithm/simd/Ignore.h +52 -0
  228. package/external/folly/folly/algorithm/simd/Movemask.h +207 -0
  229. package/external/folly/folly/algorithm/simd/detail/BUCK +70 -0
  230. package/external/folly/folly/algorithm/simd/detail/ContainsImpl.h +91 -0
  231. package/external/folly/folly/algorithm/simd/detail/SimdAnyOf.h +83 -0
  232. package/external/folly/folly/algorithm/simd/detail/SimdForEach.h +209 -0
  233. package/external/folly/folly/algorithm/simd/detail/SimdPlatform.h +445 -0
  234. package/external/folly/folly/algorithm/simd/detail/Traits.h +125 -0
  235. package/external/folly/folly/algorithm/simd/detail/UnrollUtils.h +126 -0
  236. package/external/folly/folly/base64.h +264 -0
  237. package/external/folly/folly/chrono/BUCK +29 -0
  238. package/external/folly/folly/chrono/Clock.h +65 -0
  239. package/external/folly/folly/chrono/Conv.h +712 -0
  240. package/external/folly/folly/chrono/Hardware.h +155 -0
  241. package/external/folly/folly/chrono/test/BUCK +26 -0
  242. package/external/folly/folly/chrono/test/ClockTest.cpp +68 -0
  243. package/external/folly/folly/chrono/test/ConvTest.cpp +652 -0
  244. package/external/folly/folly/concurrency/AtomicSharedPtr.h +387 -0
  245. package/external/folly/folly/concurrency/BUCK +170 -0
  246. package/external/folly/folly/concurrency/CacheLocality.cpp +633 -0
  247. package/external/folly/folly/concurrency/CacheLocality.h +460 -0
  248. package/external/folly/folly/concurrency/ConcurrentHashMap.h +822 -0
  249. package/external/folly/folly/concurrency/CoreCachedSharedPtr.h +232 -0
  250. package/external/folly/folly/concurrency/DeadlockDetector.cpp +27 -0
  251. package/external/folly/folly/concurrency/DeadlockDetector.h +44 -0
  252. package/external/folly/folly/concurrency/DynamicBoundedQueue.h +751 -0
  253. package/external/folly/folly/concurrency/PriorityUnboundedQueueSet.h +207 -0
  254. package/external/folly/folly/concurrency/ProcessLocalUniqueId.cpp +46 -0
  255. package/external/folly/folly/concurrency/ProcessLocalUniqueId.h +38 -0
  256. package/external/folly/folly/concurrency/SingletonRelaxedCounter.h +325 -0
  257. package/external/folly/folly/concurrency/ThreadCachedSynchronized.h +227 -0
  258. package/external/folly/folly/concurrency/UnboundedQueue.h +891 -0
  259. package/external/folly/folly/concurrency/container/BUCK +77 -0
  260. package/external/folly/folly/concurrency/container/FlatCombiningPriorityQueue.h +426 -0
  261. package/external/folly/folly/concurrency/container/LockFreeRingBuffer.h +306 -0
  262. package/external/folly/folly/concurrency/container/RelaxedConcurrentPriorityQueue.h +1212 -0
  263. package/external/folly/folly/concurrency/container/SingleWriterFixedHashMap.h +322 -0
  264. package/external/folly/folly/concurrency/container/atomic_grow_array.h +564 -0
  265. package/external/folly/folly/concurrency/container/test/BUCK +75 -0
  266. package/external/folly/folly/concurrency/container/test/FlatCombiningPriorityQueueTest.cpp +570 -0
  267. package/external/folly/folly/concurrency/container/test/LockFreeRingBufferTest.cpp +276 -0
  268. package/external/folly/folly/concurrency/container/test/RelaxedConcurrentPriorityQueueTest.cpp +1570 -0
  269. package/external/folly/folly/concurrency/container/test/SingleWriterFixedHashMapTest.cpp +401 -0
  270. package/external/folly/folly/concurrency/container/test/atomic_grow_array_test.cpp +187 -0
  271. package/external/folly/folly/concurrency/detail/AtomicSharedPtr-detail.h +212 -0
  272. package/external/folly/folly/concurrency/detail/ConcurrentHashMap-detail.h +1911 -0
  273. package/external/folly/folly/concurrency/memory/AtomicReadMostlyMainPtr.cpp +43 -0
  274. package/external/folly/folly/concurrency/memory/AtomicReadMostlyMainPtr.h +190 -0
  275. package/external/folly/folly/concurrency/memory/BUCK +53 -0
  276. package/external/folly/folly/concurrency/memory/PrimaryPtr.h +338 -0
  277. package/external/folly/folly/concurrency/memory/ReadMostlySharedPtr.h +511 -0
  278. package/external/folly/folly/concurrency/memory/TLRefCount.h +228 -0
  279. package/external/folly/folly/concurrency/memory/test/AtomicReadMostlyMainPtrBenchmark.cpp +56 -0
  280. package/external/folly/folly/concurrency/memory/test/AtomicReadMostlyMainPtrTest.cpp +454 -0
  281. package/external/folly/folly/concurrency/memory/test/BUCK +95 -0
  282. package/external/folly/folly/concurrency/memory/test/PrimaryPtrTest.cpp +303 -0
  283. package/external/folly/folly/concurrency/memory/test/ReadMostlySharedPtrBenchmark.cpp +138 -0
  284. package/external/folly/folly/concurrency/memory/test/ReadMostlySharedPtrStressTest.cpp +75 -0
  285. package/external/folly/folly/concurrency/memory/test/ReadMostlySharedPtrTest.cpp +378 -0
  286. package/external/folly/folly/concurrency/memory/test/RefCountBenchmark.cpp +90 -0
  287. package/external/folly/folly/concurrency/memory/test/RefCountTest.cpp +168 -0
  288. package/external/folly/folly/concurrency/test/AtomicSharedPtrCounted.h +156 -0
  289. package/external/folly/folly/concurrency/test/AtomicSharedPtrPerformance.cpp +255 -0
  290. package/external/folly/folly/concurrency/test/AtomicSharedPtrTest.cpp +257 -0
  291. package/external/folly/folly/concurrency/test/BUCK +229 -0
  292. package/external/folly/folly/concurrency/test/CacheLocalityBenchmark.cpp +392 -0
  293. package/external/folly/folly/concurrency/test/CacheLocalityTest.cpp +1229 -0
  294. package/external/folly/folly/concurrency/test/ConcurrentHashMapBench.cpp +260 -0
  295. package/external/folly/folly/concurrency/test/ConcurrentHashMapTest.cpp +1242 -0
  296. package/external/folly/folly/concurrency/test/CoreCachedSharedPtrTest.cpp +408 -0
  297. package/external/folly/folly/concurrency/test/DynamicBoundedQueueTest.cpp +984 -0
  298. package/external/folly/folly/concurrency/test/PriorityUnboundedQueueSetTest.cpp +73 -0
  299. package/external/folly/folly/concurrency/test/ProcessLocalUniqueIdTest.cpp +66 -0
  300. package/external/folly/folly/concurrency/test/SingletonRelaxedCounterBench.cpp +101 -0
  301. package/external/folly/folly/concurrency/test/SingletonRelaxedCounterTest.cpp +185 -0
  302. package/external/folly/folly/concurrency/test/ThreadCachedSynchronizedBench.cpp +76 -0
  303. package/external/folly/folly/concurrency/test/ThreadCachedSynchronizedTest.cpp +93 -0
  304. package/external/folly/folly/concurrency/test/UnboundedQueueTest.cpp +1302 -0
  305. package/external/folly/folly/container/Access.h +57 -0
  306. package/external/folly/folly/container/Array.h +87 -0
  307. package/external/folly/folly/container/BUCK +353 -0
  308. package/external/folly/folly/container/BitIterator.h +203 -0
  309. package/external/folly/folly/container/Enumerate.h +162 -0
  310. package/external/folly/folly/container/EvictingCacheMap.h +730 -0
  311. package/external/folly/folly/container/F14.md +300 -0
  312. package/external/folly/folly/container/F14Map-fwd.h +113 -0
  313. package/external/folly/folly/container/F14Map.h +2108 -0
  314. package/external/folly/folly/container/F14Set-fwd.h +95 -0
  315. package/external/folly/folly/container/F14Set.h +1603 -0
  316. package/external/folly/folly/container/FBVector.h +1711 -0
  317. package/external/folly/folly/container/Foreach-inl.h +316 -0
  318. package/external/folly/folly/container/Foreach.h +209 -0
  319. package/external/folly/folly/container/HeterogeneousAccess-fwd.h +33 -0
  320. package/external/folly/folly/container/HeterogeneousAccess.h +171 -0
  321. package/external/folly/folly/container/IntrusiveHeap.h +268 -0
  322. package/external/folly/folly/container/IntrusiveList.h +131 -0
  323. package/external/folly/folly/container/Iterator.h +843 -0
  324. package/external/folly/folly/container/MapUtil.h +376 -0
  325. package/external/folly/folly/container/Merge.h +90 -0
  326. package/external/folly/folly/container/RegexMatchCache.cpp +521 -0
  327. package/external/folly/folly/container/RegexMatchCache.h +699 -0
  328. package/external/folly/folly/container/Reserve.h +109 -0
  329. package/external/folly/folly/container/SparseByteSet.h +123 -0
  330. package/external/folly/folly/container/View.h +81 -0
  331. package/external/folly/folly/container/WeightedEvictingCacheMap.h +651 -0
  332. package/external/folly/folly/container/detail/BUCK +115 -0
  333. package/external/folly/folly/container/detail/BitIteratorDetail.h +87 -0
  334. package/external/folly/folly/container/detail/F14Defaults.h +34 -0
  335. package/external/folly/folly/container/detail/F14IntrinsicsAvailability.h +67 -0
  336. package/external/folly/folly/container/detail/F14MapFallback.h +717 -0
  337. package/external/folly/folly/container/detail/F14Mask.h +235 -0
  338. package/external/folly/folly/container/detail/F14Policy.h +1523 -0
  339. package/external/folly/folly/container/detail/F14SetFallback.h +528 -0
  340. package/external/folly/folly/container/detail/F14Table.cpp +71 -0
  341. package/external/folly/folly/container/detail/F14Table.h +2680 -0
  342. package/external/folly/folly/container/detail/Util.h +303 -0
  343. package/external/folly/folly/container/detail/tape_detail.h +135 -0
  344. package/external/folly/folly/container/detail/test/BUCK +14 -0
  345. package/external/folly/folly/container/detail/test/F14DetailTest.cpp +47 -0
  346. package/external/folly/folly/container/heap_vector_types.h +1683 -0
  347. package/external/folly/folly/container/range_traits.h +81 -0
  348. package/external/folly/folly/container/small_vector.h +1476 -0
  349. package/external/folly/folly/container/sorted_vector_types.h +1652 -0
  350. package/external/folly/folly/container/span.h +408 -0
  351. package/external/folly/folly/container/tape.h +608 -0
  352. package/external/folly/folly/container/test/.clang-tidy +12 -0
  353. package/external/folly/folly/container/test/AccessTest.cpp +138 -0
  354. package/external/folly/folly/container/test/ArrayTest.cpp +84 -0
  355. package/external/folly/folly/container/test/BUCK +568 -0
  356. package/external/folly/folly/container/test/BitIteratorBench.cpp +112 -0
  357. package/external/folly/folly/container/test/BitIteratorTest.cpp +109 -0
  358. package/external/folly/folly/container/test/EnumerateTest.cpp +294 -0
  359. package/external/folly/folly/container/test/EvictingCacheMapBench.cpp +80 -0
  360. package/external/folly/folly/container/test/EvictingCacheMapTest.cpp +842 -0
  361. package/external/folly/folly/container/test/F14AsanSupportTest.cpp +143 -0
  362. package/external/folly/folly/container/test/F14FwdTest.cpp +37 -0
  363. package/external/folly/folly/container/test/F14InterprocessTest.cpp +404 -0
  364. package/external/folly/folly/container/test/F14MapTest.cpp +2543 -0
  365. package/external/folly/folly/container/test/F14PolicyTest.cpp +49 -0
  366. package/external/folly/folly/container/test/F14SetTest.cpp +1738 -0
  367. package/external/folly/folly/container/test/F14SmallOverheads.cpp +215 -0
  368. package/external/folly/folly/container/test/F14TestUtil.h +117 -0
  369. package/external/folly/folly/container/test/FBVectorBenchmark.cpp +380 -0
  370. package/external/folly/folly/container/test/FBVectorBenchmarks.cpp.h +100 -0
  371. package/external/folly/folly/container/test/FBVectorTest.cpp +326 -0
  372. package/external/folly/folly/container/test/FBVectorTests.cpp.h +304 -0
  373. package/external/folly/folly/container/test/ForeachBenchmark.cpp +388 -0
  374. package/external/folly/folly/container/test/ForeachTest.cpp +338 -0
  375. package/external/folly/folly/container/test/HashMapsBench.cpp +458 -0
  376. package/external/folly/folly/container/test/HeterogeneousAccessTest.cpp +242 -0
  377. package/external/folly/folly/container/test/IntrusiveHeapTest.cpp +262 -0
  378. package/external/folly/folly/container/test/IteratorTest.cpp +989 -0
  379. package/external/folly/folly/container/test/MapUtilTest.cpp +365 -0
  380. package/external/folly/folly/container/test/MergeTest.cpp +66 -0
  381. package/external/folly/folly/container/test/RegexMatchCacheTest.cpp +634 -0
  382. package/external/folly/folly/container/test/ReserveTest.cpp +173 -0
  383. package/external/folly/folly/container/test/SparseByteSetBenchmark.cpp +153 -0
  384. package/external/folly/folly/container/test/SparseByteSetTest.cpp +117 -0
  385. package/external/folly/folly/container/test/TrackingTypes.h +584 -0
  386. package/external/folly/folly/container/test/UtilTest.cpp +609 -0
  387. package/external/folly/folly/container/test/WeightedEvictingCacheMapTest.cpp +800 -0
  388. package/external/folly/folly/container/test/heap_vector_types_test.cpp +1774 -0
  389. package/external/folly/folly/container/test/range_traits_test.cpp +59 -0
  390. package/external/folly/folly/container/test/small_vector_test.cpp +1571 -0
  391. package/external/folly/folly/container/test/sorted_vector_test.cpp +1589 -0
  392. package/external/folly/folly/container/test/span_test.cpp +520 -0
  393. package/external/folly/folly/container/test/tape_bench.cpp +200 -0
  394. package/external/folly/folly/container/test/tape_test.cpp +590 -0
  395. package/external/folly/folly/defs.bzl +238 -0
  396. package/external/folly/folly/detail/AsyncTrace.cpp +36 -0
  397. package/external/folly/folly/detail/AsyncTrace.h +44 -0
  398. package/external/folly/folly/detail/AtomicHashUtils.h +42 -0
  399. package/external/folly/folly/detail/AtomicUnorderedMapUtils.h +80 -0
  400. package/external/folly/folly/detail/BUCK +406 -0
  401. package/external/folly/folly/detail/DiscriminatedPtrDetail.h +172 -0
  402. package/external/folly/folly/detail/FileUtilDetail.cpp +63 -0
  403. package/external/folly/folly/detail/FileUtilDetail.h +85 -0
  404. package/external/folly/folly/detail/FileUtilVectorDetail.h +81 -0
  405. package/external/folly/folly/detail/FingerprintPolynomial.h +132 -0
  406. package/external/folly/folly/detail/Futex-inl.h +123 -0
  407. package/external/folly/folly/detail/Futex.cpp +273 -0
  408. package/external/folly/folly/detail/Futex.h +109 -0
  409. package/external/folly/folly/detail/GroupVarintDetail.h +101 -0
  410. package/external/folly/folly/detail/IPAddress.cpp +37 -0
  411. package/external/folly/folly/detail/IPAddress.h +57 -0
  412. package/external/folly/folly/detail/IPAddressSource.h +278 -0
  413. package/external/folly/folly/detail/Iterators.h +156 -0
  414. package/external/folly/folly/detail/MPMCPipelineDetail.h +122 -0
  415. package/external/folly/folly/detail/MemoryIdler.cpp +233 -0
  416. package/external/folly/folly/detail/MemoryIdler.h +216 -0
  417. package/external/folly/folly/detail/PerfScoped.cpp +112 -0
  418. package/external/folly/folly/detail/PerfScoped.h +70 -0
  419. package/external/folly/folly/detail/PolyDetail.h +921 -0
  420. package/external/folly/folly/detail/RangeCommon.cpp +55 -0
  421. package/external/folly/folly/detail/RangeCommon.h +93 -0
  422. package/external/folly/folly/detail/RangeSse42.cpp +198 -0
  423. package/external/folly/folly/detail/RangeSse42.h +30 -0
  424. package/external/folly/folly/detail/SimpleSimdStringUtils.cpp +31 -0
  425. package/external/folly/folly/detail/SimpleSimdStringUtils.h +27 -0
  426. package/external/folly/folly/detail/SimpleSimdStringUtilsImpl.h +63 -0
  427. package/external/folly/folly/detail/Singleton.h +34 -0
  428. package/external/folly/folly/detail/SlowFingerprint.h +90 -0
  429. package/external/folly/folly/detail/SocketFastOpen.cpp +175 -0
  430. package/external/folly/folly/detail/SocketFastOpen.h +89 -0
  431. package/external/folly/folly/detail/SplitStringSimd.cpp +84 -0
  432. package/external/folly/folly/detail/SplitStringSimd.h +151 -0
  433. package/external/folly/folly/detail/SplitStringSimdImpl.h +149 -0
  434. package/external/folly/folly/detail/Sse.cpp +35 -0
  435. package/external/folly/folly/detail/Sse.h +45 -0
  436. package/external/folly/folly/detail/StaticSingletonManager.cpp +119 -0
  437. package/external/folly/folly/detail/StaticSingletonManager.h +298 -0
  438. package/external/folly/folly/detail/ThreadLocalDetail.cpp +492 -0
  439. package/external/folly/folly/detail/ThreadLocalDetail.h +800 -0
  440. package/external/folly/folly/detail/TrapOnAvx512.cpp +41 -0
  441. package/external/folly/folly/detail/TrapOnAvx512.h +21 -0
  442. package/external/folly/folly/detail/TurnSequencer.h +295 -0
  443. package/external/folly/folly/detail/TypeList.h +551 -0
  444. package/external/folly/folly/detail/UniqueInstance.cpp +136 -0
  445. package/external/folly/folly/detail/UniqueInstance.h +68 -0
  446. package/external/folly/folly/detail/base64_detail/BUCK +102 -0
  447. package/external/folly/folly/detail/base64_detail/Base64Api.cpp +40 -0
  448. package/external/folly/folly/detail/base64_detail/Base64Api.h +101 -0
  449. package/external/folly/folly/detail/base64_detail/Base64Common.h +80 -0
  450. package/external/folly/folly/detail/base64_detail/Base64Constants.h +79 -0
  451. package/external/folly/folly/detail/base64_detail/Base64HiddenConstants.h +129 -0
  452. package/external/folly/folly/detail/base64_detail/Base64SWAR.cpp +161 -0
  453. package/external/folly/folly/detail/base64_detail/Base64SWAR.h +32 -0
  454. package/external/folly/folly/detail/base64_detail/Base64Scalar.h +262 -0
  455. package/external/folly/folly/detail/base64_detail/Base64Simd.h +102 -0
  456. package/external/folly/folly/detail/base64_detail/Base64_SSE4_2.cpp +42 -0
  457. package/external/folly/folly/detail/base64_detail/Base64_SSE4_2.h +33 -0
  458. package/external/folly/folly/detail/base64_detail/Base64_SSE4_2_Platform.h +167 -0
  459. package/external/folly/folly/detail/base64_detail/README.md +392 -0
  460. package/external/folly/folly/detail/base64_detail/tests/BUCK +36 -0
  461. package/external/folly/folly/detail/base64_detail/tests/Base64AgainstScalarTest.cpp +141 -0
  462. package/external/folly/folly/detail/base64_detail/tests/Base64PlatformTest.cpp +273 -0
  463. package/external/folly/folly/detail/base64_detail/tests/Base64SpecialCasesTest.cpp +555 -0
  464. package/external/folly/folly/detail/test/AsyncTraceTest.cpp +43 -0
  465. package/external/folly/folly/detail/test/BUCK +118 -0
  466. package/external/folly/folly/detail/test/FileUtilDetailTest.cpp +56 -0
  467. package/external/folly/folly/detail/test/PerfScopedTest.cpp +107 -0
  468. package/external/folly/folly/detail/test/SimpleSimdStringUtilsTest.cpp +92 -0
  469. package/external/folly/folly/detail/test/SplitStringSimdTest.cpp +242 -0
  470. package/external/folly/folly/detail/test/StaticSingletonManagerTest.cpp +121 -0
  471. package/external/folly/folly/detail/test/ThreadLocalBenchmark.cpp +116 -0
  472. package/external/folly/folly/detail/test/ThreadLocalDetailTest.cpp +194 -0
  473. package/external/folly/folly/detail/test/TrapOnAvx512TestNegative.cpp +29 -0
  474. package/external/folly/folly/detail/test/UniqueInstanceTest.cpp +60 -0
  475. package/external/folly/folly/detail/thread_local_globals.cpp +69 -0
  476. package/external/folly/folly/detail/thread_local_globals.h +36 -0
  477. package/external/folly/folly/docs/AtomicHashMap.md +134 -0
  478. package/external/folly/folly/docs/Benchmark.md +310 -0
  479. package/external/folly/folly/docs/Conv.md +291 -0
  480. package/external/folly/folly/docs/Dynamic.md +220 -0
  481. package/external/folly/folly/docs/DynamicConverter.md +71 -0
  482. package/external/folly/folly/docs/Executors.md +63 -0
  483. package/external/folly/folly/docs/FBString.md +46 -0
  484. package/external/folly/folly/docs/FBVector.md +200 -0
  485. package/external/folly/folly/docs/Fbvector--graphical_solutions.png +0 -0
  486. package/external/folly/folly/docs/Format.md +177 -0
  487. package/external/folly/folly/docs/Function.md +92 -0
  488. package/external/folly/folly/docs/Futures.md +263 -0
  489. package/external/folly/folly/docs/GroupVarint.md +46 -0
  490. package/external/folly/folly/docs/Histogram.md +104 -0
  491. package/external/folly/folly/docs/MapUtils.md +80 -0
  492. package/external/folly/folly/docs/Overview.md +263 -0
  493. package/external/folly/folly/docs/PackedSyncPtr.md +77 -0
  494. package/external/folly/folly/docs/Poly.md +500 -0
  495. package/external/folly/folly/docs/ProducerConsumerQueue.md +82 -0
  496. package/external/folly/folly/docs/Rcu.md +218 -0
  497. package/external/folly/folly/docs/SmallLocks.md +24 -0
  498. package/external/folly/folly/docs/Synchronized.md +793 -0
  499. package/external/folly/folly/docs/ThreadCachedInt.md +98 -0
  500. package/external/folly/folly/docs/ThreadLocal.md +105 -0
  501. package/external/folly/folly/docs/Traits.md +161 -0
  502. package/external/folly/folly/docs/small_vector.md +64 -0
  503. package/external/folly/folly/docs/style.css +23 -0
  504. package/external/folly/folly/dynamic-inl.h +17 -0
  505. package/external/folly/folly/dynamic.h +17 -0
  506. package/external/folly/folly/folly_extended_library.bzl +28 -0
  507. package/external/folly/folly/functional/ApplyTuple.h +204 -0
  508. package/external/folly/folly/functional/BUCK +57 -0
  509. package/external/folly/folly/functional/Invoke.h +880 -0
  510. package/external/folly/folly/functional/Partial.h +130 -0
  511. package/external/folly/folly/functional/protocol.h +203 -0
  512. package/external/folly/folly/functional/test/ApplyTupleTest.cpp +549 -0
  513. package/external/folly/folly/functional/test/BUCK +57 -0
  514. package/external/folly/folly/functional/test/InvokeTest.cpp +483 -0
  515. package/external/folly/folly/functional/test/PartialTest.cpp +141 -0
  516. package/external/folly/folly/functional/test/protocol_test.cpp +177 -0
  517. package/external/folly/folly/functional/test/traits_test.cpp +551 -0
  518. package/external/folly/folly/functional/traits.h +675 -0
  519. package/external/folly/folly/hash/BUCK +86 -0
  520. package/external/folly/folly/hash/Checksum.cpp +275 -0
  521. package/external/folly/folly/hash/Checksum.h +94 -0
  522. package/external/folly/folly/hash/FarmHash.h +46 -0
  523. package/external/folly/folly/hash/Hash.h +1045 -0
  524. package/external/folly/folly/hash/MurmurHash.h +86 -0
  525. package/external/folly/folly/hash/SpookyHashV1.cpp +391 -0
  526. package/external/folly/folly/hash/SpookyHashV1.h +307 -0
  527. package/external/folly/folly/hash/SpookyHashV2.cpp +392 -0
  528. package/external/folly/folly/hash/SpookyHashV2.h +339 -0
  529. package/external/folly/folly/hash/detail/BUCK +26 -0
  530. package/external/folly/folly/hash/detail/ChecksumDetail.cpp +296 -0
  531. package/external/folly/folly/hash/detail/ChecksumDetail.h +137 -0
  532. package/external/folly/folly/hash/detail/Crc32CombineDetail.cpp +191 -0
  533. package/external/folly/folly/hash/detail/Crc32cDetail.cpp +303 -0
  534. package/external/folly/folly/hash/test/BUCK +132 -0
  535. package/external/folly/folly/hash/test/ChecksumBenchmark.cpp +91 -0
  536. package/external/folly/folly/hash/test/ChecksumTest.cpp +587 -0
  537. package/external/folly/folly/hash/test/FarmHashTest.cpp +41 -0
  538. package/external/folly/folly/hash/test/HashBenchmark.cpp +238 -0
  539. package/external/folly/folly/hash/test/HashTest.cpp +997 -0
  540. package/external/folly/folly/hash/test/MurmurHashTest.cpp +76 -0
  541. package/external/folly/folly/hash/test/SpookyHashV1Test.cpp +559 -0
  542. package/external/folly/folly/hash/test/SpookyHashV2Test.cpp +549 -0
  543. package/external/folly/folly/hash/test/traits_test.cpp +69 -0
  544. package/external/folly/folly/hash/traits.h +115 -0
  545. package/external/folly/folly/json/BUCK +155 -0
  546. package/external/folly/folly/json/DynamicConverter.h +464 -0
  547. package/external/folly/folly/json/DynamicParser-inl.h +316 -0
  548. package/external/folly/folly/json/DynamicParser.cpp +198 -0
  549. package/external/folly/folly/json/DynamicParser.h +394 -0
  550. package/external/folly/folly/json/JSONSchema.cpp +1030 -0
  551. package/external/folly/folly/json/JSONSchema.h +73 -0
  552. package/external/folly/folly/json/JsonMockUtil.h +73 -0
  553. package/external/folly/folly/json/JsonTestUtil.cpp +167 -0
  554. package/external/folly/folly/json/JsonTestUtil.h +88 -0
  555. package/external/folly/folly/json/bser/BUCK +24 -0
  556. package/external/folly/folly/json/bser/Bser.h +107 -0
  557. package/external/folly/folly/json/bser/Dump.cpp +253 -0
  558. package/external/folly/folly/json/bser/Load.cpp +246 -0
  559. package/external/folly/folly/json/bser/test/BUCK +14 -0
  560. package/external/folly/folly/json/bser/test/BserTest.cpp +149 -0
  561. package/external/folly/folly/json/dynamic-inl.h +1438 -0
  562. package/external/folly/folly/json/dynamic.cpp +552 -0
  563. package/external/folly/folly/json/dynamic.h +1346 -0
  564. package/external/folly/folly/json/json.cpp +1118 -0
  565. package/external/folly/folly/json/json.h +238 -0
  566. package/external/folly/folly/json/json_patch.cpp +325 -0
  567. package/external/folly/folly/json/json_patch.h +126 -0
  568. package/external/folly/folly/json/json_pointer.cpp +114 -0
  569. package/external/folly/folly/json/json_pointer.h +87 -0
  570. package/external/folly/folly/json/test/BUCK +147 -0
  571. package/external/folly/folly/json/test/DynamicBenchmark.cpp +146 -0
  572. package/external/folly/folly/json/test/DynamicConverterTest.cpp +518 -0
  573. package/external/folly/folly/json/test/DynamicOtherTest.cpp +344 -0
  574. package/external/folly/folly/json/test/DynamicParserTest.cpp +443 -0
  575. package/external/folly/folly/json/test/DynamicTest.cpp +1647 -0
  576. package/external/folly/folly/json/test/JSONSchemaTest.cpp +450 -0
  577. package/external/folly/folly/json/test/JsonBenchmark.cpp +264 -0
  578. package/external/folly/folly/json/test/JsonOtherTest.cpp +51 -0
  579. package/external/folly/folly/json/test/JsonTest.cpp +1153 -0
  580. package/external/folly/folly/json/test/JsonTestUtilTest.cpp +97 -0
  581. package/external/folly/folly/json/test/json_patch_test.cpp +361 -0
  582. package/external/folly/folly/json/test/json_pointer_test.cpp +58 -0
  583. package/external/folly/folly/json/tool/BUCK +13 -0
  584. package/external/folly/folly/json/tool/JSONSchemaTester.cpp +58 -0
  585. package/external/folly/folly/json.h +17 -0
  586. package/external/folly/folly/json_patch.h +17 -0
  587. package/external/folly/folly/json_pointer.h +17 -0
  588. package/external/folly/folly/lang/Access.h +29 -0
  589. package/external/folly/folly/lang/Align.h +240 -0
  590. package/external/folly/folly/lang/Aligned.h +92 -0
  591. package/external/folly/folly/lang/Assume.h +82 -0
  592. package/external/folly/folly/lang/BUCK +287 -0
  593. package/external/folly/folly/lang/Badge.h +108 -0
  594. package/external/folly/folly/lang/Bits.h +570 -0
  595. package/external/folly/folly/lang/BitsClass.h +312 -0
  596. package/external/folly/folly/lang/Builtin.h +74 -0
  597. package/external/folly/folly/lang/CArray.h +34 -0
  598. package/external/folly/folly/lang/CString.cpp +86 -0
  599. package/external/folly/folly/lang/CString.h +55 -0
  600. package/external/folly/folly/lang/Cast.h +51 -0
  601. package/external/folly/folly/lang/CheckedMath.h +253 -0
  602. package/external/folly/folly/lang/CustomizationPoint.h +58 -0
  603. package/external/folly/folly/lang/Exception.cpp +822 -0
  604. package/external/folly/folly/lang/Exception.h +716 -0
  605. package/external/folly/folly/lang/Extern.h +55 -0
  606. package/external/folly/folly/lang/Hint-inl.h +144 -0
  607. package/external/folly/folly/lang/Hint.h +238 -0
  608. package/external/folly/folly/lang/Keep.h +98 -0
  609. package/external/folly/folly/lang/New.h +124 -0
  610. package/external/folly/folly/lang/Ordering.h +140 -0
  611. package/external/folly/folly/lang/Pretty.h +159 -0
  612. package/external/folly/folly/lang/PropagateConst.h +413 -0
  613. package/external/folly/folly/lang/RValueReferenceWrapper.h +152 -0
  614. package/external/folly/folly/lang/SafeAssert.cpp +589 -0
  615. package/external/folly/folly/lang/SafeAssert.h +188 -0
  616. package/external/folly/folly/lang/StaticConst.h +33 -0
  617. package/external/folly/folly/lang/Thunk.h +100 -0
  618. package/external/folly/folly/lang/ToAscii.cpp +348 -0
  619. package/external/folly/folly/lang/ToAscii.h +182 -0
  620. package/external/folly/folly/lang/TypeInfo.h +58 -0
  621. package/external/folly/folly/lang/UncaughtExceptions.cpp +17 -0
  622. package/external/folly/folly/lang/UncaughtExceptions.h +19 -0
  623. package/external/folly/folly/lang/test/AlignTest.cpp +87 -0
  624. package/external/folly/folly/lang/test/AlignedTest.cpp +130 -0
  625. package/external/folly/folly/lang/test/BUCK +258 -0
  626. package/external/folly/folly/lang/test/BadgeTest.cpp +89 -0
  627. package/external/folly/folly/lang/test/BitsBenchmark.cpp +164 -0
  628. package/external/folly/folly/lang/test/BitsClassBenchmark.cpp +122 -0
  629. package/external/folly/folly/lang/test/BitsClassTest.cpp +379 -0
  630. package/external/folly/folly/lang/test/BitsTest.cpp +577 -0
  631. package/external/folly/folly/lang/test/CStringTest.cpp +60 -0
  632. package/external/folly/folly/lang/test/CastTest.cpp +47 -0
  633. package/external/folly/folly/lang/test/CheckedMathTest.cpp +394 -0
  634. package/external/folly/folly/lang/test/ExceptionBench.cpp +427 -0
  635. package/external/folly/folly/lang/test/ExceptionTest.cpp +413 -0
  636. package/external/folly/folly/lang/test/ExternTest.cpp +39 -0
  637. package/external/folly/folly/lang/test/HintTest.cpp +100 -0
  638. package/external/folly/folly/lang/test/NewTest.cpp +38 -0
  639. package/external/folly/folly/lang/test/OrderingTest.cpp +105 -0
  640. package/external/folly/folly/lang/test/PrettyTest.cpp +44 -0
  641. package/external/folly/folly/lang/test/PropagateConstTest.cpp +356 -0
  642. package/external/folly/folly/lang/test/RValueReferenceWrapperTest.cpp +85 -0
  643. package/external/folly/folly/lang/test/SafeAssertTest.cpp +75 -0
  644. package/external/folly/folly/lang/test/ThunkTest.cpp +105 -0
  645. package/external/folly/folly/lang/test/ToAsciiBench.cpp +466 -0
  646. package/external/folly/folly/lang/test/ToAsciiTest.cpp +266 -0
  647. package/external/folly/folly/lang/test/TypeInfoTest.cpp +56 -0
  648. package/external/folly/folly/memcpy.S +292 -0
  649. package/external/folly/folly/memcpy_select_aarch64.cpp +145 -0
  650. package/external/folly/folly/memory/Arena-inl.h +83 -0
  651. package/external/folly/folly/memory/Arena.h +325 -0
  652. package/external/folly/folly/memory/BUCK +191 -0
  653. package/external/folly/folly/memory/JemallocHugePageAllocator.cpp +449 -0
  654. package/external/folly/folly/memory/JemallocHugePageAllocator.h +105 -0
  655. package/external/folly/folly/memory/JemallocHugePageAllocatorTest.cpp +341 -0
  656. package/external/folly/folly/memory/JemallocNodumpAllocator.cpp +176 -0
  657. package/external/folly/folly/memory/JemallocNodumpAllocator.h +119 -0
  658. package/external/folly/folly/memory/JemallocNodumpAllocatorTest.cpp +61 -0
  659. package/external/folly/folly/memory/MallctlHelper.cpp +37 -0
  660. package/external/folly/folly/memory/MallctlHelper.h +167 -0
  661. package/external/folly/folly/memory/Malloc.h +551 -0
  662. package/external/folly/folly/memory/MemoryResource.h +57 -0
  663. package/external/folly/folly/memory/ReentrantAllocator.cpp +162 -0
  664. package/external/folly/folly/memory/ReentrantAllocator.h +261 -0
  665. package/external/folly/folly/memory/SanitizeAddress.cpp +75 -0
  666. package/external/folly/folly/memory/SanitizeAddress.h +117 -0
  667. package/external/folly/folly/memory/SanitizeLeak.cpp +119 -0
  668. package/external/folly/folly/memory/SanitizeLeak.h +108 -0
  669. package/external/folly/folly/memory/ThreadCachedArena.cpp +53 -0
  670. package/external/folly/folly/memory/ThreadCachedArena.h +90 -0
  671. package/external/folly/folly/memory/UninitializedMemoryHacks.h +426 -0
  672. package/external/folly/folly/memory/detail/BUCK +10 -0
  673. package/external/folly/folly/memory/detail/MallocImpl.cpp +52 -0
  674. package/external/folly/folly/memory/detail/MallocImpl.h +97 -0
  675. package/external/folly/folly/memory/not_null-inl.h +522 -0
  676. package/external/folly/folly/memory/not_null.h +449 -0
  677. package/external/folly/folly/memory/test/ArenaTest.cpp +354 -0
  678. package/external/folly/folly/memory/test/BUCK +146 -0
  679. package/external/folly/folly/memory/test/MallctlHelperTest.cpp +169 -0
  680. package/external/folly/folly/memory/test/MallocBenchmark.cpp +91 -0
  681. package/external/folly/folly/memory/test/MallocTest.cpp +78 -0
  682. package/external/folly/folly/memory/test/MemoryResourceTest.cpp +31 -0
  683. package/external/folly/folly/memory/test/ReentrantAllocatorTest.cpp +144 -0
  684. package/external/folly/folly/memory/test/SanitizeAddressTest.cpp +67 -0
  685. package/external/folly/folly/memory/test/SanitizeLeakTest.cpp +139 -0
  686. package/external/folly/folly/memory/test/ThreadCachedArenaTest.cpp +276 -0
  687. package/external/folly/folly/memory/test/UninitializedMemoryHacksODR.cpp +21 -0
  688. package/external/folly/folly/memory/test/UninitializedMemoryHacksTest.cpp +327 -0
  689. package/external/folly/folly/memory/test/not_null_test.cpp +608 -0
  690. package/external/folly/folly/memset.S +245 -0
  691. package/external/folly/folly/memset_select_aarch64.cpp +72 -0
  692. package/external/folly/folly/portability/Asm.h +50 -0
  693. package/external/folly/folly/portability/Atomic.h +31 -0
  694. package/external/folly/folly/portability/BUCK +456 -0
  695. package/external/folly/folly/portability/Builtins.cpp +31 -0
  696. package/external/folly/folly/portability/Builtins.h +161 -0
  697. package/external/folly/folly/portability/Config.h +43 -0
  698. package/external/folly/folly/portability/Constexpr.h +145 -0
  699. package/external/folly/folly/portability/Dirent.cpp +140 -0
  700. package/external/folly/folly/portability/Dirent.h +41 -0
  701. package/external/folly/folly/portability/Event.h +44 -0
  702. package/external/folly/folly/portability/Fcntl.cpp +120 -0
  703. package/external/folly/folly/portability/Fcntl.h +67 -0
  704. package/external/folly/folly/portability/Filesystem.cpp +67 -0
  705. package/external/folly/folly/portability/Filesystem.h +114 -0
  706. package/external/folly/folly/portability/FmtCompile.h +40 -0
  707. package/external/folly/folly/portability/GFlags.h +139 -0
  708. package/external/folly/folly/portability/GMock.h +35 -0
  709. package/external/folly/folly/portability/GTest.h +35 -0
  710. package/external/folly/folly/portability/IOVec.h +34 -0
  711. package/external/folly/folly/portability/Libgen.cpp +59 -0
  712. package/external/folly/folly/portability/Libgen.h +29 -0
  713. package/external/folly/folly/portability/Libunwind.h +21 -0
  714. package/external/folly/folly/portability/Malloc.cpp +31 -0
  715. package/external/folly/folly/portability/Malloc.h +53 -0
  716. package/external/folly/folly/portability/Math.h +90 -0
  717. package/external/folly/folly/portability/Memory.h +26 -0
  718. package/external/folly/folly/portability/OpenSSL.cpp +17 -0
  719. package/external/folly/folly/portability/OpenSSL.h +102 -0
  720. package/external/folly/folly/portability/PThread.cpp +697 -0
  721. package/external/folly/folly/portability/PThread.h +148 -0
  722. package/external/folly/folly/portability/README.md +21 -0
  723. package/external/folly/folly/portability/Sched.cpp +41 -0
  724. package/external/folly/folly/portability/Sched.h +45 -0
  725. package/external/folly/folly/portability/Sockets.cpp +245 -0
  726. package/external/folly/folly/portability/Sockets.h +155 -0
  727. package/external/folly/folly/portability/SourceLocation.h +49 -0
  728. package/external/folly/folly/portability/Stdio.cpp +77 -0
  729. package/external/folly/folly/portability/Stdio.h +32 -0
  730. package/external/folly/folly/portability/Stdlib.cpp +172 -0
  731. package/external/folly/folly/portability/Stdlib.h +64 -0
  732. package/external/folly/folly/portability/String.cpp +53 -0
  733. package/external/folly/folly/portability/String.h +39 -0
  734. package/external/folly/folly/portability/SysFile.cpp +46 -0
  735. package/external/folly/folly/portability/SysFile.h +27 -0
  736. package/external/folly/folly/portability/SysMembarrier.cpp +104 -0
  737. package/external/folly/folly/portability/SysMembarrier.h +26 -0
  738. package/external/folly/folly/portability/SysMman.cpp +242 -0
  739. package/external/folly/folly/portability/SysMman.h +68 -0
  740. package/external/folly/folly/portability/SysResource.cpp +108 -0
  741. package/external/folly/folly/portability/SysResource.h +71 -0
  742. package/external/folly/folly/portability/SysStat.cpp +66 -0
  743. package/external/folly/folly/portability/SysStat.h +52 -0
  744. package/external/folly/folly/portability/SysSyscall.h +73 -0
  745. package/external/folly/folly/portability/SysTime.cpp +62 -0
  746. package/external/folly/folly/portability/SysTime.h +50 -0
  747. package/external/folly/folly/portability/SysTypes.h +44 -0
  748. package/external/folly/folly/portability/SysUio.cpp +179 -0
  749. package/external/folly/folly/portability/SysUio.h +51 -0
  750. package/external/folly/folly/portability/Syslog.h +39 -0
  751. package/external/folly/folly/portability/Time.cpp +357 -0
  752. package/external/folly/folly/portability/Time.h +74 -0
  753. package/external/folly/folly/portability/Unistd.cpp +33 -0
  754. package/external/folly/folly/portability/Unistd.h +111 -0
  755. package/external/folly/folly/portability/Windows.h +108 -0
  756. package/external/folly/folly/portability/openat2.c +30 -0
  757. package/external/folly/folly/portability/openat2.h +39 -0
  758. package/external/folly/folly/portability/test/BUCK +59 -0
  759. package/external/folly/folly/portability/test/ConstexprTest.cpp +102 -0
  760. package/external/folly/folly/portability/test/FilesystemTest.cpp +35 -0
  761. package/external/folly/folly/portability/test/LibgenTest.cpp +35 -0
  762. package/external/folly/folly/portability/test/OpenSSLPortabilityTest.cpp +108 -0
  763. package/external/folly/folly/portability/test/PThreadTest.cpp +80 -0
  764. package/external/folly/folly/portability/test/TimeTest.cpp +90 -0
  765. package/external/folly/folly/small_vector.h +17 -0
  766. package/external/folly/folly/somerge_defs.bzl +399 -0
  767. package/external/folly/folly/sorted_vector_types.h +17 -0
  768. package/external/folly/folly/stop_watch.h +317 -0
  769. package/external/folly/folly/synchronization/AsymmetricThreadFence.cpp +91 -0
  770. package/external/folly/folly/synchronization/AsymmetricThreadFence.h +60 -0
  771. package/external/folly/folly/synchronization/AtomicNotification-inl.h +146 -0
  772. package/external/folly/folly/synchronization/AtomicNotification.cpp +34 -0
  773. package/external/folly/folly/synchronization/AtomicNotification.h +117 -0
  774. package/external/folly/folly/synchronization/AtomicRef.h +181 -0
  775. package/external/folly/folly/synchronization/AtomicStruct.h +150 -0
  776. package/external/folly/folly/synchronization/AtomicUtil-inl.h +482 -0
  777. package/external/folly/folly/synchronization/AtomicUtil.h +179 -0
  778. package/external/folly/folly/synchronization/BUCK +418 -0
  779. package/external/folly/folly/synchronization/Baton.h +419 -0
  780. package/external/folly/folly/synchronization/CallOnce.h +263 -0
  781. package/external/folly/folly/synchronization/DelayedInit.h +179 -0
  782. package/external/folly/folly/synchronization/DistributedMutex-inl.h +1744 -0
  783. package/external/folly/folly/synchronization/DistributedMutex.cpp +27 -0
  784. package/external/folly/folly/synchronization/DistributedMutex.h +342 -0
  785. package/external/folly/folly/synchronization/EventCount.h +200 -0
  786. package/external/folly/folly/synchronization/FlatCombining.h +629 -0
  787. package/external/folly/folly/synchronization/Hazptr-fwd.h +217 -0
  788. package/external/folly/folly/synchronization/Hazptr.cpp +36 -0
  789. package/external/folly/folly/synchronization/Hazptr.h +209 -0
  790. package/external/folly/folly/synchronization/HazptrDomain.cpp +68 -0
  791. package/external/folly/folly/synchronization/HazptrDomain.h +832 -0
  792. package/external/folly/folly/synchronization/HazptrHolder.h +431 -0
  793. package/external/folly/folly/synchronization/HazptrObj.h +533 -0
  794. package/external/folly/folly/synchronization/HazptrObjLinked.h +315 -0
  795. package/external/folly/folly/synchronization/HazptrRec.h +68 -0
  796. package/external/folly/folly/synchronization/HazptrThrLocal.h +180 -0
  797. package/external/folly/folly/synchronization/HazptrThreadPoolExecutor.cpp +46 -0
  798. package/external/folly/folly/synchronization/HazptrThreadPoolExecutor.h +25 -0
  799. package/external/folly/folly/synchronization/Latch.h +160 -0
  800. package/external/folly/folly/synchronization/LifoSem.h +767 -0
  801. package/external/folly/folly/synchronization/Lock.h +887 -0
  802. package/external/folly/folly/synchronization/MicroSpinLock.h +154 -0
  803. package/external/folly/folly/synchronization/NativeSemaphore.h +187 -0
  804. package/external/folly/folly/synchronization/ParkingLot.cpp +37 -0
  805. package/external/folly/folly/synchronization/ParkingLot.h +330 -0
  806. package/external/folly/folly/synchronization/PicoSpinLock.h +167 -0
  807. package/external/folly/folly/synchronization/RWSpinLock.h +549 -0
  808. package/external/folly/folly/synchronization/Rcu.cpp +26 -0
  809. package/external/folly/folly/synchronization/Rcu.h +553 -0
  810. package/external/folly/folly/synchronization/RelaxedAtomic.h +336 -0
  811. package/external/folly/folly/synchronization/SanitizeThread.cpp +141 -0
  812. package/external/folly/folly/synchronization/SanitizeThread.h +166 -0
  813. package/external/folly/folly/synchronization/SaturatingSemaphore.h +324 -0
  814. package/external/folly/folly/synchronization/SmallLocks.h +36 -0
  815. package/external/folly/folly/synchronization/ThrottledLifoSem.h +362 -0
  816. package/external/folly/folly/synchronization/WaitOptions.cpp +25 -0
  817. package/external/folly/folly/synchronization/WaitOptions.h +75 -0
  818. package/external/folly/folly/synchronization/detail/AtomicUtils.h +59 -0
  819. package/external/folly/folly/synchronization/detail/BUCK +104 -0
  820. package/external/folly/folly/synchronization/detail/Hardware.cpp +192 -0
  821. package/external/folly/folly/synchronization/detail/Hardware.h +75 -0
  822. package/external/folly/folly/synchronization/detail/HazptrUtils.h +339 -0
  823. package/external/folly/folly/synchronization/detail/InlineFunctionRef.h +229 -0
  824. package/external/folly/folly/synchronization/detail/Sleeper.cpp +27 -0
  825. package/external/folly/folly/synchronization/detail/Sleeper.h +62 -0
  826. package/external/folly/folly/synchronization/detail/Spin.h +96 -0
  827. package/external/folly/folly/synchronization/detail/ThreadCachedLists.h +174 -0
  828. package/external/folly/folly/synchronization/detail/ThreadCachedReaders.h +189 -0
  829. package/external/folly/folly/synchronization/detail/ThreadCachedTag.h +26 -0
  830. package/external/folly/folly/synchronization/detail/test/BUCK +28 -0
  831. package/external/folly/folly/synchronization/detail/test/HardwareTest.cpp +74 -0
  832. package/external/folly/folly/synchronization/detail/test/InlineFunctionRefTest.cpp +286 -0
  833. package/external/folly/folly/synchronization/example/BUCK +27 -0
  834. package/external/folly/folly/synchronization/example/HazptrLockFreeLIFO.h +88 -0
  835. package/external/folly/folly/synchronization/example/HazptrSWMRSet.h +133 -0
  836. package/external/folly/folly/synchronization/example/HazptrWideCAS.h +62 -0
  837. package/external/folly/folly/synchronization/test/AtomicNotificationTest.cpp +236 -0
  838. package/external/folly/folly/synchronization/test/AtomicRefTest.cpp +170 -0
  839. package/external/folly/folly/synchronization/test/AtomicStructTest.cpp +65 -0
  840. package/external/folly/folly/synchronization/test/AtomicUtilBench.cpp +457 -0
  841. package/external/folly/folly/synchronization/test/AtomicUtilTest.cpp +650 -0
  842. package/external/folly/folly/synchronization/test/BUCK +495 -0
  843. package/external/folly/folly/synchronization/test/Barrier.h +52 -0
  844. package/external/folly/folly/synchronization/test/BarrierTest.cpp +56 -0
  845. package/external/folly/folly/synchronization/test/BatonBenchmark.cpp +77 -0
  846. package/external/folly/folly/synchronization/test/BatonTest.cpp +164 -0
  847. package/external/folly/folly/synchronization/test/BatonTestHelpers.h +118 -0
  848. package/external/folly/folly/synchronization/test/CallOnceBenchmark.cpp +72 -0
  849. package/external/folly/folly/synchronization/test/CallOnceTest.cpp +153 -0
  850. package/external/folly/folly/synchronization/test/DelayedInitTest.cpp +281 -0
  851. package/external/folly/folly/synchronization/test/DistributedMutexTest.cpp +2074 -0
  852. package/external/folly/folly/synchronization/test/EventCountTest.cpp +124 -0
  853. package/external/folly/folly/synchronization/test/FlatCombiningBenchmark.cpp +1789 -0
  854. package/external/folly/folly/synchronization/test/FlatCombiningExamples.h +222 -0
  855. package/external/folly/folly/synchronization/test/FlatCombiningTest.cpp +121 -0
  856. package/external/folly/folly/synchronization/test/FlatCombiningTestHelpers.h +227 -0
  857. package/external/folly/folly/synchronization/test/HazptrTest.cpp +1689 -0
  858. package/external/folly/folly/synchronization/test/LatchTest.cpp +224 -0
  859. package/external/folly/folly/synchronization/test/LifoSemBench.cpp +185 -0
  860. package/external/folly/folly/synchronization/test/LifoSemTests.cpp +353 -0
  861. package/external/folly/folly/synchronization/test/LockTest.cpp +1239 -0
  862. package/external/folly/folly/synchronization/test/NativeSemaphoreTest.cpp +37 -0
  863. package/external/folly/folly/synchronization/test/ParkingLotBenchmark.cpp +239 -0
  864. package/external/folly/folly/synchronization/test/ParkingLotTest.cpp +170 -0
  865. package/external/folly/folly/synchronization/test/RWSpinLockTest.cpp +235 -0
  866. package/external/folly/folly/synchronization/test/RcuBench.cpp +66 -0
  867. package/external/folly/folly/synchronization/test/RcuTest.cpp +330 -0
  868. package/external/folly/folly/synchronization/test/RelaxedAtomicTest.cpp +389 -0
  869. package/external/folly/folly/synchronization/test/SaturatingSemaphoreTest.cpp +166 -0
  870. package/external/folly/folly/synchronization/test/Semaphore.h +242 -0
  871. package/external/folly/folly/synchronization/test/SemaphoreTest.cpp +271 -0
  872. package/external/folly/folly/synchronization/test/SmallLocksBenchmark.cpp +1296 -0
  873. package/external/folly/folly/synchronization/test/SmallLocksTest.cpp +510 -0
  874. package/external/folly/folly/synchronization/test/ThreadCachedEpochBench.h +67 -0
  875. package/external/folly/folly/synchronization/test/ThreadCachedReadersBench.cpp +42 -0
  876. package/external/folly/folly/synchronization/test/ThreadCachedReadersTest.cpp +52 -0
  877. package/external/folly/folly/synchronization/test/ThrottledLifoSemTest.cpp +243 -0
  878. package/external/folly/folly/system/AtFork.cpp +205 -0
  879. package/external/folly/folly/system/AtFork.h +116 -0
  880. package/external/folly/folly/system/AuxVector.h +198 -0
  881. package/external/folly/folly/system/BUCK +144 -0
  882. package/external/folly/folly/system/EnvUtil.cpp +93 -0
  883. package/external/folly/folly/system/EnvUtil.h +113 -0
  884. package/external/folly/folly/system/HardwareConcurrency.cpp +39 -0
  885. package/external/folly/folly/system/HardwareConcurrency.h +23 -0
  886. package/external/folly/folly/system/MemoryMapping.cpp +477 -0
  887. package/external/folly/folly/system/MemoryMapping.h +287 -0
  888. package/external/folly/folly/system/Pid.cpp +87 -0
  889. package/external/folly/folly/system/Pid.h +34 -0
  890. package/external/folly/folly/system/Shell.cpp +33 -0
  891. package/external/folly/folly/system/Shell.h +93 -0
  892. package/external/folly/folly/system/ThreadId.cpp +89 -0
  893. package/external/folly/folly/system/ThreadId.h +62 -0
  894. package/external/folly/folly/system/ThreadName.cpp +330 -0
  895. package/external/folly/folly/system/ThreadName.h +72 -0
  896. package/external/folly/folly/system/test/AtForkTest.cpp +309 -0
  897. package/external/folly/folly/system/test/AuxVectorTest.cpp +55 -0
  898. package/external/folly/folly/system/test/BUCK +120 -0
  899. package/external/folly/folly/system/test/EnvUtilSubprocess.cpp +26 -0
  900. package/external/folly/folly/system/test/EnvUtilTest.cpp +197 -0
  901. package/external/folly/folly/system/test/MemoryMappingTest.cpp +179 -0
  902. package/external/folly/folly/system/test/PidTest.cpp +46 -0
  903. package/external/folly/folly/system/test/ShellTest.cpp +66 -0
  904. package/external/folly/folly/system/test/ThreadIdTest.cpp +114 -0
  905. package/external/folly/folly/system/test/ThreadNameTest.cpp +85 -0
  906. package/external/folly/folly.vcxitems +164 -0
  907. package/external/folly/static/logo.svg +1 -0
  908. package/external/folly/sync-config.json +8 -0
  909. package/package.json +3 -3
  910. package/templates/cpp-lib/example/metro.config.js +18 -2
@@ -0,0 +1,1911 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
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
+
17
+ #pragma once
18
+
19
+ #include <algorithm>
20
+ #include <atomic>
21
+ #include <mutex>
22
+ #include <new>
23
+
24
+ #include <folly/container/HeterogeneousAccess.h>
25
+ #include <folly/container/detail/F14Mask.h>
26
+ #include <folly/lang/Exception.h>
27
+ #include <folly/synchronization/Hazptr.h>
28
+
29
+ #if FOLLY_SSE_PREREQ(4, 2) && !FOLLY_MOBILE
30
+ #include <nmmintrin.h>
31
+ #endif
32
+
33
+ namespace folly {
34
+
35
+ namespace detail {
36
+
37
+ namespace concurrenthashmap {
38
+
39
+ enum class InsertType {
40
+ DOES_NOT_EXIST, // insert/emplace operations. If key exists, return false.
41
+ MUST_EXIST, // assign operations. If key does not exist, return false.
42
+ ANY, // insert_or_assign.
43
+ MATCH, // assign_if_equal (not in std). For concurrent maps, a
44
+ // way to atomically change a value if equal to some other
45
+ // value.
46
+ };
47
+
48
+ template <
49
+ typename KeyType,
50
+ typename ValueType,
51
+ typename Allocator,
52
+ template <typename>
53
+ class Atom,
54
+ typename Enabled = void>
55
+ class ValueHolder {
56
+ public:
57
+ typedef std::pair<const KeyType, ValueType> value_type;
58
+
59
+ explicit ValueHolder(const ValueHolder& other) : item_(other.item_) {}
60
+
61
+ template <typename Arg, typename... Args>
62
+ ValueHolder(std::piecewise_construct_t, Arg&& k, Args&&... args)
63
+ : item_(
64
+ std::piecewise_construct,
65
+ std::forward_as_tuple(std::forward<Arg>(k)),
66
+ std::forward_as_tuple(std::forward<Args>(args)...)) {}
67
+ value_type& getItem() { return item_; }
68
+
69
+ private:
70
+ value_type item_;
71
+ };
72
+
73
+ // If the ValueType is not copy constructible, we can instead add
74
+ // an extra indirection. Adds more allocations / deallocations and
75
+ // pulls in an extra cacheline.
76
+ template <
77
+ typename KeyType,
78
+ typename ValueType,
79
+ typename Allocator,
80
+ template <typename>
81
+ class Atom>
82
+ class ValueHolder<
83
+ KeyType,
84
+ ValueType,
85
+ Allocator,
86
+ Atom,
87
+ std::enable_if_t<
88
+ !std::is_nothrow_copy_constructible<ValueType>::value ||
89
+ !std::is_nothrow_copy_constructible<KeyType>::value>> {
90
+ typedef std::pair<const KeyType, ValueType> value_type;
91
+
92
+ struct CountedItem {
93
+ value_type kv_;
94
+ Atom<uint32_t> numlinks_{1}; // Number of incoming links
95
+
96
+ template <typename Arg, typename... Args>
97
+ CountedItem(std::piecewise_construct_t, Arg&& k, Args&&... args)
98
+ : kv_(std::piecewise_construct,
99
+ std::forward_as_tuple(std::forward<Arg>(k)),
100
+ std::forward_as_tuple(std::forward<Args>(args)...)) {}
101
+
102
+ value_type& getItem() { return kv_; }
103
+
104
+ void acquireLink() {
105
+ uint32_t count = numlinks_.fetch_add(1, std::memory_order_release);
106
+ DCHECK_GE(count, 1u);
107
+ }
108
+
109
+ bool releaseLink() {
110
+ uint32_t count = numlinks_.load(std::memory_order_acquire);
111
+ DCHECK_GE(count, 1u);
112
+ if (count > 1) {
113
+ count = numlinks_.fetch_sub(1, std::memory_order_acq_rel);
114
+ }
115
+ return count == 1;
116
+ }
117
+ }; // CountedItem
118
+ // Back to ValueHolder specialization
119
+
120
+ CountedItem* item_; // Link to unique key-value item.
121
+
122
+ public:
123
+ explicit ValueHolder(const ValueHolder& other) {
124
+ DCHECK(other.item_);
125
+ item_ = other.item_;
126
+ item_->acquireLink();
127
+ }
128
+
129
+ ValueHolder& operator=(const ValueHolder&) = delete;
130
+
131
+ template <typename Arg, typename... Args>
132
+ ValueHolder(std::piecewise_construct_t, Arg&& k, Args&&... args) {
133
+ item_ = (CountedItem*)Allocator().allocate(sizeof(CountedItem));
134
+ new (item_) CountedItem(
135
+ std::piecewise_construct,
136
+ std::forward<Arg>(k),
137
+ std::forward<Args>(args)...);
138
+ }
139
+
140
+ ~ValueHolder() {
141
+ DCHECK(item_);
142
+ if (item_->releaseLink()) {
143
+ item_->~CountedItem();
144
+ Allocator().deallocate((uint8_t*)item_, sizeof(CountedItem));
145
+ }
146
+ }
147
+
148
+ value_type& getItem() {
149
+ DCHECK(item_);
150
+ return item_->getItem();
151
+ }
152
+ }; // ValueHolder specialization
153
+
154
+ // hazptr deleter that can use an allocator.
155
+ template <typename Allocator>
156
+ class HazptrDeleter {
157
+ public:
158
+ template <typename Node>
159
+ void operator()(Node* node) {
160
+ node->~Node();
161
+ Allocator().deallocate((uint8_t*)node, sizeof(Node));
162
+ }
163
+ };
164
+
165
+ class HazptrTableDeleter {
166
+ size_t count_;
167
+
168
+ public:
169
+ HazptrTableDeleter(size_t count) : count_(count) {}
170
+ HazptrTableDeleter() = default;
171
+ template <typename Table>
172
+ void operator()(Table* table) {
173
+ table->destroy(count_);
174
+ }
175
+ };
176
+
177
+ namespace bucket {
178
+
179
+ template <
180
+ typename KeyType,
181
+ typename ValueType,
182
+ typename Allocator,
183
+ template <typename> class Atom = std::atomic>
184
+ class NodeT : public hazptr_obj_base_linked<
185
+ NodeT<KeyType, ValueType, Allocator, Atom>,
186
+ Atom,
187
+ concurrenthashmap::HazptrDeleter<Allocator>> {
188
+ public:
189
+ typedef std::pair<const KeyType, ValueType> value_type;
190
+
191
+ explicit NodeT(hazptr_obj_cohort<Atom>* cohort, NodeT* other)
192
+ : item_(other->item_) {
193
+ init(cohort);
194
+ }
195
+
196
+ template <typename Arg, typename... Args>
197
+ NodeT(hazptr_obj_cohort<Atom>* cohort, Arg&& k, Args&&... args)
198
+ : item_(
199
+ std::piecewise_construct,
200
+ std::forward<Arg>(k),
201
+ std::forward<Args>(args)...) {
202
+ init(cohort);
203
+ }
204
+
205
+ void release() { this->unlink(); }
206
+
207
+ value_type& getItem() { return item_.getItem(); }
208
+
209
+ template <typename S>
210
+ void push_links(bool m, S& s) {
211
+ if (m) {
212
+ auto p = next_.load(std::memory_order_acquire);
213
+ if (p) {
214
+ s.push(p);
215
+ }
216
+ }
217
+ }
218
+
219
+ Atom<NodeT*> next_{nullptr};
220
+
221
+ private:
222
+ void init(hazptr_obj_cohort<Atom>* cohort) {
223
+ DCHECK(cohort);
224
+ this->set_deleter( // defined in hazptr_obj
225
+ concurrenthashmap::HazptrDeleter<Allocator>());
226
+ this->set_cohort_tag(cohort); // defined in hazptr_obj
227
+ this->acquire_link_safe(); // defined in hazptr_obj_base_linked
228
+ }
229
+
230
+ ValueHolder<KeyType, ValueType, Allocator, Atom> item_;
231
+ };
232
+
233
+ template <
234
+ typename KeyType,
235
+ typename ValueType,
236
+ uint8_t ShardBits = 0,
237
+ typename HashFn = std::hash<KeyType>,
238
+ typename KeyEqual = std::equal_to<KeyType>,
239
+ typename Allocator = std::allocator<uint8_t>,
240
+ template <typename> class Atom = std::atomic,
241
+ class Mutex = std::mutex>
242
+ class alignas(64) BucketTable {
243
+ public:
244
+ // Slightly higher than 1.0, in case hashing to shards isn't
245
+ // perfectly balanced, reserve(size) will still work without
246
+ // rehashing.
247
+ static constexpr float kDefaultLoadFactor = 1.05f;
248
+ typedef std::pair<const KeyType, ValueType> value_type;
249
+
250
+ using Node =
251
+ concurrenthashmap::bucket::NodeT<KeyType, ValueType, Allocator, Atom>;
252
+ using InsertType = concurrenthashmap::InsertType;
253
+ class Iterator;
254
+
255
+ BucketTable(
256
+ size_t initial_buckets,
257
+ float load_factor,
258
+ size_t max_size,
259
+ hazptr_obj_cohort<Atom>* cohort)
260
+ : load_factor_(load_factor), max_size_(max_size) {
261
+ DCHECK(cohort);
262
+ initial_buckets = folly::nextPowTwo(initial_buckets);
263
+ DCHECK(
264
+ max_size_ == 0 ||
265
+ (isPowTwo(max_size_) &&
266
+ (folly::popcount(max_size_ - 1) + ShardBits <= 32)));
267
+ auto buckets = Buckets::create(initial_buckets, cohort);
268
+ buckets_.store(buckets, std::memory_order_release);
269
+ load_factor_nodes_ =
270
+ to_integral(static_cast<float>(initial_buckets) * load_factor_);
271
+ bucket_count_.store(initial_buckets, std::memory_order_relaxed);
272
+ }
273
+
274
+ ~BucketTable() {
275
+ auto buckets = buckets_.load(std::memory_order_relaxed);
276
+ // To catch use-after-destruction bugs in user code.
277
+ buckets_.store(nullptr, std::memory_order_release);
278
+ // We can delete and not retire() here, since users must have
279
+ // their own synchronization around destruction.
280
+ auto count = bucket_count_.load(std::memory_order_relaxed);
281
+ buckets->unlink_and_reclaim_nodes(count);
282
+ buckets->destroy(count);
283
+ }
284
+
285
+ size_t size() { return size_.load(std::memory_order_acquire); }
286
+
287
+ void clearSize() { size_.store(0, std::memory_order_release); }
288
+
289
+ void incSize() {
290
+ auto sz = size_.load(std::memory_order_relaxed);
291
+ size_.store(sz + 1, std::memory_order_release);
292
+ }
293
+
294
+ void decSize() {
295
+ auto sz = size_.load(std::memory_order_relaxed);
296
+ DCHECK_GT(sz, 0);
297
+ size_.store(sz - 1, std::memory_order_release);
298
+ }
299
+
300
+ bool empty() { return size() == 0; }
301
+
302
+ template <typename MatchFunc, typename K, typename... Args>
303
+ bool insert(
304
+ Iterator& it,
305
+ size_t h,
306
+ const K& k,
307
+ InsertType type,
308
+ MatchFunc match,
309
+ hazptr_obj_cohort<Atom>* cohort,
310
+ Args&&... args) {
311
+ return doInsert(
312
+ it, h, k, type, match, nullptr, cohort, std::forward<Args>(args)...);
313
+ }
314
+
315
+ template <typename MatchFunc, typename K, typename... Args>
316
+ bool insert(
317
+ Iterator& it,
318
+ size_t h,
319
+ const K& k,
320
+ InsertType type,
321
+ MatchFunc match,
322
+ Node* cur,
323
+ hazptr_obj_cohort<Atom>* cohort) {
324
+ return doInsert(it, h, k, type, match, cur, cohort, cur);
325
+ }
326
+
327
+ // Must hold lock.
328
+ void rehash(size_t bucket_count, hazptr_obj_cohort<Atom>* cohort) {
329
+ auto oldcount = bucket_count_.load(std::memory_order_relaxed);
330
+ // bucket_count must be a power of 2
331
+ DCHECK_EQ(bucket_count & (bucket_count - 1), 0);
332
+ if (bucket_count <= oldcount) {
333
+ return; // Rehash only if expanding.
334
+ }
335
+ auto buckets = buckets_.load(std::memory_order_relaxed);
336
+ DCHECK(buckets); // Use-after-destruction by user.
337
+ auto newbuckets = Buckets::create(bucket_count, cohort);
338
+ load_factor_nodes_ =
339
+ to_integral(static_cast<float>(bucket_count) * load_factor_);
340
+ for (size_t i = 0; i < oldcount; i++) {
341
+ auto bucket = &buckets->buckets_[i]();
342
+ auto node = bucket->load(std::memory_order_relaxed);
343
+ if (!node) {
344
+ continue;
345
+ }
346
+ auto h = HashFn()(node->getItem().first);
347
+ auto idx = getIdx(bucket_count, h);
348
+ // Reuse as long a chain as possible from the end. Since the
349
+ // nodes don't have previous pointers, the longest last chain
350
+ // will be the same for both the previous hashmap and the new one,
351
+ // assuming all the nodes hash to the same bucket.
352
+ auto lastrun = node;
353
+ auto lastidx = idx;
354
+ auto last = node->next_.load(std::memory_order_relaxed);
355
+ for (; last != nullptr;
356
+ last = last->next_.load(std::memory_order_relaxed)) {
357
+ auto k = getIdx(bucket_count, HashFn()(last->getItem().first));
358
+ if (k != lastidx) {
359
+ lastidx = k;
360
+ lastrun = last;
361
+ }
362
+ }
363
+ // Set longest last run in new bucket, incrementing the refcount.
364
+ lastrun->acquire_link(); // defined in hazptr_obj_base_linked
365
+ newbuckets->buckets_[lastidx]().store(lastrun, std::memory_order_relaxed);
366
+ // Clone remaining nodes
367
+ for (; node != lastrun;
368
+ node = node->next_.load(std::memory_order_relaxed)) {
369
+ auto newnode = (Node*)Allocator().allocate(sizeof(Node));
370
+ new (newnode) Node(cohort, node);
371
+ auto k = getIdx(bucket_count, HashFn()(node->getItem().first));
372
+ auto prevhead = &newbuckets->buckets_[k]();
373
+ newnode->next_.store(prevhead->load(std::memory_order_relaxed));
374
+ prevhead->store(newnode, std::memory_order_relaxed);
375
+ }
376
+ }
377
+
378
+ auto oldbuckets = buckets_.load(std::memory_order_relaxed);
379
+ DCHECK(oldbuckets); // Use-after-destruction by user.
380
+ seqlock_.fetch_add(1, std::memory_order_release);
381
+ bucket_count_.store(bucket_count, std::memory_order_release);
382
+ buckets_.store(newbuckets, std::memory_order_release);
383
+ seqlock_.fetch_add(1, std::memory_order_release);
384
+ oldbuckets->retire(concurrenthashmap::HazptrTableDeleter(oldcount));
385
+ }
386
+
387
+ template <typename K>
388
+ bool find(Iterator& res, size_t h, const K& k) {
389
+ auto& hazcurr = res.hazptrs_[1];
390
+ auto& haznext = res.hazptrs_[2];
391
+ size_t bcount;
392
+ Buckets* buckets;
393
+ getBucketsAndCount(bcount, buckets, res.hazptrs_[0]);
394
+
395
+ auto idx = getIdx(bcount, h);
396
+ auto prev = &buckets->buckets_[idx]();
397
+ auto node = hazcurr.protect(*prev);
398
+ while (node) {
399
+ if (KeyEqual()(k, node->getItem().first)) {
400
+ res.setNode(node, buckets, bcount, idx);
401
+ return true;
402
+ }
403
+ node = haznext.protect(node->next_);
404
+ hazcurr.swap(haznext);
405
+ }
406
+ return false;
407
+ }
408
+
409
+ template <typename K, typename MatchFunc>
410
+ std::size_t erase(size_t h, const K& key, Iterator* iter, MatchFunc match) {
411
+ Node* node{nullptr};
412
+ {
413
+ std::lock_guard<Mutex> g(m_);
414
+
415
+ size_t bcount = bucket_count_.load(std::memory_order_relaxed);
416
+ auto buckets = buckets_.load(std::memory_order_relaxed);
417
+ DCHECK(buckets); // Use-after-destruction by user.
418
+ auto idx = getIdx(bcount, h);
419
+ auto head = &buckets->buckets_[idx]();
420
+ node = head->load(std::memory_order_relaxed);
421
+ Node* prev = nullptr;
422
+ while (node) {
423
+ if (KeyEqual()(key, node->getItem().first)) {
424
+ if (!match(node->getItem().second)) {
425
+ return 0;
426
+ }
427
+ auto next = node->next_.load(std::memory_order_relaxed);
428
+ if (next) {
429
+ next->acquire_link(); // defined in hazptr_obj_base_linked
430
+ }
431
+ if (prev) {
432
+ prev->next_.store(next, std::memory_order_release);
433
+ } else {
434
+ // Must be head of list.
435
+ head->store(next, std::memory_order_release);
436
+ }
437
+
438
+ if (iter) {
439
+ iter->hazptrs_[0].reset_protection(buckets);
440
+ iter->setNode(
441
+ node->next_.load(std::memory_order_acquire),
442
+ buckets,
443
+ bcount,
444
+ idx);
445
+ iter->next();
446
+ }
447
+ decSize();
448
+ break;
449
+ }
450
+ prev = node;
451
+ node = node->next_.load(std::memory_order_relaxed);
452
+ }
453
+ }
454
+ // Delete the node while not under the lock.
455
+ if (node) {
456
+ node->release();
457
+ return 1;
458
+ }
459
+
460
+ return 0;
461
+ }
462
+
463
+ void clear(hazptr_obj_cohort<Atom>* cohort) {
464
+ size_t bcount;
465
+ Buckets* buckets;
466
+ {
467
+ std::lock_guard<Mutex> g(m_);
468
+ bcount = bucket_count_.load(std::memory_order_relaxed);
469
+ auto newbuckets = Buckets::create(bcount, cohort);
470
+ buckets = buckets_.load(std::memory_order_relaxed);
471
+ buckets_.store(newbuckets, std::memory_order_release);
472
+ clearSize();
473
+ }
474
+ DCHECK(buckets); // Use-after-destruction by user.
475
+ buckets->retire(concurrenthashmap::HazptrTableDeleter(bcount));
476
+ }
477
+
478
+ void max_load_factor(float factor) {
479
+ std::lock_guard<Mutex> g(m_);
480
+ load_factor_ = factor;
481
+ load_factor_nodes_ =
482
+ bucket_count_.load(std::memory_order_relaxed) * load_factor_;
483
+ }
484
+
485
+ Iterator cbegin() {
486
+ Iterator res;
487
+ size_t bcount;
488
+ Buckets* buckets;
489
+ getBucketsAndCount(bcount, buckets, res.hazptrs_[0]);
490
+ res.setNode(nullptr, buckets, bcount, 0);
491
+ res.next();
492
+ return res;
493
+ }
494
+
495
+ Iterator cend() { return Iterator(nullptr); }
496
+
497
+ private:
498
+ // Could be optimized to avoid an extra pointer dereference by
499
+ // allocating buckets_ at the same time.
500
+ class Buckets : public hazptr_obj_base<
501
+ Buckets,
502
+ Atom,
503
+ concurrenthashmap::HazptrTableDeleter> {
504
+ using BucketRoot = hazptr_root<Node, Atom>;
505
+
506
+ Buckets() {}
507
+ ~Buckets() {}
508
+
509
+ public:
510
+ static Buckets* create(size_t count, hazptr_obj_cohort<Atom>* cohort) {
511
+ auto buf =
512
+ Allocator().allocate(sizeof(Buckets) + sizeof(BucketRoot) * count);
513
+ auto buckets = new (buf) Buckets();
514
+ DCHECK(cohort);
515
+ buckets->set_cohort_tag(cohort); // defined in hazptr_obj
516
+ for (size_t i = 0; i < count; i++) {
517
+ new (&buckets->buckets_[i]) BucketRoot;
518
+ }
519
+ return buckets;
520
+ }
521
+
522
+ void destroy(size_t count) {
523
+ for (size_t i = 0; i < count; i++) {
524
+ buckets_[i].~BucketRoot();
525
+ }
526
+ this->~Buckets();
527
+ Allocator().deallocate(
528
+ (uint8_t*)this, sizeof(BucketRoot) * count + sizeof(*this));
529
+ }
530
+
531
+ void unlink_and_reclaim_nodes(size_t count) {
532
+ for (size_t i = 0; i < count; i++) {
533
+ auto node = buckets_[i]().load(std::memory_order_relaxed);
534
+ if (node) {
535
+ buckets_[i]().store(nullptr, std::memory_order_relaxed);
536
+ while (node) {
537
+ auto next = node->next_.load(std::memory_order_relaxed);
538
+ if (next) {
539
+ node->next_.store(nullptr, std::memory_order_relaxed);
540
+ }
541
+ node->unlink_and_reclaim_unchecked();
542
+ node = next;
543
+ }
544
+ }
545
+ }
546
+ }
547
+
548
+ BucketRoot buckets_[0];
549
+ };
550
+
551
+ public:
552
+ class Iterator {
553
+ public:
554
+ FOLLY_ALWAYS_INLINE Iterator()
555
+ : hazptrs_(make_hazard_pointer_array<3, Atom>()) {}
556
+ FOLLY_ALWAYS_INLINE explicit Iterator(std::nullptr_t) : hazptrs_() {}
557
+ FOLLY_ALWAYS_INLINE ~Iterator() {}
558
+
559
+ void setNode(
560
+ Node* node, Buckets* buckets, size_t bucket_count, uint64_t idx) {
561
+ node_ = node;
562
+ buckets_ = buckets;
563
+ idx_ = idx;
564
+ bucket_count_ = bucket_count;
565
+ }
566
+
567
+ const value_type& operator*() const {
568
+ DCHECK(node_);
569
+ return node_->getItem();
570
+ }
571
+
572
+ const value_type* operator->() const {
573
+ DCHECK(node_);
574
+ return &(node_->getItem());
575
+ }
576
+
577
+ const Iterator& operator++() {
578
+ DCHECK(node_);
579
+ node_ = hazptrs_[2].protect(node_->next_);
580
+ hazptrs_[1].swap(hazptrs_[2]);
581
+ if (!node_) {
582
+ ++idx_;
583
+ next();
584
+ }
585
+ return *this;
586
+ }
587
+
588
+ void next() {
589
+ while (!node_) {
590
+ if (idx_ >= bucket_count_) {
591
+ break;
592
+ }
593
+ DCHECK(buckets_);
594
+ node_ = hazptrs_[1].protect(buckets_->buckets_[idx_]());
595
+ if (node_) {
596
+ break;
597
+ }
598
+ ++idx_;
599
+ }
600
+ }
601
+
602
+ bool operator==(const Iterator& o) const { return node_ == o.node_; }
603
+
604
+ bool operator!=(const Iterator& o) const { return !(*this == o); }
605
+
606
+ Iterator& operator=(const Iterator& o) = delete;
607
+
608
+ Iterator& operator=(Iterator&& o) noexcept {
609
+ if (this != &o) {
610
+ hazptrs_ = std::move(o.hazptrs_);
611
+ node_ = std::exchange(o.node_, nullptr);
612
+ buckets_ = std::exchange(o.buckets_, nullptr);
613
+ bucket_count_ = std::exchange(o.bucket_count_, 0);
614
+ idx_ = std::exchange(o.idx_, 0);
615
+ }
616
+ return *this;
617
+ }
618
+
619
+ Iterator(const Iterator& o) = delete;
620
+
621
+ Iterator(Iterator&& o) noexcept
622
+ : hazptrs_(std::move(o.hazptrs_)),
623
+ node_(std::exchange(o.node_, nullptr)),
624
+ buckets_(std::exchange(o.buckets_, nullptr)),
625
+ bucket_count_(std::exchange(o.bucket_count_, 0)),
626
+ idx_(std::exchange(o.idx_, 0)) {}
627
+
628
+ // These are accessed directly from the functions above
629
+ hazptr_array<3, Atom> hazptrs_;
630
+
631
+ private:
632
+ Node* node_{nullptr};
633
+ Buckets* buckets_{nullptr};
634
+ size_t bucket_count_{0};
635
+ uint64_t idx_{0};
636
+ };
637
+
638
+ private:
639
+ // Shards have already used low ShardBits of the hash.
640
+ // Shift it over to use fresh bits.
641
+ uint64_t getIdx(size_t bucket_count, size_t hash) {
642
+ return (hash >> ShardBits) & (bucket_count - 1);
643
+ }
644
+ void getBucketsAndCount(
645
+ size_t& bcount, Buckets*& buckets, hazptr_holder<Atom>& hazptr) {
646
+ while (true) {
647
+ auto seqlock = seqlock_.load(std::memory_order_acquire);
648
+ bcount = bucket_count_.load(std::memory_order_acquire);
649
+ buckets = hazptr.protect(buckets_);
650
+ auto seqlock2 = seqlock_.load(std::memory_order_acquire);
651
+ if (!(seqlock & 1) && (seqlock == seqlock2)) {
652
+ break;
653
+ }
654
+ }
655
+ DCHECK(buckets) << "Use-after-destruction by user.";
656
+ }
657
+
658
+ template <typename MatchFunc, typename K, typename... Args>
659
+ bool doInsert(
660
+ Iterator& it,
661
+ size_t h,
662
+ const K& k,
663
+ InsertType type,
664
+ MatchFunc match,
665
+ Node* cur,
666
+ hazptr_obj_cohort<Atom>* cohort,
667
+ Args&&... args) {
668
+ std::unique_lock<Mutex> g(m_);
669
+
670
+ size_t bcount = bucket_count_.load(std::memory_order_relaxed);
671
+ auto buckets = buckets_.load(std::memory_order_relaxed);
672
+ // Check for rehash needed for DOES_NOT_EXIST
673
+ if (size() >= load_factor_nodes_ && type == InsertType::DOES_NOT_EXIST) {
674
+ if (max_size_ && size() << 1 > max_size_) {
675
+ // Would exceed max size.
676
+ throw_exception<std::bad_alloc>();
677
+ }
678
+ rehash(bcount << 1, cohort);
679
+ buckets = buckets_.load(std::memory_order_relaxed);
680
+ bcount = bucket_count_.load(std::memory_order_relaxed);
681
+ }
682
+
683
+ DCHECK(buckets) << "Use-after-destruction by user.";
684
+ auto idx = getIdx(bcount, h);
685
+ auto head = &buckets->buckets_[idx]();
686
+ auto node = head->load(std::memory_order_relaxed);
687
+ auto headnode = node;
688
+ auto prev = head;
689
+ auto& hazbuckets = it.hazptrs_[0];
690
+ auto& haznode = it.hazptrs_[1];
691
+ hazbuckets.reset_protection(buckets);
692
+ while (node) {
693
+ // Is the key found?
694
+ if (KeyEqual()(k, node->getItem().first)) {
695
+ it.setNode(node, buckets, bcount, idx);
696
+ haznode.reset_protection(node);
697
+ if (type == InsertType::MATCH) {
698
+ if (!match(node->getItem().second)) {
699
+ return false;
700
+ }
701
+ }
702
+ if (type == InsertType::DOES_NOT_EXIST) {
703
+ return false;
704
+ } else {
705
+ if (!cur) {
706
+ cur = (Node*)Allocator().allocate(sizeof(Node));
707
+ new (cur) Node(cohort, std::forward<Args>(args)...);
708
+ }
709
+ auto next = node->next_.load(std::memory_order_relaxed);
710
+ cur->next_.store(next, std::memory_order_relaxed);
711
+ if (next) {
712
+ next->acquire_link(); // defined in hazptr_obj_base_linked
713
+ }
714
+ prev->store(cur, std::memory_order_release);
715
+ it.setNode(cur, buckets, bcount, idx);
716
+ haznode.reset_protection(cur);
717
+ g.unlock();
718
+ // Release not under lock.
719
+ node->release();
720
+ return true;
721
+ }
722
+ }
723
+
724
+ prev = &node->next_;
725
+ node = node->next_.load(std::memory_order_relaxed);
726
+ }
727
+ if (type != InsertType::DOES_NOT_EXIST && type != InsertType::ANY) {
728
+ haznode.reset_protection();
729
+ hazbuckets.reset_protection();
730
+ return false;
731
+ }
732
+ // Node not found, check for rehash on ANY
733
+ if (size() >= load_factor_nodes_ && type == InsertType::ANY) {
734
+ if (max_size_ && size() << 1 > max_size_) {
735
+ // Would exceed max size.
736
+ throw_exception<std::bad_alloc>();
737
+ }
738
+ rehash(bcount << 1, cohort);
739
+
740
+ // Reload correct bucket.
741
+ buckets = buckets_.load(std::memory_order_relaxed);
742
+ DCHECK(buckets); // Use-after-destruction by user.
743
+ bcount <<= 1;
744
+ hazbuckets.reset_protection(buckets);
745
+ idx = getIdx(bcount, h);
746
+ head = &buckets->buckets_[idx]();
747
+ headnode = head->load(std::memory_order_relaxed);
748
+ }
749
+
750
+ // We found a slot to put the node.
751
+ incSize();
752
+ if (!cur) {
753
+ // InsertType::ANY
754
+ // OR DOES_NOT_EXIST, but only in the try_emplace case
755
+ DCHECK(type == InsertType::ANY || type == InsertType::DOES_NOT_EXIST);
756
+ cur = (Node*)Allocator().allocate(sizeof(Node));
757
+ new (cur) Node(cohort, std::forward<Args>(args)...);
758
+ }
759
+ cur->next_.store(headnode, std::memory_order_relaxed);
760
+ head->store(cur, std::memory_order_release);
761
+ it.setNode(cur, buckets, bcount, idx);
762
+ haznode.reset_protection(cur);
763
+ return true;
764
+ }
765
+
766
+ Mutex m_;
767
+ float load_factor_;
768
+ size_t load_factor_nodes_;
769
+ Atom<size_t> size_{0};
770
+ size_t const max_size_;
771
+
772
+ // Fields needed for read-only access, on separate cacheline.
773
+ alignas(64) Atom<Buckets*> buckets_{nullptr};
774
+ std::atomic<uint64_t> seqlock_{0};
775
+ Atom<size_t> bucket_count_;
776
+ };
777
+
778
+ } // namespace bucket
779
+
780
+ #if FOLLY_SSE_PREREQ(4, 2) && FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
781
+
782
+ namespace simd {
783
+
784
+ using folly::f14::detail::DenseMaskIter;
785
+ using folly::f14::detail::FirstEmptyInMask;
786
+ using folly::f14::detail::FullMask;
787
+ using folly::f14::detail::MaskType;
788
+ using folly::f14::detail::SparseMaskIter;
789
+
790
+ using folly::hazptr_obj_base;
791
+ using folly::hazptr_obj_cohort;
792
+
793
+ template <
794
+ typename KeyType,
795
+ typename ValueType,
796
+ typename Allocator,
797
+ template <typename> class Atom = std::atomic>
798
+ class NodeT : public hazptr_obj_base<
799
+ NodeT<KeyType, ValueType, Allocator, Atom>,
800
+ Atom,
801
+ HazptrDeleter<Allocator>> {
802
+ public:
803
+ typedef std::pair<const KeyType, ValueType> value_type;
804
+
805
+ template <typename Arg, typename... Args>
806
+ NodeT(hazptr_obj_cohort<Atom>* cohort, Arg&& k, Args&&... args)
807
+ : item_(
808
+ std::piecewise_construct,
809
+ std::forward_as_tuple(std::forward<Arg>(k)),
810
+ std::forward_as_tuple(std::forward<Args>(args)...)) {
811
+ init(cohort);
812
+ }
813
+
814
+ value_type& getItem() { return item_; }
815
+
816
+ private:
817
+ void init(hazptr_obj_cohort<Atom>* cohort) {
818
+ DCHECK(cohort);
819
+ this->set_deleter( // defined in hazptr_obj
820
+ HazptrDeleter<Allocator>());
821
+ this->set_cohort_tag(cohort); // defined in hazptr_obj
822
+ }
823
+
824
+ value_type item_;
825
+ };
826
+
827
+ constexpr std::size_t kRequiredVectorAlignment =
828
+ constexpr_max(std::size_t{16}, alignof(max_align_t));
829
+
830
+ template <
831
+ typename KeyType,
832
+ typename ValueType,
833
+ uint8_t ShardBits = 0,
834
+ typename HashFn = std::hash<KeyType>,
835
+ typename KeyEqual = std::equal_to<KeyType>,
836
+ typename Allocator = std::allocator<uint8_t>,
837
+ template <typename> class Atom = std::atomic,
838
+ class Mutex = std::mutex>
839
+ class alignas(64) SIMDTable {
840
+ public:
841
+ using Node =
842
+ concurrenthashmap::simd::NodeT<KeyType, ValueType, Allocator, Atom>;
843
+
844
+ private:
845
+ using HashPair = std::pair<std::size_t, std::size_t>;
846
+ struct alignas(kRequiredVectorAlignment) Chunk {
847
+ static constexpr unsigned kCapacity = 14;
848
+ static constexpr unsigned kDesiredCapacity = 12;
849
+
850
+ static constexpr MaskType kFullMask = FullMask<kCapacity>::value;
851
+
852
+ private:
853
+ // Non-empty tags have their top bit set.
854
+
855
+ // tags [0,8)
856
+ Atom<uint64_t> tags_low_;
857
+
858
+ // tags_hi_ holds tags [8,14), hostedOverflowCount and outboundOverflowCount
859
+
860
+ // hostedOverflowCount: the number of values in this chunk that were placed
861
+ // because they overflowed their desired chunk.
862
+
863
+ // outboundOverflowCount: num values that would have been placed into this
864
+ // chunk if there had been space, including values that also overflowed
865
+ // previous full chunks. This value saturates; once it becomes 255 it no
866
+ // longer increases nor decreases.
867
+
868
+ // Note: more bits can be used for outboundOverflowCount if this
869
+ // optimization becomes useful
870
+ Atom<uint64_t> tags_hi_;
871
+
872
+ std::array<aligned_storage_for_t<Atom<Node*>>, kCapacity> rawItems_;
873
+
874
+ public:
875
+ void clear() {
876
+ for (size_t i = 0; i < kCapacity; i++) {
877
+ item(i).store(nullptr, std::memory_order_relaxed);
878
+ }
879
+ tags_low_.store(0, std::memory_order_relaxed);
880
+ tags_hi_.store(0, std::memory_order_relaxed);
881
+ }
882
+
883
+ std::size_t tag(std::size_t index) const {
884
+ std::size_t off = index % 8;
885
+ const Atom<uint64_t>& tag_src = off == index ? tags_low_ : tags_hi_;
886
+ uint64_t tags = tag_src.load(std::memory_order_relaxed);
887
+ tags >>= (off * 8);
888
+ return tags & 0xff;
889
+ }
890
+
891
+ void setTag(std::size_t index, std::size_t tag) {
892
+ std::size_t off = index % 8;
893
+ Atom<uint64_t>& old_tags = off == index ? tags_low_ : tags_hi_;
894
+ uint64_t new_tags = old_tags.load(std::memory_order_relaxed);
895
+ uint64_t mask = 0xffULL << (off * 8);
896
+ new_tags = (new_tags & ~mask) | (tag << (off * 8));
897
+ old_tags.store(new_tags, std::memory_order_release);
898
+ }
899
+
900
+ void setNodeAndTag(std::size_t index, Node* node, std::size_t tag) {
901
+ FOLLY_SAFE_DCHECK(
902
+ index < kCapacity && (tag == 0x0 || (tag >= 0x80 && tag <= 0xff)),
903
+ "");
904
+ item(index).store(node, std::memory_order_release);
905
+ setTag(index, tag);
906
+ }
907
+
908
+ void clearNodeAndTag(std::size_t index) {
909
+ setNodeAndTag(index, nullptr, 0);
910
+ }
911
+
912
+ ////////
913
+ // Tag filtering using SSE2 intrinsics
914
+
915
+ SparseMaskIter tagMatchIter(std::size_t needle) const {
916
+ FOLLY_SAFE_DCHECK(needle >= 0x80 && needle < 0x100, "");
917
+ uint64_t low = tags_low_.load(std::memory_order_acquire);
918
+ uint64_t hi = tags_hi_.load(std::memory_order_acquire);
919
+ auto tagV = _mm_set_epi64x(hi, low);
920
+ auto needleV = _mm_set1_epi8(static_cast<uint8_t>(needle));
921
+ auto eqV = _mm_cmpeq_epi8(tagV, needleV);
922
+ auto mask = _mm_movemask_epi8(eqV) & kFullMask;
923
+ return SparseMaskIter{mask};
924
+ }
925
+
926
+ MaskType occupiedMask() const {
927
+ uint64_t low = tags_low_.load(std::memory_order_relaxed);
928
+ uint64_t hi = tags_hi_.load(std::memory_order_relaxed);
929
+ auto tagV = _mm_set_epi64x(hi, low);
930
+ return _mm_movemask_epi8(tagV) & kFullMask;
931
+ }
932
+
933
+ DenseMaskIter occupiedIter() const {
934
+ // Currently only invoked when relaxed semantics are sufficient.
935
+ return DenseMaskIter{nullptr /*unused*/, occupiedMask()};
936
+ }
937
+
938
+ FirstEmptyInMask firstEmpty() const {
939
+ return FirstEmptyInMask{occupiedMask() ^ kFullMask};
940
+ }
941
+
942
+ Atom<Node*>* itemAddr(std::size_t i) const {
943
+ return static_cast<Atom<Node*>*>(
944
+ const_cast<void*>(static_cast<void const*>(&rawItems_[i])));
945
+ }
946
+
947
+ Atom<Node*>& item(size_t i) { return *std::launder(itemAddr(i)); }
948
+
949
+ static constexpr uint64_t kOutboundOverflowIndex = 7 * 8;
950
+ static constexpr uint64_t kSaturatedOutboundOverflowCount = 0xffULL
951
+ << kOutboundOverflowIndex;
952
+ static constexpr uint64_t kOutboundOverflowOperand = 0x1ULL
953
+ << kOutboundOverflowIndex;
954
+
955
+ unsigned outboundOverflowCount() const {
956
+ uint64_t count = tags_hi_.load(std::memory_order_relaxed);
957
+ return count >> kOutboundOverflowIndex;
958
+ }
959
+
960
+ void incrOutboundOverflowCount() {
961
+ uint64_t count = tags_hi_.load(std::memory_order_relaxed);
962
+ if (count < kSaturatedOutboundOverflowCount) {
963
+ tags_hi_.store(
964
+ count + kOutboundOverflowOperand, std::memory_order_relaxed);
965
+ }
966
+ }
967
+
968
+ void decrOutboundOverflowCount() {
969
+ uint64_t count = tags_hi_.load(std::memory_order_relaxed);
970
+ if (count < kSaturatedOutboundOverflowCount) {
971
+ tags_hi_.store(
972
+ count - kOutboundOverflowOperand, std::memory_order_relaxed);
973
+ }
974
+ }
975
+
976
+ static constexpr uint64_t kHostedOverflowIndex = 6 * 8;
977
+ static constexpr uint64_t kHostedOverflowOperand = 0x10ULL
978
+ << kHostedOverflowIndex;
979
+
980
+ unsigned hostedOverflowCount() const {
981
+ uint64_t control = tags_hi_.load(std::memory_order_relaxed);
982
+ return (control >> 52) & 0xf;
983
+ }
984
+
985
+ void incrHostedOverflowCount() {
986
+ tags_hi_.fetch_add(kHostedOverflowOperand, std::memory_order_relaxed);
987
+ }
988
+
989
+ void decrHostedOverflowCount() {
990
+ tags_hi_.fetch_sub(kHostedOverflowOperand, std::memory_order_relaxed);
991
+ }
992
+ };
993
+
994
+ class Chunks : public hazptr_obj_base<Chunks, Atom, HazptrTableDeleter> {
995
+ Chunks() {}
996
+ ~Chunks() {}
997
+
998
+ public:
999
+ static Chunks* create(size_t count, hazptr_obj_cohort<Atom>* cohort) {
1000
+ auto buf = Allocator().allocate(sizeof(Chunks) + sizeof(Chunk) * count);
1001
+ auto chunks = new (buf) Chunks();
1002
+ DCHECK(cohort);
1003
+ chunks->set_cohort_tag(cohort); // defined in hazptr_obj
1004
+ for (size_t i = 0; i < count; i++) {
1005
+ new (&chunks->chunks_[i]) Chunk;
1006
+ chunks->chunks_[i].clear();
1007
+ }
1008
+ return chunks;
1009
+ }
1010
+
1011
+ void destroy(size_t count) {
1012
+ for (size_t i = 0; i < count; i++) {
1013
+ chunks_[i].~Chunk();
1014
+ }
1015
+ this->~Chunks();
1016
+ Allocator().deallocate(
1017
+ (uint8_t*)this, sizeof(Chunk) * count + sizeof(*this));
1018
+ }
1019
+
1020
+ void reclaim_nodes(size_t count) {
1021
+ for (size_t i = 0; i < count; i++) {
1022
+ Chunk& chunk = chunks_[i];
1023
+ auto occupied = chunk.occupiedIter();
1024
+ while (occupied.hasNext()) {
1025
+ auto idx = occupied.next();
1026
+ chunk.setTag(idx, 0);
1027
+ Node* node =
1028
+ chunk.item(idx).exchange(nullptr, std::memory_order_relaxed);
1029
+ // Tags and node ptrs should be in sync at this point.
1030
+ DCHECK(node);
1031
+ node->retire();
1032
+ }
1033
+ }
1034
+ }
1035
+
1036
+ Chunk* getChunk(size_t index, size_t ccount) {
1037
+ DCHECK(isPowTwo(ccount));
1038
+ return &chunks_[index & (ccount - 1)];
1039
+ }
1040
+
1041
+ private:
1042
+ Chunk chunks_[0];
1043
+ };
1044
+
1045
+ public:
1046
+ static constexpr float kDefaultLoadFactor =
1047
+ Chunk::kDesiredCapacity / (float)Chunk::kCapacity;
1048
+
1049
+ typedef std::pair<const KeyType, ValueType> value_type;
1050
+
1051
+ using InsertType = concurrenthashmap::InsertType;
1052
+
1053
+ class Iterator {
1054
+ public:
1055
+ FOLLY_ALWAYS_INLINE Iterator()
1056
+ : hazptrs_(make_hazard_pointer_array<2, Atom>()) {}
1057
+ FOLLY_ALWAYS_INLINE explicit Iterator(std::nullptr_t) : hazptrs_() {}
1058
+ FOLLY_ALWAYS_INLINE ~Iterator() {}
1059
+
1060
+ void setNode(
1061
+ Node* node,
1062
+ Chunks* chunks,
1063
+ size_t chunk_count,
1064
+ uint64_t chunk_idx,
1065
+ uint64_t tag_idx) {
1066
+ DCHECK(chunk_idx < chunk_count || chunk_idx == 0);
1067
+ DCHECK(isPowTwo(chunk_count));
1068
+ node_ = node;
1069
+ chunks_ = chunks;
1070
+ chunk_count_ = chunk_count;
1071
+ chunk_idx_ = chunk_idx;
1072
+ tag_idx_ = tag_idx;
1073
+ }
1074
+
1075
+ const value_type& operator*() const {
1076
+ DCHECK(node_);
1077
+ return node_->getItem();
1078
+ }
1079
+
1080
+ const value_type* operator->() const {
1081
+ DCHECK(node_);
1082
+ return &(node_->getItem());
1083
+ }
1084
+
1085
+ const Iterator& operator++() {
1086
+ DCHECK(node_);
1087
+ ++tag_idx_;
1088
+ findNextNode();
1089
+ return *this;
1090
+ }
1091
+
1092
+ void next() {
1093
+ if (node_) {
1094
+ return;
1095
+ }
1096
+ findNextNode();
1097
+ }
1098
+
1099
+ bool operator==(const Iterator& o) const { return node_ == o.node_; }
1100
+
1101
+ bool operator!=(const Iterator& o) const { return !(*this == o); }
1102
+
1103
+ Iterator& operator=(const Iterator& o) = delete;
1104
+
1105
+ Iterator& operator=(Iterator&& o) noexcept {
1106
+ if (this != &o) {
1107
+ hazptrs_ = std::move(o.hazptrs_);
1108
+ node_ = std::exchange(o.node_, nullptr);
1109
+ chunks_ = std::exchange(o.chunks_, nullptr);
1110
+ chunk_count_ = std::exchange(o.chunk_count_, 0);
1111
+ chunk_idx_ = std::exchange(o.chunk_idx_, 0);
1112
+ tag_idx_ = std::exchange(o.tag_idx_, 0);
1113
+ }
1114
+ return *this;
1115
+ }
1116
+
1117
+ Iterator(const Iterator& o) = delete;
1118
+
1119
+ Iterator(Iterator&& o) noexcept
1120
+ : hazptrs_(std::move(o.hazptrs_)),
1121
+ node_(std::exchange(o.node_, nullptr)),
1122
+ chunks_(std::exchange(o.chunks_, nullptr)),
1123
+ chunk_count_(std::exchange(o.chunk_count_, 0)),
1124
+ chunk_idx_(std::exchange(o.chunk_idx_, 0)),
1125
+ tag_idx_(std::exchange(o.tag_idx_, 0)) {}
1126
+
1127
+ // These are accessed directly from the functions above
1128
+ hazptr_array<2, Atom> hazptrs_;
1129
+
1130
+ private:
1131
+ void findNextNode() {
1132
+ do {
1133
+ if (tag_idx_ >= Chunk::kCapacity) {
1134
+ tag_idx_ = 0;
1135
+ ++chunk_idx_;
1136
+ }
1137
+ if (chunk_idx_ >= chunk_count_) {
1138
+ node_ = nullptr;
1139
+ break;
1140
+ }
1141
+ DCHECK(chunks_);
1142
+ // Note that iteration could also be implemented with tag filtering
1143
+ node_ = hazptrs_[1].protect(
1144
+ chunks_->getChunk(chunk_idx_, chunk_count_)->item(tag_idx_));
1145
+ if (node_) {
1146
+ break;
1147
+ }
1148
+ ++tag_idx_;
1149
+ } while (true);
1150
+ }
1151
+
1152
+ Node* node_{nullptr};
1153
+ Chunks* chunks_{nullptr};
1154
+ size_t chunk_count_{0};
1155
+ uint64_t chunk_idx_{0};
1156
+ uint64_t tag_idx_{0};
1157
+ };
1158
+
1159
+ SIMDTable(
1160
+ size_t initial_size,
1161
+ float load_factor,
1162
+ size_t max_size,
1163
+ hazptr_obj_cohort<Atom>* cohort)
1164
+ : load_factor_(load_factor),
1165
+ max_size_(max_size),
1166
+ chunks_(nullptr),
1167
+ chunk_count_(0) {
1168
+ DCHECK(cohort);
1169
+ DCHECK(
1170
+ max_size_ == 0 ||
1171
+ (isPowTwo(max_size_) &&
1172
+ (folly::popcount(max_size_ - 1) + ShardBits <= 32)));
1173
+ DCHECK(load_factor_ > 0.0);
1174
+ load_factor_ = std::min<float>(load_factor_, 1.0);
1175
+ rehash(initial_size, cohort);
1176
+ }
1177
+
1178
+ ~SIMDTable() {
1179
+ auto chunks = chunks_.load(std::memory_order_relaxed);
1180
+ // To catch use-after-destruction bugs in user code.
1181
+ chunks_.store(nullptr, std::memory_order_release);
1182
+ // We can delete and not retire() here, since users must have
1183
+ // their own synchronization around destruction.
1184
+ auto count = chunk_count_.load(std::memory_order_relaxed);
1185
+ chunks->reclaim_nodes(count);
1186
+ chunks->destroy(count);
1187
+ }
1188
+
1189
+ size_t size() { return size_.load(std::memory_order_acquire); }
1190
+
1191
+ void clearSize() { size_.store(0, std::memory_order_release); }
1192
+
1193
+ void incSize() {
1194
+ auto sz = size_.load(std::memory_order_relaxed);
1195
+ size_.store(sz + 1, std::memory_order_release);
1196
+ }
1197
+
1198
+ void decSize() {
1199
+ auto sz = size_.load(std::memory_order_relaxed);
1200
+ DCHECK_GT(sz, 0);
1201
+ size_.store(sz - 1, std::memory_order_release);
1202
+ }
1203
+
1204
+ bool empty() { return size() == 0; }
1205
+
1206
+ template <typename MatchFunc, typename K, typename... Args>
1207
+ bool insert(
1208
+ Iterator& it,
1209
+ size_t h,
1210
+ const K& k,
1211
+ InsertType type,
1212
+ MatchFunc match,
1213
+ hazptr_obj_cohort<Atom>* cohort,
1214
+ Args&&... args) {
1215
+ Node* node;
1216
+ Chunks* chunks;
1217
+ size_t ccount, chunk_idx, tag_idx;
1218
+
1219
+ auto hp = splitHash(h);
1220
+
1221
+ std::unique_lock<Mutex> g(m_);
1222
+
1223
+ if (!prepare_insert(
1224
+ it,
1225
+ k,
1226
+ type,
1227
+ match,
1228
+ cohort,
1229
+ chunk_idx,
1230
+ tag_idx,
1231
+ node,
1232
+ chunks,
1233
+ ccount,
1234
+ hp)) {
1235
+ return false;
1236
+ }
1237
+
1238
+ auto cur = (Node*)Allocator().allocate(sizeof(Node));
1239
+ new (cur) Node(cohort, std::forward<Args>(args)...);
1240
+
1241
+ if (!node) {
1242
+ std::tie(chunk_idx, tag_idx) =
1243
+ findEmptyInsertLocation(chunks, ccount, hp);
1244
+ incSize();
1245
+ }
1246
+
1247
+ Chunk* chunk = chunks->getChunk(chunk_idx, ccount);
1248
+ chunk->setNodeAndTag(tag_idx, cur, hp.second);
1249
+ it.setNode(cur, chunks, ccount, chunk_idx, tag_idx);
1250
+ it.hazptrs_[1].reset_protection(cur);
1251
+
1252
+ g.unlock();
1253
+ // Retire not under lock
1254
+ if (node) {
1255
+ node->retire();
1256
+ }
1257
+ return true;
1258
+ }
1259
+
1260
+ template <typename MatchFunc, typename K, typename... Args>
1261
+ bool insert(
1262
+ Iterator& it,
1263
+ size_t h,
1264
+ const K& k,
1265
+ InsertType type,
1266
+ MatchFunc match,
1267
+ Node* cur,
1268
+ hazptr_obj_cohort<Atom>* cohort) {
1269
+ DCHECK(cur != nullptr);
1270
+ Node* node;
1271
+ Chunks* chunks;
1272
+ size_t ccount, chunk_idx, tag_idx;
1273
+
1274
+ auto hp = splitHash(h);
1275
+
1276
+ std::unique_lock<Mutex> g(m_);
1277
+
1278
+ if (!prepare_insert(
1279
+ it,
1280
+ k,
1281
+ type,
1282
+ match,
1283
+ cohort,
1284
+ chunk_idx,
1285
+ tag_idx,
1286
+ node,
1287
+ chunks,
1288
+ ccount,
1289
+ hp)) {
1290
+ return false;
1291
+ }
1292
+
1293
+ if (!node) {
1294
+ std::tie(chunk_idx, tag_idx) =
1295
+ findEmptyInsertLocation(chunks, ccount, hp);
1296
+ incSize();
1297
+ }
1298
+
1299
+ Chunk* chunk = chunks->getChunk(chunk_idx, ccount);
1300
+ chunk->setNodeAndTag(tag_idx, cur, hp.second);
1301
+ it.setNode(cur, chunks, ccount, chunk_idx, tag_idx);
1302
+ it.hazptrs_[1].reset_protection(cur);
1303
+
1304
+ g.unlock();
1305
+ // Retire not under lock
1306
+ if (node) {
1307
+ node->retire();
1308
+ }
1309
+ return true;
1310
+ }
1311
+
1312
+ void rehash(size_t size, hazptr_obj_cohort<Atom>* cohort) {
1313
+ size_t new_chunk_count = size == 0 ? 0 : (size - 1) / Chunk::kCapacity + 1;
1314
+ rehash_internal(folly::nextPowTwo(new_chunk_count), cohort);
1315
+ }
1316
+
1317
+ template <typename K>
1318
+ bool find(Iterator& res, size_t h, const K& k) {
1319
+ auto& hazz = res.hazptrs_[1];
1320
+ auto hp = splitHash(h);
1321
+ size_t ccount;
1322
+ Chunks* chunks;
1323
+ getChunksAndCount(ccount, chunks, res.hazptrs_[0]);
1324
+
1325
+ size_t step = probeDelta(hp);
1326
+ auto& chunk_idx = hp.first;
1327
+ for (size_t tries = 0; tries < ccount; ++tries) {
1328
+ Chunk* chunk = chunks->getChunk(chunk_idx, ccount);
1329
+ auto hits = chunk->tagMatchIter(hp.second);
1330
+ while (hits.hasNext()) {
1331
+ size_t tag_idx = hits.next();
1332
+ Node* node = hazz.protect(chunk->item(tag_idx));
1333
+ if (FOLLY_LIKELY(node && KeyEqual()(k, node->getItem().first))) {
1334
+ chunk_idx = chunk_idx & (ccount - 1);
1335
+ res.setNode(node, chunks, ccount, chunk_idx, tag_idx);
1336
+ return true;
1337
+ }
1338
+ hazz.reset_protection();
1339
+ }
1340
+
1341
+ if (FOLLY_LIKELY(chunk->outboundOverflowCount() == 0)) {
1342
+ break;
1343
+ }
1344
+ chunk_idx += step;
1345
+ }
1346
+ return false;
1347
+ }
1348
+
1349
+ template <typename K, typename MatchFunc>
1350
+ std::size_t erase(size_t h, const K& key, Iterator* iter, MatchFunc match) {
1351
+ const HashPair hp = splitHash(h);
1352
+
1353
+ std::unique_lock<Mutex> g(m_);
1354
+
1355
+ size_t ccount = chunk_count_.load(std::memory_order_relaxed);
1356
+ auto chunks = chunks_.load(std::memory_order_relaxed);
1357
+ DCHECK(chunks); // Use-after-destruction by user.
1358
+ size_t chunk_idx, tag_idx;
1359
+
1360
+ Node* node = find_internal(key, hp, chunks, ccount, chunk_idx, tag_idx);
1361
+
1362
+ if (!node) {
1363
+ return 0;
1364
+ }
1365
+
1366
+ if (!match(node->getItem().second)) {
1367
+ return 0;
1368
+ }
1369
+
1370
+ Chunk* chunk = chunks->getChunk(chunk_idx, ccount);
1371
+
1372
+ // Decrement any overflow counters
1373
+ if (chunk->hostedOverflowCount() != 0) {
1374
+ size_t index = hp.first;
1375
+ size_t delta = probeDelta(hp);
1376
+ bool preferredChunk = true;
1377
+ while (true) {
1378
+ Chunk* overflowChunk = chunks->getChunk(index, ccount);
1379
+ if (chunk == overflowChunk) {
1380
+ if (!preferredChunk) {
1381
+ overflowChunk->decrHostedOverflowCount();
1382
+ }
1383
+ break;
1384
+ }
1385
+ overflowChunk->decrOutboundOverflowCount();
1386
+ preferredChunk = false;
1387
+ index += delta;
1388
+ }
1389
+ }
1390
+
1391
+ chunk->clearNodeAndTag(tag_idx);
1392
+
1393
+ decSize();
1394
+ if (iter) {
1395
+ iter->hazptrs_[0].reset_protection(chunks);
1396
+ iter->setNode(nullptr, chunks, ccount, chunk_idx, tag_idx + 1);
1397
+ iter->next();
1398
+ }
1399
+ // Retire the node while not under the lock.
1400
+ g.unlock();
1401
+ node->retire();
1402
+ return 1;
1403
+ }
1404
+
1405
+ void clear(hazptr_obj_cohort<Atom>* cohort) {
1406
+ size_t ccount;
1407
+ Chunks* chunks;
1408
+ {
1409
+ std::lock_guard<Mutex> g(m_);
1410
+ ccount = chunk_count_.load(std::memory_order_relaxed);
1411
+ auto newchunks = Chunks::create(ccount, cohort);
1412
+ chunks = chunks_.load(std::memory_order_relaxed);
1413
+ chunks_.store(newchunks, std::memory_order_release);
1414
+ clearSize();
1415
+ }
1416
+ DCHECK(chunks); // Use-after-destruction by user.
1417
+ chunks->reclaim_nodes(ccount);
1418
+ chunks->retire(HazptrTableDeleter(ccount));
1419
+ }
1420
+
1421
+ void max_load_factor(float factor) {
1422
+ DCHECK(factor > 0.0);
1423
+ if (factor > 1.0) {
1424
+ throw_exception<std::invalid_argument>("load factor must be <= 1.0");
1425
+ }
1426
+ std::lock_guard<Mutex> g(m_);
1427
+ load_factor_ = factor;
1428
+ auto ccount = chunk_count_.load(std::memory_order_relaxed);
1429
+ grow_threshold_ = ccount * Chunk::kCapacity * load_factor_;
1430
+ }
1431
+
1432
+ Iterator cbegin() {
1433
+ Iterator res;
1434
+ size_t ccount;
1435
+ Chunks* chunks;
1436
+ getChunksAndCount(ccount, chunks, res.hazptrs_[0]);
1437
+ res.setNode(nullptr, chunks, ccount, 0, 0);
1438
+ res.next();
1439
+ return res;
1440
+ }
1441
+
1442
+ Iterator cend() { return Iterator(nullptr); }
1443
+
1444
+ private:
1445
+ static HashPair splitHash(std::size_t hash) {
1446
+ std::size_t c = _mm_crc32_u64(0, hash);
1447
+ size_t tag = (c >> 24) | 0x80;
1448
+ hash += c;
1449
+ return std::make_pair(hash, tag);
1450
+ }
1451
+
1452
+ static size_t probeDelta(HashPair hp) { return 2 * hp.second + 1; }
1453
+
1454
+ // Must hold lock.
1455
+ template <typename K>
1456
+ Node* find_internal(
1457
+ const K& k,
1458
+ const HashPair& hp,
1459
+ Chunks* chunks,
1460
+ size_t ccount,
1461
+ size_t& chunk_idx,
1462
+ size_t& tag_idx) {
1463
+ // must be called with mutex held
1464
+ size_t step = probeDelta(hp);
1465
+ chunk_idx = hp.first;
1466
+
1467
+ for (size_t tries = 0; tries < ccount; ++tries) {
1468
+ Chunk* chunk = chunks->getChunk(chunk_idx, ccount);
1469
+ auto hits = chunk->tagMatchIter(hp.second);
1470
+ while (hits.hasNext()) {
1471
+ tag_idx = hits.next();
1472
+ Node* node = chunk->item(tag_idx).load(std::memory_order_acquire);
1473
+ if (FOLLY_LIKELY(node && KeyEqual()(k, node->getItem().first))) {
1474
+ chunk_idx = (chunk_idx & (ccount - 1));
1475
+ return node;
1476
+ }
1477
+ }
1478
+ if (FOLLY_LIKELY(chunk->outboundOverflowCount() == 0)) {
1479
+ break;
1480
+ }
1481
+ chunk_idx += step;
1482
+ }
1483
+ return nullptr;
1484
+ }
1485
+
1486
+ template <typename MatchFunc, typename K, typename... Args>
1487
+ bool prepare_insert(
1488
+ Iterator& it,
1489
+ const K& k,
1490
+ InsertType type,
1491
+ MatchFunc match,
1492
+ hazptr_obj_cohort<Atom>* cohort,
1493
+ size_t& chunk_idx,
1494
+ size_t& tag_idx,
1495
+ Node*& node,
1496
+ Chunks*& chunks,
1497
+ size_t& ccount,
1498
+ const HashPair& hp) {
1499
+ ccount = chunk_count_.load(std::memory_order_relaxed);
1500
+ chunks = chunks_.load(std::memory_order_relaxed);
1501
+
1502
+ if (size() >= grow_threshold_ && type == InsertType::DOES_NOT_EXIST) {
1503
+ if (max_size_ && size() << 1 > max_size_) {
1504
+ // Would exceed max size.
1505
+ throw_exception<std::bad_alloc>();
1506
+ }
1507
+ rehash_internal(ccount << 1, cohort);
1508
+ ccount = chunk_count_.load(std::memory_order_relaxed);
1509
+ chunks = chunks_.load(std::memory_order_relaxed);
1510
+ }
1511
+
1512
+ DCHECK(chunks); // Use-after-destruction by user.
1513
+ node = find_internal(k, hp, chunks, ccount, chunk_idx, tag_idx);
1514
+
1515
+ it.hazptrs_[0].reset_protection(chunks);
1516
+ if (node) {
1517
+ it.hazptrs_[1].reset_protection(node);
1518
+ it.setNode(node, chunks, ccount, chunk_idx, tag_idx);
1519
+ if (type == InsertType::MATCH) {
1520
+ if (!match(node->getItem().second)) {
1521
+ return false;
1522
+ }
1523
+ } else if (type == InsertType::DOES_NOT_EXIST) {
1524
+ return false;
1525
+ }
1526
+ } else {
1527
+ if (type != InsertType::DOES_NOT_EXIST && type != InsertType::ANY) {
1528
+ it.hazptrs_[0].reset_protection();
1529
+ return false;
1530
+ }
1531
+ // Already checked for rehash on DOES_NOT_EXIST, now check on ANY
1532
+ if (size() >= grow_threshold_ && type == InsertType::ANY) {
1533
+ if (max_size_ && size() << 1 > max_size_) {
1534
+ // Would exceed max size.
1535
+ throw_exception<std::bad_alloc>();
1536
+ }
1537
+ rehash_internal(ccount << 1, cohort);
1538
+ ccount = chunk_count_.load(std::memory_order_relaxed);
1539
+ chunks = chunks_.load(std::memory_order_relaxed);
1540
+ DCHECK(chunks); // Use-after-destruction by user.
1541
+ it.hazptrs_[0].reset_protection(chunks);
1542
+ }
1543
+ }
1544
+ return true;
1545
+ }
1546
+
1547
+ void rehash_internal(
1548
+ size_t new_chunk_count, hazptr_obj_cohort<Atom>* cohort) {
1549
+ DCHECK(isPowTwo(new_chunk_count));
1550
+ auto old_chunk_count = chunk_count_.load(std::memory_order_relaxed);
1551
+ if (old_chunk_count >= new_chunk_count) {
1552
+ return;
1553
+ }
1554
+ auto new_chunks = Chunks::create(new_chunk_count, cohort);
1555
+ auto old_chunks = chunks_.load(std::memory_order_relaxed);
1556
+ grow_threshold_ =
1557
+ to_integral(new_chunk_count * Chunk::kCapacity * load_factor_);
1558
+
1559
+ for (size_t i = 0; i < old_chunk_count; i++) {
1560
+ DCHECK(old_chunks); // Use-after-destruction by user.
1561
+ Chunk* oldchunk = old_chunks->getChunk(i, old_chunk_count);
1562
+ auto occupied = oldchunk->occupiedIter();
1563
+ while (occupied.hasNext()) {
1564
+ auto idx = occupied.next();
1565
+ Node* node = oldchunk->item(idx).load(std::memory_order_relaxed);
1566
+ size_t new_chunk_idx;
1567
+ size_t new_tag_idx;
1568
+ auto h = HashFn()(node->getItem().first);
1569
+ auto hp = splitHash(h);
1570
+ std::tie(new_chunk_idx, new_tag_idx) =
1571
+ findEmptyInsertLocation(new_chunks, new_chunk_count, hp);
1572
+ Chunk* newchunk = new_chunks->getChunk(new_chunk_idx, new_chunk_count);
1573
+ newchunk->setNodeAndTag(new_tag_idx, node, hp.second);
1574
+ }
1575
+ }
1576
+
1577
+ seqlock_.fetch_add(1, std::memory_order_release);
1578
+ chunk_count_.store(new_chunk_count, std::memory_order_release);
1579
+ chunks_.store(new_chunks, std::memory_order_release);
1580
+ seqlock_.fetch_add(1, std::memory_order_release);
1581
+ if (old_chunks) {
1582
+ old_chunks->retire(HazptrTableDeleter(old_chunk_count));
1583
+ }
1584
+ }
1585
+
1586
+ void getChunksAndCount(
1587
+ size_t& ccount, Chunks*& chunks, hazptr_holder<Atom>& hazptr) {
1588
+ while (true) {
1589
+ auto seqlock = seqlock_.load(std::memory_order_acquire);
1590
+ ccount = chunk_count_.load(std::memory_order_acquire);
1591
+ chunks = hazptr.protect(chunks_);
1592
+ auto seqlock2 = seqlock_.load(std::memory_order_acquire);
1593
+ if (!(seqlock & 1) && (seqlock == seqlock2)) {
1594
+ break;
1595
+ }
1596
+ }
1597
+ DCHECK(chunks);
1598
+ }
1599
+
1600
+ std::pair<size_t, size_t> findEmptyInsertLocation(
1601
+ Chunks* chunks, size_t ccount, const HashPair& hp) {
1602
+ size_t chunk_idx = hp.first;
1603
+ Chunk* dst_chunk = chunks->getChunk(chunk_idx, ccount);
1604
+ auto firstEmpty = dst_chunk->firstEmpty();
1605
+
1606
+ if (!firstEmpty.hasIndex()) {
1607
+ size_t delta = probeDelta(hp);
1608
+ do {
1609
+ dst_chunk->incrOutboundOverflowCount();
1610
+ chunk_idx += delta;
1611
+ dst_chunk = chunks->getChunk(chunk_idx, ccount);
1612
+ firstEmpty = dst_chunk->firstEmpty();
1613
+ } while (!firstEmpty.hasIndex());
1614
+ dst_chunk->incrHostedOverflowCount();
1615
+ }
1616
+ size_t dst_tag_idx = firstEmpty.index();
1617
+ return std::make_pair(chunk_idx & (ccount - 1), dst_tag_idx);
1618
+ }
1619
+
1620
+ Mutex m_;
1621
+ float load_factor_; // ceil of 1.0
1622
+ size_t grow_threshold_;
1623
+ Atom<size_t> size_{0};
1624
+ size_t const max_size_;
1625
+
1626
+ // Fields needed for read-only access, on separate cacheline.
1627
+ alignas(64) Atom<Chunks*> chunks_{nullptr};
1628
+ std::atomic<uint64_t> seqlock_{0};
1629
+ Atom<size_t> chunk_count_;
1630
+ };
1631
+ } // namespace simd
1632
+
1633
+ #endif // FOLLY_SSE_PREREQ(4, 2) && FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
1634
+
1635
+ } // namespace concurrenthashmap
1636
+
1637
+ /* A Segment is a single shard of the ConcurrentHashMap.
1638
+ * All writes take the lock, while readers are all wait-free.
1639
+ * Readers always proceed in parallel with the single writer.
1640
+ *
1641
+ *
1642
+ * Possible additional optimizations:
1643
+ *
1644
+ * * insert / erase could be lock / wait free. Would need to be
1645
+ * careful that assign and rehash don't conflict (possibly with
1646
+ * reader/writer lock, or microlock per node or per bucket, etc).
1647
+ * Java 8 goes halfway, and does lock per bucket, except for the
1648
+ * first item, that is inserted with a CAS (which is somewhat
1649
+ * specific to java having a lock per object)
1650
+ *
1651
+ * * I tried using trylock() and find() to warm the cache for insert()
1652
+ * and erase() similar to Java 7, but didn't have much luck.
1653
+ *
1654
+ * * We could order elements using split ordering, for faster rehash,
1655
+ * and no need to ever copy nodes. Note that a full split ordering
1656
+ * including dummy nodes increases the memory usage by 2x, but we
1657
+ * could split the difference and still require a lock to set bucket
1658
+ * pointers.
1659
+ */
1660
+ template <
1661
+ typename KeyType,
1662
+ typename ValueType,
1663
+ uint8_t ShardBits = 0,
1664
+ typename HashFn = std::hash<KeyType>,
1665
+ typename KeyEqual = std::equal_to<KeyType>,
1666
+ typename Allocator = std::allocator<uint8_t>,
1667
+ template <typename> class Atom = std::atomic,
1668
+ class Mutex = std::mutex,
1669
+ template <
1670
+ typename,
1671
+ typename,
1672
+ uint8_t,
1673
+ typename,
1674
+ typename,
1675
+ typename,
1676
+ template <typename>
1677
+ class,
1678
+ class>
1679
+ class Impl = concurrenthashmap::bucket::BucketTable>
1680
+ class alignas(64) ConcurrentHashMapSegment {
1681
+ using ImplT = Impl<
1682
+ KeyType,
1683
+ ValueType,
1684
+ ShardBits,
1685
+ HashFn,
1686
+ KeyEqual,
1687
+ Allocator,
1688
+ Atom,
1689
+ Mutex>;
1690
+
1691
+ public:
1692
+ typedef KeyType key_type;
1693
+ typedef ValueType mapped_type;
1694
+ typedef std::pair<const KeyType, ValueType> value_type;
1695
+ typedef std::size_t size_type;
1696
+
1697
+ using InsertType = concurrenthashmap::InsertType;
1698
+ using Iterator = typename ImplT::Iterator;
1699
+ using Node = typename ImplT::Node;
1700
+ static constexpr float kDefaultLoadFactor = ImplT::kDefaultLoadFactor;
1701
+
1702
+ ConcurrentHashMapSegment(
1703
+ size_t initial_buckets,
1704
+ float load_factor,
1705
+ size_t max_size,
1706
+ hazptr_obj_cohort<Atom>* cohort)
1707
+ : impl_(initial_buckets, load_factor, max_size, cohort), cohort_(cohort) {
1708
+ DCHECK(cohort);
1709
+ }
1710
+
1711
+ ~ConcurrentHashMapSegment() = default;
1712
+
1713
+ size_t size() { return impl_.size(); }
1714
+
1715
+ bool empty() { return impl_.empty(); }
1716
+
1717
+ template <typename Key>
1718
+ bool insert(Iterator& it, size_t h, std::pair<Key, mapped_type>&& foo) {
1719
+ return insert(it, h, std::move(foo.first), std::move(foo.second));
1720
+ }
1721
+
1722
+ template <typename Key, typename Value>
1723
+ bool insert(Iterator& it, size_t h, Key&& k, Value&& v) {
1724
+ auto node = (Node*)Allocator().allocate(sizeof(Node));
1725
+ new (node) Node(cohort_, std::forward<Key>(k), std::forward<Value>(v));
1726
+ auto res = insert_internal(
1727
+ it,
1728
+ h,
1729
+ node->getItem().first,
1730
+ InsertType::DOES_NOT_EXIST,
1731
+ [](const ValueType&) { return false; },
1732
+ node);
1733
+ if (!res) {
1734
+ node->~Node();
1735
+ Allocator().deallocate((uint8_t*)node, sizeof(Node));
1736
+ }
1737
+ return res;
1738
+ }
1739
+
1740
+ template <typename Key, typename... Args>
1741
+ bool try_emplace(Iterator& it, size_t h, Key&& k, Args&&... args) {
1742
+ // Note: first key is only ever compared. Second is moved in to
1743
+ // create the node, and the first key is never touched again.
1744
+ return insert_internal(
1745
+ it,
1746
+ h,
1747
+ std::forward<Key>(k),
1748
+ InsertType::DOES_NOT_EXIST,
1749
+ [](const ValueType&) { return false; },
1750
+ std::forward<Key>(k),
1751
+ std::forward<Args>(args)...);
1752
+ }
1753
+
1754
+ template <typename... Args>
1755
+ bool emplace(Iterator& it, size_t h, const KeyType& k, Node* node) {
1756
+ return insert_internal(
1757
+ it,
1758
+ h,
1759
+ k,
1760
+ InsertType::DOES_NOT_EXIST,
1761
+ [](const ValueType&) { return false; },
1762
+ node);
1763
+ }
1764
+
1765
+ template <typename Key, typename Value>
1766
+ bool insert_or_assign(Iterator& it, size_t h, Key&& k, Value&& v) {
1767
+ auto node = (Node*)Allocator().allocate(sizeof(Node));
1768
+ new (node) Node(cohort_, std::forward<Key>(k), std::forward<Value>(v));
1769
+ auto res = insert_internal(
1770
+ it,
1771
+ h,
1772
+ node->getItem().first,
1773
+ InsertType::ANY,
1774
+ [](const ValueType&) { return false; },
1775
+ node);
1776
+ if (!res) {
1777
+ node->~Node();
1778
+ Allocator().deallocate((uint8_t*)node, sizeof(Node));
1779
+ }
1780
+ return res;
1781
+ }
1782
+
1783
+ template <typename Key, typename Value>
1784
+ bool assign(Iterator& it, size_t h, Key&& k, Value&& v) {
1785
+ auto node = (Node*)Allocator().allocate(sizeof(Node));
1786
+ new (node) Node(cohort_, std::forward<Key>(k), std::forward<Value>(v));
1787
+ auto res = insert_internal(
1788
+ it,
1789
+ h,
1790
+ node->getItem().first,
1791
+ InsertType::MUST_EXIST,
1792
+ [](const ValueType&) { return false; },
1793
+ node);
1794
+ if (!res) {
1795
+ node->~Node();
1796
+ Allocator().deallocate((uint8_t*)node, sizeof(Node));
1797
+ }
1798
+ return res;
1799
+ }
1800
+ template <typename Key, typename Value, typename Predicate>
1801
+ bool assign_if(
1802
+ Iterator& it, size_t h, Key&& k, Value&& desired, Predicate&& predicate) {
1803
+ auto node = (Node*)Allocator().allocate(sizeof(Node));
1804
+ new (node)
1805
+ Node(cohort_, std::forward<Key>(k), std::forward<Value>(desired));
1806
+ auto res = insert_internal(
1807
+ it,
1808
+ h,
1809
+ node->getItem().first,
1810
+ InsertType::MATCH,
1811
+ std::forward<Predicate>(predicate),
1812
+ node);
1813
+ if (!res) {
1814
+ node->~Node();
1815
+ Allocator().deallocate((uint8_t*)node, sizeof(Node));
1816
+ }
1817
+ return res;
1818
+ }
1819
+
1820
+ template <typename Key, typename Value>
1821
+ bool assign_if_equal(
1822
+ Iterator& it,
1823
+ size_t h,
1824
+ Key&& k,
1825
+ const ValueType& expected,
1826
+ Value&& desired) {
1827
+ return assign_if(
1828
+ it,
1829
+ h,
1830
+ std::forward<Key>(k),
1831
+ std::forward<Value>(desired),
1832
+ [&expected](const ValueType& v) { return v == expected; });
1833
+ }
1834
+
1835
+ template <typename MatchFunc, typename K, typename... Args>
1836
+ bool insert_internal(
1837
+ Iterator& it,
1838
+ size_t h,
1839
+ const K& k,
1840
+ InsertType type,
1841
+ MatchFunc match,
1842
+ Args&&... args) {
1843
+ return impl_.insert(
1844
+ it, h, k, type, match, cohort_, std::forward<Args>(args)...);
1845
+ }
1846
+
1847
+ template <typename MatchFunc, typename K, typename... Args>
1848
+ bool insert_internal(
1849
+ Iterator& it,
1850
+ size_t h,
1851
+ const K& k,
1852
+ InsertType type,
1853
+ MatchFunc match,
1854
+ Node* cur) {
1855
+ return impl_.insert(it, h, k, type, match, cur, cohort_);
1856
+ }
1857
+
1858
+ // Must hold lock.
1859
+ void rehash(size_t bucket_count) {
1860
+ impl_.rehash(folly::nextPowTwo(bucket_count), cohort_);
1861
+ }
1862
+
1863
+ template <typename K>
1864
+ bool find(Iterator& res, size_t h, const K& k) {
1865
+ return impl_.find(res, h, k);
1866
+ }
1867
+
1868
+ // Listed separately because we need a prev pointer.
1869
+ template <typename K>
1870
+ size_type erase(size_t h, const K& key) {
1871
+ return erase_internal(
1872
+ h, key, nullptr, [](const ValueType&) { return true; });
1873
+ }
1874
+
1875
+ template <typename K, typename Predicate>
1876
+ size_type erase_key_if(size_t h, const K& key, Predicate&& predicate) {
1877
+ return erase_internal(h, key, nullptr, std::forward<Predicate>(predicate));
1878
+ }
1879
+
1880
+ template <typename K, typename MatchFunc>
1881
+ size_type erase_internal(
1882
+ size_t h, const K& key, Iterator* iter, MatchFunc match) {
1883
+ return impl_.erase(h, key, iter, match);
1884
+ }
1885
+
1886
+ // Unfortunately because we are reusing nodes on rehash, we can't
1887
+ // have prev pointers in the bucket chain. We have to start the
1888
+ // search from the bucket.
1889
+ //
1890
+ // This is a small departure from standard stl containers: erase may
1891
+ // throw if hash or key_eq functions throw.
1892
+ void erase(Iterator& res, Iterator& pos, size_t h) {
1893
+ erase_internal(h, pos->first, &res, [](const ValueType&) { return true; });
1894
+ // Invalidate the iterator.
1895
+ pos = cend();
1896
+ }
1897
+
1898
+ void clear() { impl_.clear(cohort_); }
1899
+
1900
+ void max_load_factor(float factor) { impl_.max_load_factor(factor); }
1901
+
1902
+ Iterator cbegin() { return impl_.cbegin(); }
1903
+
1904
+ Iterator cend() { return impl_.cend(); }
1905
+
1906
+ private:
1907
+ ImplT impl_;
1908
+ hazptr_obj_cohort<Atom>* cohort_;
1909
+ };
1910
+ } // namespace detail
1911
+ } // namespace folly