aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-03-24 06:01:27 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-03-24 06:01:27 +0000
commit3137991dfc4e0b6023c4b75b2ae1eb86bea32241 (patch)
tree7d40ea09a03f835f95092ac120d9da2db544b0a1 /libgo
parent4908b0bf1ccac0b7c738ca107be86ca77bf10c4a (diff)
downloadgcc-3137991dfc4e0b6023c4b75b2ae1eb86bea32241.zip
gcc-3137991dfc4e0b6023c4b75b2ae1eb86bea32241.tar.gz
gcc-3137991dfc4e0b6023c4b75b2ae1eb86bea32241.tar.bz2
Tuple receives indicate whether channel is closed.
From-SVN: r171380
Diffstat (limited to 'libgo')
-rw-r--r--libgo/runtime/chan.goc14
-rw-r--r--libgo/runtime/channel.h5
-rw-r--r--libgo/runtime/go-rec-big.c6
-rw-r--r--libgo/runtime/go-rec-small.c20
4 files changed, 30 insertions, 15 deletions
diff --git a/libgo/runtime/chan.goc b/libgo/runtime/chan.goc
index da0bbfc..c9de71f 100644
--- a/libgo/runtime/chan.goc
+++ b/libgo/runtime/chan.goc
@@ -12,28 +12,22 @@ typedef struct __go_channel chan;
/* Do a nonblocking channel receive. */
-func chanrecv2(c *chan, val *byte) (pres bool) {
+func chanrecv2(c *chan, val *byte) (received bool) {
if (c->element_size > 8) {
- return __go_receive_nonblocking_big(c, val);
+ return __go_receive_big(c, val, 0);
} else {
- struct __go_receive_nonblocking_small rs;
union {
char b[8];
uint64_t v;
} u;
- rs = __go_receive_nonblocking_small (c);
- if (!rs.__success) {
- __builtin_memset(val, 0, c->element_size);
- return 0;
- }
- u.v = rs.__val;
+ u.v = __go_receive_small_closed(c, 0, &received);
#ifndef WORDS_BIGENDIAN
__builtin_memcpy(val, u.b, c->element_size);
#else
__builtin_memcpy(val, u.b + 8 - c->element_size,
c->element_size);
#endif
- return 1;
+ return received;
}
}
diff --git a/libgo/runtime/channel.h b/libgo/runtime/channel.h
index 5d2f49f..ea10828 100644
--- a/libgo/runtime/channel.h
+++ b/libgo/runtime/channel.h
@@ -112,6 +112,9 @@ extern int __go_receive_nonblocking_acquire (struct __go_channel *);
extern uint64_t __go_receive_small (struct __go_channel *, _Bool);
+extern uint64_t __go_receive_small_closed (struct __go_channel *, _Bool,
+ _Bool *);
+
extern void __go_receive_release (struct __go_channel *);
struct __go_receive_nonblocking_small
@@ -123,7 +126,7 @@ struct __go_receive_nonblocking_small
extern struct __go_receive_nonblocking_small
__go_receive_nonblocking_small (struct __go_channel *);
-extern void __go_receive_big (struct __go_channel *, void *, _Bool);
+extern _Bool __go_receive_big (struct __go_channel *, void *, _Bool);
extern _Bool __go_receive_nonblocking_big (struct __go_channel *, void *);
diff --git a/libgo/runtime/go-rec-big.c b/libgo/runtime/go-rec-big.c
index 23d6529..a584fe7 100644
--- a/libgo/runtime/go-rec-big.c
+++ b/libgo/runtime/go-rec-big.c
@@ -9,7 +9,7 @@
#include "go-panic.h"
#include "channel.h"
-void
+_Bool
__go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
{
size_t alloc_size;
@@ -24,11 +24,13 @@ __go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
if (!__go_receive_acquire (channel, for_select))
{
__builtin_memset (val, 0, channel->element_size);
- return;
+ return 0;
}
offset = channel->next_fetch * alloc_size;
__builtin_memcpy (val, &channel->data[offset], channel->element_size);
__go_receive_release (channel);
+
+ return 1;
}
diff --git a/libgo/runtime/go-rec-small.c b/libgo/runtime/go-rec-small.c
index c4dc8b6..87aed3c 100644
--- a/libgo/runtime/go-rec-small.c
+++ b/libgo/runtime/go-rec-small.c
@@ -263,7 +263,8 @@ __go_unlock_and_notify_selects (struct __go_channel *channel)
/* Receive something 64 bits or smaller on a channel. */
uint64_t
-__go_receive_small (struct __go_channel *channel, _Bool for_select)
+__go_receive_small_closed (struct __go_channel *channel, _Bool for_select,
+ _Bool *received)
{
uint64_t ret;
@@ -273,11 +274,26 @@ __go_receive_small (struct __go_channel *channel, _Bool for_select)
__go_assert (channel->element_size <= sizeof (uint64_t));
if (!__go_receive_acquire (channel, for_select))
- return 0;
+ {
+ if (received != NULL)
+ *received = 0;
+ return 0;
+ }
ret = channel->data[channel->next_fetch];
__go_receive_release (channel);
+ if (received != NULL)
+ *received = 1;
+
return ret;
}
+
+/* Called by the compiler. */
+
+uint64_t
+__go_receive_small (struct __go_channel *channel, _Bool for_select)
+{
+ return __go_receive_small_closed (channel, for_select, NULL);
+}