/* * Copyright (c) 1998, 1999 The University of Utah and the Flux Group. * All rights reserved. * * This file is part of the Flux OSKit. The OSKit is free software, also known * as "open source;" you can redistribute it and/or modify it under the terms * of the GNU General Public License (GPL), version 2, as published by the Free * Software Foundation (FSF). To explore alternate licensing terms, contact * the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271. * * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have * received a copy of the GPL along with the OSKit; see the file COPYING. If * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA. */ /* * A queue of pointers to COM objects. * Reference counts are handled via oskit_iunknown_addref, etc. * * NOTE: this doesn't use the notion of size as specified in the queue * interface. * This is because it isn't needed for allocating and managing the queue. * This means that `enqueue' ignores the `size' argument and `dequeue', * and `front' do not return it. */ #include #include #include #include struct queue { oskit_queue_t q_ioi; oskit_u32_t q_count; oskit_size_t q_curlength; oskit_size_t q_maxlength; oskit_size_t q_head; oskit_size_t q_tail; oskit_iunknown_t *q_array[1]; }; #define increment(q,c) (q->c = (q->c + 1) % q->q_maxlength) static OSKIT_COMDECL queue_query(oskit_queue_t *_, const oskit_iid_t *iid, void **out_ihandle) { struct queue *q = (void *)_; assert(q && q->q_count); if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 || memcmp(iid, &oskit_queue_iid, sizeof(*iid)) == 0) { *out_ihandle = &q->q_ioi; ++q->q_count; return 0; } *out_ihandle = NULL; return OSKIT_E_NOINTERFACE; } static OSKIT_COMDECL_U queue_addref(oskit_queue_t *_) { struct queue *q = (void *)_; assert(q && q->q_count); if (q == NULL || q->q_count == 0) return OSKIT_E_INVALIDARG; return ++q->q_count; } static OSKIT_COMDECL_U queue_release(oskit_queue_t *_) { struct queue *q = (void *)_; oskit_size_t i; assert(q && q->q_count); if (--q->q_count) return q->q_count; for (i = 0; i < q->q_maxlength; i++) if (q->q_array[i]) oskit_iunknown_release(q->q_array[i]); free(q); return 0; } static OSKIT_COMDECL queue_enqueue(oskit_queue_t *_, const void *item, oskit_size_t ignored_size) { struct queue *q = (void *)_; oskit_iunknown_t *obj = (void *)item; assert(q && q->q_count); /* If the queue is full, drop it. */ if (q->q_array[q->q_tail] != NULL) { return OSKIT_E_FAIL; } /* Otherwise we have space. */ q->q_array[q->q_tail] = obj; oskit_iunknown_addref(obj); increment(q,q_tail); q->q_curlength++; return 0; } static OSKIT_COMDECL_U queue_dequeue(oskit_queue_t *_, void *item) { struct queue *q = (void *)_; oskit_iunknown_t **obj = item; assert(q && q->q_count); /* Nothing to dequeue? */ assert(q->q_curlength != 0); /* Head shouldn't be NULL if q_curlength is non-zero. */ assert(q->q_array[q->q_head] != NULL); /* Otherwise, take the head elem. */ *obj = q->q_array[q->q_head]; /* they get our ref */ q->q_array[q->q_head] = NULL; increment(q,q_head); q->q_curlength--; return 0; } static OSKIT_COMDECL_U queue_size(oskit_queue_t *_) { struct queue *q = (void *)_; assert(q && q->q_count); return q->q_curlength; } static OSKIT_COMDECL_U queue_front(oskit_queue_t *_, void *item) { struct queue *q = (void *)_; oskit_iunknown_t **obj = item; assert(q && q->q_count); /* Empty queue? */ assert(q->q_curlength != 0); /* Head shouldn't be NULL if q_curlength is non-zero. */ assert(q->q_array[q->q_head] != NULL); /* Give them a pointer to the head. */ *obj = q->q_array[q->q_head]; oskit_iunknown_addref(*obj); return 0; } static struct oskit_queue_ops queue_ops = { queue_query, queue_addref, queue_release, queue_enqueue, queue_dequeue, queue_size, queue_front }; oskit_error_t oskit_bounded_com_queue_create(oskit_size_t length, oskit_queue_t **out_q) { struct queue *q; if (length == 0) return OSKIT_E_INVALIDARG; q = calloc(sizeof(struct queue) + (length-1)*sizeof(oskit_iunknown_t), 1); if (q == NULL) return OSKIT_E_OUTOFMEMORY; q->q_ioi.ops = &queue_ops; q->q_count = 1; q->q_curlength = 0; q->q_maxlength = length; q->q_head = 0; q->q_tail = 0; /* q_array is already zeroed */ *out_q = &q->q_ioi; return 0; } #if 0 #include void oskit_bounded_com_queue_dump(oskit_queue_t *_) { struct queue *q = (void *)_; oskit_size_t i; assert(q && q->q_count); printf("%d (%d,%d): [ ", q->q_curlength, q->q_head, q->q_tail); for (i = 0; i < q->q_maxlength; i++) printf("%p ", q->q_array[i]); printf("]\n"); } #endif