我可以获得持有 CriticalSection 的线程的 id 吗?

发布于 2024-10-04 06:24:30 字数 125 浏览 3 评论 0原文

我想围绕一段复杂的多线程代码编写一些断言。 有什么方法可以做

assert(GetCurrentThreadId() == ThreadOfCriticalSection(sec));

I want to write a few asserts around a complicated multithreaded piece of code.
Is there some way to do a

assert(GetCurrentThreadId() == ThreadOfCriticalSection(sec));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淑女气质 2024-10-11 06:24:30

如果你想正确地执行此操作,我认为你在关键部分周围使用了一个包装器对象,它将跟踪哪个线程(如果有)拥有调试版本中的每个 CS。

即,您不是直接调用 EnterCriticalSection,而是调用包装器上的一个方法,该方法执行 EnterCriticalSection,然后在成功时将 GetCurrentThreadId 存储在断言将检查的 DWORD 中。另一种方法会在调用 LeaveCriticalSection 之前将该线程 ID DWORD 清零。

(在发布版本中,包装器可能会省略额外的内容,只调用 Enter/LeaveCriticalSection。)

正如 Casablanca 指出的,所有者线程 ID 位于当前的 CRITICAL_SECTION 结构中,因此使用我建议的包装器将存储冗余信息。但是,正如 Casablanca 还指出的那样,CRITICAL_SECTION 结构不是任何 API 合约的一部分,并且可能会发生变化。 (事实上​​,它在过去的 Windows 版本中已经发生了变化。)

了解内部结构对于调试很有用,但不应该在生产代码中使用。

因此,您使用哪种方法取决于您希望解决方案的“正确”程度。如果您只是想要一些临时断言来跟踪当前 Windows 版本上的问题,那么直接使用 CRITICAL_SECTION 字段对我来说似乎是合理的。只是不要指望这些断言永远有效。如果您想要保存时间更长的东西,请使用包装纸。

(使用包装器的另一个优点是您将获得 RAII。即包装器的构造函数和析构函数将处理 InitializeCriticalSection 和 DeleteCriticalSection 调用,因此您不必再担心它们。说到这一点,我发现它非常有用有一个辅助对象,它在构造时进入 CS,然后在销毁时自动将其保留。不再有因为函数在其中间隐藏了早期返回而意外锁定的情况......)

If you want to do this properly I think you have use a wrapper object around your critical sections which will track which thread (if any) owns each CS in debug builds.

i.e. Rather than call EnterCriticalSection directly, you'd call a method on your wrapper which did the EnterCriticalSection and then, when it succeeded, stored GetCurrentThreadId in a DWORD which the asserts would check. Another method would zero that thread ID DWORD before calling LeaveCriticalSection.

(In release builds, the wrapper would probably omit the extra stuff and just call Enter/LeaveCriticalSection.)

As Casablanca points out, the owner thread ID is within the current CRITICAL_SECTION structure, so using a wrapper like I suggest would be storing redundant information. But, as Casablanca also points out, the CRITICAL_SECTION structure is not part of any API contract and could change. (In fact, it has changed in past Windows versions.)

Knowing the internal structure is useful for debugging but should not be used in production code.

So which method you use depends on how "proper" you want your solution to be. If you just want some temporary asserts for tracking down problems today, on the current version of Windows, then using the CRITICAL_SECTION fields directly seems reasonable to me. Just don't expect those asserts to be valid forever. If you want something that will last longer, use a wrapper.

(Another advantage of using a wrapper is that you'll get RAII. i.e. The wrapper's constructor and destructor will take care of the InitializeCriticalSection and DeleteCriticalSection calls so you no longer have to worry about them. Speaking of which, I find it extremely useful to have a helper object which enters a CS on construction and then automatically leaves it on destruction. No more critical sections accidentally left locked because a function had an early return hidden in the middle of it...)

泅渡 2024-10-11 06:24:30

据我所知,没有记录的方法可以获取此信息。如果您查看标头,CRITICAL_SECTION 结构包含线程句柄,但我不会依赖此类信息,因为内部结构可能会在没有通知的情况下发生更改。更好的方法是每当线程进入/退出临界区时自己维护这些信息。

As far as I know, there is no documented way to get this information. If you look at the headers, the CRITICAL_SECTION structure contains a thread handle, but I wouldn't rely on such information because internal structures could change without notice. A better way would be to maintain this information yourself whenever a thread enters/exits the critical section.

梦幻的味道 2024-10-11 06:24:30

你的要求没有意义。如果当前线程不是临界区中的线程,那么当前线程中的代码将不会运行,在尝试锁定临界区时会被阻塞。

如果您的线程实际上位于关键部分内,那么您的断言将始终为真。如果不是,你的断言将永远是错误的!

所以我的意思是,假设您能够跟踪哪个线程位于关键部分,如果您将断言放在关键部分代码中,那么它将始终为真。如果你把它放在外面,它总是错误的。

Your requirement doesn't make sense. If your current thread is not the thread which is in the critical section, then the code within the current thread won't be running, it'll be blocked when trying to lock the critical section.

If your thread is actually inside the critical section, then your assertion will always be true. If it's not, your assertion will always be false!

So what I mean is, assuming you're able to track which thread is in the critical section, if you place your assertion inside the critical section code, it'll always be true. If you place it outside, it'll always be false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文