1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

SysWait() in v12.10 ... broken?

Discussion in 'Plugins' started by vefatica, Mar 25, 2011.

  1. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    This sort of routine works great in v11.

    Code:
    VOID WaitUntilTickCount64 ( ULONGLONG ullTickCountDue )
    {
        while ( TickCount64() < ullTickCountDue )
        {
            SysWait(0,2);
        }
    }
    In v12.10, SysWait(0,2) never returns.
     
  2. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    I wasn't finished with that last post. In v12.10 SysWait(0,2) (or any number of milliseconds) never returns, regardless of how I use it.

    And if I change that to SysWait(1,0) in the WaitUntilTickCount64() function below, then, after 2 or 3 times through the loop, I get an access violation. FWIW, I get TickCount64() like this:

    Code:
    ULONGLONG TickCount64()
    {
        ULONGLONG ullPerfCount;
        QueryPerformanceCounter((LARGE_INTEGER*) &ullPerfCount);
        return ullPerfCount / (global.ullPerfFreq / 1000); // ms
    }

     
  3. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    Hadn't we agreed in a previous thread that there wasn't any reason for you to be using SysWait? Unless you know the intimate details of SysWait (and you don't!) you shouldn't go near it.

    (And SysWait for 1 or 2 milliseconds is never going to work, because it will sleep more than that before doing the check.)
     
  4. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,177
    Likes Received:
    11
    Vince,

    In the event plugin I wrote, I use the
    following construct in my EventWait function:

    do

    sleep for 100 ms

    check for doneness

    tty_yield(0)
    loop


    That allows Ctrl-C processing to abort
    the wait as well as allow other stuff to happen. It has a granularity
    of 100ms.
    Did you need a high performance counter?
    Or do you just need to delay a certain number of milliseconds?

    I'm not familiar with the SysWait()
    function. Is that a Win32 API or TCMD API?

    -Scott


    vefatica <> wrote on 03/25/2011
    02:52:21 PM:


    (or

    it.



    ms

     
  5. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Fri, 25 Mar 2011 16:05:17 -0400, you wrote:

    |Hadn't we agreed in a previous thread that there wasn't any reason for you to be using SysWait? Unless you know the intimate details of SysWait (and you don't!) you shouldn't go near it.
    |
    |(And SysWait for 1 or 2 milliseconds is never going to work, because it will sleep more than that before doing the check.)

    I believe we did not discuss SysWait() at all (at least in several years).

    It does work well.

    I can

    Code:
    typedef VOID *(WINAPI *SYSWAITTYPE)(ULONGLONG, INT);
    HMODULE hTC = GetModuleHandle(L"TakeCmd.DLL");
    syswait = (SYSWAITTYPE) GetProcAddress(hTC, "SysWait");
    and that works well in v12.10. But it also gets it from earlier versions of the
    DLL though in which case, the signature is wrong and it doesn't work correctly.
    I suppose I could test _VERSION and decide whether to do that.

    In another recent post, samintz said he gets signal handling when he loops
    arounf Sleep() and tty_yield(0). I don't. ... ???
     
  6. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Fri, 25 Mar 2011 16:16:14 -0400, you wrote:

    |Vince,
    |
    |In the event plugin I wrote, I use the
    |following construct in my EventWait function:
    |
    | do
    |
    | sleep for 100 ms
    |
    | check for doneness
    |
    | tty_yield(0)
    | loop
    |
    |
    |That allows Ctrl-C processing to abort
    |the wait as well as allow other stuff to happen. It has a granularity
    |of 100ms.
    |Did you need a high performance counter?
    | Or do you just need to delay a certain number of milliseconds?
    |
    |I'm not familiar with the SysWait()
    |function. Is that a Win32 API or TCMD API?

    It's a TCMD API (see the header). Apparently in a recent change, its first arg
    went from DWORD to ULONGLONG.

    When I just loop around Sleep() and tty_yield(0), I don't get Ctrl-C handling
    ... have always had to add/remove my own handler for that.
     
  7. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    P.S., with SysWait() I get Ctrl-C handling free.
     
  8. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Fri, 25 Mar 2011 16:29:35 -0400, you wrote:

    ||(And SysWait for 1 or 2 milliseconds is never going to work, because it will sleep more than that before doing the check.)

    Sleep() has the same granularity problems (~10ms or ~16ms) doesn't it?
     
  9. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    First, your SysWait call is trying to wait 0 milliseconds, which seems pretty pointless. You're doing a lot of heavy lifting inside SysWait setting everything up, and then throwing it all away immediately.

    Second, if you want to sleep for a millisecond or two using Sleep(), you just need to adjust your timer resolution. (See the Sleep() docs for details.) If you just want to give up your time slice, use Sleep(0).
     
  10. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    tty_yield(0) does service the message queue, though only if there's a message already waiting.
     
  11. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Sat, 26 Mar 2011 09:45:59 -0400, you wrote:

    |---Quote (Originally by vefatica)---
    |In another recent post, samintz said he gets signal handling when he loops
    |arounf Sleep() and tty_yield(0). I don't. ... ???
    |---End Quote---
    |tty_yield(0) does service the message queue, though only if there's a message already waiting.

    My point was that **I** must add a ConsoleCtrlHandler if I want to interrupt
    this loop:

    Code:
    VOID WaitUntilTickCount64 ( ULONGLONG ullTickCountDue )
    {
    	while ( TickCount64() < ullTickCountDue )
    	{
    		Sleep(1);
    		tty_yield(0);
    	}
    }
    while SysWait() (apparently) adds one for me. Isn't that correct?

    But not I see that SysWait() adding/removing a ConsoleCtrlHandler every few
    milliseconds is inefficient (when I could do it just once outside the wait
    loop).
     
  12. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    No; SysWait does not set a ctrl handler.
     
  13. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Sat, 26 Mar 2011 12:51:18 -0400, you wrote:

    |No; SysWait does not set a ctrl handler.

    That's really odd since I get one with SysWait() and I don't with {Sleep(1);
    tty_yield(0);}.
     
  14. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    SysWait does this at the end of its loop:

    // check for an unhandled ^C in the exception thread
    if ( aGlobals.fBreak )
    BreakHandler();

    Which just checks to see if somebody hit a ^C. But it definitely does not
    install / remove a control handler.
     
  15. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    I ]m allowing breaking out of a wait loop like this:

    Code:
    VOID WaitUntilTickCount64 ( ULONGLONG ullDue )
    {
        while ( TickCount64() < ullDue && bContinue )
        {
            Sleep(1);
            tty_yield(0);
        }
        bContinue = TRUE;
        SetConsoleCtrlHandler(WaitCtrlHandler, FALSE);
    }
    where I add the Ctrl handler before calling the wait function. The handler just sets bContinue to FALSE. Is that kosher? How would you do it in a plugin?
     
  16. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    I wouldn't do it that way (which will mangle the existing handler, fail to execute any ON BREAK statements, and fail to shut down hooks).

    TCC already has a handler running, which sets aGlobals.fBreak to 1 whenever a ^C or ^Break is entered -- just check for that in your loop.
     
  17. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Sun, 27 Mar 2011 22:33:11 -0400, you wrote:

    |TCC already has a handler running, which sets aGlobals.fBreak to 1 whenever a ^C or ^Break is entered -- just check for that in your loop.

    That would be nice, but how do I check aGlobals? Is a pointer to it exported
    ... it's members documented?
     
  18. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Sun, 27 Mar 2011 23:19:33 -0400, you wrote:

    ||TCC already has a handler running, which sets aGlobals.fBreak to 1 whenever a ^C or ^Break is entered -- just check for that in your loop.
    |
    |That would be nice, but how do I check aGlobals? Is a pointer to it exported
    |... it's members documented?

    I'm eagerly looking forward to hearing about this.
     
  19. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    Apparently, the address of aGlobals is exported:

    Code:
    ?aGlobals@@3UGLOBAL_VARIABLES@@A
    Also apparently, the fBreak member is at byte offset 44 (that byte changes from 0 to 1 when Ctrl-C or Ctrl-Break is pressed).

    Testing that in my wait loop as you suggested works quite well, saving me adding a console ctrl handler (and possibly screwing up yours). I could eliminate ctrl handlers in four of 4UTILS commands, simplifying my coding and probably saving on dll size.

    Is it correct that fBreak is at byte offset 44? Is it likely to stay there. What's its type? [Actually, just testing the byte works.]
     
  20. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    there. What's

    The aGlobals structure changes in every new version, but (not 100%
    guaranteed!) new fields are added to the end.

    Rex
     
  21. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    Thanks. In the event the offset changed, the plugin author could do nothing, even knowing the aGlobals declaration. fBreak is useful. Would you consider exporting its location? ... should be a one-liner and very of little cost to the binary ... even decorated ... it'd be easy enough to get at it.
     
  22. Charles Dye

    Charles Dye Super Moderator
    Staff Member

    Joined:
    May 20, 2008
    Messages:
    3,277
    Likes Received:
    38
    Is this stuff documented somewhere, and I'm just to stupid to find/recognize it? Are there other useful variables in aGlobals? Or is this the kind of private internal stuff that it would be catastrophically dumb to rely upon?
     
  23. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Fri, 01 Apr 2011 22:35:12 -0400, you wrote:

    |---Quote (Originally by rconn)---
    |The aGlobals structure changes in every new version, but (not 100% guaranteed!) new fields are added to the end.
    |---End Quote---
    |Is this stuff documented somewhere, and I'm just to stupid to find/recognize it? Are there other useful variables in aGlobals? Or is this the kind of private internal stuff that it would be catastrophically dumb to rely upon?

    I first heard of it when Rex suggested testing the fBreak member instead of
    installing my own console ctrl handler. I looked around in it a bit and saw
    some stuff you might expect ... startup (?) directory, ini file name, tcstart
    file name, a couple of familiar-looking numerical constants. But I may have
    been looking well beyond it ... found the tcstart file name at byte-offset
    316040!. If you've followed this thread you see the value of the fBreak member.
    I don't know what else might be of interest that we can't already get at (except
    possibly the tcstart file name which I'd like in a variable). Maybe Rex will
    say more.

    I searched my news server archives (tens of thousands of posts) and found one
    mention of aGlobals ... in a 6-7 year-old user-posted assembly language patch to
    fix something having to do with MBCS characters.
     
  24. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    vefatica:
    ...
    | the tcstart file name which I'd like in a variable

    I just test inserting the command
    @set tcstart=%_batchname
    in my TCSTART.BTM.

    It does exactly that! BTW, I did it BEFORE detecting PIPE etc... - thus it
    is exactly what in internal variable would contain.
    --
    Steve
     
  25. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,726
    Likes Received:
    80
    It's not documented because (1) it changes in every version (and sometimes between builds), and (2) you can do irreperable harm by accessing the wrong fields. (Which might not show up until much later!)
     
  26. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,782
    Likes Received:
    29
    On Sat, 02 Apr 2011 08:48:31 -0400, you wrote:

    |vefatica:
    |...
    || the tcstart file name which I'd like in a variable
    |
    |I just test inserting the command
    | @set tcstart=%_batchname
    |in my TCSTART.BTM.
    |
    |It does exactly that! BTW, I did it BEFORE detecting PIPE etc... - thus it
    |is exactly what in internal variable would contain.

    Yes, I know, and then it would be in the environment. And I could do the same
    with _STARTPATH and maybe a few others. Everyone who was interested could do
    it. Or TCC could do it, just once, and everyone could use it.
     

Share This Page