]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Added lib_atexit_priority()
authorTimo Sirainen <tss@iki.fi>
Thu, 30 Oct 2014 20:00:14 +0000 (22:00 +0200)
committerTimo Sirainen <tss@iki.fi>
Thu, 30 Oct 2014 20:00:14 +0000 (22:00 +0200)
src/lib/lib.c
src/lib/lib.h

index 24a980e29b60613bd494269942a7badaa86d3c81..3d2051c131d68532903f4d9d231c96ec40707bbb 100644 (file)
 #include <unistd.h>
 #include <sys/time.h>
 
-static ARRAY(lib_atexit_callback_t *) atexit_callbacks = ARRAY_INIT;
+struct atexit_callback {
+       int priority;
+       lib_atexit_callback_t *callback;
+};
+
+static ARRAY(struct atexit_callback) atexit_callbacks = ARRAY_INIT;
 
 int close_keep_errno(int *fd)
 {
@@ -27,7 +32,13 @@ int close_keep_errno(int *fd)
 
 void lib_atexit(lib_atexit_callback_t *callback)
 {
-       lib_atexit_callback_t *const *callbacks;
+       lib_atexit_priority(callback, 0);
+}
+
+void lib_atexit_priority(lib_atexit_callback_t *callback, int priority)
+{
+       struct atexit_callback *cb;
+       const struct atexit_callback *callbacks;
        unsigned int i, count;
 
        if (!array_is_created(&atexit_callbacks))
@@ -36,20 +47,31 @@ void lib_atexit(lib_atexit_callback_t *callback)
                /* skip if it's already added */
                callbacks = array_get(&atexit_callbacks, &count);
                for (i = count; i > 0; i--) {
-                       if (callbacks[i-1] == callback)
+                       if (callbacks[i-1].callback == callback) {
+                               i_assert(callbacks[i-1].priority == priority);
                                return;
+                       }
                }
        }
-       array_append(&atexit_callbacks, &callback, 1);
+       cb = array_append_space(&atexit_callbacks);
+       cb->priority = priority;
+       cb->callback = callback;
+}
+
+static int atexit_callback_priority_cmp(const struct atexit_callback *cb1,
+                                       const struct atexit_callback *cb2)
+{
+       return cb1->priority - cb2->priority;
 }
 
 void lib_atexit_run(void)
 {
-       lib_atexit_callback_t *const *cbp;
+       const struct atexit_callback *cb;
 
        if (array_is_created(&atexit_callbacks)) {
-               array_foreach(&atexit_callbacks, cbp)
-                       (**cbp)();
+               array_sort(&atexit_callbacks, atexit_callback_priority_cmp);
+               array_foreach(&atexit_callbacks, cb)
+                       (*cb->callback)();
                array_free(&atexit_callbacks);
        }
 }
index 225971cb336de900284ccea9bced46a1dc1a4140..2102d195f2159f9549e9249b1125fbfcec02f37a 100644 (file)
@@ -44,6 +44,10 @@ typedef void lib_atexit_callback_t(void);
 #include "strfuncs.h"
 #include "strnum.h"
 
+#define LIB_ATEXIT_PRIORITY_HIGH -10
+#define LIB_ATEXIT_PRIORITY_DEFAULT 0
+#define LIB_ATEXIT_PRIORITY_LOW 10
+
 int close_keep_errno(int *fd);
 
 /* Call the given callback at the beginning of lib_deinit(). The main
@@ -51,6 +55,9 @@ int close_keep_errno(int *fd);
    functions are still available. Also if lib_atexit() is called multiple times
    to the same callback, it's added only once. */
 void lib_atexit(lib_atexit_callback_t *callback);
+/* Specify the order in which the callback is called. Lowest numbered
+   priorities are called first. lib_atexit() is called with priority=0. */
+void lib_atexit_priority(lib_atexit_callback_t *callback, int priority);
 /* Manually run the atexit callbacks. lib_deinit() also does this if not
    explicitly called. */
 void lib_atexit_run(void);