#ifdef WIN32
#define pdlmsuffix ".dll"
#define pdlmtype HMODULE
-#define pdlopenl(filename) LoadLibraryEx(filename, NULL, DONT_RESOLVE_DLL_REFERENCES)
+#define pdlopenl(filename) LoadLibraryEx(filename, NULL, \
+ DONT_RESOLVE_DLL_REFERENCES)
#define pdlclose(module) FreeLibrary((pdlmtype) module)
#define pdlsym(mod, sym) ((void *) GetProcAddress(mod, sym))
return LoadLibrary(filename);
}
-static char *pdlerror() {
+static char *
+pdlerror(void) {
char *amsg;
LPTSTR msg;
size = vsnprintf(NULL, 0, fmt, apc);
va_end(apc);
- *strp = malloc(size + 1);
- if (!size)
+ if (size <= 0 || !(*strp = malloc(size + 1)))
return -1;
return vsnprintf(*strp, size + 1, fmt, ap);
int reqsym, verto_ev_type reqtypes, pdlmtype *dll,
const verto_module **module)
{
+ DIR *dir;
+ struct dirent *ent = NULL;
+
*module = NULL;
- DIR *dir = opendir(dirname);
+ dir = opendir(dirname);
if (!dir)
return 0;
- struct dirent *ent = NULL;
+
while ((ent = readdir(dir))) {
- size_t flen = strlen(ent->d_name);
- size_t slen = strlen(suffix);
+ char *tmp = NULL;
+ int success;
+ size_t flen, slen;
+
+ flen = strlen(ent->d_name);
+ slen = strlen(suffix);
if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name))
continue;
if (flen < slen || strcmp(ent->d_name + flen - slen, suffix))
continue;
- char *tmp = NULL;
if (_asprintf(&tmp, "%s/%s", dirname, ent->d_name) < 0)
continue;
- int success = do_load_file(tmp, reqsym, reqtypes, dll, module);
+ success = do_load_file(tmp, reqsym, reqtypes, dll, module);
free(tmp);
if (success)
break;
static void
push_ev(verto_ctx *ctx, verto_ev *ev)
{
+ verto_ev *tmp;
+
if (!ctx || !ev)
return;
- verto_ev *tmp = ctx->events;
+ tmp = ctx->events;
ctx->events = ev;
ctx->events->next = tmp;
}
ctx->funcs.ctx_break(ctx->modpriv);
}
-#define doadd(set, type) \
- verto_ev *ev = make_ev(ctx, callback, type, flags); \
+void
+verto_reinitialize(verto_ctx *ctx)
+{
+ verto_ev *tmp, *next;
+ if (!ctx)
+ return;
+
+ /* Delete all events, but keep around the forkable ev structs */
+ for (tmp = ctx->events; tmp; tmp = next) {
+ next = ctx->events->next;
+
+ if (tmp->flags & VERTO_EV_FLAG_REINITIABLE)
+ ctx->funcs.ctx_del(ctx->modpriv, tmp, tmp->modpriv);
+ else
+ verto_del(tmp);
+ }
+
+ /* Reinit the loop */
+ ctx->funcs.ctx_reinitialize(ctx->modpriv);
+
+ /* Recreate events that were marked forkable */
+ for (tmp = ctx->events; tmp; tmp = tmp->next) {
+ tmp->actual = tmp->flags;
+ tmp->modpriv = ctx->funcs.ctx_add(ctx, tmp, &tmp->actual);
+ assert(tmp->modpriv);
+ }
+}
+
+#define doadd(ev, set, type) \
+ ev = make_ev(ctx, callback, type, flags); \
if (ev) { \
set; \
ev->actual = ev->flags; \
verto_add_io(verto_ctx *ctx, verto_ev_flag flags,
verto_callback *callback, int fd)
{
+ verto_ev *ev;
+
if (fd < 0 || !(flags & (VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE)))
return NULL;
- doadd(ev->option.fd = fd, VERTO_EV_TYPE_IO);
+
+ doadd(ev, ev->option.fd = fd, VERTO_EV_TYPE_IO);
}
verto_ev *
verto_add_timeout(verto_ctx *ctx, verto_ev_flag flags,
verto_callback *callback, time_t interval)
{
- doadd(ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT);
+ verto_ev *ev;
+ doadd(ev, ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT);
}
verto_ev *
verto_add_idle(verto_ctx *ctx, verto_ev_flag flags,
verto_callback *callback)
{
- doadd(, VERTO_EV_TYPE_IDLE);
+ verto_ev *ev;
+ doadd(ev,, VERTO_EV_TYPE_IDLE);
}
verto_ev *
verto_add_signal(verto_ctx *ctx, verto_ev_flag flags,
verto_callback *callback, int signal)
{
+ verto_ev *ev;
+
if (signal < 0)
return NULL;
#ifndef WIN32
if (!(flags & VERTO_EV_FLAG_PERSIST))
return NULL;
}
- doadd(ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL);
+ doadd(ev, ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL);
}
verto_ev *
verto_add_child(verto_ctx *ctx, verto_ev_flag flags,
verto_callback *callback, verto_proc proc)
{
+ verto_ev *ev;
+
if (flags & VERTO_EV_FLAG_PERSIST) /* persist makes no sense */
return NULL;
#ifdef WIN32
if (proc < 1)
#endif
return NULL;
- doadd(ev->option.child.proc = proc, VERTO_EV_TYPE_CHILD);
+ doadd(ev, ev->option.child.proc = proc, VERTO_EV_TYPE_CHILD);
}
-int
+void
verto_set_private(verto_ev *ev, void *priv, verto_callback *free)
{
if (!ev)
- return 0;
+ return;
if (ev->onfree && free)
ev->onfree(ev->ctx, ev);
ev->priv = priv;
ev->onfree = free;
- return 1;
}
void *
VERTO_EV_FLAG_PRIORITY_HIGH = 1 << 3,
VERTO_EV_FLAG_IO_READ = 1 << 4,
VERTO_EV_FLAG_IO_WRITE = 1 << 5,
- _VERTO_EV_FLAG_MAX = VERTO_EV_FLAG_IO_WRITE
+ VERTO_EV_FLAG_REINITIABLE = 1 << 6,
+ _VERTO_EV_FLAG_MAX = VERTO_EV_FLAG_REINITIABLE
} verto_ev_flag;
typedef void (verto_callback)(verto_ctx *ctx, verto_ev *ev);
void
verto_break(verto_ctx *ctx);
+/**
+ * Re-initializes the verto_ctx.
+ *
+ * This function deletes all events, except those which have set the
+ * VERTO_EV_FLAG_REINITIABLE flag. If you fork(), you MUST call this in the
+ * child process after the fork!
+ *
+ * @see verto_new()
+ * @see verto_default()
+ * @param ctx The verto_ctx to re-initialize.
+ */
+void
+verto_reinitialize(verto_ctx *ctx);
+
/**
* Adds a callback executed when a file descriptor is ready to be read/written.
*
* @param ev The verto_ev
* @param priv The private value to store
* @param free The callback used to free the data or NULL
- * @return 1 on success or 0 on failure
*/
-int
+void
verto_set_private(verto_ev *ev, void *priv, verto_callback *free);
/**