Nicholas Wilson によって提案されたもの以外のコンパイル時の検出を取得することは、不可能ではないにしても非常に困難ですが、「バックグラウンド」が実際には複数のスレッドではなく関数を参照していると仮定します (質問でスレッドについて言及されていないので、奇妙な言い回しだと思います)グローバルフラグとロッカーオブジェクトを簡単に使用してassert
、例外をスローするか、スローすることができます。または、デバッグメッセージを出力してください。もちろん、これはランタイムのみですが、犯罪者を非常に迅速に隔離できるはずです。また、デバッグ ビルドのオーバーヘッドは非常に低く (L1 キャッシュからの実行がほぼ保証されます)、リリース ビルドのオーバーヘッドはありません。
CaptureStackBackTraceを使用すると、問題のある関数のアドレスをキャプチャできるはずです。これは、ツールのようなものaddr2line
(または MS に相当するもの) がコード内の行に直接変換できます。おそらく、この翻訳を直接実行できるツールヘルプ機能さえあるでしょう (私にはわかりませんが)。
したがって、次のようなもの (テストされていません!) でうまくいく可能性があります。
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 によって提案されたクリティカル セクションを使用するアプローチはデッドロックする可能性があります!)。カウンターはこれを防ぎます。int
スレッドが存在する場合は、 に置き換えることstd::atomic_int
もできます。
編集:実際に2つのスレッド
が実行
されていることが明らかになったため、そのうちの1つ(「高速」スレッド)が「低速」関数を呼び出さないことだけが重要であるため、別の単純で機能するソリューションがあります(使用する例Win32 API ですが、どちらの方法でも POSIX で実行できます):
「高速」スレッドが起動すると (「低速」スレッドはこれを行う必要はありません)、スレッド ID をグローバル変数として、またはすべての高速/低速関数を含むオブジェクトのメンバーとして、どこかに保存します。アクセス可能な場所:
global::fast_thread_id = GetCurrentThreadId();
「歓迎されない」関数呼び出しを回避するマクロは、次のようになります。
#define CHECK_FAST_THREAD assert(GetCurrentThreadID() != global::fast_thread_id)
このマクロは、「高速」スレッドから呼び出されてはならない「低速」関数に追加されます。高速スレッドが呼び出してはならない関数を呼び出すと、アサートがトリガーされ、どの関数が呼び出されたかがわかります。