parent
							
								
									6e52fc3832
								
							
						
					
					
						commit
						4114651e59
					
				@ -0,0 +1,70 @@ | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by frank on 2021/08/08.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					#include "block_queue.h" | 
				
			||||||
 | 
					#include <stdlib.h> | 
				
			||||||
 | 
					#include <libavcodec/avcodec.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vlc_queue_t *vlc_queue_init(int size) { | 
				
			||||||
 | 
					    vlc_queue_t *queue = (vlc_queue_t *)(malloc(sizeof(vlc_queue_t))); | 
				
			||||||
 | 
					    queue->size = size; | 
				
			||||||
 | 
					    queue->next_to_read = 0; | 
				
			||||||
 | 
					    queue->next_to_write = 0; | 
				
			||||||
 | 
					    int i; | 
				
			||||||
 | 
					    queue->packets = (void **)(malloc(sizeof(*queue->packets) * size)); | 
				
			||||||
 | 
					    for (i = 0; i < size; i++) { | 
				
			||||||
 | 
					        queue->packets[i] = malloc(sizeof(AVPacket)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    pthread_mutex_init(&queue->mutex, NULL); | 
				
			||||||
 | 
					    pthread_cond_init(&queue->cond, NULL); | 
				
			||||||
 | 
					    return queue; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void vlc_queue_free(vlc_queue_t *queue) { | 
				
			||||||
 | 
					    int i; | 
				
			||||||
 | 
					    for (i = 0; i < queue->size; i++) { | 
				
			||||||
 | 
					        free(queue->packets[i]); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    free(queue->packets); | 
				
			||||||
 | 
					    free(queue); | 
				
			||||||
 | 
					    pthread_cond_destroy(&queue->cond); | 
				
			||||||
 | 
					    pthread_mutex_destroy(&queue->mutex); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int vlc_queue_next(vlc_queue_t *queue, int current) { | 
				
			||||||
 | 
					    return (current + 1) % queue->size; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *vlc_queue_push(vlc_queue_t *queue, void *data) { | 
				
			||||||
 | 
					    pthread_mutex_lock(&queue->mutex);//lock
 | 
				
			||||||
 | 
					    int current = queue->next_to_write; | 
				
			||||||
 | 
					    int next_to_write; | 
				
			||||||
 | 
					    for (;;) { | 
				
			||||||
 | 
					        next_to_write = vlc_queue_next(queue, current); | 
				
			||||||
 | 
					        if (next_to_write != queue->next_to_read) { | 
				
			||||||
 | 
					            break; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        pthread_cond_wait(&queue->cond, &queue->mutex); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    queue->next_to_write = next_to_write; | 
				
			||||||
 | 
					    queue->packets[current] = data;//TODO
 | 
				
			||||||
 | 
					    pthread_cond_broadcast(&queue->cond); | 
				
			||||||
 | 
					    pthread_mutex_unlock(&queue->mutex);//unlock
 | 
				
			||||||
 | 
					    return queue->packets[current]; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *vlc_queue_pop(vlc_queue_t *queue) { | 
				
			||||||
 | 
					    pthread_mutex_lock(&queue->mutex); | 
				
			||||||
 | 
					    int current = queue->next_to_read; | 
				
			||||||
 | 
					    for (;;) { | 
				
			||||||
 | 
					        if (queue->next_to_write != queue->next_to_read) { | 
				
			||||||
 | 
					            break; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        pthread_cond_wait(&queue->cond, &queue->mutex); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    queue->next_to_read = vlc_queue_next(queue, current); | 
				
			||||||
 | 
					    pthread_cond_broadcast(&queue->cond); | 
				
			||||||
 | 
					    pthread_mutex_unlock(&queue->mutex); | 
				
			||||||
 | 
					    return queue->packets[current]; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,40 @@ | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by frank on 2021/08/08.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef BLOCK_QUEUE_H | 
				
			||||||
 | 
					#define BLOCK_QUEUE_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <pthread.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus | 
				
			||||||
 | 
					extern "C" { | 
				
			||||||
 | 
					#endif | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct vlc_queue { | 
				
			||||||
 | 
					    //the size of queue
 | 
				
			||||||
 | 
					    int size; | 
				
			||||||
 | 
					    //packet array
 | 
				
			||||||
 | 
					    void **packets; | 
				
			||||||
 | 
					    //the packet next to write
 | 
				
			||||||
 | 
					    int next_to_write; | 
				
			||||||
 | 
					    //the packet next to read
 | 
				
			||||||
 | 
					    int next_to_read; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pthread_mutex_t mutex; | 
				
			||||||
 | 
					    pthread_cond_t cond; | 
				
			||||||
 | 
					} vlc_queue_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vlc_queue_t *vlc_queue_init(int size); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void vlc_queue_free(vlc_queue_t *queue); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *vlc_queue_push(vlc_queue_t *queue, void *data); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *vlc_queue_pop(vlc_queue_t *queue); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //BLOCK_QUEUE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					#endif | 
				
			||||||
@ -1,154 +0,0 @@ | 
				
			|||||||
/*****************************************************************************
 | 
					 | 
				
			||||||
 * queue.c: generic queue (FIFO) | 
					 | 
				
			||||||
 ***************************************************************************** | 
					 | 
				
			||||||
 * Copyright (C) 2020 Rémi Denis-Courmont | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it | 
					 | 
				
			||||||
 * under the terms of the GNU Lesser General Public License as published by | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 2.1 of the License, or | 
					 | 
				
			||||||
 * (at your option) any later version. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This program 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 | 
					 | 
				
			||||||
 * GNU Lesser General Public License for more details. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Lesser General Public License | 
					 | 
				
			||||||
 * along with this program; if not, write to the Free Software Foundation, | 
					 | 
				
			||||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. | 
					 | 
				
			||||||
 *****************************************************************************/ | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <assert.h> | 
					 | 
				
			||||||
#include <stdint.h> | 
					 | 
				
			||||||
#include <stdlib.h> | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "vlc_queue.h" | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Opaque struct type.
 | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * ISO C uses the same representation for all pointer-to-struct types. | 
					 | 
				
			||||||
 * Still different pointer types are not compatible, i.e. cannot alias. | 
					 | 
				
			||||||
 * So use memcpy() to read/write pointer values. | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
struct vlc_queue_entry; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void entry_set(struct vlc_queue_entry **pp, struct vlc_queue_entry *e) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    memcpy(pp, &e, sizeof (e)); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct vlc_queue_entry *entry_get(struct vlc_queue_entry *const *pp) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    struct vlc_queue_entry *e; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memcpy(&e, pp, sizeof (e)); | 
					 | 
				
			||||||
    return e; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct vlc_queue_entry **next_p(const struct vlc_queue_entry *e, | 
					 | 
				
			||||||
                                       ptrdiff_t offset) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    return (struct vlc_queue_entry **)(((unsigned char *)e) + offset); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void next_set(struct vlc_queue_entry *e, struct vlc_queue_entry *next, | 
					 | 
				
			||||||
                     ptrdiff_t offset) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    entry_set(next_p(e, offset), next); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct vlc_queue_entry *next_get(const struct vlc_queue_entry *e, | 
					 | 
				
			||||||
                                        ptrdiff_t offset) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    return entry_get(next_p(e, offset)); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void vlc_queue_Init(vlc_queue_t *q, ptrdiff_t next_offset) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    q->first = NULL; | 
					 | 
				
			||||||
    q->lastp = &q->first; | 
					 | 
				
			||||||
    q->next_offset = next_offset; | 
					 | 
				
			||||||
    pthread_mutex_init(&q->lock, NULL); | 
					 | 
				
			||||||
    pthread_cond_init(&q->wait, NULL); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void vlc_queue_EnqueueUnlocked(vlc_queue_t *q, void *entry) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    struct vlc_queue_entry **lastp; | 
					 | 
				
			||||||
    const ptrdiff_t offset = q->next_offset; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//    vlc_mutex_assert(&q->lock);
 | 
					 | 
				
			||||||
    assert(entry_get(q->lastp) == NULL); | 
					 | 
				
			||||||
    entry_set(q->lastp, entry); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (lastp = q->lastp; entry != NULL; entry = next_get(entry, offset)) | 
					 | 
				
			||||||
        lastp = next_p(entry, offset); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    q->lastp = lastp; | 
					 | 
				
			||||||
    vlc_queue_Signal(q); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void *vlc_queue_DequeueUnlocked(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
//    vlc_mutex_assert(&q->lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void *entry = q->first; | 
					 | 
				
			||||||
    const ptrdiff_t offset = q->next_offset; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (entry != NULL) { | 
					 | 
				
			||||||
        struct vlc_queue_entry *next = next_get(entry, offset); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        next_set(entry, NULL, offset); | 
					 | 
				
			||||||
        q->first = next; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (next == NULL) | 
					 | 
				
			||||||
            q->lastp = &q->first; | 
					 | 
				
			||||||
    } | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return entry; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void *vlc_queue_DequeueAllUnlocked(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
//    vlc_mutex_assert(&q->lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void *entry = q->first; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    q->first = NULL; | 
					 | 
				
			||||||
    q->lastp = &q->first; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return entry; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void vlc_queue_Enqueue(vlc_queue_t *q, void *entry) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    vlc_queue_Lock(q); | 
					 | 
				
			||||||
    vlc_queue_EnqueueUnlocked(q, entry); | 
					 | 
				
			||||||
    vlc_queue_Unlock(q); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void *vlc_queue_Dequeue(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    void *entry; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vlc_queue_Lock(q); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while (vlc_queue_IsEmpty(q)) | 
					 | 
				
			||||||
        vlc_queue_Wait(q); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    entry = vlc_queue_DequeueUnlocked(q); | 
					 | 
				
			||||||
    vlc_queue_Unlock(q); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return entry; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void *vlc_queue_DequeueAll(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    void *entry; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vlc_queue_Lock(q); | 
					 | 
				
			||||||
    entry = vlc_queue_DequeueAllUnlocked(q); | 
					 | 
				
			||||||
    vlc_queue_Unlock(q); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return entry; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -1,258 +0,0 @@ | 
				
			|||||||
/*****************************************************************************
 | 
					 | 
				
			||||||
 * vlc_queue.h: generic queue functions | 
					 | 
				
			||||||
 ***************************************************************************** | 
					 | 
				
			||||||
 * Copyright (C) 2020 Rémi Denis-Courmont | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it | 
					 | 
				
			||||||
 * under the terms of the GNU Lesser General Public License as published by | 
					 | 
				
			||||||
 * the Free Software Foundation; either version 2.1 of the License, or | 
					 | 
				
			||||||
 * (at your option) any later version. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This program 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 | 
					 | 
				
			||||||
 * GNU Lesser General Public License for more details. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Lesser General Public License | 
					 | 
				
			||||||
 * along with this program; if not, write to the Free Software Foundation, | 
					 | 
				
			||||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. | 
					 | 
				
			||||||
 *****************************************************************************/ | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef VLC_QUEUE_H | 
					 | 
				
			||||||
#define VLC_QUEUE_H | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @defgroup queue Thread-safe queues (FIFO) | 
					 | 
				
			||||||
 * @ingroup cext | 
					 | 
				
			||||||
 * @{ | 
					 | 
				
			||||||
 * @file vlc_queue.h | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdbool.h> | 
					 | 
				
			||||||
#include <stdint.h> | 
					 | 
				
			||||||
#include <string.h> | 
					 | 
				
			||||||
#include <pthread.h> | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Opaque type for queue entry. | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
struct vlc_queue_entry; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Thread-safe queue (a.k.a. FIFO). | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
typedef struct vlc_queue | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    struct vlc_queue_entry *first; | 
					 | 
				
			||||||
    struct vlc_queue_entry **lastp; | 
					 | 
				
			||||||
    ptrdiff_t next_offset; | 
					 | 
				
			||||||
    pthread_mutex_t lock; | 
					 | 
				
			||||||
    pthread_cond_t wait; | 
					 | 
				
			||||||
} vlc_queue_t; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Initializes a queue. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @param queue storage space for the queue | 
					 | 
				
			||||||
 * @param next_offset offset of the pointer to the next element | 
					 | 
				
			||||||
 *                    within a queue entry (as per @c offsetof()) | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
void vlc_queue_Init(vlc_queue_t *queue, ptrdiff_t next_offset); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @defgroup queue_ll Queue internals | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * Low-level queue functions. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * In some cases, the high-level queue functions do not exactly fit the | 
					 | 
				
			||||||
 * use case requirements, and it is necessary to access the queue internals. | 
					 | 
				
			||||||
 * This typically occurs when threads wait for elements to be added to the | 
					 | 
				
			||||||
 * queue at the same time as some other type of events. | 
					 | 
				
			||||||
 * @{ | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Locks a queue. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * No more than one thread can lock a queue at any given time, and no other | 
					 | 
				
			||||||
 * thread can modify the queue while it is locked. | 
					 | 
				
			||||||
 * Accordingly, if the queue is already locked by another thread, this function | 
					 | 
				
			||||||
 * waits. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * Use vlc_queue_Unlock() to release the lock. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @warning Recursively locking a single queue is undefined. | 
					 | 
				
			||||||
 * Also locking more than one queue at a time may lead to lock inversion: | 
					 | 
				
			||||||
 * mind the locking order! | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
static inline void vlc_queue_Lock(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    pthread_mutex_lock(&q->lock); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Unlocks a queue. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This releases the lock on a queue, allowing other threads to manipulate the | 
					 | 
				
			||||||
 * queue. The behaviour is undefined if the calling thread is not holding the | 
					 | 
				
			||||||
 * queue lock. | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
static inline void vlc_queue_Unlock(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    pthread_mutex_unlock(&q->lock); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Wakes one thread waiting for a queue entry up. | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
static inline void vlc_queue_Signal(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    pthread_cond_signal(&q->wait); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Waits for a queue entry. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @note This function is a cancellation point. | 
					 | 
				
			||||||
 * In case of cancellation, the queue will be locked, | 
					 | 
				
			||||||
 * as is consistent for condition variable semantics. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @bug This function should probably not be aware of cancellation. | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
static inline void vlc_queue_Wait(vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    pthread_cond_wait(&q->wait, &q->lock); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Queues an entry (without locking). | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This function enqueues an entry, or rather a linked-list of entries, in a | 
					 | 
				
			||||||
 * thread-safe queue, without taking the queue lock. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @warning It is assumed that the caller already holds the queue lock; | 
					 | 
				
			||||||
 * otherwise the behaviour is undefined. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @param entry NULL-terminated list of entries to queue | 
					 | 
				
			||||||
 *              (if NULL, this function has no effects) | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
void vlc_queue_EnqueueUnlocked(vlc_queue_t *, void *entry); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Dequeues the oldest entry (without locking). | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This function dequeues an entry from a thread-safe queue. It is assumed | 
					 | 
				
			||||||
 * that the caller already holds the queue lock; otherwise the behaviour is | 
					 | 
				
			||||||
 * undefined. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @warning It is assumed that the caller already holds the queue lock; | 
					 | 
				
			||||||
 * otherwise the behaviour is undefined. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @return the first entry in the queue, or NULL if the queue is empty | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
void *vlc_queue_DequeueUnlocked(vlc_queue_t *); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Dequeues all entries (without locking). | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This is equivalent to calling vlc_queue_DequeueUnlocked() repeatedly until | 
					 | 
				
			||||||
 * the queue is emptied. However this function is much faster than that, as it | 
					 | 
				
			||||||
 * does not need to update the linked-list pointers. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @warning It is assumed that the caller already holds the queue lock; | 
					 | 
				
			||||||
 * otherwise the behaviour is undefined. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @return a linked-list of all entries (possibly NULL if none) | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
void *vlc_queue_DequeueAllUnlocked(vlc_queue_t *); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Checks if a queue is empty (without locking). | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @warning It is assumed that the caller already holds the queue lock; | 
					 | 
				
			||||||
 * otherwise the behaviour is undefined. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @retval false the queue contains one or more entries | 
					 | 
				
			||||||
 * @retval true the queue is empty | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
static inline bool vlc_queue_IsEmpty(const vlc_queue_t *q) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    return q->first == NULL; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** @} */ | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Queues an entry. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This function enqueues an entry, or rather a linked-list of entries, in a | 
					 | 
				
			||||||
 * thread-safe queue. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @param entry list of entries (if NULL, this function has no effects) | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
void vlc_queue_Enqueue(vlc_queue_t *, void *entry); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Dequeues the oldest entry. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This function dequeues an entry from a thread-safe queue. If the queue is | 
					 | 
				
			||||||
 * empty, it will wait until at least one entry is available. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @param offset offset of the next pointer within a queue entry | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @return the first entry in the queue, or NULL if the queue is empty | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
void *vlc_queue_Dequeue(vlc_queue_t *); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Dequeues all entries. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * This is equivalent to calling vlc_queue_Dequeue() repeatedly until the queue | 
					 | 
				
			||||||
 * is emptied. However this function is much faster than that, as it | 
					 | 
				
			||||||
 * does not need to update the linked-list pointers. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @return a linked-list of all entries (possibly NULL if none) | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
void *vlc_queue_DequeueAll(vlc_queue_t *); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @defgroup queue_killable Killable queues | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * Thread-safe queues with an end flag. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @{ | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Marks a queue ended. | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
static inline void vlc_queue_Kill(vlc_queue_t *q, | 
					 | 
				
			||||||
                                  bool */*restrict*/ tombstone) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    vlc_queue_Lock(q); | 
					 | 
				
			||||||
    *tombstone = true; | 
					 | 
				
			||||||
    vlc_queue_Signal(q); | 
					 | 
				
			||||||
    vlc_queue_Unlock(q); | 
					 | 
				
			||||||
    pthread_cond_destroy(&q->wait); | 
					 | 
				
			||||||
    pthread_mutex_destroy(&q->lock); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Dequeues one entry from a killable queue. | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @return an entry, or NULL if the queue is empty and has been ended. | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
static inline void *vlc_queue_DequeueKillable(vlc_queue_t *q, | 
					 | 
				
			||||||
                                              bool */*restrict*/ tombstone) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
    void *entry; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vlc_queue_Lock(q); | 
					 | 
				
			||||||
    while (vlc_queue_IsEmpty(q) && !*tombstone) | 
					 | 
				
			||||||
        vlc_queue_Wait(q); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    entry = vlc_queue_DequeueUnlocked(q); | 
					 | 
				
			||||||
    vlc_queue_Unlock(q); | 
					 | 
				
			||||||
    return entry; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif | 
					 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue