小编scx*_*scx的帖子

shared_mutex锁定顺序

我的印象是,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)

c++ multithreading mutex locking c++17

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

使用未格式化的数据时,loadu_ps和set_ps有什么区别?

我有一些数据没有存储为数组结构.在寄存器中加载数据的最佳做法是什么?

__m128 _mm_set_ps (float e3, float e2, float e1, float e0) // or __m128 _mm_loadu_ps (float const* mem_addr)

使用_mm_loadu_ps,我将数据复制到临时堆栈数组中,而不是直接将数据复制为值.有区别吗?

sse simd intrinsics sse2

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

您应该通过引用还是通过复制传递 __m128 (和其他寄存器类型)?

我很长时间以来一直想知道,在 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)

c++ sse simd intrinsics

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

从最低的开始迭代所有可能的浮点值

我正在为数学函数编写单元测试,我希望能够“走”所有可能的浮点数/双精度数。

由于 IEEE 诡计,浮点类型不能++在它们的极端增加 ( )。有关更多详细信息,请参阅此问题。该答案指出:

只能添加 2^(nN) 的倍数

但从来没有提到什么是小n

这篇很棒的博客文章中给出了从 +0.0 到 +infinity 迭代所有可能值的解决方案。该技术涉及使用带有 an 的联合int来遍历 a 的不同值float。这是由于帖子中解释的以下属性而起作用,尽管它们仅对正数有效。

  1. 相邻的浮点数具有相邻的整数表示
  2. 递增浮点数的整数表示移动到下一个可表示的浮点数,远离零

他对 +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 …

c++ math floating-point numeric floating-accuracy

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

保存和加载 std::chrono::time_point 到文件

我试图简单地保存并重新加载文件中的当前时间。例如:

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错误。

任何帮助表示赞赏,或链接到好的教程/指南。谢谢

c++ fstream c++11 c++-chrono c++14

2
推荐指数
1
解决办法
2956
查看次数

使用fold表达式构造一个普通的对象

我正在尝试使用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)

c++ constructor tuples fold c++17

2
推荐指数
1
解决办法
221
查看次数

为什么原始卷曲构造函数{}不返回右值?

假设你有一个带有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)

c++ templates variadic-templates generic-lambda c++17

2
推荐指数
1
解决办法
135
查看次数

在unique_ptr中显式调用对象的复制构造函数

我正在使用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++ pimpl-idiom copy-constructor unique-ptr c++11

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