有序非重入调用的简单断言?
我有两个函数:
void prepare() 和 void finish() ,它们将按顺序调用,如下所示:
prepare();
<do something>;
finish();
...
prepare();
<do something>;
finish();
我想做一个简单的断言来简单地测试它们实际上是这样调用的,并且它们不是同时调用的应用程序中无序。
该应用程序是单线程应用程序。这是一个简单的开发/测试健全性检查,以确保这些函数按顺序调用,并且无论出于何种原因,它们都不会同时调用。此外,这些断言/健全性检查应该从生产代码中省略,因为性能至关重要!
像这样的简单的assert()效果最好吗?
int test = 0;
void prepare() {
assert(++test == 1);
.
.
.
}
void finish() {
assert(--test == 0);
.
.
.
}
I have two functions:
void prepare() and void finish() that will be called sequentially like:
prepare();
<do something>;
finish();
...
prepare();
<do something>;
finish();
I want to make a simple assertion to simply test that they are in fact being called this way and that they aren't being called concurrently or out-of-order in the application.
This application is a single-threaded application. This is a simple development/testing sanity check to make sure that these functions are being called in-order and that for whatever reason, they aren't being called concurrently. Furthermore, these assertions/sanity checks should be omitted from production code as performance is crucial!
would a simple assert() like this work best?
int test = 0;
void prepare() {
assert(++test == 1);
.
.
.
}
void finish() {
assert(--test == 0);
.
.
.
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可能希望更改
为
满足“应从生产中省略与此测试相关的任何代码”的要求。
You might want to change
to
to satisfy your requirement that "any code relating to this test should be omitted from production".
你可能想要:
you probably want:
这里存在一个竞争条件:
prepare
的两个并发实例可能会同时获取test
的值,然后都在寄存器中递增该值以获得1
,然后进行比较以获得true
。使其
易失
是There's a race condition here: two concurrent instances of
prepare
might take the value oftest
at the same time, then both increment it in a register to both obtain1
, then do the comparison to gettrue
.Making it
volatile
is not going to help. Instead, you should put a mutex ontest
, like so:您的代码没问题,除非您需要允许嵌套
prepare
和finish
调用。如果不允许嵌套,您可以使用
bool
代替int
:Your code is OK, unless you need to allow nesting
prepare
andfinish
calls.If nesting is not allowed, you could use a
bool
instead of anint
:如果将
>;
放入class
中,则可以完全减少检查的需要:只需让构造函数调用
prepare
析构函数调用finish
。然后它会自动强制正确调用它们。请注意,并发和嵌套问题仍然适用:如果您想防止嵌套,那么您仍然需要某种全局状态(静态类成员?)来跟踪它,并且如果它用于多个线程访问该状态计数器需要受到互斥保护。
另请注意,您还可以将运算符设为私有 new/delete ,以防止有人在堆上创建一个运算符而不销毁它。
If you put
<do something>;
into aclass
you can reduce the need for a check at all:Just have the constructor call
prepare
and the destructor callfinish
. Then it's automatically enforced that they're called appropriately.Note that concurrency and nesting issues still apply: If you want to prevent nesting then you'd still need some sort of global state (static class member?) to keep track of that, and if it's used in more than one thread access to that counter would need to be mutex protected.
Also note that you could also make private
operator new/delete
to prevent someone from creating one on the heap and not destroying it.既然您使用的是 C++,为什么不使用 RAII?您仍然需要检查可重入使用,但 RAII 大大简化了事情。与 NDEBUG 中的 larsmans' mutex 和 Raedwald 消除相结合:
在示例中,如果没有先准备,您就无法执行某些操作,并且即使抛出异常,也总是会完成。
关于 NDEBUG 的旁注:如果您以这种方式使用它,请确保它在所有翻译单元中始终定义或始终未定义,而不是它用于断言的方式(允许定义和未定义)在不同的点)。
Since you're using C++, why not use RAII? You'd still need to check for re-entrant use, but RAII simplifies things considerably. Combined with larsmans' mutex and Raedwald's elimination in NDEBUG:
Inside example, you simply cannot do something without first preparing, and finishing will always happen, even if an exception is thrown.
Side note about NDEBUG: if you use it this way, make sure it is either always defined or always undefined in all translation units, as opposed to how it's used for assert (allowing it to be defined and undefined at various points).