Calling TestBreak from non-Cinema thread



  • On 05/02/2016 at 02:06, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R17 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    I've hit some problems on R17 with using TestBreak from thread that was not created via C4DThread. I am trying to achieve something like this:

    // Threaded callback function executed from thirdparty library
    void threadedCallback(BaseThread* originalThread)
    {
       ...
       if (originalThread->TestBreak()) return;
       ...
    }
      
    // Function executed inside C4D thread
    void foo(BaseThread* thread, ...)
    {
        // Call (blocking) multithreaded function of thirdparty library
        thirdparty_class->processData(threadedCallback, thread);
    }
    

    Here  _thirdparty_class- >processData() _is implemented in thirdparty library (that I have no control over implementation) and it starts several new threads, each will eventually call  threadedCallback(). Now because   threadedCallback() takes quite long time to finish, I need to check for user interruption of original C4D thread. Unfortunatelly, calling TestBreak crashes C4D (note that this worked before R17).

    I can guess this is because C4D tries to find some info about calling thread in its internal structures and it crashes because it did not created calling thread. Am I correct with this assumption? If so, is there some reasonable way how to solve this?

    Note that currently I am solving this by using extra bool flag that I set from C4D thread and check in threadedCallback, ie:

    volatile bool break_flag;
      
    // Threaded callback function executed from thirdparty library
    void threadedCallback(BaseThread* originalThread)
    {
       ...
       if (break_flag) return;
       ...
    }
      
    // Function executed inside C4D thread
    void foo(BaseThread* thread, ...)
    {
        break_flag = false;
      
        // Call (non-blocking) multithreaded function of thirdparty library
        thirdparty_class->processDataNonBlocking(threadedCallback, thread);
      
        while (thirdparty_class->isRunning())
        {
            if (thread->TestBreak()) break_flag = true;
            GeSleep(100);
        }
    }
    

    Obviously this is not good solution, so I would like to find a way without active waiting...



  • On 05/02/2016 at 04:57, xxxxxxxx wrote:

    Are you sure that the BaseThread is alive for the entire time that the threadedCallback() runs?



  • On 05/02/2016 at 12:41, xxxxxxxx wrote:

    Yes, because foo() is called in thread belonging to this BaseThread. Also, second variant with active waiting works ok and the lifetime of BaseThread is the same in both situations.
    There is one thing I forgot to mention in previous post - the foo is in fact called from Execute() in video post, so the BaseThread is not actually created by my code, but it is vps.thread executed by C4D. But I believe there shouldn't be difference.



  • On 08/02/2016 at 05:34, xxxxxxxx wrote:

    not sure but what works for me:
    there is a test function in the dll that checks for the break.
    this function is actually a function pointer, it runs the test break and works fine.



  • On 09/02/2016 at 01:27, xxxxxxxx wrote:

    Hello,

    we asked your development and all they can imagine is also that the BaseThread has finished at some point and is no longer valid. So at least a nullptr check should be added.

    Best wishes,
    Sebastian



  • On 10/02/2016 at 04:52, xxxxxxxx wrote:

    So it is probably something on my side. Strange thing is the same code works in R14-R16 (even the same binary when compiled agains R14 api). I will try to do some more checking (nullptr check won't help as I'm already verifying BaseThread before it is passed to subthreads), examine execution times of each thread and write here some more info if I find anything...

    Thanks for answers.


Log in to reply