summaryrefslogtreecommitdiff
path: root/initfini/impl/simpleops-initfini-impl-common.h
diff options
context:
space:
mode:
Diffstat (limited to 'initfini/impl/simpleops-initfini-impl-common.h')
-rw-r--r--initfini/impl/simpleops-initfini-impl-common.h116
1 files changed, 116 insertions, 0 deletions
diff --git a/initfini/impl/simpleops-initfini-impl-common.h b/initfini/impl/simpleops-initfini-impl-common.h
new file mode 100644
index 0000000..fcc1c76
--- /dev/null
+++ b/initfini/impl/simpleops-initfini-impl-common.h
@@ -0,0 +1,116 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/*
+ * Copyright 2010-2011 Andrea Canciani
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author(s): Andrea Canciani <ranma42@gmail.com>
+ */
+
+#ifndef SIMPLEOPS_INITFINI_IMPL_COMMON_H
+#define SIMPLEOPS_INITFINI_IMPL_COMMON_H
+
+#ifndef SIMPLEOPS_INITFINI_IMPL_H
+#error Private header used directly
+#endif
+
+#include "simpleops/atomic/internal/simpleops-atomic-internal.h"
+#include "simpleops/tls/internal/simpleops-tls-internal.h"
+
+static void
+_simpleops_init_internals (void)
+{
+ _simpleops_atomic_init ();
+ _simpleops_tls_init ();
+}
+
+static void
+_simpleops_fini_internals (void)
+{
+ simpleops_tls_reset ();
+
+ _simpleops_tls_fini ();
+ _simpleops_atomic_fini ();
+}
+
+
+static void _simpleops_init_externals (void);
+static void _simpleops_fini_externals (void);
+
+/**
+ * This macro is used to specify what function should be called upon
+ * initialization.
+ */
+#define SIMPLEOPS_INIT(f) static void _simpleops_init_externals (void) { f (); }
+
+/**
+ * This macro is used to specify what function should be called upon
+ * termination.
+ */
+#define SIMPLEOPS_FINI(f) static void _simpleops_fini_externals (void) { f (); }
+
+static int _simpleops_initfini_counter;
+
+/* Invoke internal/external init/fini in the right order. Init only if
+ * initialization has not yet been performed, fini only if every user
+ * has already detached. */
+
+/**
+ * Perform the initialization.
+ *
+ * After this function returns, the initialization is guaranteed to be
+ * complete. This is only needed in order to enforce a specific
+ * initialization sequence in dependent libraries.
+ *
+ * This function is not thread-safe. Multiple concurrent calls may
+ * lead to undefined behavior.
+ */
+static void
+simpleops_init (void)
+{
+ if (_simpleops_initfini_counter++)
+ return;
+
+ _simpleops_init_internals ();
+ _simpleops_init_externals ();
+}
+
+/**
+ * Perform the termination.
+ *
+ * After this function returns, the termination is guaranteed to be
+ * complete. This is only needed in order to enforce a specific
+ * termination sequence in dependent libraries.
+ *
+ * This function is not thread-safe. Multiple concurrent calls may
+ * lead to undefined behavior.
+ */
+static void
+simpleops_fini (void)
+{
+ if (--_simpleops_initfini_counter)
+ return;
+
+ _simpleops_fini_externals ();
+ _simpleops_fini_internals ();
+}
+
+#endif