25 #ifndef __UT_ConcurrentClassifier__
26 #define __UT_ConcurrentClassifier__
35 #include <immintrin.h>
49 myData.setSizeNoInit(s + num_classes);
50 for (
int i = 0, ie = num_classes; i < ie; ++i)
51 myData(s + i) = (
uint32) i;
57 while (
id != parent(
id)) {
61 (value & 0xFFFFFFFF00000000ULL) | new_parent;
64 if (value != new_value)
65 myData(
id).compare_exchange_weak(value, new_value);
79 if (parent(id1) == id1)
94 uint32 r1 = rank(id1), r2 = rank(id2);
96 if (r1 > r2 || (r1 == r2 && id1 < id2))
102 uint64 old_entry = ((uint64_t) r1 << 32) | id1;
103 uint64 new_entry = ((uint64_t) r1 << 32) | id2;
105 if (!myData(id1).compare_exchange_strong(old_entry, new_entry))
109 old_entry = ((uint64_t) r2 << 32) | id2;
110 new_entry = ((uint64_t) (r2+1) << 32) | id2;
113 myData(id2).compare_exchange_weak(old_entry, new_entry);
126 const uint64 lock_flag = 1ULL << 63;
129 if ((value & lock_flag) || (
uint32) value !=
id)
134 #if defined(__i386__) || defined(__amd64__)
135 __asm__ __volatile__ (
"pause\n");
139 return myData(
id).compare_exchange_strong(value, value | lock_flag);
144 const uint64 lock_flag = 1ULL << 63;
145 myData(
id) &= ~lock_flag;
153 uint32 r1 = rank(id1), r2 = rank(id2);
154 return (r1 > r2 || (r1 == r2 && id1 < id2)) ? id1 : id2;
162 uint32 r1 = rank(id1), r2 = rank(id2);
164 if (r1 > r2 || (r1 == r2 && id1 < id2))
170 myData(id1) = ((
uint64) r1 << 32) | id2;
171 myData(id2) = ((
uint64) (r2 + ((r1 == r2) ? 1 : 0)) << 32) | id2;
181 return tbb::parallel_reduce(tbb::blocked_range<uint32>(0,
size()),
183 [&](tbb::blocked_range<uint32>
r,
uint32 total)
185 for (
uint32 i = r.begin(); i < r.end();
187 total += (i == classRoot(i));
190 }, std::plus<uint32>());
196 {
return ((
uint32) (myData[
id] >> 32)) & 0x7FFFFFFFu; }
199 uint32 parent(uint32_t
id)
const
200 {
return (uint32_t) myData(
id); }
202 using DataEntry = std::atomic<uint64>;
204 mutable DataArray myData;
bool areInSameClass(uint32 id1, uint32 id2) const
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
uint32 unionClasses(uint32 id1, uint32 id2)
unsigned long long uint64
bool try_lock(uint32 &id)
UT_ConcurrentClassifier(int32 size=0)
SYS_DECLARE_LEGACY_TR(GU_Detail)
uint32 unite_unlock(uint32 id1, uint32 id2)
uint32 classRoot(uint32 id) const
uint32 unite_index_locked(uint32 id1, uint32 id2) const
uint32 makeClass(uint32 num_classes=1)