• Experimental futex mutex test, c++20...

    From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sun Apr 14 12:53:01 2024
    From Newsgroup: comp.lang.c++

    This is a quick and dirty impl of a mutex using c++20 futexes for slow paths... Now, before I go any further, can anybody else compile and run
    the following code of mine? Thanks:

    _______________________________________

    #include <iostream>
    #include <functional>
    #include <atomic>
    #include <thread>

    #include <cstdlib>


    // Ughh, some quick test params...
    #define CT_L2_CACHE 128UL
    #define CT_THREAD_N 8UL
    #define CT_ITER_N 10000000UL


    struct alignas(CT_L2_CACHE) ct_futex_mutex
    {
    std::atomic<unsigned int> m_state = 0;

    void lock()
    {
    if (m_state.exchange(1, std::memory_order_acquire))
    {
    while (m_state.exchange(2, std::memory_order_acquire))
    {
    m_state.wait(2, std::memory_order_relaxed);
    }
    }
    }

    void unlock()
    {
    if (m_state.exchange(0, std::memory_order_release) == 2)
    {
    m_state.notify_one();
    }
    }
    };


    struct alignas(CT_L2_CACHE) ct_test_vars
    {
    long m_v0 = 0;
    long m_v1 = 0;
    long m_v2 = 0;

    void update()
    {
    m_v0 += 1;
    m_v1 += 1;
    m_v2 += 2;
    }

    void dump_state()
    {
    std::cout << "ct_test_vars::dump_state()\n";
    std::cout << "__________________________\n";
    std::cout << "m_v0 = " << m_v0 << "\n";
    std::cout << "m_v1 = " << m_v1 << "\n";
    std::cout << "m_v2 = " << m_v2 << "\n";
    std::cout << "__________________________\n" << std::endl;
    }
    };


    struct ct_shared
    {
    ct_futex_mutex m_futex_mutex;
    ct_test_vars m_test_vars;

    void dump_state()
    {
    std::cout << "ct_shared::dump_state()\n";
    m_test_vars.dump_state();
    }

    bool check_state()
    {
    if (m_test_vars.m_v0 == CT_ITER_N * CT_THREAD_N &&
    m_test_vars.m_v1 == CT_ITER_N * CT_THREAD_N &&
    m_test_vars.m_v2 == CT_ITER_N * CT_THREAD_N * 2)
    {
    return true;
    }

    return false;
    }
    };


    void ct_thread(ct_shared& shared)
    {
    for (unsigned long i = 0; i < CT_ITER_N; ++i)
    {
    shared.m_futex_mutex.lock();
    shared.m_test_vars.update();
    shared.m_futex_mutex.unlock();
    }
    }


    int main()
    {
    std::cout << "ct_c++20_futex_test\n\n";
    std::cout << "__________________________________\n\n" << std::endl;

    {
    ct_shared shared;

    std::cout << "Creating Threads..." << std::endl;

    std::thread threads[CT_THREAD_N];

    for (unsigned long i = 0; i < CT_THREAD_N; ++i)
    {
    threads[i] = std::thread(ct_thread, std::ref(shared));
    }

    std::cout << "Running...\n" << std::endl;

    for (unsigned long i = 0; i < CT_THREAD_N; ++i)
    {
    threads[i].join();
    }

    shared.dump_state();

    if (! shared.check_state())
    {
    std::cout << "OH SHIT!!!!! The crap sure hit the fan!!!\n";
    }
    }

    std::cout << "Complete!" << std::endl;

    return EXIT_SUCCESS;
    }

    _______________________________________

    --- Synchronet 3.20a-Linux NewsLink 1.114