1 /* go-send-nb-small.c -- nonblocking send of something small 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 send something on a nonblocking channel. */
16 __go_send_nonblocking_acquire (struct __go_channel *channel)
21 i = pthread_mutex_lock (&channel->lock);
24 while (channel->selected_for_send)
26 i = pthread_cond_wait (&channel->cond, &channel->lock);
30 if (channel->is_closed)
32 ++channel->closed_op_count;
33 if (channel->closed_op_count >= MAX_CLOSED_OPERATIONS)
35 i = pthread_mutex_unlock (&channel->lock);
37 __go_panic_msg ("too many operations on closed channel");
39 i = pthread_mutex_unlock (&channel->lock);
41 return SEND_NONBLOCKING_ACQUIRE_CLOSED;
44 if (channel->num_entries > 0)
45 has_space = ((channel->next_store + 1) % channel->num_entries
46 != channel->next_fetch);
49 /* This is a synchronous channel. If somebody is current
50 sending, then we can't send. Otherwise, see if somebody is
51 waiting to receive, or see if we can synch with a select. */
52 if (channel->waiting_to_send)
54 /* Some other goroutine is currently sending on this
55 channel, which means that we can't. */
58 else if (channel->waiting_to_receive)
60 /* Some other goroutine is waiting to receive a value, so we
61 can send directly to them. */
64 else if (__go_synch_with_select (channel, 1))
66 /* We found a select waiting to receive data, so we can send
68 __go_broadcast_to_select (channel);
73 /* Otherwise, we can't send, because nobody is waiting to
80 channel->waiting_to_send = 1;
81 __go_assert (channel->next_store == 0);
87 i = pthread_mutex_unlock (&channel->lock);
90 return SEND_NONBLOCKING_ACQUIRE_NOSPACE;
93 return SEND_NONBLOCKING_ACQUIRE_SPACE;
96 /* Send something 64 bits or smaller on a channel. */
99 __go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
101 __go_assert (channel->element_size <= sizeof (uint64_t));
103 int data = __go_send_nonblocking_acquire (channel);
104 if (data != SEND_NONBLOCKING_ACQUIRE_SPACE)
105 return data == SEND_NONBLOCKING_ACQUIRE_CLOSED;
107 channel->data[channel->next_store] = val;
109 __go_send_release (channel);