mirror of https://github.com/dzavalishin/oskit/
219 lines
5.0 KiB
C
Executable File
219 lines
5.0 KiB
C
Executable File
/*
|
||
* 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 <oskit/com/queue.h>
|
||
#include <oskit/c/assert.h>
|
||
#include <oskit/c/stdlib.h>
|
||
#include <oskit/c/string.h>
|
||
|
||
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 <oskit/c/stdio.h>
|
||
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
|