summary refs log tree commit diff stats
path: root/lib/system/channels.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/channels.nim')
-rw-r--r--lib/system/channels.nim25
1 files changed, 18 insertions, 7 deletions
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index bf949529b..e5535dbdc 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -1,7 +1,7 @@
 #

 #

 #            Nimrod's Runtime Library

-#        (c) Copyright 2012 Andreas Rumpf

+#        (c) Copyright 2014 Andreas Rumpf

 #

 #    See the file "copying.txt", included in this

 #    distribution, for details about the copyright.

@@ -29,7 +29,7 @@ type
     region: TMemRegion

   PRawChannel = ptr TRawChannel

   TLoadStoreMode = enum mStore, mLoad

-  TChannel*[TMsg] = TRawChannel ## a channel for thread communication

+  TChannel* {.gcsafe.}[TMsg] = TRawChannel ## a channel for thread communication

 

 const ChannelDeadMask = -2

 

@@ -49,9 +49,9 @@ proc deinitRawChannel(p: pointer) =
   deinitSysCond(c.cond)

 

 proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, 

-              mode: TLoadStoreMode)

+              mode: TLoadStoreMode) {.gcsafe.}

 proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,

-              mode: TLoadStoreMode) =

+              mode: TLoadStoreMode) {.gcsafe.} =

   var

     d = cast[TAddress](dest)

     s = cast[TAddress](src)

@@ -209,7 +209,6 @@ proc send*[TMsg](c: var TChannel[TMsg], msg: TMsg) =
 

 proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =

   # to save space, the generic is as small as possible

-  acquireSys(q.lock)

   q.ready = true

   while q.count <= 0:

     waitSysCond(q.cond, q.lock)

@@ -218,17 +217,29 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
     releaseSys(q.lock)

     sysFatal(EInvalidValue, "cannot receive message of wrong type")

   rawRecv(q, res, typ)

-  releaseSys(q.lock)

 

 proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =

   ## receives a message from the channel `c`. This blocks until

   ## a message has arrived! You may use ``peek`` to avoid the blocking.

   var q = cast[PRawChannel](addr(c))

+  acquireSys(q.lock)

   llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

+  releaseSys(q.lock)

+
+proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvaliable: bool,
+                                                  msg: TMsg] =
+  ## try to receives a message from the channel `c` if available. Otherwise
+  ## it returns ``(false, default(msg))``.
+  var q = cast[PRawChannel](addr(c))

+  if q.mask != ChannelDeadMask:

+    lockChannel(q):

+      llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
+      result.dataAvaliable = true

 

 proc peek*[TMsg](c: var TChannel[TMsg]): int =

   ## returns the current number of messages in the channel `c`. Returns -1

-  ## if the channel has been closed.

+  ## if the channel has been closed. **Note**: This is dangerous to use
+  ## as it encourages races. It's much better to use ``tryRecv`` instead.

   var q = cast[PRawChannel](addr(c))

   if q.mask != ChannelDeadMask:

     lockChannel(q):