如何使用C ++ 11原子库实现seqlock锁

 太阳神神神_890 发布于 2023-02-13 12:20

我想使用c ++ 11原子库编写一个seqlock。我已阅读有关stackoverflow上seqlock的一些问题?但是没人帮我 我使用的算法很常见,您可以在任何地方找到它,这是我的代码:

struct sequence_spinlock_t {

    void write_lock() {
        lock.lock();
        flags.fetch_add(1, memory_order_acquire); //A

    }

    void write_unlock() {
        flags.fetch_add(1, memory_order_release); //B
        lock.unlock();
    }

    void read_enter(uintptr_t *flag) {
        for (;;) {
            uintptr_t f = flags.load(memory_order_acquire); //C
            if ((f & 1) == 0) {
                *flag = f;
                break;
            }
            pause();
        }
    }

    bool_ read_leave(uintptr_t flag) {                                        

        uintptr_t f = flags.load(memory_order_relaxed); //D
        return f == flag;
    }

    spinlock_t lock;
    atomic_uintptr_t flags;
};

    //read thread
    uintptr_t flag;
    do {
        lock.read_enter(&flag);      (0)
        //read something             (1)
    } while(!lock.read_leave(flag))  (2)


    //write thread
    lock.write_lock();              (3)
    //write something               (4)
    lock.write_unlock();            (5)

我确保我在B和C处正确使用了memory_order标记。

我认为这在A和D都是不正确的。

想想我们同时读取和写入受保护的数据,我担心D处的标志的读取值太旧了,我们不读取write_lock()写入的最新值,但是我们读取受保护的数据的最新值由写线程编写(在x86系统上可能不会发生,但是我不认为代码在x86上运行。)在读取线程完成读取受保护的数据之后,由于标志的读取值太旧,找不到序列已增加。从循环读取线程产量,我们犯了一个错误。

(1)中受保护数据的读取值写入(4),(2)中标志的读取值未写入(3)(这是我们上次解锁写锁时写入的值)。为什么我认为有错误。

但是我真的不知道要解决此问题。我试图在read_leavee()和write_locke()之间建立“同步”关系(我希望“ read_leave()与write_locke()同步”)。但是没有存储read_leave()中的操作,所以我失败了。

(哦!我很难理解c ++标准规范,部分原因是我不是来自英语国家。)

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有