Rizin
unix-like reverse engineering framework and cli tools
thread_queue.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2022 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_th.h>
5 #include "thread.h"
6 
17 struct rz_th_queue_t {
20  size_t max_size;
22 };
23 
34  if (!queue) {
35  return NULL;
36  }
37 
38  queue->max_size = max_size;
39  queue->list = rz_list_newf(qfree);
40  queue->lock = rz_th_lock_new(false);
41  queue->cond = rz_th_cond_new();
42  if (!queue->list || !queue->lock || !queue->cond) {
44  return NULL;
45  }
46 
47  return queue;
48 }
49 
56  if (!queue) {
57  return;
58  }
59 
60  rz_list_free(queue->list);
61  rz_th_lock_free(queue->lock);
62  rz_th_cond_free(queue->cond);
63  free(queue);
64 }
65 
76  rz_return_val_if_fail(queue && user, false);
77 
78  bool added = false;
79  rz_th_lock_enter(queue->lock);
80  if (!queue->max_size || rz_list_length(queue->list) < queue->max_size) {
81  if (tail) {
82  added = rz_list_append(queue->list, user) != NULL;
83  } else {
84  added = rz_list_prepend(queue->list, user) != NULL;
85  }
86  }
87  if (added) {
88  rz_th_cond_signal(queue->cond);
89  }
90  rz_th_lock_leave(queue->lock);
91  return added;
92 }
93 
104 
105  void *user = NULL;
106  rz_th_lock_enter(queue->lock);
107  if (tail) {
108  user = rz_list_pop(queue->list);
109  } else {
110  user = rz_list_pop_head(queue->list);
111  }
112  rz_th_lock_leave(queue->lock);
113  return user;
114 }
115 
126 
127  void *user = NULL;
128  rz_th_lock_enter(queue->lock);
129  if (rz_list_empty(queue->list)) {
130  rz_th_cond_wait(queue->cond, queue->lock);
131  }
132  if (tail) {
133  user = rz_list_pop(queue->list);
134  } else {
135  user = rz_list_pop_head(queue->list);
136  }
137  rz_th_lock_leave(queue->lock);
138  return user;
139 }
140 
150 
151  rz_th_lock_enter(queue->lock);
152  bool is_empty = rz_list_empty(queue->list);
153  rz_th_lock_leave(queue->lock);
154  return is_empty;
155 }
156 
166 
167  rz_th_lock_enter(queue->lock);
168  bool is_full = queue->max_size != RZ_THREAD_QUEUE_UNLIMITED && rz_list_length(queue->list) >= queue->max_size;
169  rz_th_lock_leave(queue->lock);
170  return is_full;
171 }
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_BORROW RzListIter * rz_list_prepend(RZ_NONNULL RzList *list, void *data)
Appends at the beginning of the list a new element.
Definition: list.c:316
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_OWN void * rz_list_pop(RZ_NONNULL RzList *list)
Removes and returns the last element of the list.
Definition: list.c:376
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_OWN void * rz_list_pop_head(RZ_NONNULL RzList *list)
Removes and returns the first element of the list.
Definition: list.c:401
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_THREAD_QUEUE_UNLIMITED
Definition: rz_th.h:20
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
RzThreadQueue is a thread-safe queue that can be listened on from multiple threads.
Definition: thread_queue.c:17
size_t max_size
Definition: thread_queue.c:20
RzList * list
Definition: thread_queue.c:21
RzThreadCond * cond
Definition: thread_queue.c:19
RzThreadLock * lock
Definition: thread_queue.c:18
RZ_API void rz_th_cond_free(RZ_NULLABLE RzThreadCond *cond)
Frees a RzThreadCond struct.
Definition: thread_cond.c:77
RZ_API void rz_th_cond_signal(RZ_NONNULL RzThreadCond *cond)
This function shall unblock at least one of the threads that are blocked on the specified condition.
Definition: thread_cond.c:34
RZ_API void rz_th_cond_wait(RZ_NONNULL RzThreadCond *cond, RZ_NONNULL RzThreadLock *lock)
The function shall block on a condition variable and shall be called with RzThreadLock locked by the ...
Definition: thread_cond.c:63
RZ_API RZ_OWN RzThreadCond * rz_th_cond_new(void)
Condition variables are intended to be used to communicate changes in the state of data shared betwee...
Definition: thread_cond.c:13
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
Definition: thread_lock.c:89
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
Definition: thread_lock.c:14
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
Definition: thread_lock.c:45
RZ_API bool rz_th_queue_is_full(RZ_NONNULL RzThreadQueue *queue)
Returns true if the queue is full and when the size is not RZ_THREAD_QUEUE_UNLIMITED (thread-safe)
Definition: thread_queue.c:164
RZ_API bool rz_th_queue_is_empty(RZ_NONNULL RzThreadQueue *queue)
Returns true if the queue is empty (thread-safe)
Definition: thread_queue.c:148
RZ_API bool rz_th_queue_push(RZ_NONNULL RzThreadQueue *queue, RZ_NONNULL void *user, bool tail)
Pushes a new element into the queue.
Definition: thread_queue.c:75
RZ_API void rz_th_queue_free(RZ_NULLABLE RzThreadQueue *queue)
Frees a RzThreadQueue structure.
Definition: thread_queue.c:55
RZ_API RZ_OWN void * rz_th_queue_wait_pop(RZ_NONNULL RzThreadQueue *queue, bool tail)
Removes an element from the queue, but yields the thread till not empty.
Definition: thread_queue.c:124
RZ_API RZ_OWN void * rz_th_queue_pop(RZ_NONNULL RzThreadQueue *queue, bool tail)
Removes an element from the queue, but does not awaits when empty.
Definition: thread_queue.c:102
RZ_API RZ_OWN RzThreadQueue * rz_th_queue_new(size_t max_size, RZ_NULLABLE RzListFree qfree)
Allocates and initializes a new fifo queue.
Definition: thread_queue.c:32
uv_pipe_t queue
Definition: worker.c:9