@@ -17,12 +17,24 @@ ThreadFilter::~ThreadFilter() {
17
17
std::unique_lock<std::mutex> lock (_slot_mutex);
18
18
_slots.clear ();
19
19
}
20
-
21
20
ThreadFilter::SlotID ThreadFilter::registerThread () {
21
+ int top = _free_list_top.load (std::memory_order_acquire);
22
+ for (int i = 0 ; i < top; ++i) {
23
+ int value = _free_list[i].load (std::memory_order_relaxed);
24
+ if (value >= 0 ) {
25
+ int expected = value;
26
+ if (_free_list[i].compare_exchange_strong (expected, -1 , std::memory_order_acq_rel)) {
27
+ return value; // Successfully claimed a free slot
28
+ }
29
+ // If CAS fails, someone else claimed it, continue scanning
30
+ }
31
+ }
32
+
22
33
SlotID index = _next_index.fetch_add (1 , std::memory_order_relaxed);
23
34
if (index >= kMaxThreads ) {
24
35
return -1 ;
25
36
}
37
+
26
38
const int outer_idx = index >> kChunkShift ;
27
39
{
28
40
if (outer_idx < static_cast <int >(_slots.size ())) {
@@ -46,6 +58,10 @@ void ThreadFilter::clear() {
46
58
slot.value .store (-1 , std::memory_order_relaxed);
47
59
}
48
60
}
61
+ for (int i = 0 ; i < kFreeListSize ; ++i) {
62
+ _free_list[i].store (-1 , std::memory_order_relaxed);
63
+ }
64
+ _free_list_top.store (0 , std::memory_order_relaxed);
49
65
}
50
66
51
67
bool ThreadFilter::accept (SlotID slot_id) const {
@@ -73,9 +89,35 @@ void ThreadFilter::remove(SlotID slot_id) {
73
89
74
90
void ThreadFilter::unregisterThread (SlotID slot_id) {
75
91
if (slot_id < 0 ) return ;
92
+
76
93
int outer_idx = slot_id >> kChunkShift ;
77
94
int inner_idx = slot_id & kChunkMask ;
78
95
_slots[outer_idx][inner_idx].value .store (-1 , std::memory_order_relaxed);
96
+
97
+ constexpr int try_limit = 16 ;
98
+
99
+ int top = _free_list_top.load (std::memory_order_acquire);
100
+ int limit = top < kFreeListSize ? top : kFreeListSize ;
101
+ int tries = 0 ;
102
+
103
+ for (int i = 0 ; i < limit && tries < try_limit; ++i) {
104
+ int value = _free_list[i].load (std::memory_order_relaxed);
105
+ if (value == -1 ) {
106
+ int expected = -1 ;
107
+ if (_free_list[i].compare_exchange_strong (expected, slot_id, std::memory_order_acq_rel)) {
108
+ return ; // Successfully claimed empty spot
109
+ }
110
+ ++tries; // Only count actual CAS attempts
111
+ }
112
+ }
113
+
114
+ // Fallback: append if no empty slot found
115
+ int pos = _free_list_top.fetch_add (1 , std::memory_order_acq_rel);
116
+ if (pos < kFreeListSize ) {
117
+ _free_list[pos].store (slot_id, std::memory_order_release);
118
+ } else {
119
+ // Free list overflow: ignore
120
+ }
79
121
}
80
122
81
123
void ThreadFilter::collect (std::vector<int >& tids) const {
0 commit comments