Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Getting a compile-time detection other than the one proposed by Nicholas Wilson will be extremely hard if not impossible, but assuming "background" really refers to the functions, and not to multiple threads (I saw no mention of threads in the question, so I assume it's just an odd wording) you could trivially use a global flag and a locker object, and either <code>assert</code> or throw an exception. Or, output a debug message. This will, of course, be runtime-only -- but you should be able to very quickly isolate the offenders. It will also be very low overhead for debug builds (almost guaranteed to run from L1 cache), and none for release builds.</p> <p>Using <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx" rel="nofollow">CaptureStackBackTrace</a>, one should be able to capture the offending function's address, which a tool like <code>addr2line</code> (or whatever the MS equivalent is) can directly translate to a line in your code. There is probably even a toolhelp function that can directly do this translation (though I wouldn't know).</p> <p>So, something like this (untested!) might do the trick:</p> <pre><code>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, &amp;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 }; </code></pre> <p>The only real downside (apart from not being compile-time) is you have to mark each and every slow and realtime function with either marker, but since the compiler cannot magically know which is what, there's not much of a choice anyway.</p> <p>Note that the global "flag" is really a <em>counter</em>, not a flag. The reason for this is that a slow function could immediately call another slow function that returns and clears the flag -- incorrectly assuming a fast function now (the approach with critical sections suggested by xgbi might deadlock in this case!). A counter prevents this from happening. In presence of threads, one might replace <code>int</code> with <code>std::atomic_int</code>, too.</p> <p><strong>EDIT:</strong><br> As it is clear now that there are really <strong>2 threads</strong> running, and it only matters that one of them (the "fast" thread) does not ever call a "slow" function, there is another simple, working solution (example using Win32 API, but could be done with POSIX either way):</p> <p>When the "fast" thread starts up (the "slow" thread does not need to do this), store the thread ID somewhere, either as global variable, or as member of the object that contains all the fast/slow functions -- anywhere where it's accessible:</p> <pre><code>global::fast_thread_id = GetCurrentThreadId(); </code></pre> <p>The macro to bail out on "unwelcome" function calls could then look like:</p> <pre><code>#define CHECK_FAST_THREAD assert(GetCurrentThreadID() != global::fast_thread_id) </code></pre> <p>This macro is then added to any "slow" function that should never be called from the "fast" thread. If the fast thread calls a function that it must not call, the assert triggers and it is known which function is called.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload