about summary refs log tree commit diff stats
path: root/cpp/061channel.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-05 21:17:24 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-05 21:17:24 -0700
commitb96af395b9af2ff9df94b3e82213171f30827c8d (patch)
tree17c8c12648ccc25625e2534ec8d74fbe8f1542cc /cpp/061channel.mu
parent2e3b597fe85b654e82b891c22d50754fa5a26156 (diff)
downloadmu-b96af395b9af2ff9df94b3e82213171f30827c8d.tar.gz
1276 - make C++ version the default
I've tried to update the Readme, but there are at least a couple of issues.
Diffstat (limited to 'cpp/061channel.mu')
-rw-r--r--cpp/061channel.mu266
1 files changed, 0 insertions, 266 deletions
diff --git a/cpp/061channel.mu b/cpp/061channel.mu
deleted file mode 100644
index bee6b785..00000000
--- a/cpp/061channel.mu
+++ /dev/null
@@ -1,266 +0,0 @@
-# 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.
-#
-# 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.
-
-scenario channel [
-  run [
-    1:address:channel <- init-channel 3:literal/capacity
-    1:address:channel <- write 1:address:channel, 34:literal
-    2:integer, 1:address:channel <- read 1:address:channel
-  ]
-  memory-should-contain [
-    2 <- 34
-  ]
-]
-
-container channel [
-  # To avoid locking, writer and reader will never write to the same location.
-  # So channels will include fields in pairs, one for the writer and one for the
-  # reader.
-  first-full:integer  # for write
-  first-free:integer  # for read
-  # A circular buffer contains values from index first-full up to (but not
-  # including) index first-empty. The reader always modifies it at first-full,
-  # while the writer always modifies it at first-empty.
-  data:address:array:location
-]
-
-# result:address:channel <- init-channel capacity:integer
-recipe init-channel [
-  default-space:address:array:location <- new location:type, 30:literal
-  # result = new channel
-  result:address:channel <- new channel:type
-  # result.first-full = 0
-  full:address:integer <- get-address result:address:channel/deref, first-full:offset
-  full:address:integer/deref <- copy 0:literal
-  # result.first-free = 0
-  free:address:integer <- get-address result:address:channel/deref, first-free:offset
-  free:address:integer/deref <- copy 0:literal
-  # result.data = new location[ingredient+1]
-  capacity:integer <- next-ingredient
-  capacity:integer <- add capacity:integer, 1:literal  # unused slot for 'full?' below
-  dest:address:address:array:location <- get-address result:address:channel/deref, data:offset
-  dest:address:address:array:location/deref <- new location:type, capacity:integer
-  reply result:address:channel
-]
-
-# chan:address:channel <- write chan:address:channel, val:location
-recipe write [
-  default-space:address:array:location <- new location:type, 30:literal
-  chan:address:channel <- next-ingredient
-  val:location <- next-ingredient
-  {
-    # block if chan is full
-    full:boolean <- channel-full? chan:address:channel
-    break-unless full:boolean
-    full-address:address:integer <- get-address chan:address:channel/deref, first-full:offset
-    wait-for-location full-address:address:integer/deref
-  }
-  # store val
-  circular-buffer:address:array:location <- get chan:address:channel/deref, data:offset
-  free:address:integer <- get-address chan:address:channel/deref, first-free:offset
-  dest:address:location <- index-address circular-buffer:address:array:location/deref, free:address:integer/deref
-  dest:address:location/deref <- copy val:location
-  # increment free
-  free:address:integer/deref <- add free:address:integer/deref, 1:literal
-  {
-    # wrap free around to 0 if necessary
-    len:integer <- length circular-buffer:address:array:location/deref
-    at-end?:boolean <- greater-or-equal free:address:integer/deref, len:integer
-    break-unless at-end?:boolean
-    free:address:integer/deref <- copy 0:literal
-  }
-  reply chan:address:channel/same-as-ingredient:0
-]
-
-# result:location, chan:address:channel <- read chan:address:channel
-recipe read [
-  default-space:address:array:location <- new location:type, 30:literal
-  chan:address:channel <- next-ingredient
-  {
-    # block if chan is empty
-    empty:boolean <- channel-empty? chan:address:channel
-    break-unless empty:boolean
-    free-address:address:integer <- get-address chan:address:channel/deref, first-free:offset
-    wait-for-location free-address:address:integer/deref
-  }
-  # read result
-  full:address:integer <- get-address chan:address:channel/deref, first-full:offset
-  circular-buffer:address:array:location <- get chan:address:channel/deref, data:offset
-  result:location <- index circular-buffer:address:array:location/deref, full:address:integer/deref
-  # increment full
-  full:address:integer/deref <- add full:address:integer/deref, 1:literal
-  {
-    # wrap full around to 0 if necessary
-    len:integer <- length circular-buffer:address:array:location/deref
-    at-end?:boolean <- greater-or-equal full:address:integer/deref, len:integer
-    break-unless at-end?:boolean
-    full:address:integer/deref <- copy 0:literal
-  }
-  reply result:location, chan:address:channel/same-as-ingredient:0
-]
-
-scenario channel-initialization [
-  run [
-    1:address:channel <- init-channel 3:literal/capacity
-    2:integer <- get 1:address:channel/deref, first-full:offset
-    3:integer <- get 1:address:channel/deref, first-free:offset
-  ]
-  memory-should-contain [
-    2 <- 0  # first-full
-    3 <- 0  # first-free
-  ]
-]
-
-scenario channel-write-increments-free [
-  run [
-    1:address:channel <- init-channel 3:literal/capacity
-    1:address:channel <- write 1:address:channel, 34:literal
-    2:integer <- get 1:address:channel/deref, first-full:offset
-    3:integer <- get 1:address:channel/deref, first-free:offset
-  ]
-  memory-should-contain [
-    2 <- 0  # first-full
-    3 <- 1  # first-free
-  ]
-]
-
-scenario channel-read-increments-full [
-  run [
-    1:address:channel <- init-channel 3:literal/capacity
-    1:address:channel <- write 1:address:channel, 34:literal
-    _, 1:address:channel <- read 1:address:channel
-    2:integer <- get 1:address:channel/deref, first-full:offset
-    3:integer <- get 1:address:channel/deref, first-free:offset
-  ]
-  memory-should-contain [
-    2 <- 1  # first-full
-    3 <- 1  # first-free
-  ]
-]
-
-scenario channel-wrap [
-  run [
-    # channel with just 1 slot
-    1:address:channel <- init-channel 1:literal/capacity
-    # write and read a value
-    1:address:channel <- write 1:address:channel, 34:literal
-    _, 1:address:channel <- read 1:address:channel
-    # first-free will now be 1
-    2:integer <- get 1:address:channel/deref, first-free:offset
-    3:integer <- get 1:address:channel/deref, first-free:offset
-    # write second value, verify that first-free wraps
-    1:address:channel <- write 1:address:channel, 34:literal
-    4:integer <- get 1:address:channel/deref, first-free:offset
-    # read second value, verify that first-full wraps
-    _, 1:address:channel <- read 1:address:channel
-    5:integer <- get 1:address:channel/deref, first-full:offset
-  ]
-  memory-should-contain [
-    2 <- 1  # first-free after first write
-    3 <- 1  # first-full after first read
-    4 <- 0  # first-free after second write, wrapped
-    5 <- 0  # first-full after second read, wrapped
-  ]
-]
-
-## helpers
-
-# An empty channel has first-empty and first-full both at the same value.
-recipe channel-empty? [
-  default-space:address:array:location <- new location:type, 30:literal
-  chan:address:channel <- next-ingredient
-  # return chan.first-full == chan.first-free
-  full:integer <- get chan:address:channel/deref, first-full:offset
-  free:integer <- get chan:address:channel/deref, first-free:offset
-  result:boolean <- equal full:integer, free:integer
-  reply result:boolean
-]
-
-# A full channel has first-empty just before first-full, wasting one slot.
-# (Other alternatives: https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)
-recipe channel-full? [
-  default-space:address:array:location <- new location:type, 30:literal
-  chan:address:channel <- next-ingredient
-  # tmp = chan.first-free + 1
-  tmp:integer <- get chan:address:channel/deref, first-free:offset
-  tmp:integer <- add tmp:integer, 1:literal
-  {
-    # if tmp == chan.capacity, tmp = 0
-    len:integer <- channel-capacity chan:address:channel
-    at-end?:boolean <- greater-or-equal tmp:integer, len:integer
-    break-unless at-end?:boolean
-    tmp:integer <- copy 0:literal
-  }
-  # return chan.first-full == tmp
-  full:integer <- get chan:address:channel/deref, first-full:offset
-  result:boolean <- equal full:integer, tmp:integer
-  reply result:boolean
-]
-
-# result:integer <- channel-capacity chan:address:channel
-recipe channel-capacity [
-  default-space:address:array:location <- new location:type, 30:literal
-  chan:address:channel <- next-ingredient
-  q:address:array:location <- get chan:address:channel/deref, data:offset
-  result:integer <- length q:address:array:location/deref
-  reply result:integer
-]
-
-scenario channel-new-empty-not-full [
-  run [
-    1:address:channel <- init-channel 3:literal/capacity
-    2:integer <- channel-empty? 1:address:channel
-    3:integer <- channel-full? 1:address:channel
-  ]
-  memory-should-contain [
-    2 <- 1  # empty?
-    3 <- 0  # full?
-  ]
-]
-
-scenario channel-write-not-empty [
-  run [
-    1:address:channel <- init-channel 3:literal/capacity
-    1:address:channel <- write 1:address:channel, 34:literal
-    2:integer <- channel-empty? 1:address:channel
-    3:integer <- channel-full? 1:address:channel
-  ]
-  memory-should-contain [
-    2 <- 0  # empty?
-    3 <- 0  # full?
-  ]
-]
-
-scenario channel-write-full [
-  run [
-    1:address:channel <- init-channel 1:literal/capacity
-    1:address:channel <- write 1:address:channel, 34:literal
-    2:integer <- channel-empty? 1:address:channel
-    3:integer <- channel-full? 1:address:channel
-  ]
-  memory-should-contain [
-    2 <- 0  # empty?
-    3 <- 1  # full?
-  ]
-]
-
-scenario channel-read-not-full [
-  run [
-    1:address:channel <- init-channel 1:literal/capacity
-    1:address:channel <- write 1:address:channel, 34:literal
-    _, 1:address:channel <- read 1:address:channel
-    2:integer <- channel-empty? 1:address:channel
-    3:integer <- channel-full? 1:address:channel
-  ]
-  memory-should-contain [
-    2 <- 1  # empty?
-    3 <- 0  # full?
-  ]
-]