Add myself to the DOAP for GLib
[glib.git] / gio / kqueue / kqueue-utils.c
blobbba652278fcae5df76793f5e74c7ccd9d7fd2fa8
1 /*******************************************************************************
2 Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk>
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 *******************************************************************************/
23 #include <sys/types.h>
24 #include <sys/event.h>
25 #include <string.h>
26 #include <glib.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <errno.h>
30 #include "kqueue-utils.h"
32 static gboolean ku_debug_enabled = FALSE;
33 #define KU_W if (ku_debug_enabled) g_warning
37 #define KEVENTS_EXTEND_COUNT 10
40 /**
41 * kevents_init_sz:
42 * @kv: a #kevents
43 * @n_initial: the initial preallocated memory size. If it is less than
44 * %KEVENTS_EXTEND_COUNT, this value will be used instead.
46 * Initializes a #kevents object.
47 **/
48 void
49 kevents_init_sz (kevents *kv, gsize n_initial)
51 g_assert (kv != NULL);
53 memset (kv, 0, sizeof (kevents));
55 if (n_initial < KEVENTS_EXTEND_COUNT)
56 n_initial = KEVENTS_EXTEND_COUNT;
58 kv->memory = g_new0 (struct kevent, n_initial);
59 kv->kq_allocated = n_initial;
63 /**
64 * kevents_extend_sz:
65 * @kv: a #kevents
66 * @n_new: the number of new objects to be added
68 * Extends the allocated memory, if needed.
69 **/
70 void
71 kevents_extend_sz (kevents *kv, gsize n_new)
73 g_assert (kv != NULL);
75 if (kv->kq_size + n_new <= kv->kq_allocated)
76 return;
78 kv->kq_allocated += (n_new + KEVENTS_EXTEND_COUNT);
79 kv->memory = g_renew (struct kevent, kv->memory, kv->kq_allocated);
83 /**
84 * kevents_reduce:
85 * @kv: a #kevents
87 * Reduces the allocated heap size, if needed.
89 * If the allocated heap size is >= 3*used
90 * and 2*used >= %KEVENTS_EXTEND_COUNT, reduce it to 2*used.
91 **/
92 void
93 kevents_reduce (kevents *kv)
95 g_assert (kv != NULL);
96 gsize candidate_sz;
98 if (kv->kq_size == 0 || kv->kq_allocated == 0 || kv->memory == NULL)
99 return;
101 candidate_sz = 2 * kv->kq_size;
103 if (((double) kv->kq_allocated / kv->kq_size) >= 3 &&
104 candidate_sz >= KEVENTS_EXTEND_COUNT)
106 kv->kq_allocated = candidate_sz;
107 kv->memory = g_renew (struct kevent, kv->memory, kv->kq_allocated);
113 * kevents_free:
114 * @kv: a #kevents
116 * Resets the kevents object and frees all the associated memory.
118 void
119 kevents_free (kevents *kv)
121 g_assert (kv != NULL);
123 g_free (kv->memory);
124 memset (kv, 0, sizeof (kevents));
128 #define SAFE_GENERIC_OP(fcn, fd, data, size) \
129 while (size > 0) \
131 gsize retval = fcn (fd, data, size); \
132 if (retval == -1) \
134 if (errno == EINTR) \
135 continue; \
136 else \
137 return FALSE; \
139 size -= retval; \
140 data += retval; \
142 return TRUE;
146 * _ku_read:
147 * @fd: a file descriptor
148 * @data: the destination buffer
149 * @size: how many bytes to read
151 * A ready-to-EINTR version of read().
153 * This function expects to work with a blocking socket.
155 * Returns: %TRUE on success, %FALSE otherwise
157 gboolean
158 _ku_read (int fd, gpointer data, gsize size)
160 SAFE_GENERIC_OP (read, fd, data, size);
165 * _ku_write:
166 * @fd: a file descriptor
167 * @data: the buffer to write
168 * @size: how many bytes to write
170 * A ready-to-EINTR version of write().
172 * This function expects to work with a blocking socket.
174 * Returns: %TRUE on success, %FALSE otherwise
176 gboolean
177 _ku_write (int fd, gconstpointer data, gsize size)
179 SAFE_GENERIC_OP (write, fd, data, size);
184 * Get some file information by its file descriptor.
186 * @param[in] fd A file descriptor.
187 * @param[out] is_dir A flag indicating directory.
188 * @param[out] inode A file's inode number.
190 void
191 _ku_file_information (int fd, int *is_dir, ino_t *inode)
193 g_assert (fd != -1);
195 struct stat st;
196 memset (&st, 0, sizeof (struct stat));
198 if (fstat (fd, &st) == -1)
200 KU_W ("fstat failed, assuming it is just a file");
201 is_dir = NULL;
202 return;
205 if (is_dir != NULL)
206 *is_dir = ((st.st_mode & S_IFDIR) == S_IFDIR) ? 1 : 0;
208 if (inode != NULL)
209 *inode = st.st_ino;