5

我想使用 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处flags的读取值太旧,我们没有读取write_lock()写入的最新值。但是我们读取了保护数据的最新值由写线程编写(在x86系统上可能不会发生,但我不认为代码在x86上运行。)。在读线程完成读取受保护的数据后,由于标志的读取值太旧,我没有'没有发现序列已经增加。从循环中读取线程产生,我们犯了一个错误。

(1)处受保护数据的读取值在(4)处写入,(2)处flags的读取值在(3)处不写入(它是我们上次解锁写锁时写入的。)。即为什么我认为有一个错误。

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

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

4

2 回答 2

2

值得注意的是,seqlock 保护的数据必须具有原子类型,并且您必须使用原子加载/存储来访问它。不理想,但这就是 C11/C++11 给你的。Han Boehm 的 MSPC 论文详细介绍了这一点。

于 2013-12-11T16:58:17.797 回答
2

在 read_leave 中使用 memory_order_relaxed 本身是可以的,但您确实需要确保在加载标志变量之前已经加载了数据值。你可以用 std::atomic_thread_fence 做到这一点。即你的 read_leave 应该看起来像

bool read_leave(uintptr_t flag) { atomic_thread_fence(memory_order_acquire); uintptr_t f = flag.load(memory_order_relaxed); 返回 f == 标志; }

FWIW,通过此更改,您的代码大致类似于http://safari.ece.cmu.edu/MSPC2012/slides_posters/boehm-slides.pdf中的示例 3

于 2013-12-03T07:49:45.187 回答