1 /* go-rec-nb-small.c -- nonblocking receive of something smal on a channel.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
13 /* Prepare to receive something on a nonblocking channel. */
16 __go_receive_nonblocking_acquire (struct __go_channel
*channel
)
21 i
= pthread_mutex_lock (&channel
->lock
);
24 while (channel
->selected_for_receive
)
26 i
= pthread_cond_wait (&channel
->cond
, &channel
->lock
);
30 if (channel
->is_closed
31 && (channel
->num_entries
== 0
32 ? channel
->next_store
== 0
33 : channel
->next_fetch
== channel
->next_store
))
35 __go_unlock_and_notify_selects (channel
);
36 return RECEIVE_NONBLOCKING_ACQUIRE_CLOSED
;
39 if (channel
->num_entries
> 0)
40 has_data
= channel
->next_fetch
!= channel
->next_store
;
43 if (channel
->waiting_to_receive
)
45 /* Some other goroutine is already waiting for data on this
46 channel, so we can't pick it up. */
49 else if (channel
->next_store
> 0)
51 /* There is data on the channel. */
54 else if (__go_synch_with_select (channel
, 0))
56 /* We synched up with a select sending data, so there will
57 be data for us shortly. Tell the select to go, and then
59 __go_broadcast_to_select (channel
);
61 while (channel
->next_store
== 0)
63 i
= pthread_cond_wait (&channel
->cond
, &channel
->lock
);
71 /* Otherwise there is no data. */
77 channel
->waiting_to_receive
= 1;
78 __go_assert (channel
->next_store
== 1);
84 i
= pthread_mutex_unlock (&channel
->lock
);
86 return RECEIVE_NONBLOCKING_ACQUIRE_NODATA
;
89 return RECEIVE_NONBLOCKING_ACQUIRE_DATA
;
92 /* Receive something 64 bits or smaller on a nonblocking channel. */
94 struct __go_receive_nonblocking_small
95 __go_receive_nonblocking_small (struct __go_channel
*channel
)
97 uintptr_t element_size
;
98 struct __go_receive_nonblocking_small ret
;
100 element_size
= channel
->element_type
->__size
;
101 __go_assert (element_size
<= sizeof (uint64_t));
103 int data
= __go_receive_nonblocking_acquire (channel
);
104 if (data
!= RECEIVE_NONBLOCKING_ACQUIRE_DATA
)
108 ret
.__closed
= data
== RECEIVE_NONBLOCKING_ACQUIRE_CLOSED
;
112 ret
.__val
= channel
->data
[channel
->next_fetch
];
114 __go_receive_release (channel
);