about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-07-03 03:11:46 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-07-03 03:11:46 -0700
commit3ef2f7dfe02837e9ce156cb668c29025d9d49f16 (patch)
tree4a193ad54d778cf0d386c31840afb98df2f29723
parent26965dd683137d3f8cf2fab62f02a8dbf5991a68 (diff)
downloadmu-3ef2f7dfe02837e9ce156cb668c29025d9d49f16.tar.gz
3094 - start using deep-copy when writing channels
-rw-r--r--073deep_copy.cc3
-rw-r--r--074channel.mu20
2 files changed, 16 insertions, 7 deletions
diff --git a/073deep_copy.cc b/073deep_copy.cc
index 7c67425b..02da9e68 100644
--- a/073deep_copy.cc
+++ b/073deep_copy.cc
@@ -6,6 +6,9 @@
 // Implications: Refcounts of all data pointed to by the original ingredient
 // will remain unchanged. Refcounts of all data pointed to by the (newly
 // created) result will be 1, in the absence of cycles.
+//
+// We do handle cycles in the ingredient, however. All cycles are translated
+// to new cycles in the product.
 
 :(scenario deep_copy_number)
 def main [
diff --git a/074channel.mu b/074channel.mu
index c7e3dae0..361fae1a 100644
--- a/074channel.mu
+++ b/074channel.mu
@@ -1,12 +1,17 @@
 # Mu synchronizes using channels rather than locks, like Erlang and Go.
 #
 # The two ends of a channel will usually belong to different routines, but
-# each end should only be used by a single one. Don't try to read from or
-# write to it from multiple routines at once.
+# each end should (currently) only be used by a single one. Don't try to read
+# from or write to it from multiple routines at once.
 #
-# The key property of channels is that writing to a full channel or reading
-# from an empty one will put the current routine in 'waiting' state until the
-# operation can be completed.
+# Key properties of channels:
+#
+# a) Writing to a full channel or reading from an empty one will put the
+# current routine in 'waiting' state until the operation can be completed.
+#
+# b) Writing to a channel implicitly performs a deep copy, to prevent
+# addresses from being shared between routines, thereby causing race
+# conditions.
 
 scenario channel [
   run [
@@ -71,10 +76,11 @@ def write out:address:sink:_elem, val:_elem -> out:address:sink:_elem [
     full-address:location <- get-location *chan, first-full:offset
     wait-for-location full-address
   }
-  # store val
+  # store a deep copy of val
   circular-buffer:address:array:_elem <- get *chan, data:offset
   free:number <- get *chan, first-free:offset
-  *circular-buffer <- put-index *circular-buffer, free, val
+  val-copy:_elem <- deep-copy val  # on this instruction rests all Mu's concurrency-safety
+  *circular-buffer <- put-index *circular-buffer, free, val-copy
   # mark its slot as filled
   free <- add free, 1
   {