200            TIBase::ResetStatesGuard rsg{
true};
 
  203            BEAST_EXPECT(b.use_count() == 1);
 
  205            BEAST_EXPECT(b.use_count() == 1);
 
  206            auto s = b.releaseStrongRef();
 
  208            BEAST_EXPECT(b.use_count() == 0);
 
  212            auto w = b.releaseWeakRef();
 
  219            TIBase::ResetStatesGuard rsg{
true};
 
  221            using enum TrackedState;
 
  222            auto b = make_SharedIntrusive<TIBase>();
 
  224            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  225            BEAST_EXPECT(b->use_count() == 1);
 
  226            for (
int i = 0; i < 10; ++i)
 
  231            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  233            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  235            BEAST_EXPECT(TIBase::getState(
id) == deleted);
 
  237            b = make_SharedIntrusive<TIBase>();
 
  239            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  240            BEAST_EXPECT(b->use_count() == 1);
 
  241            for (
int i = 0; i < 10; ++i)
 
  244                BEAST_EXPECT(b->use_count() == 1);
 
  246            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  248            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  250            BEAST_EXPECT(TIBase::getState(
id) == partiallyDeleted);
 
  251            while (!weak.
empty())
 
  255                    BEAST_EXPECT(TIBase::getState(
id) == partiallyDeleted);
 
  257            BEAST_EXPECT(TIBase::getState(
id) == deleted);
 
  260            TIBase::ResetStatesGuard rsg{
true};
 
  262            using enum TrackedState;
 
  263            auto b = make_SharedIntrusive<TIBase>();
 
  265            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  267            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  269            BEAST_EXPECT(s && s->use_count() == 2);
 
  271            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  272            BEAST_EXPECT(s && s->use_count() == 1);
 
  274            BEAST_EXPECT(TIBase::getState(
id) == partiallyDeleted);
 
  275            BEAST_EXPECT(w.expired());
 
  281            BEAST_EXPECT(TIBase::getState(
id) == deleted);
 
  284            TIBase::ResetStatesGuard rsg{
true};
 
  286            using enum TrackedState;
 
  288            swu b = make_SharedIntrusive<TIBase>();
 
  289            BEAST_EXPECT(b.isStrong() && b.use_count() == 1);
 
  290            auto id = b.get()->id_;
 
  291            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  293            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  294            BEAST_EXPECT(w.isStrong() && b.use_count() == 2);
 
  296            BEAST_EXPECT(w.isWeak() && b.use_count() == 1);
 
  298            BEAST_EXPECT(s.isWeak() && b.use_count() == 1);
 
  300            BEAST_EXPECT(s.isStrong() && b.use_count() == 2);
 
  302            BEAST_EXPECT(TIBase::getState(
id) == alive);
 
  303            BEAST_EXPECT(s.use_count() == 1);
 
  304            BEAST_EXPECT(!w.expired());
 
  306            BEAST_EXPECT(TIBase::getState(
id) == partiallyDeleted);
 
  307            BEAST_EXPECT(w.expired());
 
  311            BEAST_EXPECT(w.isWeak());
 
  313            BEAST_EXPECT(TIBase::getState(
id) == deleted);
 
  318            TIBase::ResetStatesGuard rsg{
true};
 
  320            auto strong1 = make_SharedIntrusive<TIBase>();
 
  321            auto strong2 = make_SharedIntrusive<TIBase>();
 
  323            auto id1 = strong1->id_;
 
  324            auto id2 = strong2->id_;
 
  326            BEAST_EXPECT(id1 != id2);
 
  333            BEAST_EXPECT(union1.
get() == strong1.get());
 
  334            BEAST_EXPECT(union2.
get() == strong2.get());
 
  340            BEAST_EXPECT(union1.
get() == union2.
get());
 
  341            BEAST_EXPECT(TIBase::getState(id1) == TrackedState::alive);
 
  342            BEAST_EXPECT(TIBase::getState(id2) == TrackedState::alive);
 
  346            BEAST_EXPECT(TIBase::getState(id1) == TrackedState::alive);
 
  347            int initialRefCount = strong1->use_count();
 
  348#pragma clang diagnostic push 
  349#pragma clang diagnostic ignored "-Wself-assign-overloaded" 
  351#pragma clang diagnostic pop 
  353            BEAST_EXPECT(TIBase::getState(id1) == TrackedState::alive);
 
  354            BEAST_EXPECT(strong1->use_count() == initialRefCount);
 
  358            BEAST_EXPECT(union1.
get() == 
nullptr);
 
  364            BEAST_EXPECT(union1.
get() == 
nullptr);
 
  365            BEAST_EXPECT(TIBase::getState(id2) == TrackedState::deleted);
 
 
  381        using enum TrackedState;
 
  383        TIBase::ResetStatesGuard rsg{
true};
 
  385        auto strong = make_SharedIntrusive<TIBase>();
 
  387        bool destructorRan = 
false;
 
  388        bool partialDeleteRan = 
false;
 
  390        strong->tracingCallback_ = [&](TrackedState cur,
 
  392            using enum TrackedState;
 
  393            if (next == deletedStarted)
 
  400                BEAST_EXPECT(cur == partiallyDeleted);
 
  402            if (next == partiallyDeletedStarted)
 
  404                partialDeleteStartedSyncPoint.arrive_and_wait();
 
  405                using namespace std::chrono_literals;
 
  411            if (next == partiallyDeleted)
 
  413                BEAST_EXPECT(!partialDeleteRan && !destructorRan);
 
  414                partialDeleteRan = 
true;
 
  418                BEAST_EXPECT(!destructorRan);
 
  419                destructorRan = 
true;
 
  423            partialDeleteStartedSyncPoint.arrive_and_wait();
 
  433        BEAST_EXPECT(destructorRan && partialDeleteRan);
 
 
  449        using enum TrackedState;
 
  451        TIBase::ResetStatesGuard rsg{
true};
 
  453        auto strong = make_SharedIntrusive<TIBase>();
 
  455        bool destructorRan = 
false;
 
  456        bool partialDeleteRan = 
false;
 
  458        strong->tracingCallback_ = [&](TrackedState cur,
 
  460            using enum TrackedState;
 
  461            if (next == partiallyDeleted)
 
  463                BEAST_EXPECT(!partialDeleteRan && !destructorRan);
 
  464                partialDeleteRan = 
true;
 
  468                BEAST_EXPECT(!destructorRan);
 
  469                destructorRan = 
true;
 
  474            weakResetSyncPoint.arrive_and_wait();
 
  477            weakResetSyncPoint.arrive_and_wait();
 
  483        BEAST_EXPECT(destructorRan && !partialDeleteRan);
 
 
  489        testcase(
"Multithreaded Clear Mixed Variant");
 
  496        using enum TrackedState;
 
  497        TIBase::ResetStatesGuard rsg{
true};
 
  503            return {(s & 1) != 0, (s & 2) != 0};
 
  505        auto setDestructorRan = [&]() -> 
void {
 
  508        auto setPartialDeleteRan = [&]() -> 
void {
 
  511        auto tracingCallback = [&](TrackedState cur,
 
  513            using enum TrackedState;
 
  514            auto [destructorRan, partialDeleteRan] = getDestructorState();
 
  515            if (next == partiallyDeleted)
 
  517                BEAST_EXPECT(!partialDeleteRan && !destructorRan);
 
  518                setPartialDeleteRan();
 
  522                BEAST_EXPECT(!destructorRan);
 
  526        auto createVecOfPointers = [&](
auto const& toClone,
 
  535            auto numToCreate = toCreateDist(eng);
 
  536            result.reserve(numToCreate);
 
  537            for (
int i = 0; i < numToCreate; ++i)
 
  539                if (isStrongDist(eng))
 
  550        constexpr int loopIters = 2 * 1024;
 
  551        constexpr int numThreads = 16;
 
  553        Barrier loopStartSyncPoint{numThreads};
 
  554        Barrier postCreateToCloneSyncPoint{numThreads};
 
  555        Barrier postCreateVecOfPointersSyncPoint{numThreads};
 
  560            for (
int i = 0; i < numThreads; ++i)
 
  568        auto cloneAndDestroy = [&](
int threadId) {
 
  569            for (
int i = 0; i < loopIters; ++i)
 
  572                loopStartSyncPoint.arrive_and_wait();
 
  584                    auto [destructorRan, partialDeleteRan] =
 
  585                        getDestructorState();
 
  586                    BEAST_EXPECT(!i || destructorRan);
 
  590                    toClone.
resize(numThreads);
 
  591                    auto strong = make_SharedIntrusive<TIBase>();
 
  592                    strong->tracingCallback_ = tracingCallback;
 
  597                postCreateToCloneSyncPoint.arrive_and_wait();
 
  600                    createVecOfPointers(toClone[threadId], engines[threadId]);
 
  601                toClone[threadId].reset();
 
  604                postCreateVecOfPointersSyncPoint.arrive_and_wait();
 
  610        for (
int i = 0; i < numThreads; ++i)
 
  614        for (
int i = 0; i < numThreads; ++i)
 
 
  623        testcase(
"Multithreaded Clear Mixed Union");
 
  635        using enum TrackedState;
 
  637        TIBase::ResetStatesGuard rsg{
true};
 
  643            return {(s & 1) != 0, (s & 2) != 0};
 
  645        auto setDestructorRan = [&]() -> 
void {
 
  648        auto setPartialDeleteRan = [&]() -> 
void {
 
  651        auto tracingCallback = [&](TrackedState cur,
 
  653            using enum TrackedState;
 
  654            auto [destructorRan, partialDeleteRan] = getDestructorState();
 
  655            if (next == partiallyDeleted)
 
  657                BEAST_EXPECT(!partialDeleteRan && !destructorRan);
 
  658                setPartialDeleteRan();
 
  662                BEAST_EXPECT(!destructorRan);
 
  666        auto createVecOfPointers = [&](
auto const& toClone,
 
  671            auto numToCreate = toCreateDist(eng);
 
  673            for (
int i = 0; i < numToCreate; ++i)
 
  677        constexpr int loopIters = 2 * 1024;
 
  678        constexpr int flipPointersLoopIters = 256;
 
  679        constexpr int numThreads = 16;
 
  681        Barrier loopStartSyncPoint{numThreads};
 
  682        Barrier postCreateToCloneSyncPoint{numThreads};
 
  683        Barrier postCreateVecOfPointersSyncPoint{numThreads};
 
  684        Barrier postFlipPointersLoopSyncPoint{numThreads};
 
  689            for (
int i = 0; i < numThreads; ++i)
 
  698        auto cloneAndDestroy = [&](
int threadId) {
 
  699            for (
int i = 0; i < loopIters; ++i)
 
  702                loopStartSyncPoint.arrive_and_wait();
 
  713                    auto [destructorRan, partialDeleteRan] =
 
  714                        getDestructorState();
 
  715                    BEAST_EXPECT(!i || destructorRan);
 
  719                    toClone.
resize(numThreads);
 
  720                    auto strong = make_SharedIntrusive<TIBase>();
 
  721                    strong->tracingCallback_ = tracingCallback;
 
  726                postCreateToCloneSyncPoint.arrive_and_wait();
 
  729                    createVecOfPointers(toClone[threadId], engines[threadId]);
 
  730                toClone[threadId].reset();
 
  733                postCreateVecOfPointersSyncPoint.arrive_and_wait();
 
  736                for (
int f = 0; f < flipPointersLoopIters; ++f)
 
  740                        if (isStrongDist(engines[threadId]))
 
  752                postFlipPointersLoopSyncPoint.arrive_and_wait();
 
  758        for (
int i = 0; i < numThreads; ++i)
 
  762        for (
int i = 0; i < numThreads; ++i)
 
 
  771        testcase(
"Multithreaded Locking Weak");
 
  778        using enum TrackedState;
 
  780        TIBase::ResetStatesGuard rsg{
true};
 
  786            return {(s & 1) != 0, (s & 2) != 0};
 
  788        auto setDestructorRan = [&]() -> 
void {
 
  791        auto setPartialDeleteRan = [&]() -> 
void {
 
  794        auto tracingCallback = [&](TrackedState cur,
 
  796            using enum TrackedState;
 
  797            auto [destructorRan, partialDeleteRan] = getDestructorState();
 
  798            if (next == partiallyDeleted)
 
  800                BEAST_EXPECT(!partialDeleteRan && !destructorRan);
 
  801                setPartialDeleteRan();
 
  805                BEAST_EXPECT(!destructorRan);
 
  810        constexpr int loopIters = 2 * 1024;
 
  811        constexpr int lockWeakLoopIters = 256;
 
  812        constexpr int numThreads = 16;
 
  814        Barrier loopStartSyncPoint{numThreads};
 
  815        Barrier postCreateToLockSyncPoint{numThreads};
 
  816        Barrier postLockWeakLoopSyncPoint{numThreads};
 
  821        auto lockAndDestroy = [&](
int threadId) {
 
  822            for (
int i = 0; i < loopIters; ++i)
 
  836                    auto [destructorRan, partialDeleteRan] =
 
  837                        getDestructorState();
 
  838                    BEAST_EXPECT(!i || destructorRan);
 
  842                    toLock.
resize(numThreads);
 
  843                    auto strong = make_SharedIntrusive<TIBase>();
 
  844                    strong->tracingCallback_ = tracingCallback;
 
  849                postCreateToLockSyncPoint.arrive_and_wait();
 
  854                for (
int wi = 0; wi < lockWeakLoopIters; ++wi)
 
  856                    BEAST_EXPECT(!weak.expired());
 
  857                    auto strong = weak.lock();
 
  858                    BEAST_EXPECT(strong);
 
  862                postLockWeakLoopSyncPoint.arrive_and_wait();
 
  864                toLock[threadId].reset();
 
  868        for (
int i = 0; i < numThreads; ++i)
 
  872        for (
int i = 0; i < numThreads; ++i)