Fork/join is now implemented. Here's an example: ////////////////// var clock = Faio::mk_alarm_clock();
concurrently$ { println$ "One starts"; Faio::sleep$ clock, 1.0; println$ "One ends"; }, { println$ "Two starts"; Faio::sleep$ clock, 0.3; println$ "Two ends"; }, { println$ "Three starts"; Faio::sleep$ clock, 0.1; println$ "Three ends"; }, { println$ "Four starts"; Faio::sleep$ clock, 0.7; println$ "Four ends"; } ; //////////////////////////// This form takes an array of procedures to run in parallel. The general form takes an iterator (stream of procedures). The implementation is instructive and took about 15 minutes to write: /////////////////////////// //$ Implement fork/join protocol. open class ForkJoin { //$ Launch a set of pthreads and wait //$ until all of them are finished. proc concurrently_by_iterator (var it:1 -> opt[1->0]) { // Make a channel to signal termination. var iterm,oterm = mk_iopchannel_pair[int](); // Here's the actual procedure we're going to spawn. noinline proc manager (var p: 1->0) () { p(); write (oterm, 1); } // Variable to count the number of pthreads. var count = 0; again:> match #it with | Some ?p => ++count; spawn_pthread$ manager p; goto again; // Dreaded goto is useful! | None => while count > 0 do / / Explicitly ignore return to prevent call being optimised away C_hack::ignore (read iterm); --count; done endmatch; } proc concurrently[T with Streamable[T,1->0]] (d:T) => concurrently_by_iterator d.iterator; } //////////////////////////// The method is to create a pchannel of int. That's a nasty choice because of issues with channels of unit. Felix is supposed to eliminate unit values which would not be the right thing here! *** What we do is simple: we wrap each client procedure in a procedure that calls the client procedure then writes down a channel. After we have launched all the procedures, counting them, we just read the termination notice channel that number of times. Note carefully the noinline manager, this is to ensure a closure is formed at the right time and captures the client procedure at construction time. We want to avoid "terrifying val" bugs! Note carefully that the iterator parameter of concurrently_by_iterator is a var. It does NOT work with a val (I know! because the "terrifying val" bug bit me :) Note careully the C_hack::ignore. If you don't ignore a function return value the whole call can be elided. This is true even if the function is a generator. [This is a CAVEAT but it is NOT a bug! Use it or lose it!] ISSUE *** It should work but I get this: /Users/johnskaller/.felix/cache/text/Users/johnskaller/felix/./tfj.cpp:33:77: fatal error: no matching constructor for initialization of '::flx::rtl::unit' ps = (::flx::rtl::unit*)new(*PTF gcp, ::flx::rtl::unit_ptr_map, true) ::flx::rtl::unit (0); //assign ^ ~ build/release/lib/rtl/flx_rtl.hpp:28:19: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const flx::rtl::unit' for 1st argument struct RTL_EXTERN unit {}; // unit ^ Not sure why Felix is trying to init a unit value with 0. -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial Remotely access PCs and mobile devices and provide instant support Improve your efficiency, and focus on delivering more value-add services Discover what IT Professionals Know. Rescue delivers http://p.sf.net/sfu/logmein_12329d2d _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language