Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion threading/channels.nim
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ runnableExamples("--threads:on --gc:orc"):
when not (defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc) or defined(nimdoc)):
{.error: "This module requires one of --mm:arc / --mm:atomicArc / --mm:orc compilation flags".}

import std/[locks, isolation, atomics]
import std/[locks, isolation, atomics, options]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah. I don't like options and nothing about this new API is hardly any better than the old one:

var x: T
if tryRecv(chan, x): ...

vs:

let x = tryRecv(chan) 
if x.isSome: ...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair enough


# Channel
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -256,10 +256,15 @@ type
Chan*[T] = object ## Typed channel
d: ChannelRaw

proc tryRecv*[T](c: Chan[T]): Option[T] {.inline, raises: [].}

template frees(c) =
if c.d != nil:
# this `fetchSub` returns current val then subs
# so count == 0 means we're the last
while true:
if c.tryRecv().isNone:
break
if c.d.atomicCounter.fetchSub(1, moAcquireRelease) == 0:
freeChannel(c.d)

Expand Down Expand Up @@ -343,6 +348,22 @@ proc tryRecv*[T](c: Chan[T], dst: var T): bool {.inline.} =
## Returns `false` and does not change `dist` if no message was received.
channelReceive(c.d, dst.addr, sizeof(T), false)

proc tryRecv*[T](c: Chan[T]): Option[T] {.inline.} =
## Tries to receive a message from the channel `c`.
##
## Doesn't block waiting for messages in the channel to become available.
## Instead returns after an attempt to receive a message was made.
##
## .. warning:: In high-concurrency situations, consider using an exponential
## backoff strategy to reduce contention and improve the success rate of
## operations.
var dst: T
let dataAvailable = tryRecv(c, dst)
if dataAvailable:
result = some(dst)
else:
result = none(T)

proc send*[T](c: Chan[T], src: sink Isolated[T]) {.inline.} =
## Sends the message `src` to the channel `c`.
## This blocks the sending thread until `src` was successfully sent.
Expand Down