- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
标题问题的较长版本是:
On my machine,
sizeof(std::condition_variable)
is 72 bytes.What are these 72 bytes used for?
注意:std::condition_variable
的大小取决于实现。 附录 A 中给出了一些示例尺寸。
了解如何std::condition_variable
作品,我很满意理解wait
, notify_one
, 和成员对象。我将从 wait
开始. wait
下面给出了一个谓词。
template <class _Predicate>
void wait(unique_lock<mutex>& _Lck, _Predicate _Pred) { // wait for signal and test predicate
while (!_Pred()) {
wait(_Lck);
}
}
以上wait
调用无谓词 wait
.
void wait(unique_lock<mutex>& _Lck) { // wait for signal
// Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow
_Cnd_wait(_Mycnd(), _Lck.mutex()->_Mymtx());
}
此等待调用 _Cnd_wait
在 _Mycnd()
. _Cnd_wait
找到here .
int _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx) { // wait until signaled
const auto cs = static_cast<Concurrency::details::stl_critical_section_interface*>(_Mtx_getconcrtcs(mtx));
_Mtx_clear_owner(mtx);
cond->_get_cv()->wait(cs);
_Mtx_reset_owner(mtx);
return _Thrd_success; // TRANSITION, ABI: Always returns _Thrd_success
}
_Cnd_t
是指向 _Cnd_internal_imp_t
的指针.
using _Cnd_t = struct _Cnd_internal_imp_t*;
结构_Cnd_internal_imp_t
定义 here .
struct _Cnd_internal_imp_t { // condition variable implementation for ConcRT
std::aligned_storage_t<Concurrency::details::stl_condition_variable_max_size,
Concurrency::details::stl_condition_variable_max_alignment>
cv;
[[nodiscard]] Concurrency::details::stl_condition_variable_interface* _get_cv() noexcept {
// get pointer to implementation
return reinterpret_cast<Concurrency::details::stl_condition_variable_interface*>(&cv);
}
};
我现在正在查看 cond->_get_cv()->wait(cs);
行.要理解这一行,我需要查看 Concurrency::details::stl_condition_variable_interface
的成员(member)wait
功能。这是 virtual function .
class __declspec(novtable) stl_condition_variable_interface {
public:
virtual void wait(stl_critical_section_interface*) = 0;
virtual bool wait_for(stl_critical_section_interface*, unsigned int) = 0;
virtual void notify_one() = 0;
virtual void notify_all() = 0;
virtual void destroy() = 0;
};
编辑2
cond->_get_cv()
是指向抽象类的指针 stl_condition_variable_interface
.在施工期间的某个时刻, create_stl_condition_variable
将被调用以设置虚拟指针。此对象的虚拟指针将指向 stl_condition_variable_vista
的 vtable。给出here或 stl_condition_variable_win7
给出here . this 的最佳答案堆栈溢出问题解释了一些细节。
在我的例子中,虚拟指针指向 stl_condition_variable_win7
的表.
class stl_condition_variable_win7 final : public stl_condition_variable_interface {
public:
stl_condition_variable_win7() {
InitializeConditionVariable(&m_condition_variable);
}
~stl_condition_variable_win7() = delete;
stl_condition_variable_win7(const stl_condition_variable_win7&) = delete;
stl_condition_variable_win7& operator=(const stl_condition_variable_win7&) = delete;
void destroy() override {}
void wait(stl_critical_section_interface* lock) override {
if (!stl_condition_variable_win7::wait_for(lock, INFINITE)) {
std::terminate();
}
}
bool wait_for(stl_critical_section_interface* lock, unsigned int timeout) override {
return SleepConditionVariableSRW(&m_condition_variable,
static_cast<stl_critical_section_win7*>(lock)->native_handle(), timeout, 0)
!= 0;
}
void notify_one() override {
WakeConditionVariable(&m_condition_variable);
}
void notify_all() override {
WakeAllConditionVariable(&m_condition_variable);
}
private:
CONDITION_VARIABLE m_condition_variable;
};
所以我保留了 72 或 8 个字节来存储一个 CONDITION_VARIABLE
和wait
的本质就是打电话SleepConditionVariableSRW
.此功能描述 here .
结束编辑 2
附录 A
std::condition_variable
的唯一成员对象是
aligned_storage_t<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment> _Cnd_storage;
std::condition_variable
包含以下允许 _Cnd_storage
的成员函数被解释为 _Cnd_t
.
_Cnd_t _Mycnd() noexcept { // get pointer to _Cnd_internal_imp_t inside _Cnd_storage
return reinterpret_cast<_Cnd_t>(&_Cnd_storage);
}
sizeof(std::condition_variable)
由 sizeof(_Cnd_storage)
给出,在 xthreads.h
中定义.
// Size and alignment for _Mtx_internal_imp_t and _Cnd_internal_imp_t
#ifdef _CRT_WINDOWS
#ifdef _WIN64
_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 32;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 16;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8;
#else // _WIN64
_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 20;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 4;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 8;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 4;
#endif // _WIN64
#else // _CRT_WINDOWS
#ifdef _WIN64
_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 80;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8;
#else // _WIN64
_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 48;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 4;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 40;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 4;
#endif // _WIN64
#endif // _CRT_WINDOWS
编辑 1/附录 B
我在发布问题后考虑了这个问题,但我不确定如何让它与其他问题一起流动。 std::condition_variable
的唯一成员是
aligned_storage_t<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment> _Cnd_storage;
被解释为 _Cnd_internal_imp_t
. _Cnd_internal_imp_t
的唯一成员是
std::aligned_storage_t<Concurrency::details::stl_condition_variable_max_size, Concurrency::details::stl_condition_variable_max_alignment> cv;
有可能stl_condition_variable_max_size != _Cnd_internal_imp_size
.事实上,这暗示在这个 line
static_assert(sizeof(_Cnd_internal_imp_t) <= _Cnd_internal_imp_size, "incorrect _Cnd_internal_imp_size");
这意味着 72 个字节中的一些可能是“未使用的”。
结束编辑 1
问题:
std::condition_variable
为 CONDITION_VARIABLE
保留 72 个字节(见编辑 2)。这 72 个字节有什么用?std::condition_variable
用更少的字节逃脱?在某些机器上看起来好像std::condition_variable
s 只有 8 个字节大。看: _INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 8;
最佳答案
std::condition_variable
reserves 72 bytes for a CONDITION_VARIABLE (see Edit 2). What are these 72 bytes used for?
还有另一种由并发运行时 (ConcRT) 支持的条件变量实现。在 Visual Studio 2012 中,它是唯一的实现,但结果并不是很好。
从 VS 2015 开始,实际 CONDITION_VARIABLE
支持更好的实现。有一种多态性可以为不同的 Windows 版本创建不同的实现,因为 CONDITION_VARIABLE
从 Windows Vista 开始可用,complete SRWLOCK
从 Windows Vista 开始可用Windows 7。多态性使用 placement new 而不是 union 来隐藏实现细节并使实现符合 making it a standard-layout class 。
因此,有多个实现的地方,其中 ConcRT 是最大的。
否则,sizeof(CONDITION_VARIABLE) == sizeof(void*)
,以及 sizeof(SRWLOCK) == sizeof(void*)
,尽管它们不是t 内部指针。如果使用 CONDITION_VARIABLE
/SRWLOCK
实现,则剩余的大小将被浪费。
从 Visual Studio 2019 开始,VS 工具集不再支持 Windows XP(VS 2019 支持安装 VS 2017 工具集)。因此,my PR 删除了 ConcRT 依赖性和创建 pre-Vista condition_variable
的能力。 A follow-up PR 删除了 ConcRT 结构包装器。
从 Visual Studio 2022 开始,VS 工具集也不再支持 Windows Vista,删除 SRWLOCK
多态性的 my other PR 正在运行中。
仍然由于 VS 2015、VS 2017、VS 2019 和 VS 2022 之间的 ABI 兼容性,无法减小 condition_variable
的大小。
在 mutex
构造函数中摆脱 placement new 并修复 mutex
构造函数非 constexpr
的一致性问题也很困难 (my attempt has failed) .
所以VS 2019和VS 2022还是要为ConcRT实现预留空间,不再使用。
随着 Visual Studio 的下一个 ABI 中断版本,condition_variable
的实现很可能会发生变化。
How could a std::condition_variable get away with fewer bytes?
_CRT_WINDOWS
实现从来不需要支持 Windows XP,因此没有 ConcRT 回退。它仍然与通常的配置共享实现,显然是出于维护原因。
关于c++ - CONDITION_VARIABLE 是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72157532/
此代码是实际项目代码的简化。主线程创建工作线程并使用 std::condition_variable 等待工作线程真正启动。在下面的代码中,std::condition_variable 在 curr
reference I'm using用以下方式解释这两者: wait_for "阻塞当前线程,直到条件变量被唤醒或在指定的超时时间之后" wait_until "阻塞当前线程,直到条件变量被唤醒或到
标题问题的较长版本是: On my machine, sizeof(std::condition_variable) is 72 bytes.What are these 72 bytes used
假设我有这样的事情: bool signalled = false; std::condition_variable cv; void thread1() { while (true) {
我在下面的代码中遇到错误。 recursive_mutex m_RecurMutex; condition_variable cond; unique_lock lock(m_RecurMutex);
这是什么: bool ready; boost::mutex mutex; boost::condition_variable cond; boost::unique_lock lock(mutex)
这个问题是关于condition_variable.wait()的功能。我认为它可能没有锁定 unique_lock当它被通知时立即。让我展示一下我的代码,您会更好地理解我的测试。 注意:编译器 g+
我是条件变量的新手,我想知道为什么计数器变量等于 99 之后的这段代码块?删除for循环并改用“counter += 99”使代码工作,它与sleep_for有什么关系吗?感谢您的帮助:) #incl
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
似乎 condition_variable notify_one 并不总是按应有的方式工作。 struct Task { std::mutex mutex; std::conditio
条件变量可用于向其他线程发出信号,表明发生了某些事情: mutex m; condition_variable cv; thread t1([&cv]{ // processing .
没有 std::condition_variable 的应用程序: #include #include #include #include #include #include std::m
首先是我的代码,让我的解释更清楚: struct Foo { std::condition_variable cv; }; static Foo* foo; // dynamically cr
std::condition_variable::notify_one() 或 std::condition_variable::notify_all() 是否保证非原子内存写入当前线程之前该调用将在
我目前正在对并发队列进行编程,同时学习如何使用C++ 11的多线程功能。 当使用者调用dequeue()函数且队列中没有任何条目时,该函数应等待,直到另一个线程调用enqueue()为止。我正在为此使
我有一个关于notify_one函数的问题。在下面的代码中, #include #include #include #include #include std::condition_vari
我有一个以下类(class)- boost::condition_varaible cond_; 当我尝试编译时- [rmitra @ butterfly boost] $ make EXE = th
这是一个小代码段 request_ptr pop() { request_ptr rp; std::unique_lock lock(cv_mtx); auto time =
假设我有一个包含std::queue的ThreadQueue类,并且我将每个std::ref的实例传递给线程。进一步假设,线程1(主线程)创建并保存ThreadQueue对象,并将消息倒入其中,第二个
我有课,用 queue的 std::function成员和方法 Push和 Pop . 我要实现加法PushAndWaitUntilExecuted .当你有一个时很容易consumer-thread
我是一名优秀的程序员,十分优秀!