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

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 +8 -8
  910. package/templates/cpp-lib/example/metro.config.js +18 -2
@@ -0,0 +1,2074 @@
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
+ #include <folly/synchronization/DistributedMutex.h>
18
+
19
+ #include <chrono>
20
+ #include <cmath>
21
+ #include <thread>
22
+
23
+ #include <folly/MapUtil.h>
24
+ #include <folly/Synchronized.h>
25
+ #include <folly/container/Array.h>
26
+ #include <folly/container/Foreach.h>
27
+ #include <folly/lang/CustomizationPoint.h>
28
+ #include <folly/lang/Keep.h>
29
+ #include <folly/portability/GTest.h>
30
+ #include <folly/synchronization/Baton.h>
31
+ #include <folly/test/DeterministicSchedule.h>
32
+ #include <folly/test/TestUtils.h>
33
+
34
+ using namespace std::literals;
35
+
36
+ extern "C" FOLLY_KEEP void //
37
+ check_unique_lock_distributed_mutex_lock(
38
+ std::unique_lock<folly::DistributedMutex>& lock) {
39
+ lock.lock();
40
+ }
41
+ extern "C" FOLLY_KEEP bool //
42
+ check_unique_lock_distributed_mutex_try_lock(
43
+ std::unique_lock<folly::DistributedMutex>& lock) {
44
+ return lock.try_lock();
45
+ }
46
+ extern "C" FOLLY_KEEP bool //
47
+ check_unique_lock_distributed_mutex_try_lock_for_ns(
48
+ std::unique_lock<folly::DistributedMutex>& lock,
49
+ std::chrono::nanoseconds timeout) {
50
+ return lock.try_lock_for(timeout);
51
+ }
52
+ extern "C" FOLLY_KEEP bool //
53
+ check_unique_lock_distributed_mutex_try_lock_until_steady_clock_time_point(
54
+ std::unique_lock<folly::DistributedMutex>& lock,
55
+ std::chrono::steady_clock::time_point deadline) {
56
+ return lock.try_lock_until(deadline);
57
+ }
58
+ extern "C" FOLLY_KEEP void //
59
+ check_unique_lock_distributed_mutex_unlock(
60
+ std::unique_lock<folly::DistributedMutex>& lock) {
61
+ lock.unlock();
62
+ }
63
+ extern "C" FOLLY_KEEP void //
64
+ check_unique_lock_distributed_mutex_raii_lock( //
65
+ folly::DistributedMutex& mutex) {
66
+ std::unique_lock lock{mutex};
67
+ folly::detail::keep_sink_nx();
68
+ }
69
+ extern "C" FOLLY_KEEP void //
70
+ check_unique_lock_distributed_mutex_raii_try_lock(
71
+ folly::DistributedMutex& mutex) {
72
+ if (std::unique_lock lock{mutex, std::try_to_lock}) {
73
+ folly::detail::keep_sink_nx();
74
+ }
75
+ }
76
+ extern "C" FOLLY_KEEP void //
77
+ check_unique_lock_distributed_mutex_raii_try_lock_for_ns(
78
+ folly::DistributedMutex& mutex, //
79
+ std::chrono::nanoseconds timeout) {
80
+ if (std::unique_lock lock{mutex, timeout}) {
81
+ folly::detail::keep_sink_nx();
82
+ }
83
+ }
84
+ extern "C" FOLLY_KEEP void //
85
+ check_unique_lock_distributed_mutex_raii_try_lock_until_steady_clock_time_point(
86
+ folly::DistributedMutex& mutex,
87
+ std::chrono::steady_clock::time_point deadline) {
88
+ if (std::unique_lock lock{mutex, deadline}) {
89
+ folly::detail::keep_sink_nx();
90
+ }
91
+ }
92
+
93
+ namespace folly {
94
+ namespace test {
95
+ /**
96
+ * Like DeterministicSchedule, but allows setting callbacks that can be run
97
+ * for the current thread when an atomic access occurs, and after. This
98
+ * allows us to construct thread interleavings by hand
99
+ *
100
+ * Constructing a ManualSchedule is required to ensure that we maintain
101
+ * per-test state for threads
102
+ *
103
+ * This can also be used to order thread movement, as an alternative to
104
+ * maintaining condition variables and/or semaphores for the purposes of
105
+ * testing, for example
106
+ *
107
+ * auto one = std::thread{[&]() {
108
+ * schedule.wait(1);
109
+ * two();
110
+ * schedule.post(2);
111
+ * }};
112
+ *
113
+ * auto two = std::thread{[&]() {
114
+ * one();
115
+ * schedule.post(1);
116
+ * schedule.wait(2);
117
+ * three();
118
+ * }};
119
+ *
120
+ * The code above is guaranteed to call one(), then two(), and then three()
121
+ */
122
+ class ManualSchedule {
123
+ public:
124
+ ManualSchedule() = default;
125
+ ~ManualSchedule() {
126
+ // delete this schedule from the global map
127
+ auto schedules = schedules_.wlock();
128
+ for_each(*schedules, [&](auto& schedule, auto, auto iter) {
129
+ if (schedule.second == this) {
130
+ schedules->erase(iter);
131
+ }
132
+ });
133
+ }
134
+
135
+ /**
136
+ * These will be invoked by DeterministicAtomic to signal atomic access
137
+ * before and after the operation
138
+ */
139
+ static void beforeSharedAccess() {
140
+ if (folly::kIsDebug) {
141
+ auto id = std::this_thread::get_id();
142
+
143
+ // get the schedule assigned for the current thread, if one exists,
144
+ // otherwise proceed as normal
145
+ auto schedule = get_ptr(*schedules_.wlock(), id);
146
+ if (!schedule) {
147
+ return;
148
+ }
149
+
150
+ // now try and get the callbacks for this thread, if there is a callback
151
+ // registered for the test, it must mean that we have a callback
152
+ auto callback = get_ptr((*(*schedule)->callbacks_.wlock()), id);
153
+ if (!callback) {
154
+ return;
155
+ }
156
+ (*callback)();
157
+ }
158
+ }
159
+ static void afterSharedAccess(bool) { beforeSharedAccess(); }
160
+
161
+ /**
162
+ * Set a callback that will be called on every subsequent atomic access.
163
+ * This will be invoked before and after every atomic access, for the thread
164
+ * that called setCallback
165
+ */
166
+ void setCallback(std::function<void()> callback) {
167
+ schedules_.wlock()->insert({std::this_thread::get_id(), this});
168
+ callbacks_.wlock()->insert({std::this_thread::get_id(), callback});
169
+ }
170
+
171
+ /**
172
+ * Delete the callback set for this thread on atomic accesses
173
+ */
174
+ void removeCallbacks() {
175
+ callbacks_.wlock()->erase(std::this_thread::get_id());
176
+ }
177
+
178
+ /**
179
+ * wait() and post() for easy testing
180
+ */
181
+ void wait(int id) {
182
+ if (folly::kIsDebug) {
183
+ auto& baton = (*batons_.wlock())[id];
184
+ baton.wait();
185
+ }
186
+ }
187
+ void post(int id) {
188
+ if (folly::kIsDebug) {
189
+ auto& baton = (*batons_.wlock())[id];
190
+ baton.post();
191
+ }
192
+ }
193
+
194
+ private:
195
+ // the map of threads to the schedule started for that test
196
+ static Synchronized<std::unordered_map<std::thread::id, ManualSchedule*>>
197
+ schedules_;
198
+ // the map of callbacks to be executed for a thread's atomic accesses
199
+ Synchronized<std::unordered_map<std::thread::id, std::function<void()>>>
200
+ callbacks_;
201
+ // batons for testing, this map will only ever be written to, so it is safe
202
+ // to hold references outside lock
203
+ Synchronized<std::unordered_map<int, folly::Baton<>>> batons_;
204
+ };
205
+
206
+ Synchronized<std::unordered_map<std::thread::id, ManualSchedule*>>
207
+ ManualSchedule::schedules_;
208
+
209
+ template <typename T>
210
+ using ManualAtomic = test::DeterministicAtomicImpl<T, ManualSchedule>;
211
+ template <template <typename> class Atomic>
212
+ using TestDistributedMutex =
213
+ folly::detail::distributed_mutex::DistributedMutex<Atomic, false>;
214
+
215
+ /**
216
+ * Futex extensions for ManualAtomic
217
+ *
218
+ * Note that doing nothing in these should still result in a program that is
219
+ * well defined, since futex wait calls should be tolerant to spurious wakeups
220
+ */
221
+ int futexWakeImpl(const ::folly::detail::Futex<ManualAtomic>*, int, uint32_t) {
222
+ ManualSchedule::beforeSharedAccess();
223
+ return 1;
224
+ }
225
+ folly::detail::FutexResult futexWaitImpl(
226
+ const folly::detail::Futex<ManualAtomic>*,
227
+ uint32_t,
228
+ std::chrono::system_clock::time_point const*,
229
+ std::chrono::steady_clock::time_point const*,
230
+ uint32_t) {
231
+ ManualSchedule::beforeSharedAccess();
232
+ return folly::detail::FutexResult::AWOKEN;
233
+ }
234
+
235
+ template <typename Clock, typename Duration>
236
+ std::cv_status tag_invoke(
237
+ cpo_t<atomic_wait_until>,
238
+ const ManualAtomic<std::uintptr_t>*,
239
+ std::uintptr_t,
240
+ const std::chrono::time_point<Clock, Duration>&) {
241
+ ManualSchedule::beforeSharedAccess();
242
+ return std::cv_status::no_timeout;
243
+ }
244
+
245
+ void tag_invoke(cpo_t<atomic_notify_one>, const ManualAtomic<std::uintptr_t>*) {
246
+ ManualSchedule::beforeSharedAccess();
247
+ }
248
+ } // namespace test
249
+
250
+ namespace {
251
+ constexpr auto kStressFactor = 1000;
252
+ constexpr auto kStressTestSeconds = 2;
253
+ constexpr auto kForever = 100h;
254
+
255
+ using DSched = test::DeterministicSchedule;
256
+
257
+ int sum(int n) {
258
+ return (n * (n + 1)) / 2;
259
+ }
260
+
261
+ template <template <typename> class Atom = std::atomic>
262
+ void basicNThreads(int numThreads, int iterations = kStressFactor) {
263
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
264
+ auto&& barrier = std::atomic<int>{0};
265
+ auto&& threads = std::vector<std::thread>{};
266
+ auto&& result = std::vector<int>{};
267
+
268
+ auto&& function = [&](auto id) {
269
+ return [&, id] {
270
+ for (auto j = 0; j < iterations; ++j) {
271
+ auto lck = std::unique_lock<std::decay_t<decltype(mutex)>>{mutex};
272
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
273
+ std::this_thread::yield();
274
+ result.push_back(id);
275
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
276
+ }
277
+ };
278
+ };
279
+
280
+ for (auto i = 1; i <= numThreads; ++i) {
281
+ threads.push_back(DSched::thread(function(i)));
282
+ }
283
+ for (auto& thread : threads) {
284
+ DSched::join(thread);
285
+ }
286
+
287
+ auto total = 0;
288
+ for (auto value : result) {
289
+ total += value;
290
+ }
291
+ EXPECT_EQ(total, sum(numThreads) * iterations);
292
+ }
293
+
294
+ template <template <typename> class Atom = std::atomic>
295
+ void lockWithTryAndTimedNThreads(
296
+ int numThreads, std::chrono::seconds duration) {
297
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
298
+ auto&& barrier = std::atomic<int>{0};
299
+ auto&& threads = std::vector<std::thread>{};
300
+ auto&& stop = std::atomic<bool>{false};
301
+
302
+ auto&& lockUnlockFunction = [&]() {
303
+ while (!stop.load()) {
304
+ auto lck = std::unique_lock<std::decay_t<decltype(mutex)>>{mutex};
305
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
306
+ std::this_thread::yield();
307
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
308
+ }
309
+ };
310
+
311
+ auto tryLockFunction = [&]() {
312
+ while (!stop.load()) {
313
+ using Mutex = std::decay_t<decltype(mutex)>;
314
+ auto lck = std::unique_lock<Mutex>{mutex, std::defer_lock};
315
+ if (lck.try_lock()) {
316
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
317
+ std::this_thread::yield();
318
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
319
+ }
320
+ }
321
+ };
322
+
323
+ auto timedLockFunction = [&]() {
324
+ while (!stop.load()) {
325
+ using Mutex = std::decay_t<decltype(mutex)>;
326
+ auto lck = std::unique_lock<Mutex>{mutex, std::defer_lock};
327
+ if (lck.try_lock_for(kForever)) {
328
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
329
+ std::this_thread::yield();
330
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
331
+ }
332
+ }
333
+ };
334
+
335
+ for (auto i = 0; i < (numThreads / 3); ++i) {
336
+ threads.push_back(DSched::thread(lockUnlockFunction));
337
+ }
338
+ for (auto i = 0; i < (numThreads / 3); ++i) {
339
+ threads.push_back(DSched::thread(tryLockFunction));
340
+ }
341
+ for (auto i = 0; i < (numThreads / 3); ++i) {
342
+ threads.push_back(DSched::thread(timedLockFunction));
343
+ }
344
+
345
+ /* sleep override */
346
+ std::this_thread::sleep_for(duration);
347
+ stop.store(true);
348
+ for (auto& thread : threads) {
349
+ DSched::join(thread);
350
+ }
351
+ }
352
+
353
+ template <template <typename> class Atom = std::atomic>
354
+ void combineNThreads(int numThreads, std::chrono::seconds duration) {
355
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
356
+ auto&& barrier = std::atomic<int>{0};
357
+ auto&& threads = std::vector<std::thread>{};
358
+ auto&& stop = std::atomic<bool>{false};
359
+
360
+ auto&& function = [&]() {
361
+ return [&] {
362
+ auto&& expected = std::uint64_t{0};
363
+ auto&& local = std::atomic<std::uint64_t>{0};
364
+ auto&& result = std::atomic<std::uint64_t>{0};
365
+ while (!stop.load()) {
366
+ ++expected;
367
+ auto current = mutex.lock_combine([&]() {
368
+ result.fetch_add(1);
369
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
370
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 1);
371
+ std::this_thread::yield();
372
+ SCOPE_EXIT {
373
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
374
+ };
375
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 2);
376
+ return local.fetch_add(1);
377
+ });
378
+ EXPECT_EQ(current, expected - 1);
379
+ }
380
+
381
+ EXPECT_EQ(expected, result.load());
382
+ };
383
+ };
384
+
385
+ for (auto i = 1; i <= numThreads; ++i) {
386
+ threads.push_back(DSched::thread(function()));
387
+ }
388
+
389
+ /* sleep override */
390
+ std::this_thread::sleep_for(duration);
391
+ stop.store(true);
392
+ for (auto& thread : threads) {
393
+ DSched::join(thread);
394
+ }
395
+ }
396
+
397
+ template <template <typename> class Atom = std::atomic>
398
+ void combineWithLockNThreads(int numThreads, std::chrono::seconds duration) {
399
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
400
+ auto&& barrier = std::atomic<int>{0};
401
+ auto&& threads = std::vector<std::thread>{};
402
+ auto&& stop = std::atomic<bool>{false};
403
+
404
+ auto&& lockUnlockFunction = [&]() {
405
+ while (!stop.load()) {
406
+ auto lck = std::unique_lock<std::decay_t<decltype(mutex)>>{mutex};
407
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
408
+ std::this_thread::yield();
409
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
410
+ }
411
+ };
412
+
413
+ auto&& combineFunction = [&]() {
414
+ auto&& expected = std::uint64_t{0};
415
+ auto&& total = std::atomic<std::uint64_t>{0};
416
+
417
+ while (!stop.load()) {
418
+ ++expected;
419
+ auto current = mutex.lock_combine([&]() {
420
+ auto iteration = total.fetch_add(1);
421
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
422
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 1);
423
+ std::this_thread::yield();
424
+ SCOPE_EXIT {
425
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
426
+ };
427
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 2);
428
+ return iteration;
429
+ });
430
+
431
+ EXPECT_EQ(expected, current + 1);
432
+ }
433
+
434
+ EXPECT_EQ(expected, total.load());
435
+ };
436
+
437
+ for (auto i = 1; i < (numThreads / 2); ++i) {
438
+ threads.push_back(DSched::thread(combineFunction));
439
+ }
440
+ for (auto i = 0; i < (numThreads / 2); ++i) {
441
+ threads.push_back(DSched::thread(lockUnlockFunction));
442
+ }
443
+
444
+ /* sleep override */
445
+ std::this_thread::sleep_for(duration);
446
+ stop.store(true);
447
+ for (auto& thread : threads) {
448
+ DSched::join(thread);
449
+ }
450
+ }
451
+
452
+ template <template <typename> class Atom = std::atomic>
453
+ void combineWithTryLockNThreads(int numThreads, std::chrono::seconds duration) {
454
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
455
+ auto&& barrier = std::atomic<int>{0};
456
+ auto&& threads = std::vector<std::thread>{};
457
+ auto&& stop = std::atomic<bool>{false};
458
+
459
+ auto&& lockUnlockFunction = [&]() {
460
+ while (!stop.load()) {
461
+ auto lck = std::unique_lock<std::decay_t<decltype(mutex)>>{mutex};
462
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
463
+ std::this_thread::yield();
464
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
465
+ }
466
+ };
467
+
468
+ auto&& combineFunction = [&]() {
469
+ auto&& expected = std::uint64_t{0};
470
+ auto&& total = std::atomic<std::uint64_t>{0};
471
+
472
+ while (!stop.load()) {
473
+ ++expected;
474
+ auto current = mutex.lock_combine([&]() {
475
+ auto iteration = total.fetch_add(1);
476
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
477
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 1);
478
+ std::this_thread::yield();
479
+ SCOPE_EXIT {
480
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
481
+ };
482
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 2);
483
+ return iteration;
484
+ });
485
+
486
+ EXPECT_EQ(expected, current + 1);
487
+ }
488
+
489
+ EXPECT_EQ(expected, total.load());
490
+ };
491
+
492
+ auto tryLockFunction = [&]() {
493
+ while (!stop.load()) {
494
+ using Mutex = std::decay_t<decltype(mutex)>;
495
+ auto lck = std::unique_lock<Mutex>{mutex, std::defer_lock};
496
+ if (lck.try_lock()) {
497
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
498
+ std::this_thread::yield();
499
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
500
+ }
501
+ }
502
+ };
503
+
504
+ for (auto i = 0; i < (numThreads / 3); ++i) {
505
+ threads.push_back(DSched::thread(lockUnlockFunction));
506
+ }
507
+ for (auto i = 0; i < (numThreads / 3); ++i) {
508
+ threads.push_back(DSched::thread(combineFunction));
509
+ }
510
+ for (auto i = 0; i < (numThreads / 3); ++i) {
511
+ threads.push_back(DSched::thread(tryLockFunction));
512
+ }
513
+
514
+ /* sleep override */
515
+ std::this_thread::sleep_for(duration);
516
+ stop.store(true);
517
+ for (auto& thread : threads) {
518
+ DSched::join(thread);
519
+ }
520
+ }
521
+
522
+ template <template <typename> class Atom = std::atomic>
523
+ void combineWithLockTryAndTimedNThreads(
524
+ int numThreads, std::chrono::seconds duration) {
525
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
526
+ auto&& barrier = std::atomic<int>{0};
527
+ auto&& threads = std::vector<std::thread>{};
528
+ auto&& stop = std::atomic<bool>{false};
529
+
530
+ auto&& lockUnlockFunction = [&]() {
531
+ while (!stop.load()) {
532
+ auto lck = std::unique_lock<std::decay_t<decltype(mutex)>>{mutex};
533
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
534
+ std::this_thread::yield();
535
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
536
+ }
537
+ };
538
+
539
+ auto&& combineFunction = [&]() {
540
+ auto&& expected = std::uint64_t{0};
541
+ auto&& total = std::atomic<std::uint64_t>{0};
542
+
543
+ while (!stop.load()) {
544
+ ++expected;
545
+ auto current = mutex.lock_combine([&]() {
546
+ auto iteration = total.fetch_add(1);
547
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
548
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 1);
549
+ std::this_thread::yield();
550
+ SCOPE_EXIT {
551
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
552
+ };
553
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 2);
554
+
555
+ // return a non-trivially-copyable object that occupies all the
556
+ // storage we use to coalesce returns to test that codepath
557
+ return folly::make_array(
558
+ iteration,
559
+ iteration + 1,
560
+ iteration + 2,
561
+ iteration + 3,
562
+ iteration + 4,
563
+ iteration + 5);
564
+ });
565
+
566
+ EXPECT_EQ(expected, current[0] + 1);
567
+ EXPECT_EQ(expected, current[1]);
568
+ EXPECT_EQ(expected, current[2] - 1);
569
+ EXPECT_EQ(expected, current[3] - 2);
570
+ EXPECT_EQ(expected, current[4] - 3);
571
+ EXPECT_EQ(expected, current[5] - 4);
572
+ }
573
+
574
+ EXPECT_EQ(expected, total.load());
575
+ };
576
+
577
+ auto tryLockFunction = [&]() {
578
+ while (!stop.load()) {
579
+ using Mutex = std::decay_t<decltype(mutex)>;
580
+ auto lck = std::unique_lock<Mutex>{mutex, std::defer_lock};
581
+ if (lck.try_lock()) {
582
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
583
+ std::this_thread::yield();
584
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
585
+ }
586
+ }
587
+ };
588
+
589
+ auto timedLockFunction = [&]() {
590
+ while (!stop.load()) {
591
+ using Mutex = std::decay_t<decltype(mutex)>;
592
+ auto lck = std::unique_lock<Mutex>{mutex, std::defer_lock};
593
+ if (lck.try_lock_for(kForever)) {
594
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
595
+ std::this_thread::yield();
596
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
597
+ }
598
+ }
599
+ };
600
+
601
+ for (auto i = 0; i < (numThreads / 4); ++i) {
602
+ threads.push_back(DSched::thread(lockUnlockFunction));
603
+ }
604
+ for (auto i = 0; i < (numThreads / 4); ++i) {
605
+ threads.push_back(DSched::thread(combineFunction));
606
+ }
607
+ for (auto i = 0; i < (numThreads / 4); ++i) {
608
+ threads.push_back(DSched::thread(tryLockFunction));
609
+ }
610
+ for (auto i = 0; i < (numThreads / 4); ++i) {
611
+ threads.push_back(DSched::thread(timedLockFunction));
612
+ }
613
+
614
+ /* sleep override */
615
+ std::this_thread::sleep_for(duration);
616
+ stop.store(true);
617
+ for (auto& thread : threads) {
618
+ DSched::join(thread);
619
+ }
620
+ }
621
+ } // namespace
622
+
623
+ TEST(DistributedMutex, InternalDetailTestOne) {
624
+ auto value = 0;
625
+ auto ptr = reinterpret_cast<std::uintptr_t>(&value);
626
+ EXPECT_EQ(detail::distributed_mutex::extractPtr<int>(ptr), &value);
627
+ ptr = ptr | 0b1;
628
+ EXPECT_EQ(detail::distributed_mutex::extractPtr<int>(ptr), &value);
629
+ }
630
+
631
+ TEST(DistributedMutex, Basic) {
632
+ auto&& mutex = DistributedMutex{};
633
+ auto state = mutex.lock();
634
+ mutex.unlock(std::move(state));
635
+ }
636
+
637
+ TEST(DistributedMutex, BasicTryLock) {
638
+ auto&& mutex = DistributedMutex{};
639
+
640
+ while (true) {
641
+ auto state = mutex.try_lock();
642
+ if (state) {
643
+ mutex.unlock(std::move(state));
644
+ break;
645
+ }
646
+ }
647
+ }
648
+
649
+ TEST(DistributedMutex, TestSingleElementContentionChain) {
650
+ // Acquire the mutex once, let another thread form a contention chain on the
651
+ // mutex, and then release it. Observe the other thread grab the lock
652
+ auto&& schedule = test::ManualSchedule{};
653
+ auto&& mutex = test::TestDistributedMutex<test::ManualAtomic>{};
654
+
655
+ auto&& waiter = std::thread{[&]() {
656
+ schedule.setCallback([&, i = 0]() mutable {
657
+ if (i == 2) {
658
+ schedule.post(1);
659
+ }
660
+ ++i;
661
+ });
662
+
663
+ schedule.wait(0);
664
+ auto state = mutex.lock();
665
+ mutex.unlock(std::move(state));
666
+ }};
667
+
668
+ // lock the mutex, signal the waiter, and then wait till the first thread
669
+ // has gotten on the wait list
670
+ auto state = mutex.lock();
671
+ schedule.post(0);
672
+ schedule.wait(1);
673
+
674
+ // release the mutex, and then wait for the waiter to acquire the lock
675
+ mutex.unlock(std::move(state));
676
+ waiter.join();
677
+ }
678
+
679
+ TEST(DistributedMutex, TestTwoElementContentionChain) {
680
+ // Acquire the mutex once, let another thread form a contention chain on the
681
+ // mutex, and then release it. Observe the other thread grab the lock
682
+ auto&& schedule = test::ManualSchedule{};
683
+ auto&& mutex = test::TestDistributedMutex<test::ManualAtomic>{};
684
+
685
+ auto&& one = std::thread{[&]() {
686
+ schedule.setCallback([&, i = 0]() mutable {
687
+ if (i == 2) {
688
+ schedule.post(3);
689
+ }
690
+ ++i;
691
+ });
692
+
693
+ schedule.wait(0);
694
+ auto state = mutex.lock();
695
+ mutex.unlock(std::move(state));
696
+ }};
697
+
698
+ auto&& two = std::thread{[&]() {
699
+ schedule.setCallback([&, i = 0]() mutable {
700
+ if (i == 2) {
701
+ schedule.post(2);
702
+ }
703
+ ++i;
704
+ });
705
+
706
+ schedule.wait(1);
707
+ auto state = mutex.lock();
708
+ mutex.unlock(std::move(state));
709
+ }};
710
+
711
+ // lock the mutex, signal the waiter, and then wait till the first thread
712
+ // has gotten on the wait list
713
+ auto state = mutex.lock();
714
+ schedule.post(0);
715
+ schedule.post(1);
716
+ schedule.wait(2);
717
+ schedule.wait(3);
718
+
719
+ // release the mutex, and then wait for the waiter to acquire the lock
720
+ mutex.unlock(std::move(state));
721
+ one.join();
722
+ two.join();
723
+ }
724
+
725
+ TEST(DistributedMutex, TestTwoContentionChains) {
726
+ auto&& schedule = test::ManualSchedule{};
727
+ auto&& mutex = test::TestDistributedMutex<test::ManualAtomic>{};
728
+
729
+ auto&& one = std::thread{[&]() {
730
+ schedule.setCallback([&, i = 0]() mutable {
731
+ if (i == 2) {
732
+ schedule.post(0);
733
+ }
734
+ ++i;
735
+ });
736
+
737
+ schedule.wait(1);
738
+ auto state = mutex.lock();
739
+ schedule.wait(4);
740
+ mutex.unlock(std::move(state));
741
+ }};
742
+ auto&& two = std::thread{[&]() {
743
+ schedule.setCallback([&, i = 0]() mutable {
744
+ if (i == 2) {
745
+ schedule.post(2);
746
+ }
747
+ ++i;
748
+ });
749
+
750
+ schedule.wait(3);
751
+ auto state = mutex.lock();
752
+ schedule.wait(5);
753
+ mutex.unlock(std::move(state));
754
+ }};
755
+
756
+ auto state = mutex.lock();
757
+ schedule.post(1);
758
+ schedule.post(3);
759
+ schedule.wait(0);
760
+ schedule.wait(2);
761
+
762
+ // at this point there is one contention chain. Release it
763
+ mutex.unlock(std::move(state));
764
+
765
+ // then start a new contention chain
766
+ auto&& three = std::thread{[&]() {
767
+ schedule.setCallback([&, i = 0]() mutable {
768
+ if (i == 2) {
769
+ schedule.post(4);
770
+ schedule.post(5);
771
+ }
772
+ ++i;
773
+ });
774
+
775
+ auto lockState = mutex.lock();
776
+ schedule.post(6);
777
+ mutex.unlock(std::move(lockState));
778
+ }};
779
+
780
+ // wait for the third thread to pick up the lock
781
+ schedule.wait(6);
782
+ one.join();
783
+ two.join();
784
+ three.join();
785
+ }
786
+
787
+ TEST(DistributedMutex, StressTwoThreads) {
788
+ basicNThreads(2);
789
+ }
790
+ TEST(DistributedMutex, StressThreeThreads) {
791
+ basicNThreads(3);
792
+ }
793
+ TEST(DistributedMutex, StressFourThreads) {
794
+ basicNThreads(4);
795
+ }
796
+ TEST(DistributedMutex, StressFiveThreads) {
797
+ basicNThreads(5);
798
+ }
799
+ TEST(DistributedMutex, StressSixThreads) {
800
+ basicNThreads(6);
801
+ }
802
+ TEST(DistributedMutex, StressSevenThreads) {
803
+ basicNThreads(7);
804
+ }
805
+ TEST(DistributedMutex, StressEightThreads) {
806
+ basicNThreads(8);
807
+ }
808
+ TEST(DistributedMutex, StressSixteenThreads) {
809
+ basicNThreads(16);
810
+ }
811
+ TEST(DistributedMutex, StressThirtyTwoThreads) {
812
+ basicNThreads(32);
813
+ }
814
+ TEST(DistributedMutex, StressSixtyFourThreads) {
815
+ basicNThreads(64);
816
+ }
817
+ TEST(DistributedMutex, StressHundredThreads) {
818
+ basicNThreads(100);
819
+ }
820
+ TEST(DistributedMutex, StressHardwareConcurrencyThreads) {
821
+ basicNThreads(std::thread::hardware_concurrency());
822
+ }
823
+
824
+ TEST(DistributedMutex, StressThreeThreadsLockTryAndTimed) {
825
+ lockWithTryAndTimedNThreads(3, std::chrono::seconds{kStressTestSeconds});
826
+ }
827
+ TEST(DistributedMutex, StressSixThreadsLockTryAndTimed) {
828
+ lockWithTryAndTimedNThreads(6, std::chrono::seconds{kStressTestSeconds});
829
+ }
830
+ TEST(DistributedMutex, StressTwelveThreadsLockTryAndTimed) {
831
+ lockWithTryAndTimedNThreads(12, std::chrono::seconds{kStressTestSeconds});
832
+ }
833
+ TEST(DistributedMutex, StressTwentyFourThreadsLockTryAndTimed) {
834
+ lockWithTryAndTimedNThreads(24, std::chrono::seconds{kStressTestSeconds});
835
+ }
836
+ TEST(DistributedMutex, StressFourtyEightThreadsLockTryAndTimed) {
837
+ lockWithTryAndTimedNThreads(48, std::chrono::seconds{kStressTestSeconds});
838
+ }
839
+ TEST(DistributedMutex, StressSixtyFourThreadsLockTryAndTimed) {
840
+ lockWithTryAndTimedNThreads(64, std::chrono::seconds{kStressTestSeconds});
841
+ }
842
+ TEST(DistributedMutex, StressHwConcThreadsLockTryAndTimed) {
843
+ lockWithTryAndTimedNThreads(
844
+ std::thread::hardware_concurrency(),
845
+ std::chrono::seconds{kStressTestSeconds});
846
+ }
847
+
848
+ TEST(DistributedMutex, StressTwoThreadsCombine) {
849
+ combineNThreads(2, std::chrono::seconds{kStressTestSeconds});
850
+ }
851
+ TEST(DistributedMutex, StressThreeThreadsCombine) {
852
+ combineNThreads(3, std::chrono::seconds{kStressTestSeconds});
853
+ }
854
+ TEST(DistributedMutex, StressFourThreadsCombine) {
855
+ combineNThreads(4, std::chrono::seconds{kStressTestSeconds});
856
+ }
857
+ TEST(DistributedMutex, StressFiveThreadsCombine) {
858
+ combineNThreads(5, std::chrono::seconds{kStressTestSeconds});
859
+ }
860
+ TEST(DistributedMutex, StressSixThreadsCombine) {
861
+ combineNThreads(6, std::chrono::seconds{kStressTestSeconds});
862
+ }
863
+ TEST(DistributedMutex, StressSevenThreadsCombine) {
864
+ combineNThreads(7, std::chrono::seconds{kStressTestSeconds});
865
+ }
866
+ TEST(DistributedMutex, StressEightThreadsCombine) {
867
+ combineNThreads(8, std::chrono::seconds{kStressTestSeconds});
868
+ }
869
+ TEST(DistributedMutex, StressSixteenThreadsCombine) {
870
+ combineNThreads(16, std::chrono::seconds{kStressTestSeconds});
871
+ }
872
+ TEST(DistributedMutex, StressThirtyTwoThreadsCombine) {
873
+ combineNThreads(32, std::chrono::seconds{kStressTestSeconds});
874
+ }
875
+ TEST(DistributedMutex, StressSixtyFourThreadsCombine) {
876
+ combineNThreads(64, std::chrono::seconds{kStressTestSeconds});
877
+ }
878
+ TEST(DistributedMutex, StressHundredThreadsCombine) {
879
+ combineNThreads(100, std::chrono::seconds{kStressTestSeconds});
880
+ }
881
+ TEST(DistributedMutex, StressHardwareConcurrencyThreadsCombine) {
882
+ combineNThreads(
883
+ std::thread::hardware_concurrency(),
884
+ std::chrono::seconds{kStressTestSeconds});
885
+ }
886
+
887
+ TEST(DistributedMutex, StressTwoThreadsCombineAndLock) {
888
+ combineWithLockNThreads(2, std::chrono::seconds{kStressTestSeconds});
889
+ }
890
+ TEST(DistributedMutex, StressFourThreadsCombineAndLock) {
891
+ combineWithLockNThreads(4, std::chrono::seconds{kStressTestSeconds});
892
+ }
893
+ TEST(DistributedMutex, StressEightThreadsCombineAndLock) {
894
+ combineWithLockNThreads(8, std::chrono::seconds{kStressTestSeconds});
895
+ }
896
+ TEST(DistributedMutex, StressSixteenThreadsCombineAndLock) {
897
+ combineWithLockNThreads(16, std::chrono::seconds{kStressTestSeconds});
898
+ }
899
+ TEST(DistributedMutex, StressThirtyTwoThreadsCombineAndLock) {
900
+ combineWithLockNThreads(32, std::chrono::seconds{kStressTestSeconds});
901
+ }
902
+ TEST(DistributedMutex, StressSixtyFourThreadsCombineAndLock) {
903
+ combineWithLockNThreads(64, std::chrono::seconds{kStressTestSeconds});
904
+ }
905
+ TEST(DistributedMutex, StressHardwareConcurrencyThreadsCombineAndLock) {
906
+ combineWithLockNThreads(
907
+ std::thread::hardware_concurrency(),
908
+ std::chrono::seconds{kStressTestSeconds});
909
+ }
910
+
911
+ TEST(DistributedMutex, StressThreeThreadsCombineTryLockAndLock) {
912
+ combineWithTryLockNThreads(3, std::chrono::seconds{kStressTestSeconds});
913
+ }
914
+ TEST(DistributedMutex, StressSixThreadsCombineTryLockAndLock) {
915
+ combineWithTryLockNThreads(6, std::chrono::seconds{kStressTestSeconds});
916
+ }
917
+ TEST(DistributedMutex, StressTwelveThreadsCombineTryLockAndLock) {
918
+ combineWithTryLockNThreads(12, std::chrono::seconds{kStressTestSeconds});
919
+ }
920
+ TEST(DistributedMutex, StressTwentyFourThreadsCombineTryLockAndLock) {
921
+ combineWithTryLockNThreads(24, std::chrono::seconds{kStressTestSeconds});
922
+ }
923
+ TEST(DistributedMutex, StressFourtyEightThreadsCombineTryLockAndLock) {
924
+ combineWithTryLockNThreads(48, std::chrono::seconds{kStressTestSeconds});
925
+ }
926
+ TEST(DistributedMutex, StressSixtyFourThreadsCombineTryLockAndLock) {
927
+ combineWithTryLockNThreads(64, std::chrono::seconds{kStressTestSeconds});
928
+ }
929
+ TEST(DistributedMutex, StressHardwareConcurrencyThreadsCombineTryLockAndLock) {
930
+ combineWithTryLockNThreads(
931
+ std::thread::hardware_concurrency(),
932
+ std::chrono::seconds{kStressTestSeconds});
933
+ }
934
+
935
+ TEST(DistributedMutex, StressThreeThreadsCombineTryLockLockAndTimed) {
936
+ combineWithLockTryAndTimedNThreads(
937
+ 3, std::chrono::seconds{kStressTestSeconds});
938
+ }
939
+ TEST(DistributedMutex, StressSixThreadsCombineTryLockLockAndTimed) {
940
+ combineWithLockTryAndTimedNThreads(
941
+ 6, std::chrono::seconds{kStressTestSeconds});
942
+ }
943
+ TEST(DistributedMutex, StressTwelveThreadsCombineTryLockLockAndTimed) {
944
+ combineWithLockTryAndTimedNThreads(
945
+ 12, std::chrono::seconds{kStressTestSeconds});
946
+ }
947
+ TEST(DistributedMutex, StressTwentyFourThreadsCombineTryLockLockAndTimed) {
948
+ combineWithLockTryAndTimedNThreads(
949
+ 24, std::chrono::seconds{kStressTestSeconds});
950
+ }
951
+ TEST(DistributedMutex, StressFourtyEightThreadsCombineTryLockLockAndTimed) {
952
+ combineWithLockTryAndTimedNThreads(
953
+ 48, std::chrono::seconds{kStressTestSeconds});
954
+ }
955
+ TEST(DistributedMutex, StressSixtyFourThreadsCombineTryLockLockAndTimed) {
956
+ combineWithLockTryAndTimedNThreads(
957
+ 64, std::chrono::seconds{kStressTestSeconds});
958
+ }
959
+ TEST(DistributedMutex, StressHwConcurrencyThreadsCombineTryLockLockAndTimed) {
960
+ combineWithLockTryAndTimedNThreads(
961
+ std::thread::hardware_concurrency(),
962
+ std::chrono::seconds{kStressTestSeconds});
963
+ }
964
+
965
+ TEST(DistributedMutex, StressTryLock) {
966
+ auto&& mutex = DistributedMutex{};
967
+
968
+ for (auto i = 0; i < kStressFactor; ++i) {
969
+ while (true) {
970
+ auto state = mutex.try_lock();
971
+ if (state) {
972
+ mutex.unlock(std::move(state));
973
+ break;
974
+ }
975
+ }
976
+ }
977
+ }
978
+
979
+ namespace {
980
+ constexpr auto numIterationsDeterministicTest(int threads) {
981
+ if (threads <= 8) {
982
+ return 100;
983
+ }
984
+
985
+ return 10;
986
+ }
987
+
988
+ void runBasicNThreadsDeterministic(int threads, int iterations) {
989
+ for (auto pass = 0; pass < 3; ++pass) {
990
+ auto&& schedule = DSched{DSched::uniform(pass)};
991
+ basicNThreads<test::DeterministicAtomic>(threads, iterations);
992
+ static_cast<void>(schedule);
993
+ }
994
+ }
995
+
996
+ void combineNThreadsDeterministic(int threads, std::chrono::seconds t) {
997
+ const auto kNumPasses = 3.0;
998
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
999
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
1000
+
1001
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
1002
+ auto&& schedule = DSched{DSched::uniform(pass)};
1003
+ combineNThreads<test::DeterministicAtomic>(threads, time);
1004
+ static_cast<void>(schedule);
1005
+ }
1006
+ }
1007
+
1008
+ void combineAndLockNThreadsDeterministic(int threads, std::chrono::seconds t) {
1009
+ const auto kNumPasses = 3.0;
1010
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
1011
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
1012
+
1013
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
1014
+ auto&& schedule = DSched{DSched::uniform(pass)};
1015
+ combineWithLockNThreads<test::DeterministicAtomic>(threads, time);
1016
+ static_cast<void>(schedule);
1017
+ }
1018
+ }
1019
+
1020
+ void combineTryLockAndLockNThreadsDeterministic(
1021
+ int threads, std::chrono::seconds t) {
1022
+ const auto kNumPasses = 3.0;
1023
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
1024
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
1025
+
1026
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
1027
+ auto&& schedule = DSched{DSched::uniform(pass)};
1028
+ combineWithTryLockNThreads<test::DeterministicAtomic>(threads, time);
1029
+ static_cast<void>(schedule);
1030
+ }
1031
+ }
1032
+
1033
+ void lockWithTryAndTimedNThreadsDeterministic(
1034
+ int threads, std::chrono::seconds t) {
1035
+ const auto kNumPasses = 3.0;
1036
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
1037
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
1038
+
1039
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
1040
+ auto&& schedule = DSched{DSched::uniform(pass)};
1041
+ lockWithTryAndTimedNThreads<test::DeterministicAtomic>(threads, time);
1042
+ static_cast<void>(schedule);
1043
+ }
1044
+ }
1045
+
1046
+ void combineWithTryLockAndTimedNThreadsDeterministic(
1047
+ int threads, std::chrono::seconds t) {
1048
+ const auto kNumPasses = 3.0;
1049
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
1050
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
1051
+
1052
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
1053
+ auto&& schedule = DSched{DSched::uniform(pass)};
1054
+ combineWithLockTryAndTimedNThreads<test::DeterministicAtomic>(
1055
+ threads, time);
1056
+ static_cast<void>(schedule);
1057
+ }
1058
+ }
1059
+ } // namespace
1060
+
1061
+ TEST(DistributedMutex, DeterministicStressTwoThreads) {
1062
+ runBasicNThreadsDeterministic(2, numIterationsDeterministicTest(2));
1063
+ }
1064
+ TEST(DistributedMutex, DeterministicStressFourThreads) {
1065
+ runBasicNThreadsDeterministic(4, numIterationsDeterministicTest(4));
1066
+ }
1067
+ TEST(DistributedMutex, DeterministicStressEightThreads) {
1068
+ runBasicNThreadsDeterministic(8, numIterationsDeterministicTest(8));
1069
+ }
1070
+ TEST(DistributedMutex, DeterministicStressSixteenThreads) {
1071
+ runBasicNThreadsDeterministic(16, numIterationsDeterministicTest(16));
1072
+ }
1073
+ TEST(DistributedMutex, DeterministicStressThirtyTwoThreads) {
1074
+ runBasicNThreadsDeterministic(32, numIterationsDeterministicTest(32));
1075
+ }
1076
+
1077
+ TEST(DistributedMutex, DeterministicStressThreeThreadsLockTryAndTimed) {
1078
+ lockWithTryAndTimedNThreadsDeterministic(
1079
+ 3, std::chrono::seconds{kStressTestSeconds});
1080
+ }
1081
+ TEST(DistributedMutex, DeterministicStressSixThreadsLockTryAndTimed) {
1082
+ lockWithTryAndTimedNThreadsDeterministic(
1083
+ 6, std::chrono::seconds{kStressTestSeconds});
1084
+ }
1085
+ TEST(DistributedMutex, DeterministicStressTwelveThreadsLockTryAndTimed) {
1086
+ lockWithTryAndTimedNThreadsDeterministic(
1087
+ 12, std::chrono::seconds{kStressTestSeconds});
1088
+ }
1089
+ TEST(DistributedMutex, DeterministicStressTwentyFourThreadsLockTryAndTimed) {
1090
+ lockWithTryAndTimedNThreadsDeterministic(
1091
+ 24, std::chrono::seconds{kStressTestSeconds});
1092
+ }
1093
+ TEST(DistributedMutex, DeterministicStressFourtyEightThreadsLockTryAndTimed) {
1094
+ lockWithTryAndTimedNThreadsDeterministic(
1095
+ 48, std::chrono::seconds{kStressTestSeconds});
1096
+ }
1097
+ TEST(DistributedMutex, DeterministicStressSixtyFourThreadsLockTryAndTimed) {
1098
+ lockWithTryAndTimedNThreadsDeterministic(
1099
+ 64, std::chrono::seconds{kStressTestSeconds});
1100
+ }
1101
+ TEST(DistributedMutex, DeterministicStressHwConcThreadsLockTryAndTimed) {
1102
+ lockWithTryAndTimedNThreadsDeterministic(
1103
+ std::thread::hardware_concurrency(),
1104
+ std::chrono::seconds{kStressTestSeconds});
1105
+ }
1106
+
1107
+ TEST(DistributedMutex, CombineDeterministicStressTwoThreads) {
1108
+ combineNThreadsDeterministic(2, std::chrono::seconds{kStressTestSeconds});
1109
+ }
1110
+ TEST(DistributedMutex, CombineDeterministicStressFourThreads) {
1111
+ combineNThreadsDeterministic(4, std::chrono::seconds{kStressTestSeconds});
1112
+ }
1113
+ TEST(DistributedMutex, CombineDeterministicStressEightThreads) {
1114
+ combineNThreadsDeterministic(8, std::chrono::seconds{kStressTestSeconds});
1115
+ }
1116
+ TEST(DistributedMutex, CombineDeterministicStressSixteenThreads) {
1117
+ combineNThreadsDeterministic(16, std::chrono::seconds{kStressTestSeconds});
1118
+ }
1119
+ TEST(DistributedMutex, CombineDeterministicStressThirtyTwoThreads) {
1120
+ combineNThreadsDeterministic(32, std::chrono::seconds{kStressTestSeconds});
1121
+ }
1122
+ TEST(DistributedMutex, CombineDeterministicStressSixtyFourThreads) {
1123
+ combineNThreadsDeterministic(64, std::chrono::seconds{kStressTestSeconds});
1124
+ }
1125
+ TEST(DistributedMutex, CombineDeterministicStressHardwareConcurrencyThreads) {
1126
+ combineNThreadsDeterministic(
1127
+ std::thread::hardware_concurrency(),
1128
+ std::chrono::seconds{kStressTestSeconds});
1129
+ }
1130
+
1131
+ TEST(DistributedMutex, CombineAndLockDeterministicStressTwoThreads) {
1132
+ combineAndLockNThreadsDeterministic(
1133
+ 2, std::chrono::seconds{kStressTestSeconds});
1134
+ }
1135
+ TEST(DistributedMutex, CombineAndLockDeterministicStressFourThreads) {
1136
+ combineAndLockNThreadsDeterministic(
1137
+ 4, std::chrono::seconds{kStressTestSeconds});
1138
+ }
1139
+ TEST(DistributedMutex, CombineAndLockDeterministicStressEightThreads) {
1140
+ combineAndLockNThreadsDeterministic(
1141
+ 8, std::chrono::seconds{kStressTestSeconds});
1142
+ }
1143
+ TEST(DistributedMutex, CombineAndLockDeterministicStressSixteenThreads) {
1144
+ combineAndLockNThreadsDeterministic(
1145
+ 16, std::chrono::seconds{kStressTestSeconds});
1146
+ }
1147
+ TEST(DistributedMutex, CombineAndLockDeterministicStressThirtyTwoThreads) {
1148
+ combineAndLockNThreadsDeterministic(
1149
+ 32, std::chrono::seconds{kStressTestSeconds});
1150
+ }
1151
+ TEST(DistributedMutex, CombineAndLockDeterministicStressSixtyFourThreads) {
1152
+ combineAndLockNThreadsDeterministic(
1153
+ 64, std::chrono::seconds{kStressTestSeconds});
1154
+ }
1155
+ TEST(DistributedMutex, CombineAndLockDeterministicStressHWConcurrencyThreads) {
1156
+ combineAndLockNThreadsDeterministic(
1157
+ std::thread::hardware_concurrency(),
1158
+ std::chrono::seconds{kStressTestSeconds});
1159
+ }
1160
+
1161
+ TEST(DistributedMutex, CombineTryLockAndLockDeterministicStressThreeThreads) {
1162
+ combineTryLockAndLockNThreadsDeterministic(
1163
+ 3, std::chrono::seconds{kStressTestSeconds});
1164
+ }
1165
+ TEST(DistributedMutex, CombineTryLockAndLockDeterministicStressSixThreads) {
1166
+ combineTryLockAndLockNThreadsDeterministic(
1167
+ 6, std::chrono::seconds{kStressTestSeconds});
1168
+ }
1169
+ TEST(DistributedMutex, CombineTryLockAndLockDeterministicStressTwelveThreads) {
1170
+ combineTryLockAndLockNThreadsDeterministic(
1171
+ 12, std::chrono::seconds{kStressTestSeconds});
1172
+ }
1173
+ TEST(DistributedMutex, CombineTryLockAndLockDeterministicStressTwentyThreads) {
1174
+ combineTryLockAndLockNThreadsDeterministic(
1175
+ 24, std::chrono::seconds{kStressTestSeconds});
1176
+ }
1177
+ TEST(DistributedMutex, CombineTryLockAndLockDeterministicStressFortyThreads) {
1178
+ combineTryLockAndLockNThreadsDeterministic(
1179
+ 48, std::chrono::seconds{kStressTestSeconds});
1180
+ }
1181
+ TEST(DistributedMutex, CombineTryLockAndLockDeterministicStressSixtyThreads) {
1182
+ combineTryLockAndLockNThreadsDeterministic(
1183
+ 64, std::chrono::seconds{kStressTestSeconds});
1184
+ }
1185
+ TEST(DistributedMutex, CombineTryLockAndLockDeterministicStressHWConcThreads) {
1186
+ combineTryLockAndLockNThreadsDeterministic(
1187
+ std::thread::hardware_concurrency(),
1188
+ std::chrono::seconds{kStressTestSeconds});
1189
+ }
1190
+
1191
+ TEST(DistributedMutex, CombineTryLockAndTimedDeterministicStressThreeThreads) {
1192
+ combineWithTryLockAndTimedNThreadsDeterministic(
1193
+ 3, std::chrono::seconds{kStressTestSeconds});
1194
+ }
1195
+ TEST(DistributedMutex, CombineTryLockAndTimedDeterministicStressSixThreads) {
1196
+ combineWithTryLockAndTimedNThreadsDeterministic(
1197
+ 6, std::chrono::seconds{kStressTestSeconds});
1198
+ }
1199
+ TEST(DistributedMutex, CombineTryLockAndTimedDeterministicStressTwelveThreads) {
1200
+ combineWithTryLockAndTimedNThreadsDeterministic(
1201
+ 12, std::chrono::seconds{kStressTestSeconds});
1202
+ }
1203
+ TEST(DistributedMutex, CombineTryLockAndTimedDeterministicStressTwentyThreads) {
1204
+ combineWithTryLockAndTimedNThreadsDeterministic(
1205
+ 24, std::chrono::seconds{kStressTestSeconds});
1206
+ }
1207
+ TEST(DistributedMutex, CombineTryLockAndTimedDeterministicStressFortyThreads) {
1208
+ combineWithTryLockAndTimedNThreadsDeterministic(
1209
+ 48, std::chrono::seconds{kStressTestSeconds});
1210
+ }
1211
+ TEST(DistributedMutex, CombineTryLockAndTimedDeterministicStressSixtyThreads) {
1212
+ combineWithTryLockAndTimedNThreadsDeterministic(
1213
+ 64, std::chrono::seconds{kStressTestSeconds});
1214
+ }
1215
+ TEST(DistributedMutex, CombineTryLockAndTimedDeterministicStressHWConcThreads) {
1216
+ combineWithTryLockAndTimedNThreadsDeterministic(
1217
+ std::thread::hardware_concurrency(),
1218
+ std::chrono::seconds{kStressTestSeconds});
1219
+ }
1220
+
1221
+ TEST(DistributedMutex, TimedLockTimeout) {
1222
+ auto&& mutex = DistributedMutex{};
1223
+ auto&& start = folly::Baton<>{};
1224
+ auto&& done = folly::Baton<>{};
1225
+
1226
+ auto thread = std::thread{[&]() {
1227
+ auto state = mutex.lock();
1228
+ start.post();
1229
+ done.wait();
1230
+ mutex.unlock(std::move(state));
1231
+ }};
1232
+
1233
+ start.wait();
1234
+ auto result = mutex.try_lock_for(10ms);
1235
+ EXPECT_FALSE(result);
1236
+ done.post();
1237
+ thread.join();
1238
+ }
1239
+
1240
+ TEST(DistributedMutex, TimedLockAcquireAfterUnlock) {
1241
+ auto&& mutex = DistributedMutex{};
1242
+ auto&& start = folly::Baton<>{};
1243
+
1244
+ auto thread = std::thread{[&]() {
1245
+ auto state = mutex.lock();
1246
+ start.post();
1247
+ /* sleep override */
1248
+ std::this_thread::sleep_for(10ms);
1249
+ mutex.unlock(std::move(state));
1250
+ }};
1251
+
1252
+ start.wait();
1253
+ auto result = mutex.try_lock_for(kForever);
1254
+ EXPECT_TRUE(result);
1255
+ thread.join();
1256
+ }
1257
+
1258
+ TEST(DistributedMutex, TimedLockAcquireAfterLock) {
1259
+ auto&& mutex = test::TestDistributedMutex<test::ManualAtomic>{};
1260
+ auto&& schedule = test::ManualSchedule{};
1261
+
1262
+ auto thread = std::thread{[&] {
1263
+ schedule.setCallback([&, i = 0]() mutable {
1264
+ if (i == 1) {
1265
+ schedule.post(0);
1266
+ schedule.wait(1);
1267
+ }
1268
+
1269
+ // when this thread goes into the atomic_notify_one() we let the other
1270
+ // thread wake up
1271
+ if (i == 3) {
1272
+ schedule.post(2);
1273
+ }
1274
+
1275
+ ++i;
1276
+ });
1277
+
1278
+ auto state = mutex.lock();
1279
+ mutex.unlock(std::move(state));
1280
+ }};
1281
+
1282
+ schedule.setCallback([&, i = 0]() mutable {
1283
+ // allow the other thread to unlock after the current thread has set the
1284
+ // timed waiter state into the mutex
1285
+ if (i == 2) {
1286
+ schedule.post(1);
1287
+ schedule.wait(2);
1288
+ }
1289
+ ++i;
1290
+ });
1291
+ schedule.wait(0);
1292
+ auto state = mutex.try_lock_for(kForever);
1293
+ EXPECT_TRUE(state);
1294
+ mutex.unlock(std::move(state));
1295
+ thread.join();
1296
+ }
1297
+
1298
+ TEST(DistributedMutex, TimedLockAcquireAfterContentionChain) {
1299
+ auto&& mutex = test::TestDistributedMutex<test::ManualAtomic>{};
1300
+ auto&& schedule = test::ManualSchedule{};
1301
+
1302
+ auto one = std::thread{[&] {
1303
+ schedule.setCallback([&, i = 0]() mutable {
1304
+ if (i == 1) {
1305
+ schedule.post(0);
1306
+ schedule.wait(1);
1307
+ schedule.wait(2);
1308
+ }
1309
+ ++i;
1310
+ });
1311
+
1312
+ auto state = mutex.lock();
1313
+ mutex.unlock(std::move(state));
1314
+ }};
1315
+ auto two = std::thread{[&] {
1316
+ schedule.setCallback([&, i = 0]() mutable {
1317
+ // block the current thread until the first thread has acquired the
1318
+ // lock
1319
+ if (i == 0) {
1320
+ schedule.wait(0);
1321
+ }
1322
+
1323
+ // when the current thread enqueues, let the first thread unlock so we
1324
+ // get woken up
1325
+ //
1326
+ // then wait for the first thread to unlock
1327
+ if (i == 2) {
1328
+ schedule.post(1);
1329
+ }
1330
+
1331
+ ++i;
1332
+ });
1333
+
1334
+ auto state = mutex.lock();
1335
+ mutex.unlock(std::move(state));
1336
+ }};
1337
+
1338
+ // make the current thread wait for the first thread to unlock
1339
+ schedule.setCallback([&, i = 0]() mutable {
1340
+ // let the first thread unlock after we have enqueued ourselves on the
1341
+ // mutex
1342
+ if (i == 2) {
1343
+ schedule.post(2);
1344
+ }
1345
+ ++i;
1346
+ });
1347
+ auto state = mutex.try_lock_for(kForever);
1348
+ EXPECT_TRUE(state);
1349
+ mutex.unlock(std::move(state));
1350
+
1351
+ one.join();
1352
+ two.join();
1353
+ }
1354
+
1355
+ namespace {
1356
+ template <template <typename> class Atom = std::atomic>
1357
+ void stressTryLockWithConcurrentLocks(
1358
+ int numThreads, int iterations = kStressFactor) {
1359
+ auto&& threads = std::vector<std::thread>{};
1360
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
1361
+ auto&& atomic = std::atomic<std::uint64_t>{0};
1362
+
1363
+ for (auto i = 0; i < numThreads; ++i) {
1364
+ threads.push_back(DSched::thread([&] {
1365
+ for (auto j = 0; j < iterations; ++j) {
1366
+ auto state = mutex.lock();
1367
+ EXPECT_EQ(atomic.fetch_add(1, std::memory_order_relaxed), 0);
1368
+ EXPECT_EQ(atomic.fetch_sub(1, std::memory_order_relaxed), 1);
1369
+ mutex.unlock(std::move(state));
1370
+ }
1371
+ }));
1372
+ }
1373
+
1374
+ for (auto i = 0; i < iterations; ++i) {
1375
+ if (auto state = mutex.try_lock()) {
1376
+ EXPECT_EQ(atomic.fetch_add(1, std::memory_order_relaxed), 0);
1377
+ EXPECT_EQ(atomic.fetch_sub(1, std::memory_order_relaxed), 1);
1378
+ mutex.unlock(std::move(state));
1379
+ }
1380
+ }
1381
+
1382
+ for (auto& thread : threads) {
1383
+ DSched::join(thread);
1384
+ }
1385
+ }
1386
+ } // namespace
1387
+
1388
+ TEST(DistributedMutex, StressTryLockWithConcurrentLocksTwoThreads) {
1389
+ stressTryLockWithConcurrentLocks(2);
1390
+ }
1391
+ TEST(DistributedMutex, StressTryLockWithConcurrentLocksFourThreads) {
1392
+ stressTryLockWithConcurrentLocks(4);
1393
+ }
1394
+ TEST(DistributedMutex, StressTryLockWithConcurrentLocksEightThreads) {
1395
+ stressTryLockWithConcurrentLocks(8);
1396
+ }
1397
+ TEST(DistributedMutex, StressTryLockWithConcurrentLocksSixteenThreads) {
1398
+ stressTryLockWithConcurrentLocks(16);
1399
+ }
1400
+ TEST(DistributedMutex, StressTryLockWithConcurrentLocksThirtyTwoThreads) {
1401
+ stressTryLockWithConcurrentLocks(32);
1402
+ }
1403
+ TEST(DistributedMutex, StressTryLockWithConcurrentLocksSixtyFourThreads) {
1404
+ stressTryLockWithConcurrentLocks(64);
1405
+ }
1406
+
1407
+ TEST(DistributedMutex, DeterministicTryLockWithLocksTwoThreads) {
1408
+ auto iterations = numIterationsDeterministicTest(2);
1409
+ stressTryLockWithConcurrentLocks(2, iterations);
1410
+
1411
+ for (auto pass = 0; pass < 3; ++pass) {
1412
+ auto&& schedule = DSched{DSched::uniform(pass)};
1413
+ stressTryLockWithConcurrentLocks<test::DeterministicAtomic>(2, iterations);
1414
+ static_cast<void>(schedule);
1415
+ }
1416
+ }
1417
+ TEST(DistributedMutex, DeterministicTryLockWithFourThreads) {
1418
+ auto iterations = numIterationsDeterministicTest(4);
1419
+ stressTryLockWithConcurrentLocks(4, iterations);
1420
+
1421
+ for (auto pass = 0; pass < 3; ++pass) {
1422
+ auto&& schedule = DSched{DSched::uniform(pass)};
1423
+ stressTryLockWithConcurrentLocks<test::DeterministicAtomic>(4, iterations);
1424
+ static_cast<void>(schedule);
1425
+ }
1426
+ }
1427
+ TEST(DistributedMutex, DeterministicTryLockWithLocksEightThreads) {
1428
+ auto iterations = numIterationsDeterministicTest(8);
1429
+ stressTryLockWithConcurrentLocks(8, iterations);
1430
+
1431
+ for (auto pass = 0; pass < 3; ++pass) {
1432
+ auto&& schedule = DSched{DSched::uniform(pass)};
1433
+ stressTryLockWithConcurrentLocks<test::DeterministicAtomic>(8, iterations);
1434
+ static_cast<void>(schedule);
1435
+ }
1436
+ }
1437
+ TEST(DistributedMutex, DeterministicTryLockWithLocksSixteenThreads) {
1438
+ auto iterations = numIterationsDeterministicTest(16);
1439
+ stressTryLockWithConcurrentLocks(16, iterations);
1440
+
1441
+ for (auto pass = 0; pass < 3; ++pass) {
1442
+ auto&& schedule = DSched{DSched::uniform(pass)};
1443
+ stressTryLockWithConcurrentLocks<test::DeterministicAtomic>(16, iterations);
1444
+ static_cast<void>(schedule);
1445
+ }
1446
+ }
1447
+ TEST(DistributedMutex, DeterministicTryLockWithLocksThirtyTwoThreads) {
1448
+ auto iterations = numIterationsDeterministicTest(32);
1449
+ stressTryLockWithConcurrentLocks(32, iterations);
1450
+
1451
+ for (auto pass = 0; pass < 3; ++pass) {
1452
+ auto&& schedule = DSched{DSched::uniform(pass)};
1453
+ stressTryLockWithConcurrentLocks<test::DeterministicAtomic>(32, iterations);
1454
+ static_cast<void>(schedule);
1455
+ }
1456
+ }
1457
+ TEST(DistributedMutex, DeterministicTryLockWithLocksSixtyFourThreads) {
1458
+ stressTryLockWithConcurrentLocks(64, 5);
1459
+
1460
+ for (auto pass = 0; pass < 3; ++pass) {
1461
+ auto&& schedule = DSched{DSched::uniform(pass)};
1462
+ stressTryLockWithConcurrentLocks<test::DeterministicAtomic>(64, 5);
1463
+ static_cast<void>(schedule);
1464
+ }
1465
+ }
1466
+
1467
+ namespace {
1468
+ template <template <typename> class Atom = std::atomic>
1469
+ void concurrentTryLocks(int numThreads, int iterations = kStressFactor) {
1470
+ auto&& threads = std::vector<std::thread>{};
1471
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
1472
+ auto&& atomic = std::atomic<std::uint64_t>{0};
1473
+
1474
+ for (auto i = 0; i < numThreads; ++i) {
1475
+ threads.push_back(DSched::thread([&] {
1476
+ for (auto j = 0; j < iterations; ++j) {
1477
+ if (auto state = mutex.try_lock()) {
1478
+ EXPECT_EQ(atomic.fetch_add(1, std::memory_order_relaxed), 0);
1479
+ EXPECT_EQ(atomic.fetch_sub(1, std::memory_order_relaxed), 1);
1480
+ mutex.unlock(std::move(state));
1481
+ }
1482
+ }
1483
+ }));
1484
+ }
1485
+
1486
+ for (auto& thread : threads) {
1487
+ DSched::join(thread);
1488
+ }
1489
+ }
1490
+ } // namespace
1491
+
1492
+ TEST(DistributedMutex, StressTryLockWithTwoThreads) {
1493
+ concurrentTryLocks(2);
1494
+ }
1495
+ TEST(DistributedMutex, StressTryLockFourThreads) {
1496
+ concurrentTryLocks(4);
1497
+ }
1498
+ TEST(DistributedMutex, StressTryLockEightThreads) {
1499
+ concurrentTryLocks(8);
1500
+ }
1501
+ TEST(DistributedMutex, StressTryLockSixteenThreads) {
1502
+ concurrentTryLocks(16);
1503
+ }
1504
+ TEST(DistributedMutex, StressTryLockThirtyTwoThreads) {
1505
+ concurrentTryLocks(32);
1506
+ }
1507
+ TEST(DistributedMutex, StressTryLockSixtyFourThreads) {
1508
+ concurrentTryLocks(64);
1509
+ }
1510
+
1511
+ TEST(DistributedMutex, DeterministicTryLockTwoThreads) {
1512
+ auto iterations = numIterationsDeterministicTest(2);
1513
+ concurrentTryLocks(2, iterations);
1514
+
1515
+ for (auto pass = 0; pass < 3; ++pass) {
1516
+ auto&& schedule = DSched{DSched::uniform(pass)};
1517
+ concurrentTryLocks<test::DeterministicAtomic>(2, iterations);
1518
+ static_cast<void>(schedule);
1519
+ }
1520
+ }
1521
+ TEST(DistributedMutex, DeterministicTryLockFourThreads) {
1522
+ auto iterations = numIterationsDeterministicTest(4);
1523
+ concurrentTryLocks(4, iterations);
1524
+
1525
+ for (auto pass = 0; pass < 3; ++pass) {
1526
+ auto&& schedule = DSched{DSched::uniform(pass)};
1527
+ concurrentTryLocks<test::DeterministicAtomic>(4, iterations);
1528
+ static_cast<void>(schedule);
1529
+ }
1530
+ }
1531
+ TEST(DistributedMutex, DeterministicTryLockEightThreads) {
1532
+ auto iterations = numIterationsDeterministicTest(8);
1533
+ concurrentTryLocks(8, iterations);
1534
+
1535
+ for (auto pass = 0; pass < 3; ++pass) {
1536
+ auto&& schedule = DSched{DSched::uniform(pass)};
1537
+ concurrentTryLocks<test::DeterministicAtomic>(8, iterations);
1538
+ static_cast<void>(schedule);
1539
+ }
1540
+ }
1541
+ TEST(DistributedMutex, DeterministicTryLockSixteenThreads) {
1542
+ auto iterations = numIterationsDeterministicTest(16);
1543
+ concurrentTryLocks(16, iterations);
1544
+
1545
+ for (auto pass = 0; pass < 3; ++pass) {
1546
+ auto&& schedule = DSched{DSched::uniform(pass)};
1547
+ concurrentTryLocks<test::DeterministicAtomic>(16, iterations);
1548
+ static_cast<void>(schedule);
1549
+ }
1550
+ }
1551
+ TEST(DistributedMutex, DeterministicTryLockThirtyTwoThreads) {
1552
+ auto iterations = numIterationsDeterministicTest(32);
1553
+ concurrentTryLocks(32, iterations);
1554
+
1555
+ for (auto pass = 0; pass < 3; ++pass) {
1556
+ auto&& schedule = DSched{DSched::uniform(pass)};
1557
+ concurrentTryLocks<test::DeterministicAtomic>(32, iterations);
1558
+ static_cast<void>(schedule);
1559
+ }
1560
+ }
1561
+ TEST(DistributedMutex, DeterministicTryLockSixtyFourThreads) {
1562
+ concurrentTryLocks(64, 5);
1563
+
1564
+ for (auto pass = 0; pass < 3; ++pass) {
1565
+ auto&& schedule = DSched{DSched::uniform(pass)};
1566
+ concurrentTryLocks<test::DeterministicAtomic>(64, 5);
1567
+ static_cast<void>(schedule);
1568
+ }
1569
+ }
1570
+
1571
+ namespace {
1572
+ class TestConstruction {
1573
+ public:
1574
+ TestConstruction() = delete;
1575
+ explicit TestConstruction(int) {
1576
+ defaultConstructs().fetch_add(1, std::memory_order_relaxed);
1577
+ }
1578
+ TestConstruction(TestConstruction&&) noexcept {
1579
+ moveConstructs().fetch_add(1, std::memory_order_relaxed);
1580
+ }
1581
+ TestConstruction(const TestConstruction&) {
1582
+ copyConstructs().fetch_add(1, std::memory_order_relaxed);
1583
+ }
1584
+ TestConstruction& operator=(const TestConstruction&) {
1585
+ copyAssigns().fetch_add(1, std::memory_order_relaxed);
1586
+ return *this;
1587
+ }
1588
+ TestConstruction& operator=(TestConstruction&&) {
1589
+ moveAssigns().fetch_add(1, std::memory_order_relaxed);
1590
+ return *this;
1591
+ }
1592
+ ~TestConstruction() { destructs().fetch_add(1, std::memory_order_relaxed); }
1593
+
1594
+ static std::atomic<std::uint64_t>& defaultConstructs() {
1595
+ static auto&& atomic = std::atomic<std::uint64_t>{0};
1596
+ return atomic;
1597
+ }
1598
+ static std::atomic<std::uint64_t>& moveConstructs() {
1599
+ static auto&& atomic = std::atomic<std::uint64_t>{0};
1600
+ return atomic;
1601
+ }
1602
+ static std::atomic<std::uint64_t>& copyConstructs() {
1603
+ static auto&& atomic = std::atomic<std::uint64_t>{0};
1604
+ return atomic;
1605
+ }
1606
+ static std::atomic<std::uint64_t>& moveAssigns() {
1607
+ static auto&& atomic = std::atomic<std::uint64_t>{0};
1608
+ return atomic;
1609
+ }
1610
+ static std::atomic<std::uint64_t>& copyAssigns() {
1611
+ static auto&& atomic = std::atomic<std::uint64_t>{0};
1612
+ return atomic;
1613
+ }
1614
+ static std::atomic<std::uint64_t>& destructs() {
1615
+ static auto&& atomic = std::atomic<std::uint64_t>{0};
1616
+ return atomic;
1617
+ }
1618
+
1619
+ static void reset() {
1620
+ defaultConstructs().store(0);
1621
+ moveConstructs().store(0);
1622
+ copyConstructs().store(0);
1623
+ copyAssigns().store(0);
1624
+ destructs().store(0);
1625
+ }
1626
+ };
1627
+ } // namespace
1628
+
1629
+ TEST(DistributedMutex, TestAppropriateDestructionAndConstructionWithCombine) {
1630
+ auto&& mutex = folly::DistributedMutex{};
1631
+ auto&& stop = std::atomic<bool>{false};
1632
+
1633
+ // test the simple return path to make sure that in the absence of
1634
+ // contention, we get the right number of constructs and destructs
1635
+ mutex.lock_combine([]() { return TestConstruction{1}; });
1636
+ auto moves = TestConstruction::moveConstructs().load();
1637
+ auto defaults = TestConstruction::defaultConstructs().load();
1638
+ EXPECT_EQ(TestConstruction::defaultConstructs().load(), 1);
1639
+ EXPECT_TRUE(moves == 0 || moves == 1);
1640
+ EXPECT_EQ(TestConstruction::destructs().load(), moves + defaults);
1641
+
1642
+ // loop and make sure we were able to test the path where the critical
1643
+ // section of the thread gets combined, and assert that we see the expected
1644
+ // number of constructions and destructions
1645
+ //
1646
+ // this implements a timed backoff to test the combined path, so we use the
1647
+ // smallest possible delay in tests
1648
+ auto thread = std::thread{[&]() {
1649
+ auto&& duration = std::chrono::milliseconds{10};
1650
+ while (!stop.load()) {
1651
+ TestConstruction::reset();
1652
+ auto&& ready = folly::Baton<>{};
1653
+ auto&& release = folly::Baton<>{};
1654
+
1655
+ // make one thread start it's critical section, signal and wait for
1656
+ // another thread to enqueue, to test the
1657
+ auto innerThread = std::thread{[&]() {
1658
+ mutex.lock_combine([&]() {
1659
+ ready.post();
1660
+ release.wait();
1661
+ /* sleep override */
1662
+ std::this_thread::sleep_for(duration);
1663
+ });
1664
+ }};
1665
+
1666
+ // wait for the thread to get in its critical section, then tell it to go
1667
+ ready.wait();
1668
+ release.post();
1669
+ mutex.lock_combine([&]() { return TestConstruction{1}; });
1670
+
1671
+ innerThread.join();
1672
+
1673
+ // at this point we should have only one default construct, either 3
1674
+ // or 4 move constructs the same number of destructions as
1675
+ // constructions
1676
+ auto innerDefaults = TestConstruction::defaultConstructs().load();
1677
+ auto innerMoves = TestConstruction::moveConstructs().load();
1678
+ auto destructs = TestConstruction::destructs().load();
1679
+ EXPECT_EQ(innerDefaults, 1);
1680
+ EXPECT_TRUE(innerMoves == 3 || innerMoves == 4 || innerMoves == 1);
1681
+ EXPECT_EQ(destructs, innerMoves + innerDefaults);
1682
+ EXPECT_EQ(TestConstruction::moveAssigns().load(), 0);
1683
+ EXPECT_EQ(TestConstruction::copyAssigns().load(), 0);
1684
+
1685
+ // increase duration by 100ms each iteration
1686
+ duration = duration + 100ms;
1687
+ }
1688
+ }};
1689
+
1690
+ /* sleep override */
1691
+ std::this_thread::sleep_for(std::chrono::seconds{kStressTestSeconds});
1692
+ stop.store(true);
1693
+ thread.join();
1694
+ }
1695
+
1696
+ namespace {
1697
+ template <template <typename> class Atom = std::atomic>
1698
+ void concurrentLocksManyMutexes(int numThreads, std::chrono::seconds duration) {
1699
+ using DMutex = detail::distributed_mutex::DistributedMutex<Atom>;
1700
+ const auto&& kNumMutexes = 10;
1701
+ auto&& threads = std::vector<std::thread>{};
1702
+ auto&& mutexes = std::vector<DMutex>(kNumMutexes);
1703
+ auto&& barriers = std::vector<std::atomic<std::uint64_t>>(kNumMutexes);
1704
+ auto&& stop = std::atomic<bool>{false};
1705
+
1706
+ for (auto i = 0; i < numThreads; ++i) {
1707
+ threads.push_back(DSched::thread([&] {
1708
+ auto&& total = std::atomic<std::uint64_t>{0};
1709
+ auto&& expected = std::uint64_t{0};
1710
+
1711
+ for (auto j = 0; !stop.load(std::memory_order_relaxed); ++j) {
1712
+ auto& mutex = mutexes[j % kNumMutexes];
1713
+ auto& barrier = barriers[j % kNumMutexes];
1714
+
1715
+ ++expected;
1716
+ auto result = mutex.lock_combine([&]() {
1717
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
1718
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 1);
1719
+ std::this_thread::yield();
1720
+ SCOPE_EXIT {
1721
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
1722
+ };
1723
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 2);
1724
+ return total.fetch_add(1, std::memory_order_relaxed);
1725
+ });
1726
+ EXPECT_EQ(result, expected - 1);
1727
+ }
1728
+
1729
+ EXPECT_EQ(total.load(), expected);
1730
+ }));
1731
+ }
1732
+
1733
+ /* sleep override */
1734
+ std::this_thread::sleep_for(duration);
1735
+ stop.store(true);
1736
+ for (auto& thread : threads) {
1737
+ DSched::join(thread);
1738
+ }
1739
+ }
1740
+ } // namespace
1741
+
1742
+ TEST(DistributedMutex, StressWithManyMutexesAlternatingTwoThreads) {
1743
+ concurrentLocksManyMutexes(2, std::chrono::seconds{kStressTestSeconds});
1744
+ }
1745
+ TEST(DistributedMutex, StressWithManyMutexesAlternatingFourThreads) {
1746
+ concurrentLocksManyMutexes(4, std::chrono::seconds{kStressTestSeconds});
1747
+ }
1748
+ TEST(DistributedMutex, StressWithManyMutexesAlternatingEightThreads) {
1749
+ concurrentLocksManyMutexes(8, std::chrono::seconds{kStressTestSeconds});
1750
+ }
1751
+ TEST(DistributedMutex, StressWithManyMutexesAlternatingSixteenThreads) {
1752
+ concurrentLocksManyMutexes(16, std::chrono::seconds{kStressTestSeconds});
1753
+ }
1754
+ TEST(DistributedMutex, StressWithManyMutexesAlternatingThirtyTwoThreads) {
1755
+ concurrentLocksManyMutexes(32, std::chrono::seconds{kStressTestSeconds});
1756
+ }
1757
+ TEST(DistributedMutex, StressWithManyMutexesAlternatingSixtyFourThreads) {
1758
+ concurrentLocksManyMutexes(64, std::chrono::seconds{kStressTestSeconds});
1759
+ }
1760
+
1761
+ namespace {
1762
+ void concurrentLocksManyMutexesDeterministic(
1763
+ int threads, std::chrono::seconds t) {
1764
+ const auto kNumPasses = 3.0;
1765
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
1766
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
1767
+
1768
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
1769
+ auto&& schedule = DSched{DSched::uniform(pass)};
1770
+ concurrentLocksManyMutexes<test::DeterministicAtomic>(threads, time);
1771
+ static_cast<void>(schedule);
1772
+ }
1773
+ }
1774
+ } // namespace
1775
+
1776
+ TEST(DistributedMutex, DeterministicWithManyMutexesAlternatingTwoThreads) {
1777
+ concurrentLocksManyMutexesDeterministic(
1778
+ 2, std::chrono::seconds{kStressTestSeconds});
1779
+ }
1780
+ TEST(DistributedMutex, DeterministicWithManyMutexesAlternatingFourThreads) {
1781
+ concurrentLocksManyMutexesDeterministic(
1782
+ 4, std::chrono::seconds{kStressTestSeconds});
1783
+ }
1784
+ TEST(DistributedMutex, DeterministicWithManyMutexesAlternatingEightThreads) {
1785
+ concurrentLocksManyMutexesDeterministic(
1786
+ 8, std::chrono::seconds{kStressTestSeconds});
1787
+ }
1788
+ TEST(DistributedMutex, DeterministicWithManyMutexesAlternatingSixteenThreads) {
1789
+ concurrentLocksManyMutexesDeterministic(
1790
+ 16, std::chrono::seconds{kStressTestSeconds});
1791
+ }
1792
+ TEST(DistributedMutex, DeterministicWithManyMtxAlternatingThirtyTwoThreads) {
1793
+ concurrentLocksManyMutexesDeterministic(
1794
+ 32, std::chrono::seconds{kStressTestSeconds});
1795
+ }
1796
+ TEST(DistributedMutex, DeterministicWithManyMtxAlternatingSixtyFourThreads) {
1797
+ concurrentLocksManyMutexesDeterministic(
1798
+ 64, std::chrono::seconds{kStressTestSeconds});
1799
+ }
1800
+
1801
+ namespace {
1802
+ class ExceptionWithConstructionTrack : public std::exception {
1803
+ public:
1804
+ explicit ExceptionWithConstructionTrack(int id)
1805
+ : id_{folly::to<std::string>(id)}, constructionTrack_{id} {}
1806
+
1807
+ const char* what() const noexcept override { return id_.c_str(); }
1808
+
1809
+ private:
1810
+ std::string id_;
1811
+ TestConstruction constructionTrack_;
1812
+ };
1813
+ } // namespace
1814
+
1815
+ TEST(DistributedMutex, TestExceptionPropagationUncontended) {
1816
+ TestConstruction::reset();
1817
+ auto&& mutex = folly::DistributedMutex{};
1818
+
1819
+ auto&& thread = std::thread{[&]() {
1820
+ try {
1821
+ mutex.lock_combine([&]() { throw ExceptionWithConstructionTrack{46}; });
1822
+ } catch (std::exception& exc) {
1823
+ auto integer = folly::to<std::uint64_t>(exc.what());
1824
+ EXPECT_EQ(integer, 46);
1825
+ EXPECT_GT(TestConstruction::defaultConstructs(), 0);
1826
+ }
1827
+
1828
+ EXPECT_EQ(
1829
+ TestConstruction::defaultConstructs(), TestConstruction::destructs());
1830
+ }};
1831
+
1832
+ thread.join();
1833
+ }
1834
+
1835
+ namespace {
1836
+ template <template <typename> class Atom = std::atomic>
1837
+ void concurrentExceptionPropagationStress(
1838
+ int numThreads, std::chrono::milliseconds t) {
1839
+ // This test inexplicably aborts when ran under TSAN. TSAN reports a
1840
+ // read-write race where the exception is freed by the lock-holder / combiner
1841
+ // thread and read concurrently by the thread that requested the combine
1842
+ // operation.
1843
+ //
1844
+ // TSAN reports a similar read-write race for this code as well
1845
+ // https://gist.github.com/aary/a14ae8d008e1d48a0f2d61582209f217. Which is
1846
+ // easier to verify as being correct. Though this does not conclusively
1847
+ // prove that this test and implementation are race-free, the above repro
1848
+ // combined with error-free stress runs of this test under other modes
1849
+ // (debug and optimized builds with and without both ASAN and UBSAN) give us a
1850
+ // high signal at TSAN's error being a false-positive.
1851
+ //
1852
+ // So we are disabling it for now until some point in the future where TSAN
1853
+ // stops reporting this as a false-positive.
1854
+ SKIP_IF(folly::kIsSanitizeThread);
1855
+
1856
+ TestConstruction::reset();
1857
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
1858
+ auto&& threads = std::vector<std::thread>{};
1859
+ auto&& stop = std::atomic<bool>{false};
1860
+ auto&& barrier = std::atomic<std::uint64_t>{0};
1861
+
1862
+ for (auto i = 0; i < numThreads; ++i) {
1863
+ threads.push_back(DSched::thread([&]() {
1864
+ for (auto j = 0; !stop.load(); ++j) {
1865
+ auto value = int{0};
1866
+ try {
1867
+ value = mutex.lock_combine([&]() {
1868
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
1869
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 1);
1870
+ std::this_thread::yield();
1871
+ SCOPE_EXIT {
1872
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
1873
+ };
1874
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 2);
1875
+
1876
+ // we only throw an exception once every 3 times
1877
+ if (!(j % 3)) {
1878
+ throw ExceptionWithConstructionTrack{j};
1879
+ }
1880
+
1881
+ return j;
1882
+ });
1883
+ } catch (std::exception& exc) {
1884
+ value = folly::to<int>(exc.what());
1885
+ }
1886
+
1887
+ EXPECT_EQ(value, j);
1888
+ }
1889
+ }));
1890
+ }
1891
+
1892
+ /* sleep override */
1893
+ std::this_thread::sleep_for(t);
1894
+ stop.store(true);
1895
+ for (auto& thread : threads) {
1896
+ DSched::join(thread);
1897
+ }
1898
+ }
1899
+ } // namespace
1900
+
1901
+ TEST(DistributedMutex, TestExceptionPropagationStressTwoThreads) {
1902
+ concurrentExceptionPropagationStress(
1903
+ 2, std::chrono::seconds{kStressTestSeconds});
1904
+ }
1905
+ TEST(DistributedMutex, TestExceptionPropagationStressFourThreads) {
1906
+ concurrentExceptionPropagationStress(
1907
+ 4, std::chrono::seconds{kStressTestSeconds});
1908
+ }
1909
+ TEST(DistributedMutex, TestExceptionPropagationStressEightThreads) {
1910
+ concurrentExceptionPropagationStress(
1911
+ 8, std::chrono::seconds{kStressTestSeconds});
1912
+ }
1913
+ TEST(DistributedMutex, TestExceptionPropagationStressSixteenThreads) {
1914
+ concurrentExceptionPropagationStress(
1915
+ 16, std::chrono::seconds{kStressTestSeconds});
1916
+ }
1917
+ TEST(DistributedMutex, TestExceptionPropagationStressThirtyTwoThreads) {
1918
+ concurrentExceptionPropagationStress(
1919
+ 32, std::chrono::seconds{kStressTestSeconds});
1920
+ }
1921
+ TEST(DistributedMutex, TestExceptionPropagationStressSixtyFourThreads) {
1922
+ concurrentExceptionPropagationStress(
1923
+ 64, std::chrono::seconds{kStressTestSeconds});
1924
+ }
1925
+
1926
+ namespace {
1927
+ void concurrentExceptionPropagationDeterministic(
1928
+ int threads, std::chrono::seconds t) {
1929
+ const auto kNumPasses = 3.0;
1930
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
1931
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
1932
+
1933
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
1934
+ auto&& schedule = DSched{DSched::uniform(pass)};
1935
+ concurrentExceptionPropagationStress<test::DeterministicAtomic>(
1936
+ threads, time);
1937
+ static_cast<void>(schedule);
1938
+ }
1939
+ }
1940
+ } // namespace
1941
+
1942
+ TEST(DistributedMutex, TestExceptionPropagationDeterministicTwoThreads) {
1943
+ concurrentExceptionPropagationDeterministic(
1944
+ 2, std::chrono::seconds{kStressTestSeconds});
1945
+ }
1946
+ TEST(DistributedMutex, TestExceptionPropagationDeterministicFourThreads) {
1947
+ concurrentExceptionPropagationDeterministic(
1948
+ 4, std::chrono::seconds{kStressTestSeconds});
1949
+ }
1950
+ TEST(DistributedMutex, TestExceptionPropagationDeterministicEightThreads) {
1951
+ concurrentExceptionPropagationDeterministic(
1952
+ 8, std::chrono::seconds{kStressTestSeconds});
1953
+ }
1954
+ TEST(DistributedMutex, TestExceptionPropagationDeterministicSixteenThreads) {
1955
+ concurrentExceptionPropagationDeterministic(
1956
+ 16, std::chrono::seconds{kStressTestSeconds});
1957
+ }
1958
+ TEST(DistributedMutex, TestExceptionPropagationDeterministicThirtyTwoThreads) {
1959
+ concurrentExceptionPropagationDeterministic(
1960
+ 32, std::chrono::seconds{kStressTestSeconds});
1961
+ }
1962
+ TEST(DistributedMutex, TestExceptionPropagationDeterministicSixtyFourThreads) {
1963
+ concurrentExceptionPropagationDeterministic(
1964
+ 64, std::chrono::seconds{kStressTestSeconds});
1965
+ }
1966
+
1967
+ namespace {
1968
+ std::array<std::uint64_t, 8> makeMonotonicArray(int start) {
1969
+ auto array = std::array<std::uint64_t, 8>{};
1970
+ folly::for_each(array, [&](auto& element) { element = start++; });
1971
+ return array;
1972
+ }
1973
+
1974
+ template <template <typename> class Atom = std::atomic>
1975
+ void concurrentBigValueReturnStress(
1976
+ int numThreads, std::chrono::milliseconds t) {
1977
+ auto&& mutex = detail::distributed_mutex::DistributedMutex<Atom>{};
1978
+ auto&& threads = std::vector<std::thread>{};
1979
+ auto&& stop = std::atomic<bool>{false};
1980
+ auto&& barrier = std::atomic<std::uint64_t>{0};
1981
+
1982
+ for (auto i = 0; i < numThreads; ++i) {
1983
+ threads.push_back(DSched::thread([&]() {
1984
+ auto&& value = std::atomic<std::uint64_t>{0};
1985
+
1986
+ while (!stop.load()) {
1987
+ auto returned = mutex.lock_combine([&]() {
1988
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 0);
1989
+ EXPECT_EQ(barrier.fetch_add(1, std::memory_order_relaxed), 1);
1990
+ std::this_thread::yield();
1991
+ // return an entire cacheline worth of data
1992
+ auto current = value.fetch_add(1, std::memory_order_relaxed);
1993
+ SCOPE_EXIT {
1994
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 1);
1995
+ };
1996
+ EXPECT_EQ(barrier.fetch_sub(1, std::memory_order_relaxed), 2);
1997
+ return makeMonotonicArray(current);
1998
+ });
1999
+
2000
+ auto expected = value.load() - 1;
2001
+ folly::for_each(
2002
+ returned, [&](auto& element) { EXPECT_EQ(element, expected++); });
2003
+ }
2004
+ }));
2005
+ }
2006
+
2007
+ /* sleep override */
2008
+ std::this_thread::sleep_for(t);
2009
+ stop.store(true);
2010
+ for (auto& thread : threads) {
2011
+ DSched::join(thread);
2012
+ }
2013
+ }
2014
+ } // namespace
2015
+
2016
+ TEST(DistributedMutex, StressBigValueReturnTwoThreads) {
2017
+ concurrentBigValueReturnStress(2, std::chrono::seconds{kStressTestSeconds});
2018
+ }
2019
+ TEST(DistributedMutex, StressBigValueReturnFourThreads) {
2020
+ concurrentBigValueReturnStress(4, std::chrono::seconds{kStressTestSeconds});
2021
+ }
2022
+ TEST(DistributedMutex, StressBigValueReturnEightThreads) {
2023
+ concurrentBigValueReturnStress(8, std::chrono::seconds{kStressTestSeconds});
2024
+ }
2025
+ TEST(DistributedMutex, StressBigValueReturnSixteenThreads) {
2026
+ concurrentBigValueReturnStress(16, std::chrono::seconds{kStressTestSeconds});
2027
+ }
2028
+ TEST(DistributedMutex, StressBigValueReturnThirtyTwoThreads) {
2029
+ concurrentBigValueReturnStress(32, std::chrono::seconds{kStressTestSeconds});
2030
+ }
2031
+ TEST(DistributedMutex, StressBigValueReturnSixtyFourThreads) {
2032
+ concurrentBigValueReturnStress(64, std::chrono::seconds{kStressTestSeconds});
2033
+ }
2034
+
2035
+ namespace {
2036
+ void concurrentBigValueReturnDeterministic(
2037
+ int threads, std::chrono::seconds t) {
2038
+ const auto kNumPasses = 3.0;
2039
+ const auto seconds = std::ceil(static_cast<double>(t.count()) / kNumPasses);
2040
+ const auto time = std::chrono::seconds{static_cast<std::uint64_t>(seconds)};
2041
+
2042
+ for (auto pass = 0; pass < kNumPasses; ++pass) {
2043
+ auto&& schedule = DSched{DSched::uniform(pass)};
2044
+ concurrentBigValueReturnStress<test::DeterministicAtomic>(threads, time);
2045
+ static_cast<void>(schedule);
2046
+ }
2047
+ }
2048
+ } // namespace
2049
+
2050
+ TEST(DistributedMutex, DeterministicBigValueReturnTwoThreads) {
2051
+ concurrentBigValueReturnDeterministic(
2052
+ 2, std::chrono::seconds{kStressTestSeconds});
2053
+ }
2054
+ TEST(DistributedMutex, DeterministicBigValueReturnFourThreads) {
2055
+ concurrentBigValueReturnDeterministic(
2056
+ 4, std::chrono::seconds{kStressTestSeconds});
2057
+ }
2058
+ TEST(DistributedMutex, DeterministicBigValueReturnEightThreads) {
2059
+ concurrentBigValueReturnDeterministic(
2060
+ 8, std::chrono::seconds{kStressTestSeconds});
2061
+ }
2062
+ TEST(DistributedMutex, DeterministicBigValueReturnSixteenThreads) {
2063
+ concurrentBigValueReturnDeterministic(
2064
+ 16, std::chrono::seconds{kStressTestSeconds});
2065
+ }
2066
+ TEST(DistributedMutex, DeterministicBigValueReturnThirtyTwoThreads) {
2067
+ concurrentBigValueReturnDeterministic(
2068
+ 32, std::chrono::seconds{kStressTestSeconds});
2069
+ }
2070
+ TEST(DistributedMutex, DeterministicBigValueReturnSixtyFourThreads) {
2071
+ concurrentBigValueReturnDeterministic(
2072
+ 64, std::chrono::seconds{kStressTestSeconds});
2073
+ }
2074
+ } // namespace folly