lock_guard 在 if-initializer 而不是简单作用域中初始化
lock_guard initialization in if-initializer instead of simple scope
这样说对吗
if (std::lock_guard lk(m_state.mtx); true) {
m_state.aborting = true;
}
和
{
std::lock_guard lk(m_state.mtx)
m_state.aborting = true;
}
100% 相同?
这是我的问题的背景:在掌握C++17 STL中,作者给出了一个线程池的代码示例。它包含以下块(第 208 页):
~ThreadPool() {
if (std::lock_guard lk(m_state.mtx); true) { // <<--- Line of interest
m_state.aborting = true;
}
m_cv.notify_all();
for (std::thread& t : m_workers) {
t.join();
}
}
标记的行使用 if 语句的初始化部分来创建 lock_guard。这已在 中使用,以便将 lock_guard 的范围限制在 if 语句中,同时保护 if 语句本身的评估。
在这个例子中让我感到困惑的是 if 语句没有合适的条件。根据 cppreference page on if,
If init-statement is used, the if statement is equivalent to
{
init_statement
if ( condition )
statement-true
}
在这种情况下,这意味着 if (std::lock_guard lk(m_state.mtx); true) {...}
等同于
{
std::lock_guard lk(m_state.mtx);
if (true) {
m_state.aborting = true;
}
}
我是否遗漏了这不是 100% 相同的情况,或者它是用 if 语句编写的充分理由?
在下一页的不同示例中使用了相同的模式,所以我认为这是故意的,而不是实际情况下的遗留问题。
它们在语义上是相同的。由于这本书似乎都是关于新的 C++ 17 特性的,所以作者使用它是有道理的。但要小心:在尘埃落定之前,每个新功能都会被滥用,并且常识对使用该功能的好方法和坏方法达成共识。
以我的拙见,这种方式只会增加混乱(如果无条件执行该块,为什么会有 if 构造?)我更喜欢简单的块。时间会证明作者的方式是否会成为可接受的或不受欢迎的结构。或者,如果没有人会关心,或者它是否会永远存在争议。
我是 掌握 C++17 STL 的作者。
我已经忘记了那个结构,所以我使用它不可能有任何重要的原因。我相信伊戈尔是正确的:选择应该在
之间
~ThreadPool() {
if (std::lock_guard lk(m_state.mtx); true) {
m_state.aborting = true;
}
m_cv.notify_all();
for (std::thread& t : m_workers) {
t.join();
}
}
以及诸如
之类的东西
~ThreadPool() {
if (true) {
std::lock_guard lk(m_state.mtx);
m_state.aborting = true;
}
m_cv.notify_all();
for (std::thread& t : m_workers) {
t.join();
}
}
它做同样的事情(可以说更清晰)但是在实体书中多了一行代码。
就我个人而言,我不喜欢只写{
来打开一个块;我总是宁愿写if (true) {
。这有助于 reader 理解 if
并非意外遗漏(或合并冲突);程序员确实打算将块 运行 始终 。如果你像我(经常)那样一直抱住你所有的牙套,那么它也会保持不变,即你永远不会有一个 {
或 }
单独坐在一条线上——不管它是什么价值
那里发生的另一件事是,它专门在通知条件变量的上下文中。我以前肯定写过
std::lock_guard lk(m_state.mtx);
m_state.aborting = true;
m_cv.notify_all();
notify
发生在锁的范围内;多年来,我经常听到“你应该在 通知之前释放锁”,以至于最终我也开始这么说(尽管我对 [=47= 仍然没有很好的直觉) ]为什么 应该是这样)。这实际上是我写这本书的五年前的第四个 SO 问题的主题:C++11 std::condition_variable: can we pass our lock directly to the notified thread?
所以我可能在编写这个特定片段时分心(思考不足)and/or 自我意识(思考过多),这可能导致我尝试这个特殊的奇怪结构。[=23=]
下一页的例子实际上是条件变量完全:
void enqueue_task(UniqueFunction task) {
if (std::lock_guard lk(m_state.mtx); true) {
m_state.work_queue.push(std::move(task));
}
m_cv.notify_one();
}
线程安全方面,这完全等同于
void enqueue_task(UniqueFunction task) {
std::lock_guard lk(m_state.mtx);
m_state.work_queue.push(std::move(task));
m_cv.notify_one();
}
除了人们一直告诉我不要把通知放在锁里。因此 if (...; true)
版本勉强满足了这一流行的智慧,同时只花费一行代码而不是两行代码。
甚至有可能我最初是在锁定状态下通知的,然后这本书的一位技术审阅者说“不要在锁定状态下通知”,然后我做了这个最新的更改来专门处理这个问题最少的行数。我不记得这是否是真实的故事,但对我来说这很合理。
这样说对吗
if (std::lock_guard lk(m_state.mtx); true) {
m_state.aborting = true;
}
和
{
std::lock_guard lk(m_state.mtx)
m_state.aborting = true;
}
100% 相同?
这是我的问题的背景:在掌握C++17 STL中,作者给出了一个线程池的代码示例。它包含以下块(第 208 页):
~ThreadPool() {
if (std::lock_guard lk(m_state.mtx); true) { // <<--- Line of interest
m_state.aborting = true;
}
m_cv.notify_all();
for (std::thread& t : m_workers) {
t.join();
}
}
标记的行使用 if 语句的初始化部分来创建 lock_guard。这已在
在这个例子中让我感到困惑的是 if 语句没有合适的条件。根据 cppreference page on if,
If init-statement is used, the if statement is equivalent to
{ init_statement if ( condition ) statement-true }
在这种情况下,这意味着 if (std::lock_guard lk(m_state.mtx); true) {...}
等同于
{
std::lock_guard lk(m_state.mtx);
if (true) {
m_state.aborting = true;
}
}
我是否遗漏了这不是 100% 相同的情况,或者它是用 if 语句编写的充分理由?
在下一页的不同示例中使用了相同的模式,所以我认为这是故意的,而不是实际情况下的遗留问题。
它们在语义上是相同的。由于这本书似乎都是关于新的 C++ 17 特性的,所以作者使用它是有道理的。但要小心:在尘埃落定之前,每个新功能都会被滥用,并且常识对使用该功能的好方法和坏方法达成共识。
以我的拙见,这种方式只会增加混乱(如果无条件执行该块,为什么会有 if 构造?)我更喜欢简单的块。时间会证明作者的方式是否会成为可接受的或不受欢迎的结构。或者,如果没有人会关心,或者它是否会永远存在争议。
我是 掌握 C++17 STL 的作者。
我已经忘记了那个结构,所以我使用它不可能有任何重要的原因。我相信伊戈尔是正确的:选择应该在
之间~ThreadPool() {
if (std::lock_guard lk(m_state.mtx); true) {
m_state.aborting = true;
}
m_cv.notify_all();
for (std::thread& t : m_workers) {
t.join();
}
}
以及诸如
之类的东西~ThreadPool() {
if (true) {
std::lock_guard lk(m_state.mtx);
m_state.aborting = true;
}
m_cv.notify_all();
for (std::thread& t : m_workers) {
t.join();
}
}
它做同样的事情(可以说更清晰)但是在实体书中多了一行代码。
就我个人而言,我不喜欢只写{
来打开一个块;我总是宁愿写if (true) {
。这有助于 reader 理解 if
并非意外遗漏(或合并冲突);程序员确实打算将块 运行 始终 。如果你像我(经常)那样一直抱住你所有的牙套,那么它也会保持不变,即你永远不会有一个 {
或 }
单独坐在一条线上——不管它是什么价值
那里发生的另一件事是,它专门在通知条件变量的上下文中。我以前肯定写过
std::lock_guard lk(m_state.mtx);
m_state.aborting = true;
m_cv.notify_all();
notify
发生在锁的范围内;多年来,我经常听到“你应该在 通知之前释放锁”,以至于最终我也开始这么说(尽管我对 [=47= 仍然没有很好的直觉) ]为什么 应该是这样)。这实际上是我写这本书的五年前的第四个 SO 问题的主题:C++11 std::condition_variable: can we pass our lock directly to the notified thread?
所以我可能在编写这个特定片段时分心(思考不足)and/or 自我意识(思考过多),这可能导致我尝试这个特殊的奇怪结构。[=23=]
下一页的例子实际上是条件变量完全:
void enqueue_task(UniqueFunction task) {
if (std::lock_guard lk(m_state.mtx); true) {
m_state.work_queue.push(std::move(task));
}
m_cv.notify_one();
}
线程安全方面,这完全等同于
void enqueue_task(UniqueFunction task) {
std::lock_guard lk(m_state.mtx);
m_state.work_queue.push(std::move(task));
m_cv.notify_one();
}
除了人们一直告诉我不要把通知放在锁里。因此 if (...; true)
版本勉强满足了这一流行的智慧,同时只花费一行代码而不是两行代码。
甚至有可能我最初是在锁定状态下通知的,然后这本书的一位技术审阅者说“不要在锁定状态下通知”,然后我做了这个最新的更改来专门处理这个问题最少的行数。我不记得这是否是真实的故事,但对我来说这很合理。