#include <ucw/conf-internal.h>
#include <ucw/threads.h>
-#ifndef CONFIG_UCW_DEFAULT_CONFIG
-#define CONFIG_UCW_DEFAULT_CONFIG NULL
-#endif
+static struct cf_context cf_default_context;
-#ifndef CONFIG_UCW_ENV_VAR_CONFIG
-#define CONFIG_UCW_ENV_VAR_CONFIG NULL
-#endif
+static void
+cf_init_context(struct cf_context *cc)
+{
+ cc->need_journal = 1;
+ clist_init(&cc->conf_entries);
+}
struct cf_context *
cf_new_context(void)
{
struct cf_context *cc = xmalloc_zero(sizeof(*cc));
- cc->need_journal = 1;
- clist_init(&cc->conf_entries);
+ cf_init_context(cc);
return cc;
}
cf_free_context(struct cf_context *cc)
{
ASSERT(!cc->is_active);
+ ASSERT(cc != &cf_default_context);
xfree(cc->parser);
xfree(cc);
}
return prev;
}
+static void CONSTRUCTOR_WITH_PRIORITY(10100)
+cf_init_default_context(void)
+{
+ cf_init_context(&cf_default_context);
+ ucwlib_thread_context()->cf_context = &cf_default_context;
+ cf_default_context.is_active = 1;
+}
+
struct cf_context *
cf_obtain_context(void)
{
- struct ucwlib_context *uc = ucwlib_thread_context();
- if (unlikely(!uc->cf_context))
- {
- struct cf_context *cc = cf_new_context();
- uc->cf_context = cc;
- cc->is_active = 1;
- }
- return uc->cf_context;
+ return cf_get_context();
}
int
cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
{
- struct cf_context *cc = cf_obtain_context();
+ struct cf_context *cc = cf_get_context();
cc->postpone_commit = 1;
while (1) {
static inline struct cf_context *
cf_get_context(void)
{
- return ucwlib_thread_context()->cf_context;
+ struct cf_context *cc = ucwlib_thread_context()->cf_context;
+ ASSERT(cc->is_active);
+ return cc;
}
+// In fact, this is equivalent to cf_get_context(), but it is not inlined,
+// because we want to force the linker to include conf-context.c, which contains
+// a constructor of the whole context mechanism.
+struct cf_context *cf_obtain_context(void);
+
/* conf-intr.c */
#define OP_MASK 0xff // only get the operation
#define OP_OPEN 0x100 // here we only get an opening brace instead of parameters
* ~~~~~~~~~~~~~~~~~~~~~~
*
* The state of the configuration parser is stored within a configuration context.
- * If you do not create contexts explicitly, the library will create one for you
- * and you need not care, as long as you use a single configuration file.
+ * One such context is automatically created during initialization of the library
+ * and you need not care about more, as long as you use a single configuration file.
*
- * In whole generality, you can define as many context as you wish and switch
+ * In full generality, you can define as many context as you wish and switch
* between them. Each thread has its own pointer to the current context, which
* must not be shared with other threads.
***/
/**
* Free a configuration context. The context must not be set as current
- * for any thread.
+ * for any thread, nor can it be the default context.
*
* All configuration settings made within the context are rolled back
* (except when journalling is turned off). All memory allocated on behalf
**/
struct cf_context *cf_switch_context(struct cf_context *cc);
-/**
- * Return a pointer to the current context, or create the default context
- * if there is no context active.
- **/
-struct cf_context *cf_obtain_context(void);
-
/*** === Data types [[conf_types]] ***/
enum cf_class { /** Class of the configuration item. **/
char *cf_parse_ip(const char *p, u32 *varp); /** Parser for IP addresses. **/
#endif
-
#define NONRET __attribute__((noreturn)) /** Function does not return **/
#define UNUSED __attribute__((unused)) /** Variable/parameter is knowingly unused **/
#define CONSTRUCTOR __attribute__((constructor)) /** Call function upon start of program **/
+#define CONSTRUCTOR_WITH_PRIORITY(p) __attribute__((constructor(p))) /** Define constructor with a given priority **/
#define PACKED __attribute__((packed)) /** Structure should be packed **/
#define CONST __attribute__((const)) /** Function depends only on arguments **/
#define PURE __attribute__((pure)) /** Function depends only on arguments and global vars **/
}
};
-static void CONSTRUCTOR
+static void CONSTRUCTOR_WITH_PRIORITY(19999)
ucwlib_threads_conf_init(void)
{
cf_declare_section("Threads", &threads_config, 0);
/*** Thread context ***/
-static void CONSTRUCTOR
+static void CONSTRUCTOR_WITH_PRIORITY(10000)
ucwlib_threads_init_master(void)
{
pthread_mutex_init(&ucwlib_master_mutex, NULL);
xfree(p);
}
-static void CONSTRUCTOR
+static void CONSTRUCTOR_WITH_PRIORITY(10000)
ucwlib_threads_init(void)
{
if (pthread_key_create(&ucwlib_context_key, ucwlib_free_thread_context) < 0)