queueof.c
来自「Sun公司Dream项目」· C语言 代码 · 共 212 行
C
212 行
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* in compliance with the License.
*
* You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If
* applicable, add the following below this CDDL HEADER,
* with the fields enclosed by brackets "[]" replaced
* with your own identifying information:
* Portions Copyright [yyyy]
* [name of copyright owner]
*/
/*
* $(@)QueueOf.c $Revision: 1.2 $ $Date: 2006/07/15 00:02:34 $
*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*/
/*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*/
#pragma ident "@(#)QueueOf.c 1.3 99/10/27 SMI"
#include <errno.h>
#include <stdlib.h>
#include <synch.h>
#include "cobjs/Log.h"
#include "cobjs/Macros.h"
#include "cobjs/Types.h"
#include "cobjs/QueueOf.h"
/*
* OBJECT QueueOf Instance Variables
*/
struct _QueueOf {
void **items;
int len;
size_t itemSize;
int in;
int out;
mutex_t mutex;
cond_t inAvailCond;
cond_t outAvailCond;
Boolean isShutdown;
};
static Boolean _queueOfIsFull(QueueOf queue);
static Boolean _queueOfIsEmpty(QueueOf queue);
/*
* OBJECT QueueOf Class Interface
*/
QueueOf
queueOfNew(size_t itemSize, int maxLen)
{
QueueOf queue = NEW(struct _QueueOf, 1);
queue->len = maxLen + 1;
queue->itemSize = itemSize;
queue->items = (void **)CALLOC(queue->len, queue->itemSize);
queue->in = 0;
queue->out = 0;
queue->isShutdown = FALSE;
ABORT_IF_ERRNO(mutex_init(&queue->mutex, USYNC_THREAD, 0));
ABORT_IF_ERRNO(cond_init(&queue->inAvailCond, USYNC_THREAD, 0));
ABORT_IF_ERRNO(cond_init(&queue->outAvailCond, USYNC_THREAD, 0));
return queue;
}
/*
* OBJECT QueueOf Instance Interface
*/
/*
* Enqueues item on queue. If queue is full, will block until room available
* in queue or until the timeoutDate occurs. timeoutDatep == NULL implies
* block until successful.
*
* Attempting to enqueue NULL is an error.
*
* Returns TRUE if enqueue successful, FALSE if timeout or queue is shutdown.
*/
Boolean
queueOfEnqueue(QueueOf queue, void *item, timestruc_t *timeoutDatep)
{
Boolean didEnqueue = FALSE;
int error = 0;
CHECK_IF_ERRNO(mutex_lock(&queue->mutex));
while (_queueOfIsFull(queue) && !queue->isShutdown && error != ETIME) {
error = (timeoutDatep != NULL)
? cond_timedwait(&queue->inAvailCond, &queue->mutex, timeoutDatep)
: cond_wait(&queue->inAvailCond, &queue->mutex);
if (error != 0 && error != ETIME && error != EINTR) {
ABORT_WITH_ERRNO(error, "cond_timedwait");
}
}
if (! _queueOfIsFull(queue) && ! queue->isShutdown) {
void *queueItem;
CHECK_IF_ERRNO(cond_broadcast(&queue->outAvailCond));
queueItem = ((char *) (queue->items)) + (queue->in++ * queue->itemSize);
(void) memcpy(queueItem, item, queue->itemSize);
if (queue->in >= queue->len) {
queue->in = 0;
}
didEnqueue = TRUE;
}
CHECK_IF_ERRNO(mutex_unlock(&queue->mutex));
return didEnqueue;
}
/*
* Dequeues item from queue, blocks if no items are present until
* timeoutDate. timeoutDatep == NULL implies block until item available or
* queue shutdown is done. Returns TRUE if item dequeued. Returns FALSE if
* timeout or queue shutdown.
*
* Returns FALSE if timeout or queue shutdown and empty.
*/
Boolean
queueOfDequeue(QueueOf queue, void *item, timestruc_t *timeoutDatep)
{
/*
* Dequeues item from queue, blocks if not items are present.
*/
int error = 0;
Boolean retVal = FALSE;
CHECK_IF_ERRNO(mutex_lock(&queue->mutex));
while (_queueOfIsEmpty(queue) && !queue->isShutdown && error != ETIME) {
error = (timeoutDatep != NULL)
? cond_timedwait(&queue->outAvailCond, &queue->mutex, timeoutDatep)
: cond_wait(&queue->outAvailCond, &queue->mutex);
if (error != 0 && error != ETIME && error != EINTR) {
ABORT_WITH_ERRNO(error, "cond_timedwait");
}
}
if (! _queueOfIsEmpty(queue)) {
void *queueItem;
queueItem = ((char *) (queue->items))
+ (queue->out++ * queue->itemSize);
(void) memcpy(item, queueItem, queue->itemSize);
retVal = TRUE;
if (queue->out >= queue->len) {
queue->out = 0;
}
CHECK_IF_ERRNO(cond_broadcast(&queue->inAvailCond));
}
CHECK_IF_ERRNO(mutex_unlock(&queue->mutex));
return retVal;
}
void
queueOfShutdown(QueueOf queue)
{
CHECK_IF_ERRNO(mutex_lock(&queue->mutex));
queue->isShutdown = TRUE;
CHECK_IF_ERRNO(cond_broadcast(&queue->outAvailCond));
CHECK_IF_ERRNO(cond_broadcast(&queue->inAvailCond));
CHECK_IF_ERRNO(mutex_unlock(&queue->mutex));
}
Boolean
queueOfIsActive(QueueOf queue)
{
return Boolean(!queue->isShutdown);
}
void
queueOfFree(QueueOf queue)
{
ASSERT(queue->in == queue->out);
ABORT_IF_ERRNO(mutex_destroy(&queue->mutex));
ABORT_IF_ERRNO(cond_destroy(&queue->inAvailCond));
ABORT_IF_ERRNO(cond_destroy(&queue->outAvailCond));
free(queue->items);
free(queue);
}
static Boolean
_queueOfIsFull(QueueOf queue)
{
/*
* Returns TRUE if queue is full, FALSE otherwise.
*/
return Boolean(((queue->in + 1) % queue->len) == queue->out);
}
static Boolean
_queueOfIsEmpty(QueueOf queue)
{
/*
* Returns TRUE if the queue is empty, FALSE otherwise.
*/
return Boolean(queue->in == queue->out);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?