Skip to content

Commit 0990fa9

Browse files
authored
Merge pull request #33647 from mikeash/shrink-concurrentreadablehashmap
[Runtime] Shrink ConcurrentReadableHashMap a bit.
2 parents c48a676 + 4cd1b71 commit 0990fa9

File tree

2 files changed

+37
-29
lines changed

2 files changed

+37
-29
lines changed

include/swift/Runtime/Concurrent.h

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -635,30 +635,49 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
635635
std::atomic<Index> &at(size_t i) { return (&Mask)[i]; }
636636
};
637637

638+
/// A simple linked list representing pointers that need to be freed.
639+
struct FreeListNode {
640+
FreeListNode *Next;
641+
void *Ptr;
642+
643+
static void add(FreeListNode **head, void *ptr) {
644+
auto *newNode = new FreeListNode{*head, ptr};
645+
*head = newNode;
646+
}
647+
648+
static void freeAll(FreeListNode **head) {
649+
auto *node = *head;
650+
while (node) {
651+
auto *next = node->Next;
652+
free(node->Ptr);
653+
delete node;
654+
node = next;
655+
}
656+
*head = nullptr;
657+
}
658+
};
659+
638660
/// The number of readers currently active, equal to the number of snapshot
639661
/// objects currently alive.
640-
std::atomic<size_t> ReaderCount;
662+
std::atomic<uint32_t> ReaderCount{0};
641663

642664
/// The number of elements in the elements array.
643-
std::atomic<size_t> ElementCount;
665+
std::atomic<uint32_t> ElementCount{0};
644666

645667
/// The array of elements.
646-
std::atomic<ElemTy *> Elements;
668+
std::atomic<ElemTy *> Elements{nullptr};
647669

648670
/// The array of indices.
649-
std::atomic<IndexStorage *> Indices;
671+
std::atomic<IndexStorage *> Indices{nullptr};
650672

651673
/// The writer lock, which must be taken before any mutation of the table.
652674
Mutex WriterLock;
653675

654676
/// The maximum number of elements that the current elements array can hold.
655-
size_t ElementCapacity;
677+
uint32_t ElementCapacity{0};
656678

657-
/// The list of element arrays to be freed once no readers are active.
658-
std::vector<ElemTy *> ElementFreeList;
659-
660-
/// The list of index arrays to be freed once no readers are active.
661-
std::vector<IndexStorage *> IndicesFreeList;
679+
/// The list of pointers to be freed once no readers are active.
680+
FreeListNode *FreeList{nullptr};
662681

663682
void incrementReaders() {
664683
ReaderCount.fetch_add(1, std::memory_order_acquire);
@@ -668,24 +687,11 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
668687
ReaderCount.fetch_sub(1, std::memory_order_release);
669688
}
670689

671-
/// Free all the arrays in the free lists.
672-
void deallocateFreeList() {
673-
for (auto *storage : ElementFreeList)
674-
free(storage);
675-
ElementFreeList.clear();
676-
ElementFreeList.shrink_to_fit();
677-
678-
for (auto *indices : IndicesFreeList)
679-
free(indices);
680-
IndicesFreeList.clear();
681-
IndicesFreeList.shrink_to_fit();
682-
}
683-
684690
/// Free all the arrays in the free lists if there are no active readers. If
685691
/// there are active readers, do nothing.
686692
void deallocateFreeListIfSafe() {
687693
if (ReaderCount.load(std::memory_order_acquire) == 0)
688-
deallocateFreeList();
694+
FreeListNode::freeAll(&FreeList);
689695
}
690696

691697
/// Grow the elements array, adding the old array to the free list and
@@ -702,7 +708,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
702708
ElemTy *newElements = static_cast<ElemTy *>(malloc(newSize));
703709
if (elements) {
704710
memcpy(newElements, elements, elementCount * sizeof(ElemTy));
705-
ElementFreeList.push_back(elements);
711+
FreeListNode::add(&FreeList, elements);
706712
}
707713

708714
ElementCapacity = newCapacity;
@@ -739,7 +745,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
739745

740746
Indices.store(newIndices, std::memory_order_release);
741747

742-
IndicesFreeList.push_back(indices);
748+
FreeListNode::add(&FreeList, indices);
743749

744750
return newIndices;
745751
}
@@ -792,7 +798,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
792798
~ConcurrentReadableHashMap() {
793799
assert(ReaderCount.load(std::memory_order_acquire) == 0 &&
794800
"deallocating ConcurrentReadableHashMap with outstanding snapshots");
795-
deallocateFreeList();
801+
FreeListNode::freeAll(&FreeList);
796802
}
797803

798804
/// Readers take a snapshot of the hash map, then work with the snapshot.
@@ -943,8 +949,8 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
943949
Elements.store(nullptr, std::memory_order_relaxed);
944950
ElementCapacity = 0;
945951

946-
IndicesFreeList.push_back(indices);
947-
ElementFreeList.push_back(elements);
952+
FreeListNode::add(&FreeList, indices);
953+
FreeListNode::add(&FreeList, elements);
948954

949955
deallocateFreeListIfSafe();
950956
}

test/stdlib/symbol-visibility-linux.test-sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA80_cEEEvv \
3232
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA88_cEEEvv \
3333
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA104_cEEEvv \
34+
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA168_cEEEvv \
3435
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA216_cEEEvv \
3536
// RUN: -e _ZN9__gnu_cxx12__to_xstringISscEET_PFiPT0_mPKS2_P13__va_list_tagEmS5_z \
3637
// RUN: > %t/swiftCore-all.txt
@@ -55,6 +56,7 @@
5556
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA80_cEEEvv \
5657
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA88_cEEEvv \
5758
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA104_cEEEvv \
59+
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA168_cEEEvv \
5860
// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA216_cEEEvv \
5961
// RUN: -e _ZN9__gnu_cxx12__to_xstringISscEET_PFiPT0_mPKS2_P13__va_list_tagEmS5_z \
6062
// RUN: > %t/swiftRemoteMirror-all.txt

0 commit comments

Comments
 (0)