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
);