Announcement

Collapse
No announcement yet.

WGFMO or SetTimer

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • WGFMO or SetTimer

    Hi,

    I noticed during heavy (multi-user) stress testing the there's a problem with the TIMER function.
    I looked it up on the forum, and yes, code like this is not thread-safe
    Code:
    local lresult    as long
    dim hThread(1)   as local long
    
    local UDT1       as MyType PTR  
    
    CoTaskMemAlloc (SIZEOF(@UDT1)
    @UDT1.CounterValue = 0           ' can be set to -1 by the caller to interrupt the thread and make it close
    @UDT1.Result       = 0           ' will provide a result. If thread finishes without result, it will become -1.
    
    LOCAL Timer1     as double
    
    THREAD CREATE MyThread0 (@UDT1) TO hThread(0)
    SLEEP 1
    THREAD CREATE MyThread1 (@UDT1) TO hThread(1)
    SLEEP 1
    
    Timer1 = TIMER
    DO WHILE @UDT1.result = 0
        SLEEP 1
        IF TIMER - Timer1 > 5 THEN         ' this the problem!
            @UDT1.CounterValue = -1
            EXIT DO
        END IF
    LOOP
    
    ' handle results
    IF @UDT1.result = -1 THEN         
        ' failure
    ELSEIF @UDT1.result > 0 then
        ' success of one of the threads
    ELSEIF @UDT1.CounterValue = -1 THEN
        ' 
    END IF
    
    THREAD CLOSE hThread(0) TO lResult
    THREAD CLOSE hThread(1) TO lResult
    OK, so I stripped the TIMER and just let the threads finish. Tested OK.

    Now how can I solve this?? I looked at SetTimer but it seems that I need a handle to a window. My program is solely Dlls so I have no handle.
    I thought of WAITFORMULTIPLEOBJECTS but that's where I got stuck. I must be missing something.
    Here's some example code:
    Code:
    local lresult    as long
    dim hThread(1)   as local long
    
    local UDT1       as MyType PTR  
    
    CoTaskMemAlloc (SIZEOF(@UDT1)
    @UDT1.CounterValue = 0           ' can be set to -1 by the caller to interrupt the thread and make it close
    @UDT1.Result       = 0           ' will provide a result. If thread finishes without result, it will become -1.
    
    
    THREAD CREATE MyThread0 (@UDT1) TO hThread(0)
    SLEEP 1
    THREAD CREATE MyThread1 (@UDT1) TO hThread(1)
    SLEEP 1
    
    local WaitingTime      as double
    WaitingTime = 5000
    
    result& = WAITFORMULTIPLEOBJECTS(2, hThread(0), %FALSE, WaitingTime)
    
    ' handle results
    IF @UDT1.result = -1 THEN         
        ' failure
    ELSEIF @UDT1.result > 0 then
        ' success of one of the threads
    ELSEIF @UDT1.CounterValue = -1 THEN
        ' 
    END IF
    
    THREAD CLOSE hThread(0) TO lResult
    THREAD CLOSE hThread(1) TO lResult
    Yet, it doesn't wait!!! It just goes on and of course then @UDT1.result is still 0.
    What am I forgetting here???
    Or is there another way of doing this??

    Regards
    Jeroen



    ------------------

  • #2
    As I see it, your task is:

    "I want to interrupt an executing thread if it's been running too long".

    (If that's wrong, the rest of this will make no sense)

    WFMO is a pretty clever way of doing "Timer without a window," and gives you a solution based on, "what happens first: one thread ends or timeout period elapses?"

    But WFMO's result& is not the thread status: If WFMO returns WAIT_OBJECT_0 or WAIT_OBJECT_0 +1 , then one of the threads finished; if it returns WAIT_TIMEOUT, the timeout period has expired.

    As far I can tell, your "signal" to the thread to quit because it's been running too long is OK, but without seeing the thread fucntion itself, it's hard to tell if the thread has a chance to read your signal.

    Why don't you post the thread function and we can all take a look.


    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Hi Michael,

      Thanks for your reply.
      One part of the problem I solved: setting the FUNCTION = seems to trigger a callback (which I didn't want).
      Yet, if my second thread does nothing more than sleep
      Code:
      for i = 1 to 70
         sleep 100
      next i
      The WaitForMultipleObject continues without waiting. The result = -1 (all the time), so it's neither WAIT_OBJECT_0 or WAIT_OBJECT_0 +1 nor WAIT_TIME.
      What this problem is, I don't now.

      I haven't had the change to write the code for the second thread yet. When I changed my code to one thread, using WaitforSingleObject the problem is gone.

      I still don't know what this is. I hope that it will 'go away' once I code my second thread but I know that's kind of silly.

      If you've had this before, please let me know.

      Regards
      Jeroen

      ------------------

      Comment


      • #4
        When "Result& = -1" it means WAIT_FAILED (which, by the way, is not in my Win32API.inc file).

        When WaitForMultipleObjects returns this, you need to call GetLastError to find out why WAIT_FAILED and fix up whatever is wrong.

        Your setup and call look OK, so I think we need that GetLastError value to figger out what's wrong.

        You should also note that THREAD CLOSE does not terminate the thread; it only closes your process's access to the thread.

        MCM


        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          %WAIT_FAILED has been in Win32API.inc for over a year. It is currently
          defined as &HFFFFFFFF??? which would be equivalent to -1 if assigned to
          a LONG. The latest Win32API files may be found here.

          ------------------
          Tom Hanlin
          PowerBASIC Staff

          Comment


          • #6
            Jeroen,

            You should test on result& instead of @UDT1.result....
            Code:
            Result& = WAITFORMULTIPLEOBJECTS(2, hThread(0), %FALSE, 5000)
            Select Case Result&
              Case %WAIT_FAILED
            ' Do whatever on waitevent failure (should normally never happen)
              Case %WAIT_OBJECT_0
            ' Do whatever needed if thread #1 ends...
              Case %WAIT_OBJECT_0 +1
            ' Do whatever needed if thread #2 ends...
              Case %WAIT_TIMEOUT
            ' Do whatever on timeout (5000ms elapsed without event)
            End Select
            Be sure threads are up and running before calling waitformultipleobjects, or
            it'll generate a %WAIT_OBJECT_.. immediately also...
            ------------------
            Peter.
            mailto[email protected][email protected]</A>



            [This message has been edited by Peter Lameijn (edited August 29, 2001).]
            Regards,
            Peter

            "Simplicity is a prerequisite for reliability"

            Comment


            • #7
              Thanks everyone,

              When I was searching for the problem, I already found that I should check result& ( the UDT is solely MY result). So Peter, thanks.
              Michael, good that you pointed this out. I didn't find anything on WAIT_FAILED so far (strange!) but I'll have a look with GetLastError on what's wrong.

              I'm learning (slowly).

              I'll let you know how far I get.

              Regards
              Jeroen




              ------------------

              Comment

              Working...
              X