diff --git a/src/ucore_threadqueue.c b/src/ucore_threadqueue.c index d5a10b0..953ccde 100644 --- a/src/ucore_threadqueue.c +++ b/src/ucore_threadqueue.c @@ -149,8 +149,33 @@ int uc_thread_queue_get(struct uc_threadqueue *queue, const struct timespec *tim return 0; } +static void uc_thread_queue_walk_unlocled(struct uc_threadqueue *queue, uc_thread_queue_walk_func walk_func) +{ + struct uc_threadmsg *p; + struct uc_threadmsg *next; + for(p = queue->first; p; p = next) { + next = p->next; + walk_func(p); + } +} + +int uc_thread_queue_walk(struct uc_threadqueue *queue, uc_thread_queue_walk_func walk_func) +{ + if (queue == NULL || !walk_func) { + return EINVAL; + } + + pthread_mutex_lock(&queue->mutex); + + uc_thread_queue_walk_unlocled(queue, walk_func); + + pthread_mutex_unlock(&queue->mutex); + + return 0; +} + //maybe caller should supply a callback for cleaning the elements ? -int uc_thread_queue_cleanup(struct uc_threadqueue *queue, int freedata) +int uc_thread_queue_cleanup(struct uc_threadqueue *queue, uc_thread_queue_walk_func free_func) { int rc; @@ -172,13 +197,8 @@ int uc_thread_queue_cleanup(struct uc_threadqueue *queue, int freedata) return EBUSY; } - if(freedata) { - struct uc_threadmsg *p; - struct uc_threadmsg *next; - for(p = queue->first; p; p = next) { - next = p->next; - free(p); - } + if(free_func) { + uc_thread_queue_walk_unlocled(queue, free_func); } pthread_mutex_unlock(&queue->mutex); @@ -190,6 +210,7 @@ int uc_thread_queue_cleanup(struct uc_threadqueue *queue, int freedata) } + long thread_queue_length(struct uc_threadqueue *queue) { long length; diff --git a/src/ucore_threadqueue.h b/src/ucore_threadqueue.h index 3d9a36e..b89aeb1 100644 --- a/src/ucore_threadqueue.h +++ b/src/ucore_threadqueue.h @@ -70,6 +70,8 @@ struct uc_threadmsg{ struct uc_threadmsg *next; }; +typedef int (*uc_thread_queue_walk_func) (struct uc_threadmsg *msg); + /** * A ThreadQueue @@ -242,22 +244,36 @@ long uc_thread_queue_length( struct uc_threadqueue *queue ); /** * @ingroup ThreadQueue - * Destroy a queue. - * * Destroy the queue. * - * If freedata is != 0 free(3) will be called on all pending messages in the queue + * If free_func is != NULL, free_func will be called for every item, allowing you to free + * the item. * You cannot call this if there are someone currently adding or getting messages * from the queue. * After a queue have been cleaned, it cannot be used again untill #thread_queue_init * has been called on the queue. * * @param queue Pointer to the queue that should be cleaned - * @param freedata set to nonzero if free(3) should be called on remaining - * messages + * @param free_func pointer to function that will be called for each item. + * The function must not in anyway interact with the queue. * @return 0 on success EINVAL if queue is NULL EBUSY if someone is holding any locks on the queue */ -int uc_thread_queue_destroy(struct uc_threadqueue *queue, int freedata); +int uc_thread_queue_destroy(struct uc_threadqueue *queue, uc_thread_queue_walk_func free_func); + +/** + * @ingroup ThreadQueue + * Walk the elements of the queue, intended for debugging + * + * The supplied function will be called for each item in the queue, internal queue + * locks are held while the function is called, so the supplied function must not + * interact with the queue, else deadlock occors. + * + * @param queue Pointer to the queue to walk + * @param free_func pointer to function that will be called for each item. + * The function must not in anyway interact with the queue. + * @return 0 on success + */ +int uc_thread_queue_walk(struct uc_threadqueue *queue, uc_thread_queue_walk_func walk_func); #ifdef __cplusplus }