Shayne .. when you're playing with fthread be aware of the well known "gotcha".
When you do something like var x = 1; spawn_fthread { .. println$ x; }; x = 2; the "x" in the fthread is just a reference to a variable. There's no knowing what the value will be, it may be 1 or 2. Unlike pthreads the assignment can't be pre-empted half way through resulting in crap, but still the order of access is notionally non-deterministic. Now you may think if you do this: proc myproc (myx:int) () { println$ myx; } spawn_fthread { myproc x; } that will use the current value at the point of spawning but you'd be wrong. Even when "myproc" starts to run it is not copying the value of x at the time it runs into myx, because myx can be lazily evaluated. In particular expect this code to reduce by inlining and substitution to just saying "println$ x; ". Again you may think this will fix it: proc myproc (var myx:int) () { .. } because that forces myx to be eagerly evaluated. Again, you'd be wrong. All that means it is that myx is calculated before the print. So inlining myproc the code reads: myx = x; println myx; instead of println x; In other words, what's being "assigned to myx" is just the current value of x. The only way to fix this is to ensure that the closure is formed at the time you want the value of x, one way to do that is: myproc ... var closure = myproc x; spawn_fthread closure; "Technically" the semantics don't even guarantee that will work, but it does at the moment. You can also mark a procedure "noinline" which prevents it being inlined, which means a closure has to be formed to call it. Note that again is not a guarantee semantically. That's because "noinline" means the procedure must not be inlined at its point of call. It does NOT mean the arguments to the procedure cannot be inlined into the procedure. As already mentioned this *includes* making the parameter a var. This does not technically ensure the "right" value of the variable is assigned. All it ensures is that the assignment takes place before the body of the procedure evaluates .. that can be ANY time before. With lazy evaluation you're ensuring the parameter is not assigned by the argument expression until it is used, which is typically implemented in Felix by simply inlining the expression, but it can also be done by passing a closure (which inlines the expression for later evaluation). With fthreads there is a semantically guaranteed way to fix this problem. Use schannels. Instead of passing a value .. WRITE the value down an schannel at the point in time you want to, and read it in the fthread. For example: var x = 1; var ich, och = @mk_ioschannel_pair; spawn_fthread { var y = read ich; println$ y; }; ++x; write (och, x); // writes 2, no questions asked! ++x; We will always print 2 because the value of x at the time the write occurs is 2. The increment happens after that, and the "2" is already gone up the channel. In fact Felix copies the value of x to do this, and passes a pointer to the copy: var p = new x; send p along och; Note of course if x is a mutable data structure represented by a pointer you're only copying the pointer :) With ordinary procedures and functions you cannot use schannels, because read and write block the fthread. You can, however, cheat the way I just did: var x = 1; var p = new x; // copies the value in x NOW ++x; f p; // passes p This will only work if p is a var, for a val any "p" can be replaced by its initialiser. Again this is a cheat, its not guaranteed semantically. In this case the rule guarantee that new x is done before ++x, and the call of f must be done after ++x. If we remove the ++x, it still works because "f p" is a direct call. But suppose we use a closure: proc f (px:&int) () { println$ *px; } and write: var x = 1; var p = new x; var cls = f p; ++x; cls (); it will still work but it's less certain .. p has to be bound at the point cls is calculated .. but p is just a variable name .. there's no assurance that the value in "slot p" is calculated yet. It has to be calculated before ps is used .. but that's AFTER x is incremented. I actually think this is assured by the semantics .. but i'm not certain (particularly as the semantics are just in my head :) -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ CenturyLink Cloud: The Leader in Enterprise Cloud Services. Learn Why More Businesses Are Choosing CenturyLink Cloud For Critical Workloads, Development Environments & Everything In Between. Get a Quote or Start a Free Trial Today. http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language