我最近遇到了一些同步问题,这使我成为自旋锁和原子计数器.然后,我正在寻找多一点,这些工作是如何找到的std :: memory_order及记忆力障碍(mfence,lfence和sfence).
所以现在,似乎我应该使用获取/释放螺旋锁并放松计数器.
x86 MFENCE - 内存围栏
x86 LOCK - 断言LOCK#信号
这三个操作(lock = test_and_set,unlock = clear,increment = operator ++ = fetch_add)的默认(seq_cst)内存顺序和获取/释放/放松的机器代码(编辑:见下文)是什么(按此顺序排列三个操作).有什么区别(哪些内存屏障在哪里)和成本(多少CPU周期)?
我只是想知道我的旧代码(没有指定内存顺序= seq_cst使用)真的是多么糟糕,如果我应该创建一些class atomic_counter派生std::atomic但使用轻松的内存排序 (以及在某些地方使用获取/释放而不是互斥锁的好螺旋锁. ..或者使用来自boost库的东西 - 到目前为止我已经避免了提升).
到目前为止,我确实理解自旋锁比自身保护更多(但也有一些共享资源/内存),因此,必须有一些东西可以使一些内存视图对于多个线程/内核(即获取/释放和内存围栏)保持一致).原子计数器只为自己而存在,只需要原子增量(不涉及其他内存,当我读它时我并不真正关心它的价值,它是信息性的,可以是几个循环旧,没问题).有一些LOCK前缀和一些xchg …
在你阅读之前: const_reference是typedef,不需要const T&像你看到的那样std::vector<bool>::const_reference = bool.请在阅读其他内容时牢记这一点,以便正确理解它(如值得一提的,这对很多人来说很难).
我想将STL容器用于简单类型(例如int)并发现它们使用次优的const T& "反模式" - 它适用于大类,但对于简单/基本类型而言,如果不内联则是次优的 - 考虑嵌入式系统,例如在ARM/ATSAM4L上,具有实例化.
问题是:为什么例如从C++ 11开始vector::push_back重新设计参数(const value_type&)而不是(Allocator::const_reference)?对于泛型应该是相同的allocator,但是以另一种方式执行它将帮助我为基本类型编写自定义分配器(或模板特化),这将定义const_reference为类型本身(请参阅参考资料vector<bool>::const_reference = bool).
问题2:是否有适合我的适配器类?
像这样的东西:
template<class T, class base = std::vector<T> >
class myvect: protected base {
public:
typedef T const_reference;
void push_back(const_reference value) {
base::push_back(value); }}
Run Code Online (Sandbox Code Playgroud)
最终用法将是这样的:
typedef void (*action_t)(void*,int);
extern "C" void work(void *, action_t);
work(&vect, (action_t)&vect::push_back);
Run Code Online (Sandbox Code Playgroud)
(注意:忽略以前代码块中可能存在的转换问题,希望你有这个想法.) …
我发现for (auto& e : cont)有时使用而不是普通for (auto e : cont)(cont例如,某些容器std::vector).到目前为止,我找到了两个原因:
std::thread)经过几次测试,我可以看到:
for (auto& e : cont)适用于任何std::vector<T>除外std::vector<bool>for (cont::reference e : cont)适用于任何std::vector<T> 包括std::vector<bool>(这里显而易见的问题是:for (auto& e : cont)?std::vector<bool>不被认为是真正的容器,许多人认为它应该被重命名(实现很好,很有用,但应该有不同的名称,如bitset或bitfield或dynamic_bitset)std::vector<bool>可以以一种for (auto& e : cont)可行的方式实现(参见下面的尝试)这是我用于测试的代码:(
诀窍是使用reference& iterator::operator * () { return *this; })
#include <vector>
#include <iostream>
#include …Run Code Online (Sandbox Code Playgroud) 想象一下写下这样的东西boost::any:
class any {
public:
any();
any(const any &);
any(any &&);
template<typename ValueType> any(const ValueType &);
template<typename ValueType> any(ValueType &&);
Run Code Online (Sandbox Code Playgroud)
是否可以调用适当的(复制/移动)构造函数any?或者它必须与SFINAE一起编写,例如:
template<typename ValueType,
typename = typename std::enable_if<
!std::is_same<any, typename std::decay<ValueType>::type>::value
>::type>
any(const ValueType& value)
template<typename ValueType,
typename = typename std::enable_if<
!std::is_same<any, typename std::decay<ValueType>::type>::value
>::type>
any(ValueType&& value)
Run Code Online (Sandbox Code Playgroud)
问题是:我是否需要保护模板化构造函数(any从某个值构造)或者我可以保留它,因为非模板(复制/移动)构造函数将始终匹配any?怎么样volatile修改或者一些奇怪的std::move((const any&)it),如果这是可能的吗?
谢谢你说,描述搜索构造函数的答案最为贴切.
编辑:构建any包含另一个any将是一个问题,我definitelly想要避免(SFINAE确保它不会发生).
在给定的代码中是否存在此错误的真正原因,或者只是在一般使用中可能会出错,其中跨交互器步骤需要引用(在这种情况下并非如此)?
IEnumerable<string> EnumerateStatic()
{
foreach (int i in dict.Values)
{
ref var p = ref props[i]; //< CS8176: Iterators cannot have by-reference locals
int next = p.next;
yield return p.name;
while (next >= 0)
{
p = ref props[next];
next = p.next;
yield return p.name;
}
}
}
struct Prop
{
public string name;
public int next;
// some more fields like Func<...> read, Action<..> write, int kind
}
Prop[] props;
Dictionary<string, int> dict;
Run Code Online (Sandbox Code Playgroud)
dict是名称索引映射,不区分大小写
Prop.next是 …