]> mj.ucw.cz Git - libucw.git/commitdiff
Conf: Made the default context static
authorMartin Mares <mj@ucw.cz>
Sat, 28 Apr 2012 21:29:56 +0000 (23:29 +0200)
committerMartin Mares <mj@ucw.cz>
Sun, 29 Apr 2012 11:57:30 +0000 (13:57 +0200)
This involves some bits of magic with constructor priorities
and a hack, which forces linking of conf-context.c.

ucw/conf-context.c
ucw/conf-input.c
ucw/conf-internal.h
ucw/conf.h
ucw/lib.h
ucw/threads-conf.c
ucw/threads.c

index 1584143cb98a24b959dda540935105d2ea084620..8a7b4a6b113a772e552fcf2225b9f6bbec5147a1 100644 (file)
 #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;
 }
 
@@ -33,6 +33,7 @@ void
 cf_free_context(struct cf_context *cc)
 {
   ASSERT(!cc->is_active);
+  ASSERT(cc != &cf_default_context);
   xfree(cc->parser);
   xfree(cc);
 }
@@ -53,15 +54,16 @@ cf_switch_context(struct cf_context *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();
 }
index 92acb35d9baf831d377788549343730ba0fc3861..f8ed1ff092def0014d415db32c67435ab8cb1386 100644 (file)
@@ -475,7 +475,7 @@ final_commit(struct cf_context *cc)
 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) {
index 7f10a85fa911ce3e459ebae2f6332064e21242ba..a47ab46678303ac2f5b03121be93d9f789eb2e96 100644 (file)
@@ -63,9 +63,16 @@ struct cf_context {
 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
index a15d0da28c2eca376bb904e4eb552273efd8371b..82bc852f7ca9093f8d8f96664e394d3b1bfa5771 100644 (file)
@@ -21,10 +21,10 @@ struct mempool;
  * ~~~~~~~~~~~~~~~~~~~~~~
  *
  * 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.
  ***/
@@ -34,7 +34,7 @@ struct cf_context *cf_new_context(void);
 
 /**
  * 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
@@ -49,12 +49,6 @@ void cf_free_context(struct cf_context *cc);
  **/
 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. **/
@@ -423,4 +417,3 @@ char *cf_parse_double(const char *str, double *ptr);        /** Parser for doubles. **/
 char *cf_parse_ip(const char *p, u32 *varp);           /** Parser for IP addresses. **/
 
 #endif
-
index f894d2c4271c3de3ff69082d9c4fcc9a6c6b3576..e7518defa3d64a30cbcdfe9b39e9a3cbfc1fa21a 100644 (file)
--- a/ucw/lib.h
+++ b/ucw/lib.h
@@ -59,6 +59,7 @@
 #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 **/
index b96f867f5869853e2cdd4cc2cb60b01990e2ee18..68abbdae95de9ad5ca035abf90b1141d2cebb1f8 100644 (file)
@@ -20,7 +20,7 @@ static struct cf_section threads_config = {
   }
 };
 
-static void CONSTRUCTOR
+static void CONSTRUCTOR_WITH_PRIORITY(19999)
 ucwlib_threads_conf_init(void)
 {
   cf_declare_section("Threads", &threads_config, 0);
index bd2423108f6536319be0ff7c441a4a9c0b4a3231..1377733bc2660ce5d8cb0cdac289a2e6d0a35bb1 100644 (file)
@@ -67,7 +67,7 @@ ucwlib_tid(void)
 
 /*** Thread context ***/
 
-static void CONSTRUCTOR
+static void CONSTRUCTOR_WITH_PRIORITY(10000)
 ucwlib_threads_init_master(void)
 {
   pthread_mutex_init(&ucwlib_master_mutex, NULL);
@@ -95,7 +95,7 @@ ucwlib_free_thread_context(void *p)
   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)