在C ++ 98中有关C ++ 0x原子实现的问题

我已经编写了以下原子模板,以模仿将在即将到来的c ++ 0x标准中提供的原子操作。

但是,我不确定_sync_synchronize()调用是否需要返回基础值。

从我的理解,__sync_synchronize()是一个完整的内存屏障,我不确定在返回对象值时我需要这么昂贵的调用。

我很确定它会在价值的设置周围需要,但我也可以在程序集中实现。

__asm__ __volatile__ ( "rep;nop": : :"memory" );

有谁知道,我肯定需要同步()返回的对象。

M.

template < typename T >
struct atomic
{
private:
    volatile T obj;

public:
    atomic( const T & t ) :
        obj( t )
    {
    }

    inline operator T()
    {
        __sync_synchronize();   // Not sure this is overkill
        return obj;
    }

    inline atomic< T > & operator=( T val )
    {
        __sync_synchronize();   // Not sure if this is overkill
        obj = val;
        return *this;
    }

    inline T operator++()
    {
        return __sync_add_and_fetch( &obj, (T)1 );
    }

    inline T operator++( int )
    {
        return __sync_fetch_and_add( &obj, (T)1 );
    }

    inline T operator+=( T val )
    {
        return __sync_add_and_fetch( &obj, val );
    }

    inline T operator--()
    {
        return __sync_sub_and_fetch( &obj, (T)1 );
    }

    inline T operator--( int )
    {
        return __sync_fetch_and_sub( &obj, (T)1 );
    }

    inline T operator-=( T )
    {
        return __sync_sub_and_fetch( &obj, val );
    }

    // Perform an atomic CAS operation
    // returning the value before the operation
    inline T exchange( T oldVal, T newVal )
    {
        return __sync_val_compare_and_swap( &obj, oldval, newval );
    }

};

更新:由于编译器优化,我希望确保操作在面对读/写重新排序时是一致的。


首先,一些小的评论:

volatile T obj;

挥发性在这里是无用的,甚至更多的是你自己制造所有的障碍。

inline T operator++( int )

内联是不需要的,因为它是在类内定义方法时隐含的。

吸气剂和吸附剂:

inline operator T()
{
    __sync_synchronize();   // (I)
    T tmp=obj;
    __sync_synchronize();   // (II)
    return tmp;
}

inline atomic< T > & operator=( T val )
{
    __sync_synchronize();   // (III)
    obj = val;
    __sync_synchronize();   // (IV)
    return *this;
}

为了确保在读取和写入时存储器访问的总次序,每次访问需要两个屏障(像这样)。 只有屏障(II)和(III)我才会感到满意,因为它们足以满足某些用途(例如指针/布尔表示数据在那里,螺旋锁),但除非另有说明,否则我不会忽略其他用途,因为有人可能需要他们(如果有人表示你可以忽略一些障碍而不限制可能的用途,这将是很好的,但我认为这是不可能的)。

当然,这将是不必要的复杂和缓慢。

也就是说,我只是倾倒障碍,甚至是在类似模板的任何地方使用障碍的想法。 注意:

  • 该接口的排序语义全由您定义; 如果你决定界面在这里或那里有障碍,他们必须在这里或那里,一段时间。 如果你没有定义它,你可以想出更有效率的设计,因为并不是所有的障碍,或者甚至不是完全的障碍,都可能需要特定的问题。
  • 通常情况下,如果你有一个无锁算法可以给你一个性能优势,你就可以使用原子。 这意味着一个过早使用访问权限的界面可能无法用作其构建块,因为它会妨碍性能本身。
  • 无锁算法通常包含无法用一种原子数据类型封装的通信,因此您需要知道算法中发生了什么,才能将屏障精确地放置在其所属的位置(例如,实施锁定时,您需要屏障,已经获得了它,但是在你释放它之前,至少原则上这两个都是写入)
  • 如果你不想遇到问题,也不确定是否明确地将算法设置在算法中,那么就使用基于锁的算法。 没有什么不好的。
  • 顺便说一句,C ++ 0x接口允许你指定精确的内存排序约束。


    inline operator T()
    {
        __sync_synchronize();   // Not sure this is overkill
        return obj;
    }
    

    简短版本:这是过度杀伤力。

    长版本:

    为什么你想把这个类作为模板来实现呢? 它没有任何意义,因为原子操作只允许从1-8字节的整数类型中进行,甚至不能确定所有平台上都支持8字节的整数。

    您应该将您的原子类实现为非模板版本,并使用硬件/系统的“本地”整数类型。 这是32位处理器/ os上的int32_t和64位系统上的int64_t。 例如:

    #ifdef ...
    typedef ... native_int_type;
    #endif
    // verify that you choosed the correct integer type
    BOOST_STATIC_ASSERT(sizeof(native_int_type) == sizeof(void*));
    

    BOOST_STATIC_ASSERT直接来自C ++ 0x中的“static_assert()”。

    如果您使用“完美匹配”整数类型,则可以像这样编写运算符:

    operator native_int_type() { return obj; }
    

    由于obj是易失性的,因此保证获取该值并且不返回任何缓存的值。 因为你使用的是“本地”整数类型,所以你可以确定读取这样的值是原子的。

    atomic& operator=( native_integer_type val )
    

    同样,如果您使用正确的整数类型,则不需要同步。 在intel 32位系统上读取/设置int32是原子,因此在64位系统上读取/设置int64。

    我没有看到将atomic作为模板实现的好处。 原子操作依赖于平台。 最好提供一个“atomic_int”类,只保证至少有4个字节(如果你支持32位和64位系统),如果你需要的话可以使用“atomic_pointer”。 这样,这个类的名字也意味着一个语义和一个目的。

    如果你只是使用“原子”而不是人们能想到的:“哇,我只需要把我的字符串类放在这个模板中,然后它就是线程安全的!”。


    编辑:回答您的更新:“由于编译器优化,我希望确保操作在面对读/写重新排序时保持一致。”

    为了防止编译器和cpu重新排列读/写操作,你需要__sync_synchronize()。

    但请注意,获取/释放语义可能会产生比完全障碍更好的性能。


    EDIT2:

    inline atomic< T > & operator=( T val )
    {
        __sync_synchronize();   // Not sure if this is overkill
        obj = val;
        return *this;
    }
    

    你想防止重新排序? 在大多数情况下,你想写这个:

        obj = val;
        __sync_synchronize();
    

    代替。 因为您希望确保该值已写入,所以一旦从函数返回。

    链接地址: http://www.djcxy.com/p/45217.html

    上一篇: C++0x atomic implementation in c++98 question about

    下一篇: Extract information from conditional formula