Mstdlib-1.24.0
m_queue.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2015 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_QUEUE_H__
25#define __M_QUEUE_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31#include <mstdlib/base/m_sort.h>
32
33/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
34
35/*! \addtogroup m_queue Queue
36 * \ingroup m_datastructures
37 *
38 * Queue, meant for storing a list of pointers in either insertion order or
39 * sorted as per a user-defined callback. The usage is very similar to that of
40 * an M_llist_t, and infact an M_llist_t is used as one of the backing data types,
41 * but it also uses an M_hashtable_t in order to make lookups and removals of
42 * queue members by pointer O(1) rather than O(log n) for sorted lists
43 * or O(n) for unsorted lists.
44 *
45 * Usage Example:
46 *
47 * \code{.c}
48 * M_queue_t *queue;
49 * void *member = NULL;
50 * M_queue_foreach_t *q_foreach = NULL;
51 *
52 * queue = M_queue_create(M_sort_compar_str, M_free);
53 * M_queue_insert(queue, M_strdup("b. hello world"));
54 * M_queue_insert(queue, M_strdup("c. goodbye"));
55 * M_queue_insert(queue, M_strdup("a! -- I should end up enumerated first"));
56 * M_printf("queue members: %zu\n", M_queue_len(queue));
57 *
58 * while (M_queue_foreach(queue, &q_foreach, &member)) {
59 * M_printf("removing member: %s\n", (const char *)member);
60 * M_queue_remove(queue, member);
61 * }
62 *
63 * M_printf("queue members: %zu\n", M_queue_len(queue));
64 * M_queue_destroy(queue);
65 * \endcode
66 *
67 * @{
68 */
69
70__BEGIN_DECLS
71
72struct M_queue;
73/*! Data type used as the main queue object */
74typedef struct M_queue M_queue_t;
75
76struct M_queue_foreach;
77/*! Data type used for enumeration of a queue */
79
80/*! Create a queue (list of objects) that stores user-provided pointers. The pointers
81 * stored may be kept in insertion order or sorted, depending on how the queue is
82 * initialized.
83 * \param sort_cb If the pointers should be stored in a sorted order, register this
84 * callback with the routine for sorting. If insertion order is
85 * desired, pass NULL.
86 * \param free_cb Upon removal of a pointer from the queue, this callback will be
87 * called. This applies to M_queue_destroy() and M_queue_remove().
88 * If no free callback desired, pass NULL.
89 * \return Allocated M_queue_t * on success that should be free'd with M_queue_destroy(),
90 * otherwise NULL.
91 */
92M_API M_queue_t *M_queue_create(M_sort_compar_t sort_cb, void (*free_cb)(void *));
93
94
95/*! Destroy's an initialized M_queue_t * object.
96 * \param queue Initialized queue object returned by M_queue_create()
97 */
98M_API void M_queue_destroy(M_queue_t *queue);
99
100
101/*! Insert a user-supplied queue object (pointer) into the queue. The object specified
102 * should not already be in the queue.
103 * \param queue Initialized queue object returned by M_queue_create()
104 * \param member User-supplied queue object (pointer) to insert, must not be NULL.
105 * \return M_TRUE on success, M_FALSE on failure such as if the user-supplied object
106 * already exists in the queue */
107M_API M_bool M_queue_insert(M_queue_t *queue, void *member);
108
109
110/*! Remove a user-supplied queue object (pointer) from the queue. If M_queue_create()
111 * registered the free_cb, the free_cb will be called upon removal.
112 * \param queue Initialized queue object returned by M_queue_create()
113 * \param member User-supplied queue object (pointer) to remove.
114 * \return M_TRUE on success, M_FALSE on failure such as object not found.
115 */
116M_API M_bool M_queue_remove(M_queue_t *queue, const void *member);
117
118
119/*! See if queue member still exists.
120 * \param queue Initialized queue object returned by M_queue_create()
121 * \param member User-supplied queue object (pointer) to find.
122 * \return M_TRUE if member exists, M_FALSE otherwise.
123 */
124M_API M_bool M_queue_exists(const M_queue_t *queue, const void *member);
125
126
127/*! Take control of a user-supplied queue object (pointer). This will remove the
128 * object from the list without freeing the object (assuming free_cb was registered).
129 * If no free_cb was registered in M_queue_create(), this has the same behavior
130 * as M_queue_remove().
131 * \param queue Initialized queue object returned by M_queue_create()
132 * \param member User-supplied queue object (pointer) to take ownership of.
133 * \return M_TRUE on success, M_FALSE on failure such as object not found.
134 */
135M_API M_bool M_queue_take(M_queue_t *queue, const void *member);
136
137
138/*! Take control of the first queue member. This will remove the object
139 * from the list without freeing the object (assuming free_cb was registered).
140 *
141 * \param queue Initialized queue object returned by M_queue_create()
142 * \return pointer to first queue object, NULL if none
143 */
144M_API void *M_queue_take_first(M_queue_t *queue);
145
146
147/*! Retrieve the number of items in the specified queue.
148 * \param queue Initialized queue object returned by M_queue_create()
149 * \return count of items in the queue.
150 */
151M_API size_t M_queue_len(const M_queue_t *queue);
152
153
154/*! Retrieve the first queue entry in the specified queue.
155 * \param queue Initialized queue object returned by M_queue_create()
156 * \return First queue entry, NULL if no entries
157 */
158M_API void *M_queue_first(M_queue_t *queue);
159
160
161/*! Retrieve the last queue entry in the specified queue.
162 * \param queue Initialized queue object returned by M_queue_create()
163 * \return Last queue entry, NULL if no entries
164 */
165M_API void *M_queue_last(M_queue_t *queue);
166
167
168/*! Enumerate across all members in the queue. This function is designed to be run
169 * in a while() loop until it returns M_FALSE. The q_foreach parameter will be
170 * automatically deallocated if this returns M_FALSE, otherwise if breaking out of
171 * the loop early, M_queue_foreach_free must be called.
172 *
173 * During an enumeration, it is allowable to remove the *current* member from the
174 * queue. It is undefined behavior to remove any other member during an enumeration.
175 * Addition to the queue is also allowed during an enumeration, however it is not
176 * defined if the new value will end up in the enumerated set.
177 * \param queue Initialized queue object returned by M_queue_create()
178 * \param q_foreach M_queue_foreach_t * passed By Reference, and initialized to NULL
179 * before the first call to M_queue_foreach(). The value returned
180 * is not meant to be interpreted and must be passed back in, unmodified
181 * to the next call of M_queue_foreach(). If breaking out of the loop
182 * prior to M_queue_foreach() returning M_FALSE, this object should be
183 * free'd with M_queue_foreach_free().
184 * \param member Pointer to member to be filled in, passed By Reference. This value
185 * will be populated with the current member in the enumeration. Must
186 * not be NULL.
187 * \return M_TRUE if there are more members to enumerate, M_FALSE if no more members and no
188 * result was returned.
189 */
190M_API M_bool M_queue_foreach(const M_queue_t *queue, M_queue_foreach_t **q_foreach, void **member);
191
192
193/*! Free's the M_queue_foreach_t * filled in by M_queue_foreach. This only needs to be
194 * called if the enumeration was ended early and not allowed to run to completion.
195 * NOTE: This may currently be a no-op if q_foreach just references an internal pointer.
196 * \param q_foreach M_queue_foreach_t * initialized by M_queue_foreach.
197 */
199
200__END_DECLS
201
202/*! @} */
203
204#endif /* __M_QUEUE_H__ */
M_bool M_queue_insert(M_queue_t *queue, void *member)
void * M_queue_take_first(M_queue_t *queue)
M_bool M_queue_remove(M_queue_t *queue, const void *member)
void M_queue_destroy(M_queue_t *queue)
M_bool M_queue_foreach(const M_queue_t *queue, M_queue_foreach_t **q_foreach, void **member)
M_bool M_queue_exists(const M_queue_t *queue, const void *member)
void * M_queue_last(M_queue_t *queue)
M_queue_t * M_queue_create(M_sort_compar_t sort_cb, void(*free_cb)(void *))
void M_queue_foreach_free(M_queue_foreach_t *q_foreach)
M_bool M_queue_take(M_queue_t *queue, const void *member)
size_t M_queue_len(const M_queue_t *queue)
void * M_queue_first(M_queue_t *queue)
struct M_queue M_queue_t
Definition: m_queue.h:74
struct M_queue_foreach M_queue_foreach_t
Definition: m_queue.h:78
int(* M_sort_compar_t)(const void *arg1, const void *arg2, void *thunk)
Definition: m_sort.h:78