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