Path: ...!weretis.net!feeder8.news.weretis.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: "Chris M. Thomasson" Newsgroups: comp.arch Subject: Re: Is Intel exceptionally unsuccessful as an architecture designer? Date: Mon, 23 Sep 2024 15:51:29 -0700 Organization: A noiseless patient Spider Lines: 427 Message-ID: References: <20240918190027.00003e4e@yahoo.com> <920c561c4e39e91d3730b6aab103459b@www.novabbs.org> <%dAHO.54667$S9Vb.39628@fx45.iad> <4f84910a01d7db353eedadd7c471d7d3@www.novabbs.org> <20240923105336.0000119b@yahoo.com> <6577e60bd63883d1a7bd51c717531f38@www.novabbs.org> <23d9473740db6c0ecc7e1d4a2179c75e@www.novabbs.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Tue, 24 Sep 2024 00:51:30 +0200 (CEST) Injection-Info: dont-email.me; posting-host="cc0aa948cfee330c0e613beeb38c6255"; logging-data="3032365"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19li+YLiOli3jA/YgxtSIW8howZcEGA7ZU=" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:fFnq4M93oj2HNws7WnQq4hc2ngs= In-Reply-To: Content-Language: en-US Bytes: 11868 On 9/23/2024 3:32 PM, MitchAlsup1 wrote: > On Mon, 23 Sep 2024 22:19:37 +0000, Chris M. Thomasson wrote: [...] Getting around ABA and/or DWCAS. A way, in a portable C++11 program. One of my proxy collectors can do it. It's not the only tool in the box for sure! So, well, that's that. Here is some code. Can you compile and give it a run? The missing (#include ) aside for a moment, does it compile on your end? _____________ #include #include #include #include #define CT_READERS 10 #define CT_WRITERS 5 #define CT_THREADS (CT_WRITERS + CT_READERS) #define CT_ITERS 10000000 #define CT_COLLECT 1024 // These are for debug and some statistics only... static std::atomic g_debug_alloc(0); static std::atomic g_debug_free(0); // Chris M. Thomassons single target proxy collector: // https://pastebin.com/raw/f71480694 namespace ct_proxy { struct node { std::atomic m_next; node* m_defer_next; node() { // debug only! g_debug_alloc.fetch_add(1); } ~node() { // debug only! g_debug_free.fetch_add(1); } }; class proxy { static void prv_destroy(node* n) { while (n) { node* next = n->m_defer_next; delete n; n = next; } } public: class collector { friend class proxy; private: std::atomic m_defer; std::atomic m_count; public: collector() : m_defer(nullptr), m_count(0) { } ~collector() { prv_destroy(m_defer.load(std::memory_order_relaxed)); } }; private: std::atomic m_current; std::atomic m_quiesce; node* m_defer; collector m_collectors[2]; public: proxy() : m_current(0), m_quiesce(false), m_defer(nullptr) { } ~proxy() { prv_destroy(m_defer); } private: void prv_quiesce_begin() { // Try to begin the quiescence process. if (! m_quiesce.exchange(true, std::memory_order_acquire)) { // advance the current collector and grab the old one. unsigned int old = m_current.load(std::memory_order_relaxed) & 0xFU; old = m_current.exchange((old + 1) & 1, std::memory_order_acq_rel); collector& c = m_collectors[old & 0xFU]; // decode reference count. unsigned int refs = old & 0xFFFFFFF0U; // verify reference count and previous collector index. assert(! (refs & 0x10U) && (old & 0xFU) == (&c - m_collectors)); // increment and generate an odd reference count. if (c.m_count.fetch_add(refs + 0x10U, std::memory_order_release) == -(int)refs) { // odd reference count and drop-to-zero condition detected! prv_quiesce_complete(c); } } } void prv_quiesce_complete(collector& c) { // the collector `c' is now in a quiescent state! :^) std::atomic_thread_fence(std::memory_order_acquire); ========== REMAINDER OF ARTICLE TRUNCATED ==========