我的印象是,std::shared_mutex如果获取了太多共享锁,则使用c ++ 17实现的多读取器/单写入器模式可能永远不会放弃唯一锁。
在探究cppreference之后,我不确定是这种情况。具体来说:
单个互斥锁上的所有锁定和解锁操作均以单个总顺序发生
例如,鉴于对进行以下操作shared_mutex,我认为unique_lock可能永远不会获得。假设无限数量的shared_locks,并且这些锁在第一次shared_locks发行之前获得。
shared_lock
shared_lock
shared_lock
unique_lock
shared_lock
[...]
shared_lock
Run Code Online (Sandbox Code Playgroud)
具有以下特征。
{ shared_lock, shared_lock, shared_lock, shared_lock, ..., shared_lock } // never releases
unique_lock
Run Code Online (Sandbox Code Playgroud)
但是,如果我正确理解了cppreference,那么一旦unique_lock尝试获取cppreference,continuous shared_locks将会阻塞直到unique_lock释放。提供以下线程特征。
{ shared_lock, shared_lock, shared_lock} // simultaneous
unique_lock
{ shared_lock, ..., shared_lock} // waits, then simultaneous
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,std::shared_mutex共享锁和唯一锁之间是否保持顺序?防止unique_locks由于大量获取而永远无法获取的情况shared_locks。
编辑:
这是一个代码示例,可以帮助您理解问题,并且为了后代。在MSVC 2019上,它shared_mutex很安全,可以根据需要进行订购。在unique_lock没有得到的“无限”量前处理shared_locks。
现在的问题是,这个平台依赖吗?
#include <chrono>
#include …Run Code Online (Sandbox Code Playgroud) 我有一些数据没有存储为数组结构.在寄存器中加载数据的最佳做法是什么?
__m128 _mm_set_ps (float e3, float e2, float e1, float e0)
// or
__m128 _mm_loadu_ps (float const* mem_addr)
使用_mm_loadu_ps,我将数据复制到临时堆栈数组中,而不是直接将数据复制为值.有区别吗?
我很长时间以来一直想知道,在 C++ 中传递寄存器类型的最佳方法是什么?
在我的特定情况下,我有一些抽象层,它们依次调用所需的内在函数。Immintrin 函数按值接受(副本),所以我的猜测是它应该是一个副本。但我想确定一下(并满足我的好奇心)。
又名,
__m128 func(__m128 a, __m128 b) {
return _mm_something(a, b);
}
// vs.
__m128 func(const __m128& a, const __m128& b) {
return _mm_something(a, b);
}
Run Code Online (Sandbox Code Playgroud) 我正在为数学函数编写单元测试,我希望能够“走”所有可能的浮点数/双精度数。
由于 IEEE 诡计,浮点类型不能++在它们的极端增加 ( )。有关更多详细信息,请参阅此问题。该答案指出:
只能添加 2^(nN) 的倍数
但从来没有提到什么是小n。
这篇很棒的博客文章中给出了从 +0.0 到 +infinity 迭代所有可能值的解决方案。该技术涉及使用带有 an 的联合int来遍历 a 的不同值float。这是由于帖子中解释的以下属性而起作用,尽管它们仅对正数有效。
- 相邻的浮点数具有相邻的整数表示
- 递增浮点数的整数表示移动到下一个可表示的浮点数,远离零
他对 +0.0 到 +infinity ( 0.fto std::numeric_limits<float>::max()) 的解决方案:
union Float_t {
int32_t RawExponent() const { return (i >> 23) & 0xFF; }
int32_t i;
float f;
};
Float_t allFloats;
allFloats.f = 0.0f;
while (allFloats.RawExponent() < 255) {
allFloats.i += 1;
}
Run Code Online (Sandbox Code Playgroud)
有 -infinity 到 +0.0 …
我试图简单地保存并重新加载文件中的当前时间。例如:
std::ifstream ifs(solar_system_cache_file,
std::ios::in | std::ios::binary);
if (!ifs.is_open()) {
return false;
}
std::chrono::system_clock::time_point cache_valid_time;
ifs >> cache_valid_time;
if (std::chrono::system_clock::now() < cache_valid_time) {
std::cout << "Cache is VALID." << std::endl;
}
ifs.close();
return true;
Run Code Online (Sandbox Code Playgroud)
和
std::ofstream ofs(solar_system_cache_file,
std::ios::out | std::ios::binary);
if (!ofs.is_open())
return;
ofs << std::chrono::system_clock::now() + 12h;
ofs.close();
Run Code Online (Sandbox Code Playgroud)
这种事情并不复杂,但我已经找了几个小时了,找不到相关信息。有一些关于如何使用 进行转换的示例duration_cast<long, std::milli>,但std::chrono非常复杂且难以导航(和消化)。
简而言之,我相信我需要将当前时间转换为long(或一些类似的大型类型)并保存它。在反序列化时间时,我只需要将其转换回time_point. 这听起来很容易,但我做不到。
最后,简单地输入时间fstream会产生通常的invalid operands to binary expression错误。
任何帮助表示赞赏,或链接到好的教程/指南。谢谢
我正在尝试使用std::apply和折叠表达式构造一个对象.从我在线阅读文档可以看出,折叠逗号应该可行.这是一个澄清的例子.
struct my_pair final {
float x;
float y;
};
struct test final {
my_pair back() {
return std::apply(
[](auto&... vector) {
return my_pair{ (vector.back(), ...) }; },
data);
}
std::tuple<std::vector<float>, std::vector<float>> data
= { { 0.f }, { 1.f } };
};
Run Code Online (Sandbox Code Playgroud)
我解压缩元组,获取最后的元素并尝试使用元素返回一个新对象.
各种编译器抱怨y从未初始化.不知何故,扩张并未发生.至少,不是我的期望.
error: missing field
'y' initializer [-Werror,-Wmissing-field-initializers]
...[](auto&... vector) { return my_pair{ (vector.back(), ...) }; },
^
Run Code Online (Sandbox Code Playgroud)
如果我禁用-Werror,则第一个值为my_pair1,第二个值为0.我尝试使用一元左折,但结果相同.
看起来这应该有用,cppreference有这个push_back看起来相似的矢量示例(从我的角度来看).
template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args) …Run Code Online (Sandbox Code Playgroud) 假设你有一个带有a的可变类std::tuple,可以使用args + 1 new arg构造.当使用std::apply()和原始花括号构造函数构造时,该构造函数不返回rvalue.这意味着班级不是移动构造的.下面举一个例子来澄清.
#include <cstdio>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <vector>
template <class... Args>
struct icecream {
icecream() = default;
template <class... MoreArgs>
icecream(icecream<MoreArgs...>&& ice) {
std::apply(
[this](auto&&... ds) {
data = { std::move(ds)..., {} };
},
std::move(ice.data));
}
// This works :
// template <class... MoreArgs>
// icecream(icecream<MoreArgs...>&& ice) {
// std::apply(
// [this](auto&&... ds) {
// data = { std::move(ds)...,
// std::move(std::vector<double>{}) };
// },
// std::move(ice.data));
// }
std::tuple<std::vector<Args>...> …Run Code Online (Sandbox Code Playgroud) 我正在使用pimpl成语const std::unique_ptr来保存类实现.我的班级需要支持复制构建和复制分配.我想要做的是手动调用impl类中的类的复制构造函数unique_ptr.但是,我没有看到如何.
#include <memory>
struct potato {
potato();
~potato();
potato(const potato& p);
private:
struct impl;
const std::unique_ptr<impl> _pimpl;
};
struct potato::impl {
int carbs = 42;
};
potato::potato()
: _pimpl(std::make_unique<impl>()) {
}
potato::~potato() = default;
potato::potato(const potato& p) {
// Try to call the copy constructor of impl, stored in unique_ptr, not the
// unique_ptr copy-constructor (which doesn't exist).
_pimpl.get()->impl(p._pimpl); // This doesn't work.
}
Run Code Online (Sandbox Code Playgroud)
我已经检查了另一个关于在对象上显式调用copy-constructor的问题.一个答案建议使用placement new.
Object dstObject;
new(&dstObject) Object(&anotherObject);
Run Code Online (Sandbox Code Playgroud)
我可以在我的拷贝构造函数中使用它吗?如果是这样,怎么样?我真的不明白那里发生了什么.谢谢.
c++ ×7
c++17 ×3
c++11 ×2
intrinsics ×2
simd ×2
sse ×2
c++-chrono ×1
c++14 ×1
constructor ×1
fold ×1
fstream ×1
locking ×1
math ×1
mutex ×1
numeric ×1
pimpl-idiom ×1
sse2 ×1
templates ×1
tuples ×1
unique-ptr ×1