Changeset 367

Show
Ignore:
Timestamp:
06/25/08 10:45:35 (5 months ago)
Author:
FeepingCreature
Message:
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tools/dsss.conf

    r344 r367  
    77target=tools_test 
    88# buildflags=-full -unittest -g -O -debug 
    9 buildflags=-full -unittest -O 
     9buildflags=-full -unittest -debug -g 
  • trunk/tools/tools/behave_as.d

    r315 r367  
    112112  foo++; foo -= 4; 
    113113  mustEqual("BehaveAsEqualityTest", foo, 2); 
    114   mustFail("RangedTest", foo += 100); 
     114  debug { mustFail("RangedTest", foo += 100); } 
    115115  auto x = new Test2; x.f = 5; 
    116116  x.f_pf++; x.f_pf -= 4; 
  • trunk/tools/tools/downloader.d

    r366 r367  
    300300    if (len==0) { reuseConnection=false; logln("Connection closed at ", received.length); break; } 
    301301    received ~= buffer[0..len]; 
     302    string _res; if (checkProgress(chunked, _res)) return _res; 
    302303    if (chunked) if (receiveChunked) continue; else break; 
    303     string _res; if (checkProgress(chunked, _res)) return _res; 
    304304    if (length && (received.length !< length)) { if (!quiet) logln("Received all data"); break; } 
    305305  } 
  • trunk/tools/tools/mersenne.d

    r361 r367  
    1010    logln("Downloading random data from Hotbits"); 
    1111    res ~= cast(ubyte[]) download(Format("http://www.fourmilab.ch/cgi-bin/Hotbits?nbytes=", count-res.length, "&fmt=bin")); 
     12    logln("Now got ", res.length); 
    1213  } 
    1314  return res; 
     
    2425    } 
    2526  } 
    26   void seed_hotbits() { mt[] = cast(size_t[]) get_hotbits(N*4); } 
    27   void init_by_array(size_t init_key[], size_t key_length) { 
    28     int i=1, j=0, k=(N>key_length ? N : key_length); 
     27  void seed_hotbits() { 
     28    //mt[0 .. 16] = cast(size_t[]) get_hotbits(64); 
     29    init_by_array(cast(size_t[]) get_hotbits(64)); 
     30  } 
     31  void init_by_array(size_t[] key) { 
     32    int i=1, j=0, k=(N>key.length ? N : key.length); 
    2933    seed(19650218UL); 
    3034    while (k--) { 
    31       mt[i] = cast(uint) ((mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + init_key[j] + j); /* non linear */ 
     35      mt[i] = cast(uint) ((mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + key[j] + j); /* non linear */ 
    3236      mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 
    3337      i++; j++; 
    3438      if (i>=N) { mt[0] = mt[N-1]; i=1; } 
    35       if (j>=key_length) j=0; 
     39      if (j>=key.length) j=0; 
    3640    } 
    3741    k=N-1; while (k--) { 
  • trunk/tools/tools/stackthreads.d

    r319 r367  
    1 /// This file, insofar as copyright is applicable, 
    2 /// shall fall under the BSD license. --the author 
    31module tools.stackthreads; 
    4 public import tools.base; 
    5 // stupid DSSS 
    6 // mixin(expandImport("tools.[base; log; functional; stackthreads_impl]; std.string")); 
    7 import std.string, tools.base, tools.log, tools.functional, tools.stackthreads_impl; 
     2import tools.stackthreads_impl, tools.log, tools.threads; 
    83 
    9 const int defaultsize=1024*1024; // as stack space is mmapped, it starts out smaller and grows on usage. 
    10  
    11 class Pipe(I, O) { 
    12   static if (is(I==void)) alias Tuple!() InputPar; else alias Tuple!(I[]) InputPar; 
    13   static if (is(O==void)) alias void OutputPar; else static if (is(I==void)) alias O OutputPar; else alias O[] OutputPar; 
    14   alias I InputType; alias O OutputType; 
    15   abstract  { 
    16     bool ready(); 
    17     OutputPar opCall(InputPar input); 
     4class Coroutine { 
     5  static TLS!(Exception) failures; 
     6  static this() { New(failures, { return cast(Exception) null; }); } 
     7  private context ctx; 
     8  proc dg; 
     9  void safe_exec() { 
     10    toMain(); 
     11    try dg(); 
     12    catch (Exception ex) { 
     13      failures.set(ex); 
     14      toMain(); 
     15      asm { int 3; } 
     16    } 
     17    toMain(); 
     18    failures.set(new Exception("Coroutine has ended. Cannot invoke again.")); 
     19    toMain(); 
    1820  } 
    19   const string descof="("~InputType.stringof~"->"~OutputType.stringof~")"; 
    20   Pipe!(InputType, W.OutputType) opCat(W)(W other) { 
    21     alias typeof(this) V; 
    22     return new class(this, other) Pipe!(InputType, W.OutputType) { 
    23       V stage1; W stage2; 
    24       this(V _one, W _two) { stage1=_one; stage2=_two; } 
    25       bool ready() { return stage1.ready() && stage2.ready(); } 
    26       OutputPar opCall(InputPar par) { return stage2(stage1(par)); } 
    27     }; 
     21  this(proc dg, size_t stacksize=1024*1024) { 
     22    this.dg = dg; 
     23    ctx.genstack(stacksize); 
     24    ctx.run(&safe_exec, getActiveContext()); 
    2825  } 
    29   static if (is(OutputPar==void) && is(InputPar==Tuple!())) void execute() { while (ready) opCall(); } 
     26  void failcheck(string info) { 
     27    if (auto ex = failures()) throw new Exception(info~ex.toString()); 
     28  } 
     29  void opCall() { 
     30    failcheck("Trying to invoke coroutine failed with "); 
     31    ctx.activate(getActiveContext()); 
     32    failcheck("Coroutine failed with "); 
     33  } 
     34  static void toMain() { yield_main(getActiveContext()); } 
    3035} 
    3136 
    32 static if (enableStackthreads) { 
    33  
    34 class StackThread(T, U) : Pipe!(T, U) { 
    35   const bool gotInput=!is(InputType==void); 
    36   const bool gotOutput=!is(OutputType==void); 
    37   final bool runsMe() { return ctx.runsMe(); } 
    38   /*ubyte[] backup() { return ctx.backup(); } 
    39   void restore(ubyte[] v) { ctx.restore(v); }*/ 
    40   Exception threadex; 
    41   private { 
    42     void delegate() _yield; 
    43     context!() ctx; 
    44     final void gencall(void delegate() y) { 
    45       _yield = y; 
    46       y(); 
    47       try func(); 
    48       catch (Exception e) { 
    49         threadex=e; 
    50         ctx.myState=ctxState.aborted; 
    51         y(); 
    52       } 
    53       ctx.myState=ctxState.completed; 
    54       y(); 
    55       asm { int 3; } 
    56     } 
    57     static if(gotInput) InputType *input; 
    58     static if(gotOutput) OutputType *output; 
    59   } 
    60   final void resume() { ctx.resume(); if (threadex) throw threadex; } 
    61   final void resume_samethread() { ctx.resume_samethread(); if (threadex) throw threadex; } 
    62   protected { 
    63     abstract void func(); 
    64     bool reading=false; 
    65     static if(gotInput) InputType read() { 
    66       reading=true; 
    67       scope(exit) { reading=false; input=null; } 
    68       while (!input) _yield(); 
    69       return *input; 
    70     } 
    71     static if(gotOutput) { 
    72       void yield(OutputType u) { 
    73         if (output) throw new Exception("Axiomatic exception: output buffer still filled"); 
    74         output=&u; 
    75         while (output) _yield(); 
    76       } 
    77     } else void yield() { _yield(); } 
    78   } 
    79   void reset() { 
    80     static if(gotInput) input=null; 
    81     static if(gotOutput) output=null; 
    82     ctx.run(&gencall); 
    83   } 
    84   this(int size=defaultsize) { ctx.genstack(size); reset; } 
    85   ~this() { 
    86     ctx.cleanup; 
    87   } 
    88   final { 
    89     static if (gotOutput) { 
    90       static if (!gotInput) { 
    91         OutputType opCall() { 
    92           while (!output) { if (!ready) throw new Exception("Cannot call ST: not ready"); resume; } 
    93           scope(exit) output=null; 
    94           return *output; 
    95         } 
    96       } else { 
    97         void flush(ref OutputType[] target) { 
    98           while (input) { 
    99             if (output) { target ~= *output; output=null; } 
    100             resume; 
    101           } 
    102           while (output) { 
    103             target ~= *output; 
    104             output=null; 
    105             if (ready) resume; 
    106           } 
    107         } 
    108         OutputType[] opCall(InputType inp) { 
    109           OutputType[] res; 
    110           flush(res); 
    111           input = &inp; 
    112           flush(res); 
    113           return res; 
    114         } 
    115         OutputType[] opCall(InputType[] inp) { 
    116           OutputType[] res; 
    117           foreach (ref i; inp) { 
    118             flush(res); 
    119             input = &i; 
    120           } 
    121           flush(res); 
    122           return res; 
    123         } 
    124       } 
    125     } else { 
    126       static if (gotInput) { 
    127         void opCall(InputType inp) { while (input) resume; input=&inp; while (input) resume; } 
    128         void opCall(InputType[] inp) { while (input) resume; foreach (ref i; inp) { input=&i; while (input) resume; } } 
    129       } else { 
    130         void opCall() { resume; } 
    131       } 
    132     } 
    133     final bool ready() { return ctx.myState==ctxState.sleeping; } 
    134     static if (gotOutput) bool hasOutput() { while (!output) { if (!ready) return false; resume; } return true; } 
    135     final bool run() { 
    136       if (ready && !reading) resume; 
    137       return ready; 
    138     } 
    139     final bool run_samethread() { 
    140       if (ready && !reading) resume_samethread; 
    141       return ready; 
    142     } 
    143   } 
     37import tools.tests; 
     38unittest { 
     39  logln("StackThread test"); 
     40  auto test = new Coroutine({ 
     41    logln("This is virtual stack context!"); 
     42    Coroutine.toMain(); 
     43    logln("Hi again. Finishing now."); 
     44  }); 
     45  logln("> This is main."); test(); 
     46  logln("> Reinvoking."); test(); 
     47  logln("> done"); 
     48  mustFail("ReinvokeTest", test()); 
     49  asm { int 3; } 
    14450} 
    145  
    146 import std.stdio; 
    147 final class DelegateStackThread(T, U, bool reverse=false) : StackThread!(T, U) { 
    148   static if (is(U==void)) { 
    149     static if (is(T==void)) void delegate(proc yield) dg; 
    150     else { 
    151       static if (reverse) void delegate(T delegate() read, proc yield) dg; 
    152       else void delegate(proc yield, T delegate() read) dg; 
    153     } 
    154   } else static if (is(T==void)) void delegate(void delegate(U) yield) dg; 
    155   else 
    156     static if (reverse) void delegate(T delegate() read, void delegate(U) yield) dg; 
    157     else void delegate(void delegate(U) yield, T delegate() read) dg; 
    158   this(typeof(dg) _dg, int size=defaultsize) { dg=_dg; super(size); } 
    159   void func() { 
    160     static if (is(T==void)) dg(&yield); 
    161     else static if (reverse) dg(&read, &yield); 
    162     else dg(&yield, &read); 
    163   } 
    164 } 
    165 struct stackthread { 
    166   static StackThread!(T, U) opAssign(T, U)(void delegate(void delegate(U) yield, T delegate() read) dg) { 
    167     return new DelegateStackThread!(T, U)(dg); 
    168   } 
    169   static StackThread!(T, U) opAssign(T, U)(void delegate(T delegate() read, void delegate(U) yield) dg) { 
    170     return new DelegateStackThread!(T, U, true)(dg); 
    171   } 
    172   static StackThread!(void, IF!(U.length, U), IF!(!U.length, Tuple!(void))) opAssign(U...)(void delegate(void delegate(U) yield) dg) { 
    173     return new DelegateStackThread!(void, IF!(U.length, U), IF!(!U.length, void))(dg); 
    174   } 
    175   static StackThread!(T, void) opAssign(T)(void delegate(proc yield, T delegate() read) dg) { 
    176     return new DelegateStackThread!(T, void)(dg); 
    177   } 
    178   static StackThread!(T, void) opAssign(T)(void delegate(T delegate() read, proc yield) dg) { 
    179     return new DelegateStackThread!(T, void, true)(dg); 
    180   } 
    181   static StackThread!(T, void) opAssign(T)(void delegate(T delegate() read) dg) { 
    182     static if (is(T==void)) { 
    183       return new DelegateStackThread!(void, void)(dg); 
    184     } else { 
    185       return new DelegateStackThread!(T, void)((typeof(dg) _dg, proc yield, T delegate() read) { 
    186         _dg(read); 
    187       } /fix/ dg); 
    188     } 
    189   } 
    190 } 
    191  
    192 import tools.tests, std.gc; 
    193 unittest { 
    194   logln("stackthreads test"); 
    195   auto sieve = stackthread = (void delegate(int) yield) { 
    196     auto length = 20, removed = new bool[length]; 
    197     for (int i = 2; i < length; i = i + 1) { 
    198       if (removed[i] == false) { yield (i); for (int z = i * 2; z < length; z += i) removed[z]=true; } 
    199     } 
    200   }; 
    201   int[] res; 
    202   while (sieve.hasOutput) res ~= sieve(); 
    203   mustEqual("SieveTest", res, [2, 3, 5, 7, 11, 13, 17, 19]); 
    204   delete sieve; 
    205 } 
    206  
    207 /* 
    208 void main() { 
    209   auto sched=new StackThreadSched; 
    210   sched~=(proc yield, void delegate(float) wait) { for (int i=0; i<3; ++i) { writefln("I: ", i, ": waiting 1s"); wait(1f); } }; 
    211   sched~=(proc yield, void delegate(float) wait) { for (int i=0; i<9; ++i) { writefln("II: ", i, ": waiting .3s"); wait(0.3f); } }; 
    212   while (sched.contexts.length) sched(); 
    213 } 
    214 */ 
    215 } else { pragma(msg, "StackThreads are not supported on your architecture. Sorry ._."); } 
  • trunk/tools/tools/stackthreads_impl.d

    r361 r367  
    11module tools.stackthreads_impl; 
    2 import std.thread, tools.base, std.stdio
     2import tools.base
    33 
    44static if (size_t.sizeof==8) const string regsize="r"; 
    55else const string regsize="e"; 
    66 
    7 const bool patchedPhobos = is(typeof((new Thread).stack)); 
    8  
    97version (BigEndian) const bool enableStackthreads = false; 
    108else const bool enableStackthreads = true; 
    119static if (enableStackthreads) { 
    12   static if (!patchedPhobos) { 
    13     pragma(msg, "Your Phobos does not incorporate the MultiStacks patch. The GC will be disabled while StackThreads are active."); 
    14     pragma(msg, "This may, in certain not-so-corner-cases, cause memory leaks. Blame the lack of Phobos maintenance."); 
    15   } 
    16    
    17   //TLS!(void*) original_stack_start; 
    18   //static this() { New(original_stack_start, { return &(new Stuple!(void*))._0; }); } 
    1910  // this is a template so it's not compiled into static library code 
    2011  // thus allowing the debug segments to depend on the application's debug mode, not the library's 
    2112  struct djmpinfo() { 
    22     void* jmpaddr; 
    23     debug bool loaded=false; 
    24     void reset() { debug loaded=false; } 
    25     final void swap(ref djmpinfo other) { 
    26       debug { 
    27         if (loaded) { 
    28           writefln(this, " - Cannot save to a loaded jmp point"); 
    29           asm { int 3; } 
    30         } 
    31         loaded=true; 
    32         if (!other.loaded) { 
    33           writefln(&other, " - Cannot load from an unloaded jmp point"); 
    34           asm { int 3; } 
    35         } 
    36         other.loaded=false; 
     13    void* esp, start; // start is for the GC 
     14    static void switch_gc(ref djmpinfo from, djmpinfo to) { 
     15      auto thr = Thread.getThis(); 
     16      disable; // don't enable it again until you've switched over 
     17      from.start = thr.stackBottom; 
     18      thr.stackBottom = to.start; 
     19      auto esp = getESP(); 
     20      if (esp < from.start) addRange(esp, from.start); // this range is now static and not being updated on collection 
     21      else addRange(from.start, esp); 
     22      // remove to's range from the scanlist because it's going Active 
     23      with (to) if (esp) { 
     24        if (esp < start) removeRange(esp); 
     25        else if (start < esp) removeRange(start); 
    3726      } 
    38       auto ja=&jmpaddr, ja2=&other.jmpaddr; 
     27      // I hope I didn't forget anything. 
     28    } 
     29    static void swap(ref djmpinfo from, ref djmpinfo to) { 
     30      switch_gc(from, to); 
     31      auto ep=&from.esp; 
    3932      // now save to local, resume from other. 
    4033      static if (gccasm) { 
     
    4437          0: 
    4538           
    46           push #ax\n push #bx\n push #si\n push #di\n push #bp 
     39          pushal 
    4740           
    4841          mov #sp, (#cx) 
    49           mov (#dx), #sp 
     42          mov #dx, #sp 
    5043           
    51           pop #bp\n pop #di\n pop #si\n pop #bx\n pop #ax 
     44          popal 
    5245           
    5346          ret 
    54           1:\" : : \"c\" ja, \"d\" ja2 : \"ax\", \"bx\"; 
     47          1:\" : : \"c\" ep, \"d\" to.esp : \"ax\", \"bx\"; 
    5548        }", "#", "%%"~regsize)); 
    5649      } else { 
    5750        asm { 
    58           mov ECX, ja; mov EDX, ja2
     51          mov ECX, ep; mov EDX, to.esp
    5952          call fuckery; jmp end; fuckery: 
    6053           
     
    6255           
    6356          mov [ECX], ESP; 
    64           mov ESP, [EDX]
     57          mov ESP, EDX
    6558           
    6659          popad; 
     
    7063        } 
    7164      } 
     65      enable; 
    7266    } 
    73     void set(void* vstack, void delegate() dg) { 
    74       debug { 
    75         if (loaded) { 
    76           writefln(this, " - trying to set jmp point twice"); 
    77           asm { int 3; } 
    78         } 
    79         loaded=true; 
    80       } 
    81       void *ja=&jmpaddr; 
    82       bool _loaded = void; 
     67    void set(void* vstack, ref djmpinfo invoker, void delegate() dg) { 
     68      switch_gc(invoker, *this); 
     69      void *ep=&invoker.esp; 
     70      start = esp = vstack; 
     71      bool loaded = void; 
    8372      auto dg_ptr = &dg; 
    8473      typeof(dg_ptr) new_ptr; 
     
    9079            jmp 1f 
    9180             
    92             0: push %%ax\n push %%bx\n push %%si\n push %%di\n push %%bp 
     81            0: pushal 
    9382            mov %%sp, (%%bx) 
    9483            mov %%cx, %%sp 
    9584             
    9685            push $1 
    97             1: pop %%cx\" : \"=c\" _loaded, \"=d\" new_ptr : \"b\" ja, \"c\" vstack, \"d\" dg_ptr; 
     86            1: pop %%cx\" : \"=c\" loaded, \"=d\" new_ptr : \"b\" ep, \"c\" esp, \"d\" dg_ptr; 
    9887          }", "%%", "%%"~regsize 
    9988        )); 
    10089      } else asm { 
    101         mov EBX, ja; mov ECX, vstack; mov EDX, dg_ptr; 
     90        mov EBX, ep; mov ECX, esp; mov EDX, dg_ptr; 
    10291        call set_fuckery; 
    103         mov _loaded, 0; jmp set_end; 
     92        mov loaded, 0; jmp set_end; 
    10493        set_fuckery: 
    10594         
     
    10998         
    11099        mov new_ptr, EDX; 
    111         mov _loaded, 1; 
     100        mov loaded, 1; 
    112101        set_end:; 
    113102      } 
    114       if (!_loaded) return; 
     103      enable; 
     104      if (!loaded) return; 
    115105      (*new_ptr)(); 
     106      asm { int 3; } 
    116107    } 
    117108  } 
    118109   
    119   import std.gc, std.mmfile
     110  import std.gc, std.mmfile, std.thread, tools.threads
    120111   
    121112  /// NOT "mov res, EBP". Trust me on this one. 
     
    124115  enum ctxState { dormant, running, sleeping, aborted, completed } 
    125116   
    126   // see rationale for djmpinfo being templates 
    127   struct context() { 
    128     djmpinfo!() main, virtual; /// register and jump values for caller and stackthread 
    129     ctxState myState = ctxState.dormant; /// my current state (running, sleeping, dead) 
     117  TLS!(context) mainline; 
     118  TLS!(context*) active; 
     119  static this() { 
     120    New(mainline, { return new context; }); 
     121    New(active, { auto res = new Stuple!(context*); return &res._0; }); 
     122  } 
     123  void yield_main(context* invoker) { mainline.ptr().activate(invoker); } 
     124  context* getActiveContext() { 
     125    auto res = active.ptr(); 
     126    if (!res || !*res) return mainline.ptr(); 
     127    else return *res; 
     128  } 
     129   
     130  struct context { 
     131    djmpinfo!() info; // jump info for stackthread. 
     132    ctxState state = ctxState.dormant; /// my current state (running, sleeping, dead) 
    130133    void[] vstack; /// the virtual stack 
    131134    MmFile vstack_file=null; /// the underlying MmFile for the stack. 
    132135    void genstack(size_t size) { 
    133136      assert(!vstack_file); 
    134       version(Win32) { 
    135         pragma(msg, "Using new for the vstack. Blame Walter and win32's broken MmFile."); 
    136         pragma(msg, "If anonymous MmFile has been fixed by now, please notify the author and disregard this warning."); 
    137         vstack = new void[size]; 
    138       } else vstack=(vstack_file=new MmFile(null, MmFile.Mode.ReadWriteNew, size, null))[]; 
    139       static if (patchedPhobos) me = addStack(vstack.ptr, vstack.ptr + vstack.length); 
    140       addRange(vstack.ptr, vstack.ptr + vstack.length); 
     137      vstack=(vstack_file=new MmFile(null, MmFile.Mode.ReadWriteNew, size, null))[]; 
     138      // hasPointers(vstack.ptr); 
    141139    } 
    142     static if (patchedPhobos) Stack* me, caller; 
    143     void cleanup() { 
    144       static if (patchedPhobos) delStack(me); 
    145       if (vstack_file) delete vstack_file; 
    146       vstack_file=null; 
    147     } 
     140    void cleanup() { vstack_file=null; } 
    148141    // size_t size() { return vstack.length/uint.sizeof; } 
    149142    bool runsMe() { 
     
    155148      return (esp>=vstack.ptr) && (esp < vstack.ptr+vstack.length); 
    156149    } 
    157     void yield() { 
    158       if (myState == ctxState.running) myState = ctxState.sleeping; 
    159       static if (patchedPhobos) { 
    160         me.lastESP = getESP(); 
    161         lastExecutingThread.stack = caller; // reset to calling stack 
    162       } else enable; 
    163       virtual.swap(main); 
     150    void run(void delegate() dg, context* invoker) { 
     151      scope(failure) logln(" >>run fails"); 
     152      state = ctxState.running; 
     153      if (!invoker) invoker = mainline.ptr(); 
     154      invoker.state = ctxState.sleeping; 
     155      *active.ptr() = this; 
     156      /// leave a bit of space on the other side 
     157      info.set(vstack.ptr + vstack.length - 256, invoker.info, dg); 
    164158    } 
    165     void delegate(proc yield) dg; 
    166     void execute() { dg(&yield); } 
    167     static if (patchedPhobos) Thread lastExecutingThread; 
    168     void run(void delegate(void delegate() yield) dg) { 
    169       scope(failure) writefln(" >>run fails"); 
    170       main.reset; virtual.reset; 
    171       auto vbp = vstack.ptr + vstack.length - 256; /// leave a bit of space on the other side 
    172       myState = ctxState.running; 
    173       this.dg=dg; 
    174       static if (patchedPhobos) { 
    175         auto esp = getESP(); 
    176         lastExecutingThread = Thread.getThis; 
    177         caller = lastExecutingThread.stack; 
    178         assert(caller.contains(esp)); 
    179         caller.lastESP = esp; 
    180         lastExecutingThread.stack = me; 
    181       } else disable; 
    182       main.set(vbp, &execute); 
    183     } 
    184     void resume_samethread() { 
    185       if (myState != ctxState.sleeping) throw new Exception(Format("Trying to resume from invalid state ", myState, "!")); 
    186       myState = ctxState.running; 
    187       static if (patchedPhobos) { 
    188         auto esp = getESP(); 
    189         caller = lastExecutingThread.stack; 
    190         assert(caller.contains(esp)); 
    191         caller.lastESP = esp; 
    192         lastExecutingThread.stack = me; // switch the thread's active stack 
    193       } else disable; 
    194       main.swap(virtual); 
    195     } 
    196     void resume() { 
    197       static if (patchedPhobos) { 
    198         assert(!!lastExecutingThread); 
    199         if (!lastExecutingThread.isSelf()) lastExecutingThread = Thread.getThis(); 
    200       } 
    201       resume_samethread(); 
     159    void activate(context* invoker) { 
     160      *active.ptr() = this; 
     161      if (state != ctxState.sleeping) throw new Exception(Format("Cannot activate context: invalid state ", state, "!")); 
     162      state = ctxState.running; 
     163      if (!invoker) invoker = mainline.ptr(); 
     164      invoker.state = ctxState.sleeping; 
     165      typeof(info).swap(invoker.info, info); 
    202166    } 
    203167  } 
  • trunk/tools/tools/threads.d

    r365 r367  
    9090        if (!res) { 
    9191          res = maker(); 
    92           synchronized values ~= res; 
     92          synchronized(this) values ~= res; 
    9393          check("TlsSetValue", TlsSetValue(key, cast(void*) res)); 
    9494        } 
     
    207207        if (!res) { 
    208208          res = maker(); 
    209           synchronized values ~= res; 
     209          synchronized(this) values ~= res; 
    210210          check("pthread_setspecific", pthread_setspecific(key, cast(void*) res)); 
    211211        }