# HG changeset patch # User IBBoard # Date 1506109124 -3600 # Node ID 03782444978f02318f2d8f35495ac52d783bb94b # Parent 46a8072897249c0f5dd2efcf0067eb847e76a1ba Add coroutine, actor and futures code diff -r 46a807289724 -r 03782444978f 2-Io/day3-concurrency.io --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/2-Io/day3-concurrency.io Fri Sep 22 20:38:44 2017 +0100 @@ -0,0 +1,58 @@ +# Concurrency and coroutines don't appear to need any special syntax beyond "yield" +# and a slight tweak to how you invoke the method/send the message + +vizzini := Object clone +vizzini talk := method( + "Fezzik, are there rocks ahead?" println + yield + "No more rhymes now, I mean it." println + yield +) + +fezzik := Object clone +fezzik rhyme := method( + yield + "If there are, we'll all be dead." println + yield + "Anoybody want a peanut?" println +) + +# The magic happens here - call it with "@@" and it gets kicked off in a thread +vizzini @@talk; fezzik @@rhyme +# And further magic with classes/functions we never knew existed before, +# which holds the thread open until the threads are done +# (Initially this looked like two lines of Coroutine output joined together in print!) +#Coroutine currentCoroutine pause +# It's not clear WHY they're yielding to each other. Nothing in the code appears to +# create a relationship, and in other languages then the threads would run at +# arbitrary slices and (semi-randomly) intersperse their output without the yields. +# But Io. +# Oh, and apparently we can't use it when we want to do other things afterwards, +# because we get "Scheduler: nothing left to resume so we are exiting". So +# it isn't the same as "join" in other languages to wait for threads to finish/merge + +# Apparently "asyny messages" (@@) makes something an actor +slower := Object clone +slower start := method(wait(2); writeln("2s delay")) +faster := Object clone +faster start := method(wait(1); writeln("1s delay")) +# Even though slower starts first, they should be threaded so faster should print first +slower @@start; faster @@start; wait(3) + + +# Futures use a single "@" and are more sensible. They return a placeholder straight away +# but let you carry on with other things, then block when you call them until the value +# is *actually* available +slow_method := method(wait(3); return "Some slow value") +"Calling slow method" println +value := @slow_method +"Now we do other stuff…" println +"And a bit more" println +"And now we try to print the value…" println +value println +"That should have paused, but not due to the outer code" println +"Wut?" println +"Now everything prints twice!" println +"What is going on?" println +"It's as if Io created a second thread for no discernable reason!" println +"But it isn't anything to do with our slower/faster threads, because everything before printing 'value' is fine" println \ No newline at end of file