Tcl package Thread source code

Ticket Change Details
Login
Overview

Artifact ID: 6dd7409b18e374fa9325c0d117a684a2dd896b0e04b21aa93689222cb9ae1fb6
Ticket: b5709ea9060d17f58ba48110351c964b3408e362
[::thread::send -async] posting order not respected when sending to current thread
User & Date: adrianmedranocalvo 2018-07-31 16:22:35
Changes

  1. icomment:
    Hello sebres,
    
    there's definitely some misunderstanding.  English is not my mother language, it's not the first time I cause a mess...
    
    I'll try to explain with code.
    
    One important point is: I don't care about the order of [after idle] events nor [after 0] events with respect to [thread::send -async] events.  I only care about the order of [thread::send -async] events.
    
    Please, try the following script:
    
    ~~~
    package require Thread;
    
    set t(main) [::thread::id]
    set t(other) [::thread::create]
    
    # Let t(other) know the main thread's id, t(main).
    ::thread::send $t(other) [list array set t [array get t]]
    
    # Async thread::send to current thread (the main thread).
    # I expect this script to be inserted at the end of the thread event queue.
    ::thread::send -async $t(main) {
        lappend ::trace LOCAL-THREAD-SEND;
    }
    
    ::thread::send $t(other) {
        # Async thread::send to other thread (the main thread).
        # I expect this script to be inserted at the end of the
        # thread event queue, after the one above.
        ::thread::send -async $t(main) {
    	  lappend ::trace REMOTE-THREAD-SEND;
        }
    }
    
    after 100 {set forever 1};
    vwait forever;
    puts [join $::trace "\n"];
    ~~~
    
    This is the output:
    
    ~~~
    REMOTE-THREAD-SEND
    LOCAL-THREAD-SEND
    ~~~
    
    This is not expected, because the [thread::send -async] lappending LOCAL-THREAD-SEND ran before the one lappending REMOTE-THREAD-SEND.
    
    When I remove the following code:
      https://core.tcl-lang.org/thread/artifact?udc=1&ln=2742-2759&name=61003585d6458178&udc=1
    
    I obtain the expected output:
    
    ~~~
    LOCAL-THREAD-SEND
    REMOTE-THREAD-SEND
    ~~~
    
    Are there any downsides in removing the following code?
      https://core.tcl-lang.org/thread/artifact?udc=1&ln=2742-2759&name=61003585d6458178&udc=1
    
    ----------------------------------------
    
    I'll now try to respond to your points.
    
    > if you'll do that, the event will be appended directly into the queue of the thread, so in this case it will be not LAST (as by idle) but FIRST event (because timer events coming later via processing of event-sources).
    >
    > So again, it cannot be "on the order they were posted", because they are another types of events. It will be not between your timer-events, but either hereafter (like now) or before (if direct appended to event-queue). But definitely not between.
    
    I think that's what I want and expect, that the [thread::send -async] is appended to the queue of the thread.  I don't expect them to be handled between other types of events.
    
    > For this case "thread::send -async [thread::id]" should be quasi rewritten as "after 0", and I'm definitely against this, because it produces unexpected overhead.
    
    I'm also against this.  In fact that's the precise problem: "thread::send -async [thread::id]" is being rewritten into "after idle".  See the part of the code where that happens (https://core.tcl-lang.org/thread/artifact?udc=1&ln=2742-2759&name=61003585d6458178&udc=1):
    
      2742      /*
      2743       * Short circuit sends to ourself.
      2744       */
      2745  
      2746      if (thrId == Tcl_GetCurrentThread()) {
      2747          Tcl_MutexUnlock(&threadMutex);
      2748          if ((flags & THREAD_SEND_WAIT)) {
      2749              int code = (*send->execProc)(interp, (ClientData)send);
      2750              ThreadFreeProc((ClientData)send);
      2751              return code;
      2752          } else {
      2753              send->interp = interp;
      2754              Tcl_Preserve((ClientData)send->interp);
      2755              Tcl_DoWhenIdle((Tcl_IdleProc*)ThreadIdleProc, (ClientData)send);
      2756              return TCL_OK;
      2757          }
      2758      }
    
    > Possibly for my another event-branch (that I wrote in tcl-core-repo), where "after 0" have O(1) by changing of timer-queue, does not generate extra overhead as regards time-compare at all (because creates an immediate timer-event), etc.
    If this will be accepted sometimes... 
    
    More performant event handling is always welcome... thank you for your efforts, I hope it gets merged soon.
    
  2. login: "adrianmedranocalvo"
  3. mimetype: "text/plain"
  4. username: "[email protected]"