更多信息,慢速和关键功能都是同一类的一部分,并共享相同的标题.
一些更多信息,关键功能在非常快的线程(> 10KHz)下运行,较慢的线程在不同的较慢线程(< = 1KHz)下运行.使用慢函数中的关键部分来保护类成员变量,因为它们都使用相同的类成员变量.这就是在关键功能中调用慢功能的原因会降低整体系统性能.这就是为什么我喜欢自动找到所有这些功能而不是手动检查. 谢谢….
解决方法
使用CaptureStackBackTrace,应该能够捕获违规函数的地址,像addr2line这样的工具(或者等价的MS)可以直接转换为代码中的一行.甚至可能有一个toolhelp函数可以直接进行这种翻译(虽然我不知道).
所以,这样的事情(未经测试!)可能会做到这一点:
namespace global { int slow_flag = 0; } struct slow_func_locker { slow_func_locker() { ++global::slow_flag; } ~slow_func_locker(){ --global::slow_flag; } }; #indef NDEBUG #define REALTIME if(global::slow_flag) \ { \ void* backtrace; \ CaptureStackBackTrace(0,1,&backtrace,0); \ printf("RT function %s called from %08x\n",__FUNCTION__,backtrace); \ } #define SLOW_FUNC slow_func_locker slow_func_locker_; #else #define REALTIME #define SLOW_FUNC #endif foo_class::some_realtime_function(...) { REALTIME; //... }; foo_class::some_slow_function(...) { SLOW_FUNC; //... some_realtime_function(blah); // this will trigger };
唯一真正的缺点(除了不是编译时)你必须用任何一个标记来标记每个慢速和实时功能,但由于编译器不能神奇地知道哪个是什么,所以无论如何都没有多少选择.
请注意,全局“标志”实际上是一个计数器,而不是一个标志.原因是慢速函数可以立即调用另一个返回并清除标志的慢速函数 – 错误地假设现在有一个快速函数(在这种情况下xgbi建议的关键部分的方法可能会死锁!).计数器可以防止这种情况发生.在存在线程的情况下,也可以用std :: atomic_int替换int.
编辑:
现在很清楚,实际上有2个线程正在运行,并且只关注其中一个(“快速”线程)不会调用“慢”函数,还有另一个简单,有效的解决方案(使用Win32 API的示例),但可以用POSIX完成任何一种方式):
当“快速”线程启动时(“慢”线程不需要这样做),将线程ID存储在某处,作为全局变量,或作为包含所有快/慢功能的对象的成员 – 在任何地方在哪里可以访问:
global::fast_thread_id = GetCurrentThreadId();
#define CHECK_FAST_THREAD assert(GetCurrentThreadID() != global::fast_thread_id)
然后将此宏添加到任何“慢”函数中,该函数永远不应从“快速”线程调用.如果快速线程调用它不能调用的函数,则断言触发并且知道调用哪个函数.