icecat: add release icecat-140.10.1-1gnu1 for ecne
This commit is contained in:
parent
a5f93cb214
commit
ff85d7c623
1256 changed files with 63469 additions and 24141 deletions
|
|
@ -43,6 +43,37 @@ ThreadSafeAutoRefCnt nsThreadSafeAutoRefCntRunner::sRefCnt;
|
|||
Atomic<uint32_t, Relaxed> nsThreadSafeAutoRefCntRunner::sIncToOne(0);
|
||||
Atomic<uint32_t, Relaxed> nsThreadSafeAutoRefCntRunner::sDecToZero(0);
|
||||
|
||||
class nsThreadSafeAutoRefCntDecrementWithLimitRunner final : public Runnable {
|
||||
public:
|
||||
static constexpr size_t kDecrementsPerThread = 1000;
|
||||
|
||||
NS_IMETHOD Run() final {
|
||||
for (size_t i = 0; i < kDecrementsPerThread; i++) {
|
||||
auto [ok, count] = sRefCnt.DecrementWithLimit<1>();
|
||||
if (!ok) {
|
||||
sLimitHits++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static ThreadSafeAutoRefCnt sRefCnt;
|
||||
// Relaxed ordering so sLimitHits doesn't affect the ordering properties of
|
||||
// DecrementWithLimit being tested.
|
||||
static Atomic<uint32_t, Relaxed> sLimitHits;
|
||||
|
||||
nsThreadSafeAutoRefCntDecrementWithLimitRunner()
|
||||
: Runnable("nsThreadSafeAutoRefCntDecrementWithLimitRunner") {}
|
||||
|
||||
private:
|
||||
~nsThreadSafeAutoRefCntDecrementWithLimitRunner() = default;
|
||||
};
|
||||
|
||||
ThreadSafeAutoRefCnt nsThreadSafeAutoRefCntDecrementWithLimitRunner::sRefCnt;
|
||||
Atomic<uint32_t, Relaxed>
|
||||
nsThreadSafeAutoRefCntDecrementWithLimitRunner::sLimitHits(0);
|
||||
|
||||
// When a refcounted object is actually owned by a cache, we may not
|
||||
// want to release the object after last reference gets released. In
|
||||
// this pattern, the cache may rely on the balance of increment to one
|
||||
|
|
@ -51,16 +82,87 @@ TEST(AutoRefCnt, ThreadSafeAutoRefCntBalance)
|
|||
{
|
||||
static const size_t kThreadCount = 4;
|
||||
nsCOMPtr<nsIThread> threads[kThreadCount];
|
||||
for (size_t i = 0; i < kThreadCount; i++) {
|
||||
nsresult rv =
|
||||
NS_NewNamedThread("AutoRefCnt Test", getter_AddRefs(threads[i]),
|
||||
new nsThreadSafeAutoRefCntRunner);
|
||||
for (auto& thread : threads) {
|
||||
nsresult rv = NS_NewNamedThread("AutoRefCnt Test", getter_AddRefs(thread),
|
||||
new nsThreadSafeAutoRefCntRunner);
|
||||
EXPECT_NS_SUCCEEDED(rv);
|
||||
}
|
||||
for (size_t i = 0; i < kThreadCount; i++) {
|
||||
threads[i]->Shutdown();
|
||||
for (const auto& thread : threads) {
|
||||
thread->Shutdown();
|
||||
}
|
||||
EXPECT_EQ(nsThreadSafeAutoRefCntRunner::sRefCnt, nsrefcnt(0));
|
||||
EXPECT_EQ(nsThreadSafeAutoRefCntRunner::sIncToOne,
|
||||
nsThreadSafeAutoRefCntRunner::sDecToZero);
|
||||
}
|
||||
|
||||
// Spawns kThreadCount threads each attempting kDecrementsPerThread
|
||||
// decrements, then verifies the final refcount is 1 and that exactly
|
||||
// aExpectedLimitHits threads hit the limit.
|
||||
// kInitial is derived from aExpectedLimitHits so that exactly
|
||||
// (kThreadCount - aExpectedLimitHits) threads can complete all their
|
||||
// decrements; the rest hit the limit.
|
||||
static void RunDecrementWithLimitThreaded(uint32_t aExpectedLimitHits) {
|
||||
static const size_t kThreadCount = 4;
|
||||
const nsrefcnt kInitial =
|
||||
(kThreadCount - aExpectedLimitHits) *
|
||||
nsThreadSafeAutoRefCntDecrementWithLimitRunner::kDecrementsPerThread +
|
||||
1;
|
||||
nsThreadSafeAutoRefCntDecrementWithLimitRunner::sRefCnt = kInitial;
|
||||
nsThreadSafeAutoRefCntDecrementWithLimitRunner::sLimitHits = 0;
|
||||
|
||||
nsCOMPtr<nsIThread> threads[kThreadCount];
|
||||
for (auto& thread : threads) {
|
||||
nsresult rv =
|
||||
NS_NewNamedThread("AutoRefCnt Test", getter_AddRefs(thread),
|
||||
new nsThreadSafeAutoRefCntDecrementWithLimitRunner);
|
||||
EXPECT_NS_SUCCEEDED(rv);
|
||||
}
|
||||
for (const auto& thread : threads) {
|
||||
thread->Shutdown();
|
||||
}
|
||||
EXPECT_EQ(nsThreadSafeAutoRefCntDecrementWithLimitRunner::sRefCnt,
|
||||
nsrefcnt(1));
|
||||
EXPECT_EQ(nsThreadSafeAutoRefCntDecrementWithLimitRunner::sLimitHits,
|
||||
uint32_t(aExpectedLimitHits));
|
||||
}
|
||||
|
||||
// Verify DecrementWithLimit with no lost updates when the limit is never hit.
|
||||
TEST(AutoRefCnt, ThreadSafeAutoRefCntDecrementWithLimitNoHit)
|
||||
{
|
||||
RunDecrementWithLimitThreaded(0);
|
||||
}
|
||||
|
||||
// Verify DecrementWithLimit correctly enforces the limit. With kInitial == 1
|
||||
// (equal to Limit), all threads hit the limit on their first attempt,
|
||||
// giving a deterministic sLimitHits == kThreadCount.
|
||||
TEST(AutoRefCnt, ThreadSafeAutoRefCntDecrementWithLimitHit)
|
||||
{
|
||||
static const size_t kThreadCount = 4;
|
||||
RunDecrementWithLimitThreaded(kThreadCount);
|
||||
}
|
||||
|
||||
// Verify DecrementWithLimit performs exactly kDecrementsPerThread successful
|
||||
// decrements before hitting the limit. Single-threaded for determinism.
|
||||
TEST(AutoRefCnt, ThreadSafeAutoRefCntDecrementWithLimitSequential)
|
||||
{
|
||||
const nsrefcnt kDecrementsPerThread =
|
||||
nsThreadSafeAutoRefCntDecrementWithLimitRunner::kDecrementsPerThread;
|
||||
// Initialize so exactly kDecrementsPerThread decrements succeed before
|
||||
// hitting the limit at 1.
|
||||
nsThreadSafeAutoRefCntDecrementWithLimitRunner::sRefCnt =
|
||||
kDecrementsPerThread + 1;
|
||||
|
||||
size_t successes = 0;
|
||||
while (true) {
|
||||
auto [ok, count] = nsThreadSafeAutoRefCntDecrementWithLimitRunner::sRefCnt
|
||||
.DecrementWithLimit<1>();
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
successes++;
|
||||
}
|
||||
|
||||
EXPECT_EQ(successes, size_t(kDecrementsPerThread));
|
||||
EXPECT_EQ(nsThreadSafeAutoRefCntDecrementWithLimitRunner::sRefCnt,
|
||||
nsrefcnt(1));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue