OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-cogutil commits / 7c104b3

Barrier redesign part the first.
This is still broken; the latch needs to be removed next. But I think its better than the holy horrors that Claude has been creating for me. I am so sorry I pushed any of this crapola into github. I'm thinking of doig a hard reset once this is fixed. Lesson learned: Claude does not yet understand threading; it just pretends to. One day, I suppose it will be better than me. But that day has not yet arrived.
7c104b34b90e335d1234bb58c341eba8a79af69b
by Linas Vepstas <linasvepstas@gmail.com> · 2025-12-07T19:04:30.000Z

Changed files (1) +24 -36

opencog/util/async_buffer.h +24 -36
……@@ -142,8 +142,8 @@ class async_buffer
142142
143143 bool _stall_writers;
144144
145 // Per-thread barrier synchronization
146 std::atomic<unsigned> _barrier_phase;
145 // Barrier synchronization
146 const Element* _current_barrier;
147147 std::latch* _barrier_latch;
148148
149149 void start_writer_thread();
……@@ -218,7 +218,7 @@ async_buffer<Writer, Element>::async_buffer(Writer* wr,
218218 _pending = 0;
219219 _stall_writers = false;
220220 _in_drain = false;
221 _barrier_phase = 0;
221 _current_barrier = nullptr;
222222 _barrier_latch = nullptr;
223223
224224 _high_watermark = DEFAULT_HIGH_WATER_MARK;
……@@ -359,7 +359,7 @@ void async_buffer<Writer, Element>::stop_writer_threads()
359359 (_writer->*_do_write)(elt);
360360 }
361361
362 _barrier_phase = 0;
362 _current_barrier = nullptr;
363363 _barrier_latch = nullptr;
364364
365365 // Its now OK to start new threads, if desired ...(!)
……@@ -446,25 +446,24 @@ void async_buffer<Writer, Element>::barrier()
446446/// workers that do caching or lazy initialization or implement
447447/// other actions that require synchronization that the default
448448/// `barrier(void)` would miss.
449///
449450template<typename Writer, typename Element>
450451void async_buffer<Writer, Element>::barrier(const Element& elt)
451452{
452453 std::unique_lock<std::mutex> lock(_enqueue_mutex);
453454
454 // First, drain existing work
455455 drain();
456456
457 // Set up the barrier using std::latch for synchronization
458457 std::latch completion(_thread_count);
459458 _barrier_latch = &completion;
460 _barrier_phase++;
459 _current_barrier = &elt;
461460
462 // Enqueue one element for each thread.
463 for (unsigned int i = 0; i < _thread_count; i++)
464 do_insert(elt);
461 _store_set.cancel();
465462
466 // Wait for all threads to complete their barrier work
467463 completion.wait();
464
465 _store_set.cancel_reset();
466 _current_barrier = nullptr;
468467 _barrier_latch = nullptr;
469468}
470469
……@@ -473,13 +472,9 @@ void async_buffer<Writer, Element>::barrier(const Element& elt)
473472template<typename Writer, typename Element>
474473void async_buffer<Writer, Element>::write_loop()
475474{
476 // Track which barrier phase this thread has completed.
477 // Used to ensure each thread processes exactly one barrier element.
478 static thread_local unsigned my_last_phase = 0;
479
480 try
475 while (true)
481476 {
482 while (true)
477 try
483478 {
484479 // Do nothing, if asked to stall.
485480 while (_stall_writers and _store_set.size() < _low_watermark)
……@@ -489,31 +484,24 @@ void async_buffer<Writer, Element>::write_loop()
489484
490485 Element elt = _store_set.value_get();
491486 _busy_writers ++;
492
493 unsigned current_phase = _barrier_phase.load();
494 if (my_last_phase < current_phase)
487 (_writer->*_do_write)(elt);
488 _busy_writers --;
489 _pending --;
490 _pending.notify_all();
491 }
492 catch (typename concurrent_set<Element>::Canceled& e)
493 {
494 if (_current_barrier != nullptr)
495495 {
496 // This is barrier work - process and signal completion
497 my_last_phase = current_phase;
498 (_writer->*_do_write)(elt);
496 (_writer->*_do_write)(*_current_barrier);
499497 _barrier_latch->count_down();
500 }
501 else
502 {
503 // Regular work
504 (_writer->*_do_write)(elt);
498 _barrier_latch->wait();
505499 }
506500
507 _busy_writers --;
508 _pending --;
509 _pending.notify_all();
501 // We are so out of here. Nothing to do, just exit this thread.
502 if (_stopping_writers) return;
510503 }
511504 }
512 catch (typename concurrent_set<Element>::Canceled& e)
513 {
514 // We are so out of here. Nothing to do, just exit this thread.
515 return;
516 }
517505}
518506
519507