- 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/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!