mutouyun / cpp-ipc

C++ IPC Library: A high-performance inter-process communication using shared memory on Linux/Windows.
Other
1.78k stars 339 forks source link

single-multi broadcast 模式下,生产者-消费者同步问题 #122

Open cy2333ytu opened 3 months ago

cy2333ytu commented 3 months ago

single-multi broadcast 模式,push function我的理解是:使用 epoch_ 以及 rem_cc来检查当前生产的元素是否被消费者们消费完毕,请问这样理解对吗,还有请问使用 epoch_ 来实现的逻辑该怎么理解呢?

同时我对以下代码感到疑惑

if ((cc & rem_cc) && ((cur_rc & ~ep_mask) == epoch_)) {
       return false; // has not finished yet
    }

只使用 cc&&rem_cc来检查是否可以吗?

 if (el->rc_.compare_exchange_weak(
             cur_rc, epoch_ | static_cast<rc_t>(cc), std::memory_order_release)) {
     break;
}

compare_exchange_weaktrue,我理解的是:代表当前线程执行成功,为什么可以判断当前元素被所有消费者消费完毕呢以及为什么要给el->rc_ 赋值 epoch_ | static_cast<rc_t>(cc)

mutouyun commented 3 months ago

时间太久了,我有点忘记当时的做法了。我记得epoch_是用来分代的,不过在这里,标记的其实是force_push,因为生产者只有一个,所以force_push的行为只会由唯一的那个生产者发起。当出现(cur_rc & ~ep_mask) != epoch_的情况,其实说明生产者由于等待超时而做了一次force_push,如果在push里只判断cc & rem_cc,那么队列中还剩多少元素,就得超时多少次。这里的cc应该是连接标记集合,每一位代表一个连接,因此只要cc & rem_cc的判断通过,就说明当前存活的连接都已经消费过这个元素了,因此compare_exchange_weak并不是用来判断的,单纯只是一次执行。至于这里为啥用compare_exchange_weak而不用store,我隐约记得是有一些corner case,细节有点忘记了。。