* Copyright (c) 2021-2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "blocking_queue.h"
void HdfBlockingQueueInit(struct HdfBlockingQueue *queue)
{
HdfSListInit(&queue->list);
OsalSemInit(&queue->sem);
OsalMutexInit(&queue->mutex);
}
void HdfBlockingQueueDestroy(struct HdfBlockingQueue *queue)
{
HdfSListInit(&queue->list);
OsalSemDestroy(&queue->sem);
OsalMutexDestroy(&queue->mutex);
}
void HdfBlockingQueueFlush(struct HdfBlockingQueue *queue)
{
OsalMutexLock(&queue->mutex);
HdfSListFlush(&queue->list, HdfSListRemove);
OsalMutexUnlock(&queue->mutex);
OsalSemPost(&queue->sem);
}
void *HdfBlockingQueueTake(struct HdfBlockingQueue *queue)
{
void *data = HdfBlockingQueueGet(queue);
if (data == NULL) {
OsalSemWait(&queue->sem, OSAL_WAIT_FOREVER);
data = HdfBlockingQueueGet(queue);
}
return data;
}
void *HdfBlockingQueueGet(struct HdfBlockingQueue *queue)
{
void *data = NULL;
struct HdfSListEntry *entry;
OsalMutexLock(&queue->mutex);
entry = (struct HdfSListEntry *)HdfSListPeek(&queue->list);
OsalMutexUnlock(&queue->mutex);
if (entry != NULL) {
data = entry->data;
HdfSListEntryFree(entry);
}
return data;
}
void *HdfBlockingQueueFind(struct HdfBlockingQueue *queue, long matchKey, SlList_Comparer comparer)
{
void *matchData = NULL;
struct HdfSListIterator it;
struct HdfSListEntry *entry = NULL;
if (comparer == NULL) {
return NULL;
}
OsalMutexLock(&queue->mutex);
HdfSListIteratorInit(&it, &queue->list);
while (HdfSListIteratorHasNext(&it)) {
entry = (struct HdfSListEntry *) HdfSListIteratorNext(&it);
if (comparer(matchKey, entry->data)) {
matchData = entry->data;
break;
}
}
OsalMutexUnlock(&queue->mutex);
return matchData;
}
void HdfBlockingQueueRemove(struct HdfBlockingQueue *queue, void *data)
{
bool targetListChanged = false;
struct HdfSListIterator it;
struct HdfSListEntry *entry = NULL;
OsalMutexLock(&queue->mutex);
HdfSListIteratorInit(&it, &queue->list);
while (HdfSListIteratorHasNext(&it)) {
entry = (struct HdfSListEntry *)HdfSListIteratorNext(&it);
if (entry->data == data) {
HdfSListIteratorRemove(&it);
HdfSListEntryFree(entry);
targetListChanged = true;
break;
}
}
OsalMutexUnlock(&queue->mutex);
if (targetListChanged) {
OsalSemPost(&queue->sem);
}
}
void *HdfBlockingQueuePoll(struct HdfBlockingQueue *queue, long timeout)
{
void *data = HdfBlockingQueueGet(queue);
if (data == NULL) {
OsalSemWait(&queue->sem, timeout);
data = HdfBlockingQueueGet(queue);
}
return data;
}
int HdfBlockingQueueOffer(struct HdfBlockingQueue *queue, void *val, long timeout)
{
struct HdfSListEntry *entry = NULL;
if (OsalSemWait(&queue->sem, timeout) != 0) {
return -1;
}
entry = HdfSListEntryNew(val);
if (entry != NULL) {
OsalMutexLock(&queue->mutex);
HdfSListAddTail(&queue->list, &entry->node);
OsalMutexUnlock(&queue->mutex);
}
OsalSemPost(&queue->sem);
}