diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-03-24 06:01:27 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-03-24 06:01:27 +0000 |
commit | 3137991dfc4e0b6023c4b75b2ae1eb86bea32241 (patch) | |
tree | 7d40ea09a03f835f95092ac120d9da2db544b0a1 /libgo | |
parent | 4908b0bf1ccac0b7c738ca107be86ca77bf10c4a (diff) | |
download | gcc-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.goc | 14 | ||||
-rw-r--r-- | libgo/runtime/channel.h | 5 | ||||
-rw-r--r-- | libgo/runtime/go-rec-big.c | 6 | ||||
-rw-r--r-- | libgo/runtime/go-rec-small.c | 20 |
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); +} |