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 if (channel
->saw_close
)
37 ++channel
->closed_op_count
;
38 if (channel
->closed_op_count
>= MAX_CLOSED_OPERATIONS
)
40 i
= pthread_mutex_unlock (&channel
->lock
);
42 __go_panic_msg ("too many operations on closed channel");
45 channel
->saw_close
= 1;
46 __go_unlock_and_notify_selects (channel
);
47 return RECEIVE_NONBLOCKING_ACQUIRE_CLOSED
;
50 if (channel
->num_entries
> 0)
51 has_data
= channel
->next_fetch
!= channel
->next_store
;
54 if (channel
->waiting_to_receive
)
56 /* Some other goroutine is already waiting for data on this
57 channel, so we can't pick it up. */
60 else if (channel
->next_store
> 0)
62 /* There is data on the channel. */
65 else if (__go_synch_with_select (channel
, 0))
67 /* We synched up with a select sending data, so there will
68 be data for us shortly. Tell the select to go, and then
70 __go_broadcast_to_select (channel
);
72 while (channel
->next_store
== 0)
74 i
= pthread_cond_wait (&channel
->cond
, &channel
->lock
);
82 /* Otherwise there is no data. */
88 channel
->waiting_to_receive
= 1;
89 __go_assert (channel
->next_store
== 1);
95 i
= pthread_mutex_unlock (&channel
->lock
);
97 return RECEIVE_NONBLOCKING_ACQUIRE_NODATA
;
100 return RECEIVE_NONBLOCKING_ACQUIRE_DATA
;
103 /* Receive something 64 bits or smaller on a nonblocking channel. */
105 struct __go_receive_nonblocking_small
106 __go_receive_nonblocking_small (struct __go_channel
*channel
)
108 struct __go_receive_nonblocking_small ret
;
110 __go_assert (channel
->element_size
<= sizeof (uint64_t));
112 int data
= __go_receive_nonblocking_acquire (channel
);
113 if (data
!= RECEIVE_NONBLOCKING_ACQUIRE_DATA
)
116 ret
.__success
= data
== RECEIVE_NONBLOCKING_ACQUIRE_CLOSED
;
120 ret
.__val
= channel
->data
[channel
->next_fetch
];
122 __go_receive_release (channel
);