/* go-new-channel.c -- allocate a new channel. Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #include #include "go-alloc.h" #include "go-assert.h" #include "go-panic.h" #include "channel.h" struct __go_channel* __go_new_channel (size_t element_size, size_t entries) { struct __go_channel* ret; size_t alloc_size; int i; if ((size_t) (int) entries != entries || entries > (size_t) -1 / element_size) __go_panic_msg ("chan size out of range"); alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); /* We use a circular buffer which means that when next_fetch == next_store we don't know whether the buffer is empty or full. So we allocate an extra space, and always leave a space open. FIXME. */ if (entries != 0) ++entries; ret = (struct __go_channel*) __go_alloc (sizeof (struct __go_channel) + ((entries == 0 ? 1 : entries) * alloc_size * sizeof (uint64_t))); i = pthread_mutex_init (&ret->lock, NULL); __go_assert (i == 0); i = pthread_cond_init (&ret->cond, NULL); __go_assert (i == 0); ret->element_size = element_size; ret->closed_op_count = 0; ret->waiting_to_send = 0; ret->waiting_to_receive = 0; ret->selected_for_send = 0; ret->selected_for_receive = 0; ret->is_closed = 0; ret->saw_close = 0; ret->select_send_queue = NULL; ret->select_receive_queue = NULL; ret->select_mutex = NULL; ret->select_cond = NULL; ret->num_entries = entries; ret->next_store = 0; ret->next_fetch = 0; return ret; }