小编eth*_*ice的帖子

何时只有编译器的内存屏障(例如std :: atomic_signal_fence)有用吗?

当我正在阅读有关内存模型,障碍,排序,原子等等时,编译器栅栏的概念经常会出现,但通常情况下,它也会CPU栅栏配对,正如人们所期望的那样.

但是,偶尔我会读到适用于编译器的fence构造.一个例子是C++ 11 std::atomic_signal_fence函数,它在cppreference.com上声明:

std :: atomic_signal_fence等效于std :: atomic_thread_fence,除了没有发出内存排序的CPU指令.仅按顺序指示抑制编译器对指令的重新排序.

我有五个与此主题相关的问题:

  1. 正如名称所暗示的那样std::atomic_signal_fence,是一个异步中断(例如一个被内核抢占以执行信号处理程序的线程)唯一一种只有编译器的栅栏才有用的情况?

  2. 它的用处是否适用于所有体系结构,包括强烈排序的体系结构x86

  3. 是否可以提供一个特定的示例来演示仅编译器栅栏的用途?

  4. 使用时std::atomic_signal_fence,使用acq_relseq_cst订购之间有什么区别吗?(我希望它没有任何区别.)

  5. 这个问题可能是由第一个问题所覆盖,但我足够的好奇,一下也无妨具体问:是否曾经需要使用围栏与thread_local访问?(如果有的话,我希望只有编译器的围栏atomic_signal_fence才能成为首选工具.)

谢谢.

c++ atomic memory-fences memory-barriers c++11

32
推荐指数
1
解决办法
3300
查看次数

std :: reference_wrapper <T>的隐式T&constructor是否使用它很危险?

boost::reference_wrapper<T>有一个显式的 T&构造函数,而std::reference_wrapper<T>有一个式的构造函数.因此,在以下代码中:

foo = bar;
Run Code Online (Sandbox Code Playgroud)

如果foo是a boost::reference_wrapper,则代码将无法编译(这很好,因为reference_wrapper没有与实际引用相同的语义.

如果foo是a std::reference_wrapper,则代码将"重新绑定"对其foo的引用bar(而不是像人们可能错误地指望的那样分配值).

这可能导致难以捉摸的错误......请考虑以下示例:

在某些假设库的1.0版中:

void set_max(int& i, int a, int b) {
    i = (a > b) ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

在新版本(1.1)中,set_max转换为模板以接受任何宽度(或UDT)的整数而不更改接口:

template<typename T1, typename T2, typename T3>
void set_max(T1& i, T2 a, T3 b) {
    i = (a > b) ? a : …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

24
推荐指数
1
解决办法
663
查看次数

clang错误:非类型模板参数是指没有链接的函数 - bug?

我有一些非常简单的(C++ 11)代码,最新的clang(版本3.4 trunk 187493)无法编译,但GCC编译得很好.

代码(下面)foo使用函数本地类型 实例化函数模板,Bar然后尝试将其地址用作类模板的非类型模板参数Func:

template<void(*FUNC_PTR)(void)>
struct Func {};

template<typename T> extern inline
void foo() {
    using Foo = Func<foo<T>>;
}
int main() {
    struct Bar {}; // function-local type
    foo<Bar>();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

clang发出以下错误:

错误:非类型模板参数是指没有链接的函数'foo'

但是,如果我将类型移动Bar到全局范围(通过将其从函数中取出),则clang可以很好地编译它,证明问题在于函数本地类型.

那么clang是否正确发出此错误,或者标准是否不支持这种情况(在这种情况下,GCC通过允许它过于宽松)?


编辑#1:要清楚,这不是这个问题的重复,因为在C++ 11中删除了'不能使用本地类型作为模板参数'限制.但是,仍然不清楚使用本地类型是否涉及链接问题,以及发出此错误时clang是否正确.


编辑#2:已经确定clang对于上面的代码发出错误是正确的(参见@jxh的回答),但它错误地也为下面的代码发出错误(using声明从foo<Bar>()范围移到main()范围):

template<void(*FUNC_PTR)(void)>
struct Func …
Run Code Online (Sandbox Code Playgroud)

c++ gcc templates clang c++11

9
推荐指数
1
解决办法
1765
查看次数

C++ 11:如何检查类型是否是"异构"非类型参数的给定类模板的实例化?

我知道检查类型是否是采用TYPE参数的类模板的实例化是很简单的,如下所述:如何检查类型是否是给定类模板的实例化?

但是......是否有可能有一个可变的"is_instantiation_of__ntp <...>"(NTP代表非类型参数),它将接受具有任意数量的异构 NON-TYPE参数的模板?例如:

template<char*, bool, long, size_t, char>
struct many_hetero_nontype_params_example {};

char HELLO_WORLD[] = "hello world";
using ManyHeteroNontypeParamsEx = many_hetero_nontype_params_example<HELLO_WORLD, false, -16, 777, 'x'>;
Run Code Online (Sandbox Code Playgroud)

并能够如下使用它:

is_instantiation_of__ntp<char*, bool, long, size_t, char, many_hetero_nontype_params_example, ManyHeteroNontypeParamsEx>::value
Run Code Online (Sandbox Code Playgroud)

我知道这可以很容易地实现NON-TYPE参数列表,这些参数列表是1)"同类"(相同类型的值),或2)很少的参数(这样非可变解决方案是实用的).我甚至写了一个测试用例来演示这些特殊情况(用gcc 4.7.0编译),以便更好地了解我在说什么:

namespace test__is_instantiation_of__
{
    // is_instantiation_of
    template< template<typename...> class Template, typename T >
    struct is_instantiation_of : std::false_type {};
    template< template<typename...> class Template, typename... Args >
    struct is_instantiation_of< Template, Template<Args...> > : std::true_type {};

    // is_instantiation_of__homogeneous_nontype_params__
    template< typename NTP, template<NTP...> class Template, …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-meta-programming variadic-templates c++11

7
推荐指数
1
解决办法
1407
查看次数

boost :: mpl占位符评估的行为不一致

在以下代码中(为演示而简化):

  namespace mpl = boost::mpl;

  using if1 = mpl::if_<std::is_same<double, mpl::_1>, double, void>;
//using if2 = mpl::if_<std::is_same<double, mpl::_1>, typename std::common_type<double, mpl::_1>::type, void>;

  using apply1 = boost::mpl::apply<if1, double>::type;
//using apply2 = boost::mpl::apply<if2, double>::type;
Run Code Online (Sandbox Code Playgroud)

std::is_same<double, mpl::_1>,占位符被正确替换double,就好像实例化明确std::is_same<double, double>导致正确/预期的行为.

但是,在std::common_type<double, mpl::_1>占位符中没有替换占位符,就好像实例化是明确的std::common_type<double, mpl_::arg<1>>,这会导致以下错误,因为显然没有"常见"类型:

error: incompatible operand types ('double' and 'mpl_::arg<1>')
Run Code Online (Sandbox Code Playgroud)


问题:为什么mpl::_1占位符正确转换/置换doublestd::is_same,而不是std::common_type?有解决方法吗?


c++ boost boost-mpl template-meta-programming c++11

7
推荐指数
1
解决办法
362
查看次数

在gdb中打印boost :: mpl :: string <...>类型

我使用boost::mpl::string<...>类型广泛......以至于它会真的与调试有类型适合打印帮助gdb.

所以...而不是gdb像目前那样显示单个(多字符文字)组件......

boost::mpl::string<1668248165, 778856802, 778858343, ..., ..., 0, 0, 0, 0, 0, 0>
Run Code Online (Sandbox Code Playgroud)

它会显示等效的字符串值而不是......

boost::mpl::string<"The way out is through">
Run Code Online (Sandbox Code Playgroud)

我已经看过gdb用于漂亮打印STL容器的宏和python脚本gdb,但我找不到一个漂亮的打印boost::mpl字符串.有人能帮忙吗?


更新:我添加了一个+100赏金......我要找的是采用了最新的GDB支持通过Python漂亮的印刷(如描述的解决方案在这里对STL容器).

c++ boost gdb metaprogramming boost-mpl

6
推荐指数
1
解决办法
1039
查看次数

强制clang为类模板实例化的从未引用的静态成员函数发出代码

我可以gcc使用usednoinline 函数属性轻松实现这一点(参见下面的代码),但这并不适用,clang即使它应该支持这两个函数属性.

一个简化的例子:

template<typename T>
struct Factory {
    static __attribute__((used, noinline))
    T createFoo() { return T(); }
};

int main() {
    Factory<int> f; // instantiate and use Factory<int>
}
Run Code Online (Sandbox Code Playgroud)

编译代码gcc并使用nm确认gcc正确发出函数:

nm --demangle test | grep createFoo
0000000000403185 W Factory<int>::createFoo()
Run Code Online (Sandbox Code Playgroud)

代码编译良好clang,但它不会createFoo()像它应该的那样为静态函数发出代码.

如何强制clang发出从未引用过的静态函数?

c++ gcc clang

6
推荐指数
1
解决办法
1744
查看次数

shm_open和ftruncate竞争条件可能吗?

shm_open手册页:

新的共享内存对象最初的长度为零.可以使用ftruncate(2)设置对象的大小.[...] shm_open()函数本身不会创建指定大小的共享对象,因为这样做会复制现有函数,该函数设置文件描述符引用的对象的大小.

这不会使应用程序暴露于竞争条件吗?考虑以下伪代码:

int fd = shm_open("/foo", CREATE);
if ( fd is valid ) {
  // created shm object, so set its size
  ftruncate(fd, 128);
} else {
  fd = shm_open("/foo", GET_EXISTING);
}
void* mem = mmap(fd, 128);
Run Code Online (Sandbox Code Playgroud)

由于shm_openftruncate调用(一起)不是原子的,你可能有一个竞争条件,一个进程调用shm_open(CREATEcase),但是在调用之前ftruncate,另一个进程调用shm_open(GET_EXISTINGcase)并尝试mmap0大小的对象,甚至可能写入它.

我可以想到两种避免这种竞争条件的方法:

  1. 使用IPC互斥量/信号量使整个事物同步,或者......

  2. 如果它是安全的(按POSIX),请ftruncate同时调用CREATEGET_EXISTING案例.

哪种方法可以避免这种竞争条件?

c c++ linux mmap shared-memory

5
推荐指数
1
解决办法
2078
查看次数

参数化和重用 HTML5 中定义的自定义 SVG 过滤器?

我需要一种方法来根据其 alpha 蒙版向透明 PNG 图像添加“描边”(轮廓)和阴影效果,而我能找到的唯一解决方案是使用自定义 SVG 滤镜。(注意:我需要这些效果的网络应用程序是供我自己私人使用的,因此该解决方案与旧版浏览器不兼容也没关系。继续...)

我以前从未使用过 SVG,但单独创建描边和阴影滤镜非常简单。不幸的是,我无法找到一种方法来创建组合效果,而不需要将过滤器实际复制并粘贴到新过滤器中,如下面的代码所示:

<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">

    <!-- drop shadow -->
    <filter id="drop-shadow">
        <feGaussianBlur in="SourceAlpha" stdDeviation="4" />
        <feOffset result="m_offsetBlurred" dx="12" dy="12" />
        <feFlood result="m_floodTrans50" flood-color="rgba(0,0,0,0.5)" />
        <feComposite result="m_offsetBlurredTrans50" in="m_floodTrans50" in2="m_offsetBlurred" operator="in" />
        <feMerge>
            <feMergeNode in="m_offsetBlurredTrans50" />
            <feMergeNode in="SourceGraphic" />
        </feMerge>
    </filter>


    <!-- outer stroke -->
    <filter id="outer-stroke">
        <!-- create rectangle of the desired color -->
        <feFlood result="m_floodRect" flood-color="black" />

        <!-- create copy of png's alpha mask and expand -->
        <feMorphology result="m_expandedMask" …
Run Code Online (Sandbox Code Playgroud)

html css svg svg-filters

5
推荐指数
1
解决办法
1916
查看次数

抢先式多任务是否会干扰C++ 11发布 - 获取语义?

是(理论上)线程可以acquire在一个CPU上执行,然后立即被抢占并在另一个acquire从未执行过的CPU上恢复(因此根据发布 - 获取语义从不同步)?

对于前者 考虑以下使用C++ 11原子和release-acquire内存排序的代码来执行无锁线程安全初始化:

if ( false == _initFlag.load(memory_order_acquire) ) {
    _foo = ...; // initialize global
    _bar = ...; // initialize global
    ... = ...; // initialize more globals
    _initFlag.store(true, memory_order_release);
}
// use the initialized values ...
Run Code Online (Sandbox Code Playgroud)

如果_initFlag.load(memory_order_acquire)返回true,则调用线程会知道的初始化值_foo,_bar等...可见(传播)到CPU 上,它目前正在执行.但是如果线程在之后立即被抢占并移动到另一个CPU怎么办?

C++ 11标准是否保证新CPU将同步?是否有任何可能容易受到此类竞争条件影响的实施或架构?

c++ memory-barriers c++11

4
推荐指数
1
解决办法
152
查看次数

没有动态调度开销的基类抽象方法的C++习惯用法?

在C++中,是否有任何方法可以使用"抽象"基类方法(,从基类声明和调用,但在子类中实现)而不将该方法声明为virtual

当然,这个问题仅适用于不需要多态的情况(指针/对基类型的引用从未使用过).考虑以下:

#define NO_OPT asm volatile ("");  // to prevent some compiler optimization

template<typename DerivedType>
void doSomething(DerivedType& d) { d.foo(); }

namespace test1 {

    struct Base {
        inline void foo()
        {
            // ... do common stuff pre-call ...
            foo_impl();
            // ... do common stuff post-call ...
        }
        virtual void foo_impl() = 0; // the abstract method
    };
    struct D1 : public Base { virtual void foo_impl() final { NO_OPT } };
    struct D2 : public Base …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

4
推荐指数
1
解决办法
1075
查看次数

如何为类似x86的系统实现C++ 11内存屏障?

我对C++ 11的std::memory_order类型有一个很好的概念性理解(轻松获取 - 发布顺序一致 ......),但我想更好地理解它们通常是如何为x86实现的(通过编译器)(或x86_64)目标.

具体而言,低级别的细节(例如用于处理器之间的同步状态或高速缓存存储器的重要相关的CPU指令)为每个顺序的限制进行比较(memory_order_consume,memory_order_acquire,memory_order_release,和memory_order_seq_cst).

请提供尽可能多的低级细节,最好是x86_64或类似架构.非常感谢您的帮助.

c++ x86 x86-64 memory-barriers c++11

3
推荐指数
1
解决办法
497
查看次数

使用带有可变参数函数模板的参数的std :: algorithms的大多数cpu效率方法?

假设您有一个可变参数函数模板,它采用仿函数和一系列同类型,并且您希望使用它std::accumulate来折叠序列,如下所示:

template<typename BinaryFuncType, typename... ArgTypes>
do_something(const BinaryFuncType& f, const ArgTypes&... objects)
{
    // ...
    // use std::accumulate to fold 'objects' using 'f'
    // ...
}
Run Code Online (Sandbox Code Playgroud)

是否有可能通过一个可变参数(objects)的范围算法(std::accumulate)直接的,即,不会导致对象复制的费用(或引用)到一个可迭代容器?

c++ variadic-templates c++11

3
推荐指数
1
解决办法
212
查看次数