merge from backend (plugin loader)
Merge commit 'lumi/master' into proc
This commit is contained in:
commit
d64d822690
38 changed files with 2609 additions and 123 deletions
|
|
@ -62,7 +62,6 @@ include $(top_srcdir)/icons/Makefile.am
|
|||
include $(top_srcdir)/tests/common/Makefile.am
|
||||
include $(top_srcdir)/tests/components/Makefile.am
|
||||
include $(top_srcdir)/tests/Makefile.am
|
||||
include $(top_srcdir)/tests/plugin/Makefile.am
|
||||
|
||||
#EXTRA_DIST += admin debian doc depcomp README.BUILD LICENSE \
|
||||
# cinelerra-cvs-current.spec
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
AC_INIT(lumiera, 0.1pre)
|
||||
AC_CONFIG_SRCDIR(src/lib/plugin.c)
|
||||
AC_CONFIG_SRCDIR(src/lib/luid.c)
|
||||
AC_CONFIG_AUX_DIR(scripts)
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_PREREQ(2.59)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
liblumibackend_a_srcdir = $(top_srcdir)/src/backend
|
||||
noinst_LIBRARIES += liblumibackend.a
|
||||
|
||||
liblumibackend_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror
|
||||
liblumibackend_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wextra -Wall -Werror
|
||||
|
||||
liblumibackend_a_SOURCES = \
|
||||
$(liblumibackend_a_srcdir)/mediaaccessfacade.cpp \
|
||||
|
|
@ -27,10 +27,13 @@ liblumibackend_a_SOURCES = \
|
|||
$(liblumibackend_a_srcdir)/filehandle.c \
|
||||
$(liblumibackend_a_srcdir)/filedescriptor.c \
|
||||
$(liblumibackend_a_srcdir)/filehandlecache.c \
|
||||
$(liblumibackend_a_srcdir)/interface.c \
|
||||
$(liblumibackend_a_srcdir)/interfaceregistry.c \
|
||||
$(liblumibackend_a_srcdir)/config.c \
|
||||
$(liblumibackend_a_srcdir)/config_typed.c \
|
||||
$(liblumibackend_a_srcdir)/config_wordlist.c \
|
||||
$(liblumibackend_a_srcdir)/configentry.c \
|
||||
$(liblumibackend_a_srcdir)/configitem.c \
|
||||
$(liblumibackend_a_srcdir)/configitem.c \
|
||||
$(liblumibackend_a_srcdir)/config_lookup.c
|
||||
|
||||
|
||||
|
|
@ -41,8 +44,11 @@ noinst_HEADERS += \
|
|||
$(liblumibackend_a_srcdir)/filehandle.h \
|
||||
$(liblumibackend_a_srcdir)/filedescriptor.h \
|
||||
$(liblumibackend_a_srcdir)/filehandlecache.h \
|
||||
$(liblumibackend_a_srcdir)/interface.h \
|
||||
$(liblumibackend_a_srcdir)/interfaceregistry.h \
|
||||
$(liblumibackend_a_srcdir)/interfacedescriptor.h \
|
||||
$(liblumibackend_a_srcdir)/config.h \
|
||||
$(liblumibackend_a_srcdir)/configentry.h \
|
||||
$(liblumibackend_a_srcdir)/configitem.h \
|
||||
$(liblumibackend_a_srcdir)/configitem.h \
|
||||
$(liblumibackend_a_srcdir)/config_lookup.h
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ lumiera_config_init (const char* path)
|
|||
lumiera_configitem_init (&lumiera_global_config->files);
|
||||
lumiera_configitem_init (&lumiera_global_config->TODO_unknown);
|
||||
|
||||
lumiera_rwlock_init (&lumiera_global_config->lock, "config rwlock", &NOBUG_FLAG (config));
|
||||
lumiera_mutex_init (&lumiera_global_config->lock, "config mutex", &NOBUG_FLAG (config));
|
||||
|
||||
lumiera_config_setdefault (lumiera_tmpbuf_snprintf (SIZE_MAX, "config.path = %s", path));
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ lumiera_config_destroy ()
|
|||
TRACE (config);
|
||||
if (lumiera_global_config)
|
||||
{
|
||||
lumiera_rwlock_destroy (&lumiera_global_config->lock, &NOBUG_FLAG (config));
|
||||
lumiera_mutex_destroy (&lumiera_global_config->lock, &NOBUG_FLAG (config));
|
||||
lumiera_configitem_destroy (&lumiera_global_config->defaults, &lumiera_global_config->keys);
|
||||
lumiera_configitem_destroy (&lumiera_global_config->files, &lumiera_global_config->keys);
|
||||
lumiera_configitem_destroy (&lumiera_global_config->TODO_unknown, &lumiera_global_config->keys);
|
||||
|
|
@ -146,6 +146,7 @@ lumiera_config_destroy ()
|
|||
int
|
||||
lumiera_config_load (const char* file)
|
||||
{
|
||||
(void) file;
|
||||
TRACE (config);
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
|
|
@ -164,6 +165,7 @@ lumiera_config_save ()
|
|||
int
|
||||
lumiera_config_purge (const char* filename)
|
||||
{
|
||||
(void) filename;
|
||||
TRACE (config);
|
||||
|
||||
UNIMPLEMENTED();
|
||||
|
|
@ -290,7 +292,7 @@ lumiera_config_setdefault (const char* line)
|
|||
|
||||
LumieraConfigitem item = NULL;
|
||||
|
||||
LUMIERA_WRLOCK_SECTION (config, &lumiera_global_config->lock)
|
||||
LUMIERA_MUTEX_SECTION (config, &lumiera_global_config->lock)
|
||||
{
|
||||
const char* key = line;
|
||||
while (*key && isspace (*key))
|
||||
|
|
@ -342,6 +344,7 @@ lumiera_config_dump (FILE* out)
|
|||
int
|
||||
lumiera_config_reset (const char* key)
|
||||
{
|
||||
(void) key;
|
||||
TRACE (config);
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
|
|
@ -351,6 +354,9 @@ lumiera_config_reset (const char* key)
|
|||
int
|
||||
lumiera_config_info (const char* key, const char** filename, unsigned* line)
|
||||
{
|
||||
(void) key;
|
||||
(void) filename;
|
||||
(void) line;
|
||||
TRACE (config);
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
//TODO: Support library includes//
|
||||
#include "lib/error.h"
|
||||
#include "lib/rwlock.h"
|
||||
#include "lib/mutex.h"
|
||||
|
||||
//TODO: Forward declarations//
|
||||
struct lumiera_config_struct;
|
||||
|
|
@ -74,14 +74,7 @@ struct lumiera_config_struct
|
|||
lumiera_configitem files; /* all loaded files */
|
||||
lumiera_configitem TODO_unknown; /* all values which are not part of a file and not default TODO: this will be removed when file support is finished */
|
||||
|
||||
/*
|
||||
all access is protected with rwlock's.
|
||||
We use rwlocks here since concurrent reads are likely common.
|
||||
|
||||
So far this is a global config lock, if this is a problem we might granularize it by locking on a file level.
|
||||
config access is not planned to be transactional yet, if this is a problem we need to expose the rwlock to a config_acquire/config_release function pair
|
||||
*/
|
||||
lumiera_rwlock lock;
|
||||
lumiera_mutex lock;
|
||||
};
|
||||
|
||||
typedef struct lumiera_config_struct lumiera_config;
|
||||
|
|
@ -96,6 +89,7 @@ typedef lumiera_config* LumieraConfig;
|
|||
LUMIERA_CONFIG_TYPE(number, signed long long) \
|
||||
LUMIERA_CONFIG_TYPE(real, long double) \
|
||||
LUMIERA_CONFIG_TYPE(string, const char*) \
|
||||
LUMIERA_CONFIG_TYPE(wordlist, const char*) \
|
||||
LUMIERA_CONFIG_TYPE(word, const char*) \
|
||||
LUMIERA_CONFIG_TYPE(bool, int)
|
||||
|
||||
|
|
@ -197,7 +191,7 @@ lumiera_config_set (const char* key, const char* delim_value);
|
|||
* Installs a default value for a config key.
|
||||
* Any key might have an associated default value which is used when
|
||||
* no other configuration is available, this can be set once.
|
||||
* Any subsequent call will be a no-op. This function writelocks the config system.
|
||||
* Any subsequent call will be a no-op. This function locks the config system.
|
||||
* @param line line with key, delimiter and value to store as default value
|
||||
* @return NULL in case of an error, else a pointer to the default configitem
|
||||
*/
|
||||
|
|
@ -223,7 +217,57 @@ lumiera_config_setdefault (const char* line);
|
|||
LUMIERA_CONFIG_TYPES
|
||||
#undef LUMIERA_CONFIG_TYPE
|
||||
|
||||
/**
|
||||
* Wordlists
|
||||
* Wordlists are lists of single words delimited by any of " \t,;".
|
||||
* They can be used to store groups of keys and other kinds of simple references into the config
|
||||
* system. Here are some functions to manipulate single word entries in a wordlist.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get nth word of a wordlist.
|
||||
* @param key key under which this wordlist is stored
|
||||
* @param nth index of the word to get, starting with 0
|
||||
* @return pointer to a tempbuf holding the nth word or NULL in case of error
|
||||
*/
|
||||
const char*
|
||||
lumiera_config_wordlist_get_nth (const char* key, unsigned nth);
|
||||
|
||||
|
||||
/**
|
||||
* Find the index of a word in a wordlist.
|
||||
* @param key key under which this wordlist is stored
|
||||
* @param value word to find
|
||||
* @return index of the first occurence of the word or -1 in case of failure
|
||||
*/
|
||||
int
|
||||
lumiera_config_wordlist_find (const char* key, const char* value);
|
||||
|
||||
|
||||
/**
|
||||
* Universal word replacement function.
|
||||
* Replaces a word with up to two new words. This can be used to delete a word (no replacements),
|
||||
* insert a new word before an existing word (giving the new word as subst1 and the old word as subst2)
|
||||
* insert a new word after an existing word (giving the old word as subst1 and the new word as subst2)
|
||||
* or simply give 2 new words.
|
||||
* @param key key under which this wordlist is stored
|
||||
* @param value word to be replaced
|
||||
* @param subst1 first replacement word
|
||||
* @param subst2 second replacement word
|
||||
* @return internal representation of the wordlist in a tmpbuf or NULL in case of an error
|
||||
*/
|
||||
const char*
|
||||
lumiera_config_wordlist_replace (const char* key, const char* value, const char* subst1, const char* subst2);
|
||||
|
||||
|
||||
/**
|
||||
* Add a word to the end of a wordlist if it doesnt exist already
|
||||
* @param key key under which this wordlist is stored
|
||||
* @param value new word to add
|
||||
* @return internal representation of the wordlist in a tmpbuf or NULL in case of an error
|
||||
*/
|
||||
const char*
|
||||
lumiera_config_wordlist_add (const char* key, const char* value);
|
||||
|
||||
// * {{{ lumiera_config_TYPE_set (const char* key, TYPE*value, const char* fmt) }}}
|
||||
// Highlevel interface for different types, fmt is a printf format specifier for the desired format, when NULL, defaults apply.
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ extern LumieraConfig lumiera_global_config;
|
|||
const char*
|
||||
lumiera_config_link_get (const char* key, const char** value)
|
||||
{
|
||||
(void) key; (void) value;
|
||||
TRACE (config_typed);
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
|
|
@ -49,6 +50,7 @@ lumiera_config_link_get (const char* key, const char** value)
|
|||
LumieraConfigitem
|
||||
lumiera_config_link_set (const char* key, const char** value)
|
||||
{
|
||||
(void) key; (void) value;
|
||||
TRACE (config_typed);
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
|
|
@ -66,7 +68,7 @@ lumiera_config_number_get (const char* key, long long* value)
|
|||
|
||||
const char* raw_value = NULL;
|
||||
|
||||
LUMIERA_RDLOCK_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
if (lumiera_config_get (key, &raw_value))
|
||||
{
|
||||
|
|
@ -94,7 +96,7 @@ lumiera_config_number_set (const char* key, long long* value)
|
|||
|
||||
LumieraConfigitem item = NULL;
|
||||
|
||||
LUMIERA_WRLOCK_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
const char* fmt = "= %lld"; TODO ("use the config system (config.format*...) to deduce the desired format for this key");
|
||||
item = lumiera_config_set (key, lumiera_tmpbuf_snprintf (SIZE_MAX, fmt, *value));
|
||||
|
|
@ -111,6 +113,7 @@ lumiera_config_number_set (const char* key, long long* value)
|
|||
const char*
|
||||
lumiera_config_real_get (const char* key, long double* value)
|
||||
{
|
||||
(void) key; (void) value;
|
||||
TRACE (config_typed);
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
|
|
@ -119,6 +122,7 @@ lumiera_config_real_get (const char* key, long double* value)
|
|||
LumieraConfigitem
|
||||
lumiera_config_real_set (const char* key, long double* value)
|
||||
{
|
||||
(void) key; (void) value;
|
||||
TRACE (config_typed);
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
|
|
@ -195,7 +199,7 @@ lumiera_config_string_get (const char* key, const char** value)
|
|||
|
||||
const char* raw_value = *value = NULL;
|
||||
|
||||
LUMIERA_RDLOCK_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
if (lumiera_config_get (key, &raw_value))
|
||||
{
|
||||
|
|
@ -218,7 +222,7 @@ lumiera_config_string_set (const char* key, const char** value)
|
|||
|
||||
LumieraConfigitem item = NULL;
|
||||
|
||||
LUMIERA_WRLOCK_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
const char* fmt = "= %s"; TODO ("use the config system (config.format*...) to deduce the desired format for this key");
|
||||
item = lumiera_config_set (key, lumiera_tmpbuf_snprintf (SIZE_MAX, fmt, *value));
|
||||
|
|
@ -228,6 +232,53 @@ lumiera_config_string_set (const char* key, const char** value)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wordlist
|
||||
* words delimited by any of " \t,;"
|
||||
*/
|
||||
|
||||
const char*
|
||||
lumiera_config_wordlist_get (const char* key, const char** value)
|
||||
{
|
||||
TRACE (config_typed, "KEY %s", key);
|
||||
|
||||
const char* raw_value = *value = NULL;
|
||||
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
if (lumiera_config_get (key, &raw_value))
|
||||
{
|
||||
if (raw_value)
|
||||
{
|
||||
*value = raw_value;
|
||||
}
|
||||
else
|
||||
LUMIERA_ERROR_SET (config, CONFIG_NO_ENTRY);
|
||||
|
||||
TODO ("remove the ERROR_SET because config_get sets it already? also in all other getters in this file");
|
||||
}
|
||||
}
|
||||
|
||||
return *value;
|
||||
}
|
||||
|
||||
|
||||
LumieraConfigitem
|
||||
lumiera_config_wordlist_set (const char* key, const char** value)
|
||||
{
|
||||
TRACE (config_typed);
|
||||
|
||||
LumieraConfigitem item = NULL;
|
||||
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
const char* fmt = "= %s"; TODO ("use the config system (config.format*...) to deduce the desired format for this key");
|
||||
item = lumiera_config_set (key, lumiera_tmpbuf_snprintf (SIZE_MAX, fmt, *value));
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Word
|
||||
|
|
@ -262,7 +313,7 @@ lumiera_config_word_get (const char* key, const char** value)
|
|||
|
||||
const char* raw_value = *value = NULL;
|
||||
|
||||
LUMIERA_RDLOCK_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
if (lumiera_config_get (key, &raw_value))
|
||||
{
|
||||
|
|
@ -285,7 +336,7 @@ lumiera_config_word_set (const char* key, const char** value)
|
|||
|
||||
LumieraConfigitem item = NULL;
|
||||
|
||||
LUMIERA_WRLOCK_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
const char* fmt = "= %s"; TODO ("use the config system (config.format*...) to deduce the desired format for this key");
|
||||
item = lumiera_config_set (key, lumiera_tmpbuf_snprintf (SIZE_MAX, fmt, scan_word (*value)));
|
||||
|
|
@ -302,6 +353,7 @@ lumiera_config_word_set (const char* key, const char** value)
|
|||
const char*
|
||||
lumiera_config_bool_get (const char* key, int* value)
|
||||
{
|
||||
(void) key; (void) value;
|
||||
TRACE (config_typed);
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
|
|
@ -311,6 +363,7 @@ lumiera_config_bool_get (const char* key, int* value)
|
|||
LumieraConfigitem
|
||||
lumiera_config_bool_set (const char* key, int* value)
|
||||
{
|
||||
(void) key; (void) value;
|
||||
TRACE (config_typed);
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
|
|
|
|||
217
src/backend/config_wordlist.c
Normal file
217
src/backend/config_wordlist.c
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
config_wordlist.c - Lumiera wordlist access functions
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
//TODO: Support library includes//
|
||||
#include "lib/error.h"
|
||||
#include "lib/safeclib.h"
|
||||
|
||||
|
||||
//TODO: Lumiera header includes//
|
||||
#include "backend/config.h"
|
||||
|
||||
//TODO: internal/static forward declarations//
|
||||
extern LumieraConfig lumiera_global_config;
|
||||
|
||||
|
||||
//TODO: System includes//
|
||||
|
||||
/**
|
||||
* return nth word of a wordlist
|
||||
*/
|
||||
const char*
|
||||
lumiera_config_wordlist_get_nth (const char* key, unsigned nth)
|
||||
{
|
||||
const char* value;
|
||||
size_t len;
|
||||
|
||||
if (!lumiera_config_wordlist_get (key, &value))
|
||||
return NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
value += strspn (value, " \t,;");
|
||||
len = strcspn (value, " \t,;");
|
||||
if (!nth && *value)
|
||||
break;
|
||||
|
||||
--nth;
|
||||
value += len;
|
||||
|
||||
if (!*value)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lumiera_tmpbuf_strndup (value, len);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lumiera_config_wordlist_find (const char* key, const char* value)
|
||||
{
|
||||
const char* itr;
|
||||
size_t vlen = strlen (value);
|
||||
size_t len;
|
||||
|
||||
if (!lumiera_config_wordlist_get (key, &itr))
|
||||
return -1;
|
||||
|
||||
for (int idx = 0; *itr; itr += len, ++idx)
|
||||
{
|
||||
itr += strspn (itr, " \t,;");
|
||||
len = strcspn (itr, " \t,;");
|
||||
|
||||
if (len == vlen && !strncmp (itr, value, vlen))
|
||||
return idx;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
lumiera_config_wordlist_replace (const char* key, const char* value, const char* subst1, const char* subst2)
|
||||
{
|
||||
const char* wordlist;
|
||||
const char* str = NULL;
|
||||
size_t vlen = strlen (value);
|
||||
size_t len;
|
||||
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
if (lumiera_config_get (key, &wordlist))
|
||||
{
|
||||
const char* start = wordlist + strspn (wordlist, " \t,;");
|
||||
|
||||
for (const char* itr = start; *itr; itr += len)
|
||||
{
|
||||
const char* left_end = itr;
|
||||
itr += strspn (itr, " \t,;");
|
||||
len = strcspn (itr, " \t,;");
|
||||
|
||||
if (len == vlen && !strncmp (itr, value, vlen))
|
||||
{
|
||||
TODO ("figure delimiter from original string out");
|
||||
const char* delim = " ";
|
||||
|
||||
/* step over the word */
|
||||
itr += len;
|
||||
itr += strspn (itr, " \t,;");
|
||||
|
||||
/* getting the delimiters right for the corner cases looks ugly, want to refactor it? just do it */
|
||||
str = lumiera_tmpbuf_snprintf (SIZE_MAX,
|
||||
"%.*s%.*s%s%s%s%s%s%s",
|
||||
start - wordlist, wordlist,
|
||||
left_end - start, start,
|
||||
(left_end - start && subst1 && *subst1) ? delim : "",
|
||||
(subst1 && *subst1) ? subst1 : "",
|
||||
((left_end - start || (subst1 && *subst1)) && subst2 && *subst2) ? delim : "",
|
||||
(subst2 && *subst2) ? subst2 : "",
|
||||
((left_end - start || (subst1 && *subst1) || (subst2 && *subst2)) && *itr) ? delim : "",
|
||||
itr
|
||||
);
|
||||
|
||||
if (!lumiera_config_set (key, lumiera_tmpbuf_snprintf (SIZE_MAX, "=%s", str)))
|
||||
str = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
lumiera_config_wordlist_add (const char* key, const char* value)
|
||||
{
|
||||
const char* wordlist = NULL;
|
||||
|
||||
if (value && *value)
|
||||
{
|
||||
LUMIERA_MUTEX_SECTION (config_typed, &lumiera_global_config->lock)
|
||||
{
|
||||
if (lumiera_config_get (key, &wordlist))
|
||||
{
|
||||
size_t vlen = strlen (value);
|
||||
size_t len;
|
||||
|
||||
for (const char* itr = wordlist; *itr; itr += len)
|
||||
{
|
||||
itr += strspn (itr, " \t,;");
|
||||
len = strcspn (itr, " \t,;");
|
||||
|
||||
if (len == vlen && !strncmp (itr, value, vlen))
|
||||
goto end;
|
||||
}
|
||||
|
||||
TODO ("figure delimiter from original string out");
|
||||
const char* delim = " ";
|
||||
|
||||
wordlist = lumiera_tmpbuf_snprintf (SIZE_MAX, "%s%s%s",
|
||||
wordlist,
|
||||
wordlist[strspn (wordlist, " \t,;")]?delim:"",
|
||||
value);
|
||||
|
||||
if (!lumiera_config_set (key, lumiera_tmpbuf_snprintf (SIZE_MAX, "=%s", wordlist)))
|
||||
wordlist = NULL;
|
||||
}
|
||||
end:;
|
||||
}
|
||||
}
|
||||
|
||||
return wordlist;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
const char*
|
||||
lumiera_config_wordlist_remove_nth (const char* key, unsigned nth)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LumieraConfigitem
|
||||
lumiera_config_wordlist_append (const char* key, const char** value, unsigned nth)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LumieraConfigitem
|
||||
lumiera_config_wordlist_preprend (const char* key, const char** value, unsigned nth)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -241,8 +241,8 @@ lumiera_configitem_parse (LumieraConfigitem self, const char* line)
|
|||
itr += self->key_size;
|
||||
|
||||
/*we need a key with a length greather than zero and
|
||||
* either the end of the line
|
||||
* or a whitespace after the key */
|
||||
* either end of line
|
||||
* or whitespace after key */
|
||||
|
||||
if ( self->key_size && ( !*itr || (*itr && isspace(*itr)) ))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ NOBUG_DEFINE_FLAG_PARENT (filedescriptor, file_all);
|
|||
This registry stores all acquired filedescriptors for lookup, they will be freed when not referenced anymore.
|
||||
*/
|
||||
static PSplay registry = NULL;
|
||||
static lumiera_mutex registry_mutex = {PTHREAD_MUTEX_INITIALIZER};
|
||||
static lumiera_mutex registry_mutex = {PTHREAD_MUTEX_INITIALIZER NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER};
|
||||
|
||||
|
||||
static int
|
||||
|
|
@ -96,7 +96,9 @@ lumiera_filedescriptor_registry_init (void)
|
|||
if (!registry)
|
||||
LUMIERA_DIE (NO_MEMORY);
|
||||
|
||||
RESOURCE_HANDLE_INIT (registry_mutex.rh);
|
||||
TODO ("LumieraMutex lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag);");
|
||||
|
||||
// RESOURCE_HANDLE_INIT (registry_mutex.rh);
|
||||
RESOURCE_ANNOUNCE (filedescriptor, "mutex", "filedescriptor registry", ®istry, registry_mutex.rh);
|
||||
}
|
||||
|
||||
|
|
@ -108,6 +110,8 @@ lumiera_filedescriptor_registry_destroy (void)
|
|||
|
||||
RESOURCE_FORGET (filedescriptor, registry_mutex.rh);
|
||||
|
||||
TODO ("LumieraMutex lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag);");
|
||||
|
||||
if (registry)
|
||||
psplay_destroy (registry);
|
||||
registry = NULL;
|
||||
|
|
|
|||
293
src/backend/interface.c
Normal file
293
src/backend/interface.c
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
interface.c - Lumiera interface api
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "lib/mutex.h"
|
||||
#include "lib/safeclib.h"
|
||||
|
||||
#include "backend/interface.h"
|
||||
|
||||
#include "backend/interfaceregistry.h"
|
||||
|
||||
#include <nobug.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
* From a programmers perspective interfaces only need to be opened when needed and closed
|
||||
* when finished with them. There is no difference if the interface is internally provided
|
||||
* by the core or provided by an external plugin.
|
||||
* Interfaces can be opened multiple times and cross reference each other.
|
||||
*/
|
||||
|
||||
|
||||
static LumieraInterfacenode
|
||||
lumiera_interface_open_interfacenode (LumieraInterfacenode self);
|
||||
|
||||
static void
|
||||
lumiera_interfacenode_close (LumieraInterfacenode self);
|
||||
|
||||
|
||||
LumieraInterface
|
||||
lumiera_interface_open (const char* interface, unsigned version, size_t minminorversion, const char* name)
|
||||
{
|
||||
LumieraInterfacenode self = NULL;
|
||||
TRACE (interface, "%s", name);
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
self = lumiera_interfaceregistry_interfacenode_find (interface, version, name);
|
||||
|
||||
if (!self)
|
||||
{
|
||||
UNIMPLEMENTED ("query plugindb and load plugin if exists");
|
||||
}
|
||||
|
||||
if (self)
|
||||
{
|
||||
if (minminorversion > self->interface->size)
|
||||
{
|
||||
UNIMPLEMENTED ("set error");
|
||||
self = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
self = lumiera_interface_open_interfacenode (self);
|
||||
}
|
||||
}
|
||||
}
|
||||
return self->interface;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
push_dependency (LumieraInterfacenode parent, LumieraInterfacenode child)
|
||||
{
|
||||
/* push a dependency on the dependency array, allcoate or resize it on demand */
|
||||
TRACE (interface, "%s %s", parent->interface->name, child->interface->name);
|
||||
|
||||
/* no dependencies recorded yet, alloc a first block for 4 pointers */
|
||||
if (!parent->deps_size)
|
||||
parent->deps = lumiera_calloc (parent->deps_size = 4, sizeof (LumieraInterfacenode));
|
||||
|
||||
size_t sz = parent->deps_size;
|
||||
LumieraInterfacenode* itr = parent->deps;
|
||||
|
||||
while (*itr)
|
||||
{
|
||||
--sz;
|
||||
++itr;
|
||||
if (sz == 1)
|
||||
{
|
||||
/* block to small, realloc it with twice its size, we keep the block NULL terminated */
|
||||
sz = parent->deps_size + 1;
|
||||
parent->deps_size *= 2;
|
||||
parent->deps = lumiera_realloc (parent->deps, parent->deps_size * sizeof (LumieraInterface));
|
||||
itr = parent->deps + sz - 2;
|
||||
memset (itr, 0, sz * sizeof (LumieraInterface));
|
||||
}
|
||||
}
|
||||
|
||||
/* found free element, store self in dependencies */
|
||||
*itr = child;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
depwalk (LumieraInterfacenode self, LumieraInterfacenode* stack)
|
||||
{
|
||||
/* increment refcount for all non-cyclic dependencies recursively */
|
||||
if (self->deps)
|
||||
{
|
||||
TRACE (interface, "%s %d", self->interface->name, self->refcnt);
|
||||
for (LumieraInterfacenode* dep = self->deps; *dep; ++dep)
|
||||
{
|
||||
TRACE (interface, "loop %s", (*dep)->interface->name);
|
||||
int cycle = 0;
|
||||
for (LumieraInterfacenode itr = *stack; itr; itr = itr->lnk)
|
||||
{
|
||||
if (itr == *dep)
|
||||
{
|
||||
TRACE (interface, "CYCLE");
|
||||
cycle = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cycle)
|
||||
{
|
||||
++(*dep)->refcnt;
|
||||
|
||||
(*dep)->lnk = *stack;
|
||||
*stack = *dep;
|
||||
|
||||
depwalk (*dep, stack);
|
||||
|
||||
*stack = (*dep)->lnk;
|
||||
(*dep)->lnk = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static LumieraInterfacenode
|
||||
lumiera_interface_open_interfacenode (LumieraInterfacenode self)
|
||||
{
|
||||
static unsigned collect_dependencies = 0;
|
||||
static LumieraInterfacenode stack = NULL;
|
||||
|
||||
/*
|
||||
Ok, this got little more complicated than it should be,
|
||||
but finally it handles any kind of cross dependencies between interfaces gracefully
|
||||
*/
|
||||
|
||||
if (self)
|
||||
{
|
||||
TRACE (interface, "%s %d (%s)", self->interface->name, self->refcnt, stack?stack->interface->name:"");
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
/* discover cycles, cycles don't refcount! */
|
||||
int cycle = 0;
|
||||
|
||||
for (LumieraInterfacenode itr = stack; itr; itr = itr->lnk)
|
||||
{
|
||||
if (itr == self)
|
||||
{
|
||||
TRACE (interface, "CYCLE");
|
||||
cycle = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 'stack' is ensured to be !NULL here because only a parent call can switch collect_dependencies on */
|
||||
if (collect_dependencies)
|
||||
push_dependency (stack, self);
|
||||
|
||||
if (!cycle)
|
||||
{
|
||||
++self->refcnt;
|
||||
self->lnk = stack;
|
||||
stack = self;
|
||||
int collect_dependencies_bak = collect_dependencies;
|
||||
|
||||
if (self->refcnt == 1)
|
||||
{
|
||||
/* first opening, run acquire, recursive opening shall record its dependencies here */
|
||||
if (self->interface->acquire)
|
||||
{
|
||||
TRACE (interface, "Acquire %s", self->interface->name);
|
||||
collect_dependencies = self->deps?0:1;
|
||||
self->interface = self->interface->acquire (self->interface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* opening again recurse dependencies */
|
||||
collect_dependencies = 0;
|
||||
depwalk (self, &stack);
|
||||
}
|
||||
|
||||
collect_dependencies = collect_dependencies_bak;
|
||||
stack = self->lnk;
|
||||
self->lnk = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lumiera_interface_close (LumieraInterface self)
|
||||
{
|
||||
TRACE (interface);
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
lumiera_interfacenode_close ((LumieraInterfacenode)psplay_find (lumiera_interfaceregistry, self, 100));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* internal function, does no locking! */
|
||||
static void
|
||||
lumiera_interfacenode_close (LumieraInterfacenode self)
|
||||
{
|
||||
static LumieraInterfacenode stack = NULL;
|
||||
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
TRACE (interface, "%s %d (%s)", self->interface->name, self->refcnt, stack?stack->interface->name:"");
|
||||
|
||||
REQUIRE (self->refcnt);
|
||||
|
||||
int cycle = 0;
|
||||
|
||||
for (LumieraInterfacenode itr = stack; itr; itr = itr->lnk)
|
||||
{
|
||||
if (itr == self)
|
||||
{
|
||||
TRACE (interface, "CYCLE");
|
||||
cycle = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cycle)
|
||||
{
|
||||
self->lnk = stack;
|
||||
stack = self;
|
||||
|
||||
if (self->refcnt == 1)
|
||||
{
|
||||
if (self->interface->release)
|
||||
{
|
||||
TRACE (interface, "Release %s", self->interface->name);
|
||||
self->interface->release (self->interface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->deps)
|
||||
{
|
||||
TRACE (interface, "Recurse %s %d", self->interface->name, self->refcnt);
|
||||
|
||||
for (LumieraInterfacenode* dep = self->deps; *dep; ++dep)
|
||||
lumiera_interfacenode_close (*dep);
|
||||
}
|
||||
}
|
||||
|
||||
stack = self->lnk;
|
||||
self->lnk = NULL;
|
||||
--self->refcnt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
408
src/backend/interface.h
Normal file
408
src/backend/interface.h
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
interface.h - Lumiera interface macros and structures
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef LUMIERA_INTERFACE_H
|
||||
#define LUMIERA_INTERFACE_H
|
||||
|
||||
#include "lib/luid.h"
|
||||
#include "lib/ppmpl.h"
|
||||
#include "lib/psplay.h"
|
||||
|
||||
/* TODO better doxygen formating */
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Lumiera interface macros and structures.
|
||||
*
|
||||
* Instead just simple function/library bindings, Lumiera uses a system of
|
||||
* versioned interfaces. This interfaces are C-binding compatible and thus
|
||||
* can be used by any language which can bind to C. This interfaces are versioned
|
||||
* to provide exceptional forward and backward compatibility for both, source and
|
||||
* binary deployment of modules. This interfaces play a central role on the Lumiera
|
||||
* architecture, other facilities, like serializing sessions and distributed computing
|
||||
* will use them extensively.
|
||||
*
|
||||
* Overview
|
||||
*
|
||||
* Interfaces are used for two purposes in Lumiera:
|
||||
* 1. The core uses them internally and exports its functionality though them.
|
||||
* 2. Plugins (effects,...) extend Lumiera by providing interfaces
|
||||
*
|
||||
* We define some macros here which ease the declaration and definition of interfaces.
|
||||
*
|
||||
* Declaration of an interface happens in a header and has the form:
|
||||
* LUMIERA_INTERFACE_DECLARE(name, version,
|
||||
* LUMIERA_INTERFACE_SLOT(ret, name, params),
|
||||
* ...
|
||||
* )
|
||||
* Any code which want to use this interface must then include its declaration.
|
||||
*
|
||||
* Basic definition of an interface is done by mapping functions to slots or giving
|
||||
* inline definitions for slot functions:
|
||||
* LUMIERA_INTERFACE_INSTANCE(iname, version, name, descriptor, acquire, release,
|
||||
* LUMIERA_INTERFACE_MAP (slot, luid, function),
|
||||
* LUMIERA_INTERFACE_INLINE (slot, luid, ret, params, {body}),
|
||||
* ...
|
||||
* )
|
||||
*
|
||||
* There are 2 ways to define collections of interfaces:
|
||||
* LUMIERA_EXPORT(queryfunc,
|
||||
* LUMIERA_INTERFACE_DEFINE(...),
|
||||
* ...
|
||||
* )
|
||||
* to export interfaces from the core.
|
||||
*
|
||||
* LUMIERA_PLUGIN(descriptor, acquire, release, luid,
|
||||
* LUMIERA_INTERFACE_DEFINE(...),
|
||||
* ...
|
||||
* )
|
||||
* is used to export interfaces from a plugin.
|
||||
*
|
||||
* Naming and Versioning
|
||||
* Interfaces have unique names and a major and minor version. The name and the major version
|
||||
* is used to construct a C identifier for the interface, the minor version is implicit defined
|
||||
* by the number of functions a interface. Interface instances are not versioned by the
|
||||
* interface system, versioning these shall be defined somewhere else.
|
||||
*
|
||||
* Slot names are normal C identifiers, how these shall be versioned has to be defined somewhere
|
||||
* else and is not subject of the interface system. Each function can has its own unique uuid.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Interface declaration macros
|
||||
*/
|
||||
|
||||
/**
|
||||
* Construct a type identifier for an interface
|
||||
* @param name name of the interface
|
||||
* @param version major version of this interface
|
||||
*/
|
||||
#define LUMIERA_INTERFACE_INAME(name, version) name##_##version
|
||||
|
||||
/**
|
||||
* Construct a definition identifier for an interface
|
||||
* @param iname name of the interface
|
||||
* @param version major version of the interface
|
||||
* @param dname name for the instance
|
||||
*/
|
||||
#define LUMIERA_INTERFACE_DNAME(iname, version, dname) PPMPL_CAT (LUMIERA_INTERFACE_INAME(iname, version), _##dname)
|
||||
|
||||
|
||||
/**
|
||||
* Return a reference (pointer) to an interface implementation
|
||||
* @param iname name of the interface
|
||||
* @param version major version of the interface
|
||||
* @param dname name for the instance
|
||||
*/
|
||||
#define LUMIERA_INTERFACE_REF(iname, version, dname) \
|
||||
(LumieraInterface)&LUMIERA_INTERFACE_DNAME(iname, version, dname)
|
||||
|
||||
|
||||
/**
|
||||
* Construct the type of the interface
|
||||
* @param name name of the interface
|
||||
* @param version major version of this interface
|
||||
*/
|
||||
#define LUMIERA_INTERFACE_TYPE(name, version) struct LUMIERA_INTERFACE_INAME(name, version)
|
||||
|
||||
|
||||
/**
|
||||
* Construct a cast to the target interface type
|
||||
* Used to cast a generic LumieraInterface to the real type
|
||||
* @param name name of the interface
|
||||
* @param version major version of this interface
|
||||
*/
|
||||
#define LUMIERA_INTERFACE_CAST(name, version) (LUMIERA_INTERFACE_TYPE(name, version)*)
|
||||
|
||||
|
||||
/**
|
||||
* Declare an interface.
|
||||
* @param name name of the interface
|
||||
* @param version major version of this interface declaration. 0 denotes a experimental interface,
|
||||
* otherwise this shall be counting from 1 upwards for each new (incompatible) change of an interface.
|
||||
* The older interface declarations may still be maintained in parallel (backwards compatibility!).
|
||||
* @param ... Slot declarations for the functions provided by this interface @see LUMIERA_INTERFACE_SLOT
|
||||
* The number of Slots in an interface defines its 'minor' version.
|
||||
* New slots must be added at the end. The prototype and order of existing slots must not be changed.
|
||||
* Slots may be renamed, for example a slot 'foo' can be renamed to 'foo_old' when a new 'foo' slot is
|
||||
* added. Binary modules will then still use the 'foo_old' slot which was the 'foo' slot at their
|
||||
* compile time while compiling modules from source will use the new 'foo' slot. This may be
|
||||
* intentionally used to break compilation and force the update of modules to a new api.
|
||||
*/
|
||||
#define LUMIERA_INTERFACE_DECLARE(name, version, ...) \
|
||||
LUMIERA_INTERFACE_TYPE(name, version) \
|
||||
{ \
|
||||
lumiera_interface interface_header_; \
|
||||
PPMPL_FOREACH(_, __VA_ARGS__) \
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare function slot inside an interface.
|
||||
* @param ret return type of the function
|
||||
* @param name name of this slot
|
||||
* @param params parentized list of parameters for the function
|
||||
*/
|
||||
#define PPMPL_FOREACH_LUMIERA_INTERFACE_SLOT(ret, name, params) ret (*name) params; lumiera_uid name##_uid;
|
||||
|
||||
|
||||
/*
|
||||
Interface definition macros
|
||||
*/
|
||||
|
||||
/**
|
||||
* Define a interface instance.
|
||||
* @param iname name of the interface to instance
|
||||
* @param version major version of the interface to instance
|
||||
* @param name name of the instance
|
||||
* @param descriptor pointer to an interface instance which provides a description of this interface, might be NULL
|
||||
* @param acquire a function which is called whenever this interface is opened for using, might be NULL
|
||||
* @param release a function which is called whenever this interface is closed after use, might be NULL
|
||||
* @param ... map functions to interface slots @see LUMIERA_INTERFACE_MAP
|
||||
*/
|
||||
#define LUMIERA_INTERFACE_INSTANCE(iname, version, name, descriptor, acquire, release, ...) \
|
||||
PPMPL_FOREACH(_P1_, __VA_ARGS__) \
|
||||
LUMIERA_INTERFACE_TYPE(iname, version) LUMIERA_INTERFACE_DNAME(iname, version, name) = \
|
||||
{ \
|
||||
{ \
|
||||
#iname, \
|
||||
version, \
|
||||
#name, \
|
||||
sizeof (LUMIERA_INTERFACE_TYPE(iname, version)), \
|
||||
descriptor, \
|
||||
acquire, \
|
||||
release \
|
||||
}, \
|
||||
PPMPL_FOREACH(_P2_, __VA_ARGS__) \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map a function to a interface slot
|
||||
* @param slot name of the slot to be mapped
|
||||
* @param luid unique identifier for this function, use the magic word LUIDGEN here and run the
|
||||
* lumiera uuid generator tool (to be written) over the source file to generate luid's automatically
|
||||
* @param function name of the function to be mapped on slot
|
||||
*
|
||||
* @note C++ requires that all mappings are in the same order than defined in the interface declaration,
|
||||
* this would be good style for C too anyways
|
||||
*/
|
||||
#define PPMPL_FOREACH_P1_LUMIERA_INTERFACE_MAP(slot, luid, function)
|
||||
#ifdef __cplusplus
|
||||
#define PPMPL_FOREACH_P2_LUMIERA_INTERFACE_MAP(slot, luid, function) \
|
||||
function, LUMIERA_UID_INITIALIZER (luid),
|
||||
#else
|
||||
#define PPMPL_FOREACH_P2_LUMIERA_INTERFACE_MAP(slot, luid, function) \
|
||||
.slot = function, .slot##_uid = LUMIERA_UID_INITIALIZER (luid),
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Map a inline defined function to a interface slot
|
||||
* @param slot name of the slot to be mapped
|
||||
* @param luid unique identifier for this function, use the magic word LUIDGEN here and run the
|
||||
* lumiera uuid generator tool (to be written) over the source file to generate luid's automatically
|
||||
* @param ret return type of the inline function
|
||||
* @param params parentized list of parameters given to the function
|
||||
* @param ... braced function body
|
||||
*
|
||||
* @note C++ requires that all mappings are in the same order than defined in the interface declaration,
|
||||
* this would be good style for C too anyways
|
||||
*/
|
||||
#define PPMPL_FOREACH_P1_LUMIERA_INTERFACE_INLINE(slot, luid, ret, params, ...) \
|
||||
static ret \
|
||||
LUMIERA_INTERFACE_INLINE_NAME(slot) params \
|
||||
__VA_ARGS__
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define PPMPL_FOREACH_P2_LUMIERA_INTERFACE_INLINE(slot, luid, ret, params, ...) \
|
||||
LUMIERA_INTERFACE_INLINE_NAME(slot), LUMIERA_UID_INITIALIZER (luid),
|
||||
#else
|
||||
#define PPMPL_FOREACH_P2_LUMIERA_INTERFACE_INLINE(slot, luid, ret, params, ...) \
|
||||
.slot = LUMIERA_INTERFACE_INLINE_NAME(slot), .slot##_uid = LUMIERA_UID_INITIALIZER (luid),
|
||||
#endif
|
||||
|
||||
#define LUMIERA_INTERFACE_INLINE_NAME(slot) PPMPL_CAT(lumiera_##slot##_l, __LINE__)
|
||||
|
||||
|
||||
#define PPMPL_FOREACH_L1_P1_LUMIERA_INTERFACE_DEFINE(iname, version, name, descriptor, acquire, release, ...) \
|
||||
LUMIERA_INTERFACE_INSTANCE (iname, version, \
|
||||
name, \
|
||||
descriptor, \
|
||||
acquire, \
|
||||
release, \
|
||||
__VA_ARGS__ \
|
||||
);
|
||||
|
||||
|
||||
#define PPMPL_FOREACH_L1_P2_LUMIERA_INTERFACE_DEFINE(iname, version, name, descriptor, acquire, release, ...) \
|
||||
&LUMIERA_INTERFACE_DNAME(iname, version, name).interface_header_,
|
||||
|
||||
|
||||
/**
|
||||
* Generate interface container suitable for enumerating interfaces.
|
||||
* This takes a list of interface definitions, instantiates them and places pointers to them
|
||||
* into a zero terminated array which address is returned by the a created function.
|
||||
* For interfaces generated by he core, the user is responsible to register these at the
|
||||
* plugindb dynamically
|
||||
* @param queryfunc name of the function to be created.
|
||||
* @param ... list of LUMIERA_INTERFACE_DEFINE() for all interfaces this plugin provides.
|
||||
*/
|
||||
#define LUMIERA_EXPORT(queryfunc, ...) \
|
||||
PPMPL_FOREACH_L1(_P1_, __VA_ARGS__) \
|
||||
static LumieraInterface* \
|
||||
queryfunc (void) \
|
||||
{ \
|
||||
static LumieraInterface interfaces[] = \
|
||||
{ \
|
||||
PPMPL_FOREACH_L1(_P2_, __VA_ARGS__) \
|
||||
NULL \
|
||||
}; \
|
||||
return interfaces; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate interface container suitable for a lumiera plugin.
|
||||
* This takes a list of interface definitions and places pointers to them into a zero terminated array. Further
|
||||
* it instances a local 'plugin interface' which will be picked up by the plugin loader to query the array of
|
||||
* provided interfaces.
|
||||
* @param descriptor pointer to an interface instance which provides a description of this plugin, might be NULL
|
||||
* @param acquire a function which is called whenever the plugin interface is opened for using, might be NULL
|
||||
* @param release a function which is called whenever this plugin interface is closed after use, might be NULL
|
||||
* @param luid unique identifier for the this plugin interfaces query, use the magic word LUIDGEN here and run the
|
||||
* lumiera uuid generator tool (to be written) over the source file to generate luid's automatically
|
||||
* @param ... list of LUMIERA_INTERFACE_DEFINE() for all interfaces this plugin provides.
|
||||
*/
|
||||
#define LUMIERA_PLUGIN(descriptor, acquire, release, luid, ...) \
|
||||
LUMIERA_EXPORT(plugin_interfaces, __VA_ARGS__) \
|
||||
LUMIERA_INTERFACE_DEFINE (lumieraorg_plugin, 0, \
|
||||
lumieraorg_plugin_0, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
LUMIERA_INTERFACE_MAP (plugin_interfaces, plugin_interfaces, luid) \
|
||||
)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* create a handle for a interface (WIP)
|
||||
*/
|
||||
|
||||
#define LUMIERA_INTERFACE_HANDLE(interface, version) \
|
||||
LUMIERA_INTERFACE_TYPE(interface, version)*
|
||||
|
||||
#define LUMIERA_INTERFACE_OPEN(interface, version, minminor, name) \
|
||||
LUMIERA_INTERFACE_CAST(interface, version) lumiera_interface_open (#interface, version, minminor, #name)
|
||||
|
||||
|
||||
typedef struct lumiera_interfaceslot_struct lumiera_interfaceslot;
|
||||
typedef lumiera_interfaceslot* LumieraInterfaceslot;
|
||||
|
||||
typedef struct lumiera_interface_struct lumiera_interface;
|
||||
typedef lumiera_interface* LumieraInterface;
|
||||
|
||||
/**
|
||||
* This is just a placeholder for an entry in a interface table.
|
||||
* It consists of one here generic, later correctly prototyped function pointer and
|
||||
* a unique identifier which is associated with this function.
|
||||
*/
|
||||
struct lumiera_interfaceslot_struct
|
||||
{
|
||||
void (*func)(void);
|
||||
lumiera_uid uid;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Header for an interface, just the absolute necessary metadata.
|
||||
*/
|
||||
struct lumiera_interface_struct
|
||||
{
|
||||
/** name of the interface (type) */
|
||||
const char* interface;
|
||||
|
||||
/** major version, 0 means experimental */
|
||||
unsigned version;
|
||||
|
||||
/** name of this instance */
|
||||
const char* name;
|
||||
|
||||
/** size of the whole interface structure (minor version) */
|
||||
size_t size;
|
||||
|
||||
/** metadata descriptor, itself a interface (or NULL) */
|
||||
LumieraInterface descriptor;
|
||||
|
||||
/**
|
||||
* Must be called before this interface is used.
|
||||
* might be nested.
|
||||
* @param self pointer to the interface to be acquired
|
||||
* @return pointer to the interface or NULL on error
|
||||
*/
|
||||
LumieraInterface (*acquire)(LumieraInterface self);
|
||||
/**
|
||||
* called when finished using this interface
|
||||
* must match the acquire calls
|
||||
* @param self pointer to the interface to be released
|
||||
*/
|
||||
void (*release)(LumieraInterface self);
|
||||
|
||||
#ifndef __cplusplus
|
||||
/** placeholder array for the following function slots, C++ doesn't support flexible arrays */
|
||||
lumiera_interfaceslot functions[];
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
API to handle interfaces
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Open an interface by version and name.
|
||||
* Looks up the requested interface, possibly loading it from a plugin.
|
||||
* @param interface name of the interface definition
|
||||
* @param version major version of the interface definition
|
||||
* @param minminorversion required minor version (structure size)
|
||||
* @param name name of the interface implementation
|
||||
* @return the queried interface handle on success, else NULL
|
||||
*/
|
||||
LumieraInterface
|
||||
lumiera_interface_open (const char* interface, unsigned version, size_t minminorversion, const char* name);
|
||||
|
||||
/**
|
||||
* Close an interface after use.
|
||||
* @param self interface to be closed
|
||||
* consider 'self' to be invalidated after this call
|
||||
*/
|
||||
void
|
||||
lumiera_interface_close (LumieraInterface iface);
|
||||
|
||||
|
||||
#endif /* LUMIERA_INTERFACE_H */
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
48
src/backend/interfacedescriptor.h
Normal file
48
src/backend/interfacedescriptor.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
interfacedescriptor.h - Metadata interface for Lumiera interfaces
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef LUMIERA_INTERFACEDESCRIPTOR_H
|
||||
#define LUMIERA_INTERFACEDESCRIPTOR_H
|
||||
|
||||
#include "backend/interface.h"
|
||||
|
||||
/**
|
||||
* WIP: interface descriptor, needs some generic metadata interface
|
||||
*/
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_interfacedescriptor, 0,
|
||||
/* The following slots are some human-readable descriptions of certain properties */
|
||||
LUMIERA_INTERFACE_SLOT (const char*, name, (LumieraInterface)),
|
||||
LUMIERA_INTERFACE_SLOT (const char*, version, (LumieraInterface)),
|
||||
LUMIERA_INTERFACE_SLOT (const char*, author, (LumieraInterface)),
|
||||
LUMIERA_INTERFACE_SLOT (const char*, copyright, (LumieraInterface)),
|
||||
LUMIERA_INTERFACE_SLOT (const char*, license, (LumieraInterface))
|
||||
/* TODO add more things here, dependencies, provisions etc */
|
||||
);
|
||||
|
||||
|
||||
|
||||
#endif /* LUMIERA_INTERFACEDESCRIPTORS_H */
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
255
src/backend/interfaceregistry.c
Normal file
255
src/backend/interfaceregistry.c
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
interfaceregistry.c - Lumiera interface registry
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "lib/mutex.h"
|
||||
#include "lib/error.h"
|
||||
#include "lib/psplay.h"
|
||||
#include "lib/safeclib.h"
|
||||
|
||||
|
||||
#include <nobug.h>
|
||||
|
||||
|
||||
|
||||
#include "backend/interfaceregistry.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Interface instances are published and activated by registering them
|
||||
* into a global registry, which is defined here. This instances are identified
|
||||
* by their name and major version.
|
||||
*/
|
||||
|
||||
NOBUG_DEFINE_FLAG_PARENT (interface_all, backend);
|
||||
NOBUG_DEFINE_FLAG_PARENT (interfaceregistry, interface_all);
|
||||
NOBUG_DEFINE_FLAG_PARENT (interface, interface_all);
|
||||
|
||||
PSplay lumiera_interfaceregistry;
|
||||
lumiera_mutex lumiera_interface_mutex;
|
||||
|
||||
static int
|
||||
cmp_fn (const void* keya, const void* keyb);
|
||||
|
||||
static const void*
|
||||
key_fn (const PSplaynode node);
|
||||
|
||||
|
||||
static LumieraInterfacenode
|
||||
lumiera_interfacenode_new (LumieraInterface iface)
|
||||
{
|
||||
LumieraInterfacenode self = lumiera_malloc (sizeof (*self));
|
||||
|
||||
psplaynode_init (&self->node);
|
||||
self->interface = iface;
|
||||
self->refcnt = 0;
|
||||
self->lnk = NULL;
|
||||
self->deps_size = 0;
|
||||
self->deps = NULL;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lumiera_interfacenode_delete (LumieraInterfacenode self)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
REQUIRE (self->refcnt == 0);
|
||||
lumiera_free (self->deps);
|
||||
lumiera_free (self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the interface registry
|
||||
*/
|
||||
void
|
||||
lumiera_interfaceregistry_init (void)
|
||||
{
|
||||
NOBUG_INIT_FLAG (interface_all);
|
||||
NOBUG_INIT_FLAG (interfaceregistry);
|
||||
NOBUG_INIT_FLAG (interface);
|
||||
TRACE (interfaceregistry);
|
||||
REQUIRE (!lumiera_interfaceregistry);
|
||||
|
||||
lumiera_interfaceregistry = psplay_new (cmp_fn, key_fn, NULL);
|
||||
if (!lumiera_interfaceregistry)
|
||||
LUMIERA_DIE (ERRNO);
|
||||
|
||||
lumiera_recmutex_init (&lumiera_interface_mutex, "interfaceregistry", &NOBUG_FLAG(interfaceregistry));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_destroy (void)
|
||||
{
|
||||
TRACE (interfaceregistry);
|
||||
REQUIRE (!psplay_nelements (lumiera_interfaceregistry));
|
||||
|
||||
lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(interfaceregistry));
|
||||
|
||||
if (lumiera_interfaceregistry)
|
||||
psplay_destroy (lumiera_interfaceregistry);
|
||||
lumiera_interfaceregistry = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_register_interface (LumieraInterface self)
|
||||
{
|
||||
TRACE (interfaceregistry);
|
||||
REQUIRE (self);
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
TRACE (interfaceregistry, "interface %s, version %d, instance %s", self->interface, self->version, self->name);
|
||||
psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (self)->node, 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self)
|
||||
{
|
||||
TRACE (interfaceregistry);
|
||||
REQUIRE (self);
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
while (*self)
|
||||
{
|
||||
TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name);
|
||||
psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self)->node, 100);
|
||||
++self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_remove_interface (LumieraInterface self)
|
||||
{
|
||||
TRACE (interfaceregistry);
|
||||
REQUIRE (self);
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, self, 0);
|
||||
REQUIRE (node->refcnt == 0, "but is %d", node->refcnt);
|
||||
|
||||
lumiera_interfacenode_delete ((LumieraInterfacenode)psplay_remove (lumiera_interfaceregistry, &node->node));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (LumieraInterface* self)
|
||||
{
|
||||
TRACE (interfaceregistry);
|
||||
REQUIRE (self);
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
while (*self)
|
||||
{
|
||||
TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name);
|
||||
|
||||
LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, *self, 0);
|
||||
REQUIRE (node->refcnt == 0, "but is %d", node->refcnt);
|
||||
|
||||
lumiera_interfacenode_delete ((LumieraInterfacenode) psplay_remove (lumiera_interfaceregistry, &node->node));
|
||||
|
||||
++self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LumieraInterfacenode
|
||||
lumiera_interfaceregistry_interfacenode_find (const char* interface, unsigned version, const char* name)
|
||||
{
|
||||
TRACE (interfaceregistry);
|
||||
struct lumiera_interface_struct cmp;
|
||||
cmp.interface = interface;
|
||||
cmp.version = version;
|
||||
cmp.name = name;
|
||||
|
||||
LumieraInterfacenode ret = NULL;
|
||||
|
||||
LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex)
|
||||
{
|
||||
ret = (LumieraInterfacenode)psplay_find (lumiera_interfaceregistry, &cmp, 100);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LumieraInterface
|
||||
lumiera_interfaceregistry_interface_find (const char* interface, unsigned version, const char* name)
|
||||
{
|
||||
return lumiera_interfaceregistry_interfacenode_find (interface, version, name)->interface;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_fn (const void* keya, const void* keyb)
|
||||
{
|
||||
const LumieraInterface a = (const LumieraInterface)keya;
|
||||
const LumieraInterface b = (const LumieraInterface)keyb;
|
||||
|
||||
int r = strcmp (a->interface, b->interface);
|
||||
if (r<0)
|
||||
return -1;
|
||||
else if (r>0)
|
||||
return 1;
|
||||
|
||||
if (a->version < b->version)
|
||||
return -1;
|
||||
else if (a->version > b->version)
|
||||
return 1;
|
||||
|
||||
r = strcmp (a->name, b->name);
|
||||
if (r<0)
|
||||
return -1;
|
||||
else if (r>0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const void*
|
||||
key_fn (const PSplaynode node)
|
||||
{
|
||||
return ((LumieraInterfacenode)node)->interface;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
114
src/backend/interfaceregistry.h
Normal file
114
src/backend/interfaceregistry.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
interfaceregistry.h - Lumiera interface registry
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef LUMIERA_INTERFACEREGISTRY_H
|
||||
#define LUMIERA_INTERFACEREGISTRY_H
|
||||
|
||||
#include "lib/mutex.h"
|
||||
#include "lib/psplay.h"
|
||||
|
||||
#include "backend/interface.h"
|
||||
|
||||
#include <nobug.h>
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Interface instances are published and activated by registering them
|
||||
* into a gloabl registry, which is defined here. This instances are identified
|
||||
* by their name and major version.
|
||||
*/
|
||||
|
||||
NOBUG_DECLARE_FLAG (interface_all);
|
||||
NOBUG_DECLARE_FLAG (interfaceregistry);
|
||||
NOBUG_DECLARE_FLAG (interface);
|
||||
|
||||
extern PSplay lumiera_interfaceregistry;
|
||||
extern lumiera_mutex lumiera_interface_mutex;
|
||||
|
||||
|
||||
/**
|
||||
* Interface management node.
|
||||
* All active interfaces managed through this node which contains the dynamic data for
|
||||
* dependency tracking and reference counting.
|
||||
*/
|
||||
typedef struct lumiera_interfacenode_struct lumiera_interfacenode;
|
||||
typedef lumiera_interfacenode* LumieraInterfacenode;
|
||||
|
||||
struct lumiera_interfacenode_struct
|
||||
{
|
||||
/** all known interfaces are registered in a tree */
|
||||
psplaynode node;
|
||||
|
||||
/** the interface itself */
|
||||
LumieraInterface interface;
|
||||
|
||||
/** reference counters and link used for internal reference management */
|
||||
unsigned refcnt;
|
||||
/** temporary used to stack interfaces when recursively opening/closing them */
|
||||
LumieraInterfacenode lnk;
|
||||
/** allocated size of the following deps table */
|
||||
size_t deps_size;
|
||||
/** NULL terminated table of all dependenncies (interfaces opened on initialization) */
|
||||
LumieraInterfacenode* deps;
|
||||
};
|
||||
|
||||
extern lumiera_mutex lumiera_interface_mutex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the interface registry
|
||||
*/
|
||||
void
|
||||
lumiera_interfaceregistry_init (void);
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_destroy (void);
|
||||
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_register_interface (LumieraInterface self);
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self);
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_remove_interface (LumieraInterface self);
|
||||
|
||||
void
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (LumieraInterface* self);
|
||||
|
||||
LumieraInterfacenode
|
||||
lumiera_interfaceregistry_interfacenode_find (const char* interface, unsigned version, const char* name);
|
||||
|
||||
LumieraInterface
|
||||
lumiera_interfaceregistry_interface_find (const char* interface, unsigned version, const char* name);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* LUMIERA_INTERFACEREGISTRY_H */
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -27,8 +27,9 @@
|
|||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "safeclib.h"
|
||||
#include "lib/safeclib.h"
|
||||
|
||||
#include "backend/plugin.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
|
|
@ -20,22 +20,20 @@ noinst_LIBRARIES += liblumi.a
|
|||
|
||||
liblumi_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror
|
||||
|
||||
liblumi_a_SOURCES = \
|
||||
$(liblumi_a_srcdir)/plugin.c \
|
||||
$(liblumi_a_srcdir)/error.c \
|
||||
$(liblumi_a_srcdir)/mutex.c \
|
||||
$(liblumi_a_srcdir)/rwlock.c \
|
||||
$(liblumi_a_srcdir)/condition.c \
|
||||
$(liblumi_a_srcdir)/luid.c \
|
||||
$(liblumi_a_srcdir)/safeclib.c \
|
||||
$(liblumi_a_srcdir)/cuckoo.c \
|
||||
$(liblumi_a_srcdir)/psplay.c \
|
||||
$(liblumi_a_srcdir)/mrucache.c \
|
||||
$(liblumi_a_srcdir)/time.c \
|
||||
liblumi_a_SOURCES = \
|
||||
$(liblumi_a_srcdir)/error.c \
|
||||
$(liblumi_a_srcdir)/mutex.c \
|
||||
$(liblumi_a_srcdir)/rwlock.c \
|
||||
$(liblumi_a_srcdir)/condition.c \
|
||||
$(liblumi_a_srcdir)/luid.c \
|
||||
$(liblumi_a_srcdir)/safeclib.c \
|
||||
$(liblumi_a_srcdir)/cuckoo.c \
|
||||
$(liblumi_a_srcdir)/psplay.c \
|
||||
$(liblumi_a_srcdir)/mrucache.c \
|
||||
$(liblumi_a_srcdir)/time.c \
|
||||
$(liblumi_a_srcdir)/appconfig.cpp
|
||||
|
||||
noinst_HEADERS += \
|
||||
$(liblumi_a_srcdir)/plugin.h \
|
||||
$(liblumi_a_srcdir)/error.h \
|
||||
$(liblumi_a_srcdir)/mutex.h \
|
||||
$(liblumi_a_srcdir)/rwlock.h \
|
||||
|
|
@ -46,6 +44,7 @@ noinst_HEADERS += \
|
|||
$(liblumi_a_srcdir)/psplay.h \
|
||||
$(liblumi_a_srcdir)/mrucache.h \
|
||||
$(liblumi_a_srcdir)/time.h \
|
||||
$(liblumi_a_srcdir)/ppmpl.h \
|
||||
$(liblumi_a_srcdir)/appconfig.hpp \
|
||||
$(liblumi_a_srcdir)/lifecycleregistry.hpp
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,22 @@
|
|||
*/
|
||||
|
||||
typedef unsigned char lumiera_uid[16];
|
||||
typedef lumiera_uid* LumieraUid;
|
||||
|
||||
/*
|
||||
C++ can't initialize arrays from string literals with the trailing \0 cropped
|
||||
C can't initialize non constant members,
|
||||
there we go
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define LUMIERA_UID_INITIALIZER(l) \
|
||||
{ \
|
||||
l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], \
|
||||
l[8], l[9], l[10], l[11], l[12], l[13], l[14], l[15] \
|
||||
}
|
||||
#else
|
||||
#define LUMIERA_UID_INITIALIZER(l) l
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Retrieve a generic pointer stored in a luid
|
||||
|
|
|
|||
|
|
@ -44,6 +44,30 @@ lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* f
|
|||
}
|
||||
|
||||
|
||||
static pthread_once_t recursive_mutexattr_once = PTHREAD_ONCE_INIT;
|
||||
static pthread_mutexattr_t recursive_mutexattr;
|
||||
|
||||
static void recursive_mutexattr_init()
|
||||
{
|
||||
pthread_mutexattr_init (&recursive_mutexattr);
|
||||
pthread_mutexattr_settype (&recursive_mutexattr, PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
|
||||
|
||||
LumieraMutex
|
||||
lumiera_recmutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
pthread_once(&recursive_mutexattr_once, recursive_mutexattr_init);
|
||||
pthread_mutex_init (&self->mutex, &recursive_mutexattr);
|
||||
NOBUG_RESOURCE_HANDLE_INIT (self->rh);
|
||||
NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "recmutex", purpose, self, self->rh);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
LumieraMutex
|
||||
lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag)
|
||||
{
|
||||
|
|
|
|||
118
src/lib/mutex.h
118
src/lib/mutex.h
|
|
@ -39,15 +39,78 @@ LUMIERA_ERROR_DECLARE (MUTEX_DESTROY);
|
|||
/**
|
||||
* Mutual exclusive section.
|
||||
*/
|
||||
#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1}; \
|
||||
#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ \
|
||||
= {(LumieraMutex)1 NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_EXCLUSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
({ \
|
||||
if (lumiera_mutex_section_.mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \
|
||||
lumiera_mutex_section_.mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \
|
||||
} \
|
||||
}))
|
||||
|
||||
/**
|
||||
* Mutual exclusion chainbuilder section.
|
||||
* Usage: LUMIERA_MUTEX_SECTION(a){LUMIERA_MUTEX_SECTION_CHAIN(b){run();}}
|
||||
* calls lock(a); lock(b); unlock(a); run(); unlock(b);
|
||||
* This macro should only be used inside LUMIERA_MUTEX_SECTION and should be
|
||||
* called on the correct mutexes, period.
|
||||
*/
|
||||
#define LUMIERA_MUTEX_SECTION_CHAIN(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer *lumiera_mutex_section_old_ = &lumiera_mutex_section_, \
|
||||
NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \
|
||||
NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_EXCLUSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
if (lumiera_mutex_section_old_->mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_old_->mutex->mutex); \
|
||||
lumiera_mutex_section_old_->mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_old_->rh); \
|
||||
} \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
({ \
|
||||
if (lumiera_mutex_section_.mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \
|
||||
lumiera_mutex_section_.mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \
|
||||
} \
|
||||
}))
|
||||
|
||||
|
||||
/**
|
||||
* Recursive Mutual exclusive section.
|
||||
*/
|
||||
#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \
|
||||
NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_EXCLUSIVE, lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
|
|
@ -61,6 +124,43 @@ LUMIERA_ERROR_DECLARE (MUTEX_DESTROY);
|
|||
}))
|
||||
|
||||
|
||||
/**
|
||||
* Mutual exclusion chainbuilder section.
|
||||
* Usage: LUMIERA_MUTEX_SECTION(a){LUMIERA_RECMUTEX_SECTION_CHAIN(b){run();}}
|
||||
* calls lock(a); lock(b); unlock(a); run(); unlock(b);
|
||||
* This macro should only be used inside LUMIERA_MUTEX_SECTION and should be
|
||||
* called on the correct mutexes, period.
|
||||
*/
|
||||
#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer *lumiera_mutex_section_old_ = &lumiera_mutex_section_, \
|
||||
NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \
|
||||
NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
if (lumiera_mutex_section_old_->mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_old_->mutex->mutex); \
|
||||
lumiera_mutex_section_old_->mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_old_->rh); \
|
||||
} \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
({ \
|
||||
if (lumiera_mutex_section_.mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \
|
||||
lumiera_mutex_section_.mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \
|
||||
} \
|
||||
}))
|
||||
|
||||
|
||||
/**
|
||||
* Mutex.
|
||||
*
|
||||
|
|
@ -76,12 +176,22 @@ typedef lumiera_mutex* LumieraMutex;
|
|||
|
||||
/**
|
||||
* Initialize a mutex variable
|
||||
* This initializes a 'fast' default mutex which must not be locked recursively from one thread.
|
||||
* @param self is a pointer to the mutex to be initialized
|
||||
* @return self as given
|
||||
*/
|
||||
LumieraMutex
|
||||
lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag);
|
||||
|
||||
/**
|
||||
* Initialize a mutex variable
|
||||
* Initializes a 'recursive' mutex which might be locked by the same thread multiple times.
|
||||
* @param self is a pointer to the mutex to be initialized
|
||||
* @return self as given
|
||||
*/
|
||||
LumieraMutex
|
||||
lumiera_recmutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag);
|
||||
|
||||
|
||||
/**
|
||||
* Destroy a mutex variable
|
||||
|
|
|
|||
158
src/lib/ppmpl.h
Normal file
158
src/lib/ppmpl.h
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
ppmpl.h - preprocessor meta programming library
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef PPMPL_H
|
||||
#define PPMPL_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Preprocessor metaprogramming library. We define some useful preprocessor
|
||||
* tricks here.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over a list of macros.
|
||||
* @param p used to disambiguate up to three passes, use _, _P1_ or _P2_
|
||||
* @param ... list of macros to be expanded. The user has to supply a definition
|
||||
* in the form of PPMPL_FOREACH##p##macroname which shall expand to the desired text.
|
||||
*
|
||||
* This user defined macro shall be undefed after use.
|
||||
*
|
||||
* @example
|
||||
* #define PPMPL_FOREACH_P1_FOO(arg) arg,
|
||||
*
|
||||
* {PPMPL_FOREACH(P1, FOO(1), FOO(2), FOO(3)), -1}
|
||||
*
|
||||
* #undef PPMPL_FOREACH_P1_FOO
|
||||
*
|
||||
* Would expand to the sequence:
|
||||
* {1, 2, 3, -1}
|
||||
*
|
||||
* One can not recursively nest preprocessor macros. To allow this we define PPMPL_FOREACH_L1
|
||||
* to PPMPL_FOREACH_L2 with the same semantics as PPMPL_FOREACH, This allowes to nest the
|
||||
* FOREACH loop up to three nesting levels.
|
||||
*/
|
||||
#define PPMPL_FOREACH(p, ...) PPMPL_FOREACH0(p, __VA_ARGS__, PPMPL_FOREACH_NIL))
|
||||
|
||||
/* internal */
|
||||
#define PPMPL_FOREACH0(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH1(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH1(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH2(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH2(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH3(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH3(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH4(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH4(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH5(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH5(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH6(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH6(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH7(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH7(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH8(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH8(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH9(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH9(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH10(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH10(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH11(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH11(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH12(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH12(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH13(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH13(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH14(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH14(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH15(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH15(p, h, ...) PPMPL_FOREACH##p##h
|
||||
#define PPMPL_FOREACH_
|
||||
#define PPMPL_FOREACH_P1_
|
||||
#define PPMPL_FOREACH_P2_
|
||||
#define PPMPL_FOREACH_PPMPL_FOREACH_NIL PPMPL_FOREACH_FINAL(
|
||||
#define PPMPL_FOREACH_P1_PPMPL_FOREACH_NIL PPMPL_FOREACH_FINAL(
|
||||
#define PPMPL_FOREACH_P2_PPMPL_FOREACH_NIL PPMPL_FOREACH_FINAL(
|
||||
#define PPMPL_FOREACH_FINAL(...)
|
||||
|
||||
|
||||
|
||||
|
||||
#define PPMPL_FOREACH_L1(p, ...) PPMPL_FOREACH_L1_0(p, __VA_ARGS__, PPMPL_FOREACH_L1_NIL))
|
||||
|
||||
/* internal */
|
||||
#define PPMPL_FOREACH_L1_0(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_1(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_1(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_2(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_2(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_3(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_3(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_4(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_4(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_5(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_5(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_6(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_6(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_7(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_7(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_8(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_8(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_9(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_9(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_10(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_10(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_11(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_11(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_12(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_12(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_13(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_13(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_14(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_14(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_15(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L1_15(p, h, ...) PPMPL_FOREACH_L1##p##h
|
||||
#define PPMPL_FOREACH_L1_
|
||||
#define PPMPL_FOREACH_L1_P1_
|
||||
#define PPMPL_FOREACH_L1_P2_
|
||||
#define PPMPL_FOREACH_L1_PPMPL_FOREACH_L1_NIL PPMPL_FOREACH_L1_FINAL(
|
||||
#define PPMPL_FOREACH_L1_P1_PPMPL_FOREACH_L1_NIL PPMPL_FOREACH_L1_FINAL(
|
||||
#define PPMPL_FOREACH_L1_P2_PPMPL_FOREACH_L1_NIL PPMPL_FOREACH_L1_FINAL(
|
||||
#define PPMPL_FOREACH_L1_FINAL(...)
|
||||
|
||||
|
||||
|
||||
|
||||
#define PPMPL_FOREACH_L2(p, ...) PPMPL_FOREACH_L2_0(p, __VA_ARGS__, PPMPL_FOREACH_L2_NIL))
|
||||
|
||||
/* internal */
|
||||
#define PPMPL_FOREACH_L2_0(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_1(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_1(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_2(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_2(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_3(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_3(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_4(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_4(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_5(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_5(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_6(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_6(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_7(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_7(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_8(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_8(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_9(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_9(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_10(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_10(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_11(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_11(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_12(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_12(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_13(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_13(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_14(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_14(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_15(p, __VA_ARGS__)
|
||||
#define PPMPL_FOREACH_L2_15(p, h, ...) PPMPL_FOREACH_L2##p##h
|
||||
#define PPMPL_FOREACH_L2_
|
||||
#define PPMPL_FOREACH_L2_P1_
|
||||
#define PPMPL_FOREACH_L2_P2_
|
||||
#define PPMPL_FOREACH_L2_PPMPL_FOREACH_L2_NIL PPMPL_FOREACH_L2_FINAL(
|
||||
#define PPMPL_FOREACH_L2_P1_PPMPL_FOREACH_L2_NIL PPMPL_FOREACH_L2_FINAL(
|
||||
#define PPMPL_FOREACH_L2_P2_PPMPL_FOREACH_L2_NIL PPMPL_FOREACH_L2_FINAL(
|
||||
#define PPMPL_FOREACH_L2_FINAL(...)
|
||||
|
||||
/**
|
||||
* Canonical preprocessor concat implementation which evaluates its arguments
|
||||
*/
|
||||
#define PPMPL_CAT(a,b) PPMPL_CAT_(a,b)
|
||||
#define PPMPL_CAT_(a,b) a##b
|
||||
|
||||
|
||||
#define PPMPL_STRINGIFY(a) PPMPL_STRINGIFY_(a)
|
||||
#define PPMPL_STRINGIFY_(a) #a
|
||||
|
||||
#endif
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -51,6 +51,7 @@ struct psplaynode_struct
|
|||
PSplaynode right;
|
||||
};
|
||||
|
||||
#define PSPLAYNODE_INITIALIZER {NULL, NULL}
|
||||
|
||||
/**
|
||||
* Function use to compare keys
|
||||
|
|
|
|||
|
|
@ -51,6 +51,17 @@ lumiera_calloc (size_t n, size_t size)
|
|||
}
|
||||
|
||||
|
||||
void*
|
||||
lumiera_realloc (void* ptr, size_t size)
|
||||
{
|
||||
void* o = size ? realloc (ptr, size) : NULL;
|
||||
if (!o)
|
||||
LUMIERA_DIE (NO_MEMORY);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
lumiera_strndup (const char* str, size_t len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,16 @@ void*
|
|||
lumiera_calloc (size_t n, size_t size);
|
||||
|
||||
|
||||
/**
|
||||
* Change the size of a memory block.
|
||||
* @param ptr pointer to the old memory block obtained by lumiera_malloc or lumiera_calloc
|
||||
* @param size new size of the block
|
||||
* @return address of new block
|
||||
*/
|
||||
void*
|
||||
lumiera_realloc (void* ptr, size_t size);
|
||||
|
||||
|
||||
/**
|
||||
* Free previously allocated memory.
|
||||
* @param mem pointer to the memory block obtained by lumiera_malloc or lumiera_calloc
|
||||
|
|
|
|||
|
|
@ -18,6 +18,18 @@ out: inner mutex locked section
|
|||
END
|
||||
|
||||
|
||||
TEST "chained mutex section" chainedmutexsection <<END
|
||||
out: outer mutex locked section
|
||||
out: inner but not outer mutex locked section
|
||||
END
|
||||
|
||||
|
||||
TEST "recursive mutex section" recursivemutexsection <<END
|
||||
out: mutex locked once
|
||||
out: mutex locked twice
|
||||
END
|
||||
|
||||
|
||||
TEST "rwlock section" rwlocksection <<END
|
||||
out: write locked section 1
|
||||
out: read locked section 2
|
||||
|
|
|
|||
|
|
@ -21,6 +21,73 @@ out: delim = '='
|
|||
out: value = ' baz'
|
||||
END
|
||||
|
||||
TEST "reset a value" change_value foo.bar '=foo' '=bar' <<END
|
||||
out: foo
|
||||
out: bar
|
||||
END
|
||||
|
||||
TEST "create configitem with empty line" configitem_simple_ctor_dtor '' <<END
|
||||
END
|
||||
|
||||
TEST "create configitem with blank line" configitem_simple_ctor_dtor $' \t \t' <<END
|
||||
END
|
||||
|
||||
TEST "create configitem with comment" configitem_simple_ctor_dtor $' #\t comment bla' <<END
|
||||
END
|
||||
|
||||
TEST "create configitem with section" configitem_simple_ctor_dtor $'\t[prefix suffix ] bla' <<END
|
||||
END
|
||||
|
||||
TEST "create configitem with directive" configitem_simple_ctor_dtor $' @include \t\t file \t' <<END
|
||||
END
|
||||
|
||||
TEST "create configitem with configentry" configitem_simple_ctor_dtor $' key \t=\t value' <<END
|
||||
END
|
||||
|
||||
TEST "create configitem with configentry (redirect)" configitem_simple_ctor_dtor $'keya <\t\t keyb ' <<END
|
||||
END
|
||||
|
||||
TEST "check content of configitem with empty line" configitem_simple_content_check $'' << END
|
||||
END
|
||||
|
||||
TEST "check content of configitem with comment" configitem_simple_content_check $'\t #comment bla' << END
|
||||
out: item->line = ' #comment bla'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with section" configitem_simple_content_check $'[ key.foo suffix.bar ] ' << END
|
||||
out: item->line = '[ key.foo suffix.bar ] '
|
||||
out: item->key_size = '7'
|
||||
out: item->key = 'key.foo suffix.bar ] '
|
||||
out: item->delim = ' suffix.bar ] '
|
||||
END
|
||||
|
||||
TEST "check content of configitem with directive (without argument)" configitem_simple_content_check $'\t @directive ' << END
|
||||
out: item->line = ' @directive '
|
||||
out: item->key_size = '9'
|
||||
out: item->key = '@directive '
|
||||
END
|
||||
|
||||
TEST "check content of configitem with directive (with argument)" configitem_simple_content_check $'\t @directive \targument' << END
|
||||
out: item->line = ' @directive argument'
|
||||
out: item->key_size = '9'
|
||||
out: item->key = '@directive argument'
|
||||
out: item->delim = ' argument'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with configentry" configitem_simple_content_check $' \t\t key.foo \t\t=\tbar' << END
|
||||
out: item->line = ' key.foo = bar'
|
||||
out: item->key_size = '7'
|
||||
out: item->key = 'key.foo = bar'
|
||||
out: item->delim = '= bar'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with configentry (redirect)" configitem_simple_content_check $' \t\t key.foo \t\t<\tkey.bar' << END
|
||||
out: item->line = ' key.foo < key.bar'
|
||||
out: item->key_size = '7'
|
||||
out: item->key = 'key.foo < key.bar'
|
||||
out: item->delim = '< key.bar'
|
||||
END
|
||||
|
||||
|
||||
TEST "set a config and retrieve it" basic_set_get 'foo' '=bar' <<END
|
||||
out: bar
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
TESTING "test plugin example code" ./test-plugin
|
||||
|
||||
TEST "C plugin example" C <<END
|
||||
PLANNED "C plugin example" C <<END
|
||||
out: opened
|
||||
out: Hallo Welt!
|
||||
out: Tschuess C
|
||||
|
|
@ -11,7 +11,7 @@ out: closed
|
|||
out: closed
|
||||
END
|
||||
|
||||
TEST "C++ plugin example" C++ <<END
|
||||
PLANNED "C++ plugin example" C++ <<END
|
||||
out: opened
|
||||
out: Hallo Welt!
|
||||
out: Tschuess C++
|
||||
|
|
|
|||
|
|
@ -131,64 +131,116 @@ END
|
|||
PLANNED "bool set" <<END
|
||||
END
|
||||
|
||||
TEST "create configitem with empty line" configitem_simple_ctor_dtor '' <<END
|
||||
TEST "wordlist get item from empty list should fail" wordlist_get_nth 'foo.bar' '' 0 << END
|
||||
out: 'NULL'
|
||||
END
|
||||
|
||||
TEST "create configitem with blank line" configitem_simple_ctor_dtor $' \t \t' <<END
|
||||
TEST "wordlist get item past end should fail" wordlist_get_nth 'foo.bar' 'baz barf gnarf' 3 << END
|
||||
out: 'NULL'
|
||||
END
|
||||
|
||||
TEST "create configitem with comment" configitem_simple_ctor_dtor $' #\t comment bla' <<END
|
||||
TEST "wordlist get first item" wordlist_get_nth 'foo.bar' 'baz barf gnarf' 0 << END
|
||||
out: 'baz'
|
||||
END
|
||||
|
||||
TEST "create configitem with section" configitem_simple_ctor_dtor $'\t[prefix suffix ] bla' <<END
|
||||
TEST "wordlist get last item" wordlist_get_nth 'foo.bar' 'baz barf; gnarf' 2 << END
|
||||
out: 'gnarf'
|
||||
END
|
||||
|
||||
TEST "create configitem with directive" configitem_simple_ctor_dtor $' @include \t\t file \t' <<END
|
||||
TEST "wordlist get middle" wordlist_get_nth 'foo.bar' 'baz barf, gnarf' 1 << END
|
||||
out: 'barf'
|
||||
END
|
||||
|
||||
TEST "create configitem with configentry" configitem_simple_ctor_dtor $' key \t=\t value' <<END
|
||||
TEST "wordlist find, non existing" wordlist_find 'foo.bar' 'baz barf, gnarf' blah << END
|
||||
out: '-1'
|
||||
END
|
||||
|
||||
TEST "create configitem with configentry (redirect)" configitem_simple_ctor_dtor $'keya <\t\t keyb ' <<END
|
||||
TEST "wordlist find, first" wordlist_find 'foo.bar' 'baz barf, gnarf' baz << END
|
||||
out: '0'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with empty line" configitem_simple_content_check $'' << END
|
||||
TEST "wordlist find, middle" wordlist_find 'foo.bar' 'baz barf, gnarf' barf << END
|
||||
out: '1'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with comment" configitem_simple_content_check $'\t #comment bla' << END
|
||||
out: item->line = ' #comment bla'
|
||||
TEST "wordlist find, last" wordlist_find 'foo.bar' 'baz barf, gnarf' gnarf << END
|
||||
out: '2'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with section" configitem_simple_content_check $'[ key.foo suffix.bar ] ' << END
|
||||
out: item->line = '[ key.foo suffix.bar ] '
|
||||
out: item->key_size = '7'
|
||||
out: item->key = 'key.foo suffix.bar ] '
|
||||
out: item->delim = ' suffix.bar ] '
|
||||
TEST "wordlist replace, middle, insert after" wordlist_replace 'foo.bar' 'baz barf gnarf' barf barf foof << END
|
||||
out: ' baz barf foof gnarf'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with directive (without argument)" configitem_simple_content_check $'\t @directive ' << END
|
||||
out: item->line = ' @directive '
|
||||
out: item->key_size = '9'
|
||||
out: item->key = '@directive '
|
||||
TEST "wordlist replace, middle, insert before" wordlist_replace 'foo.bar' 'baz barf gnarf' barf foof barf << END
|
||||
out: ' baz foof barf gnarf'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with directive (with argument)" configitem_simple_content_check $'\t @directive \targument' << END
|
||||
out: item->line = ' @directive argument'
|
||||
out: item->key_size = '9'
|
||||
out: item->key = '@directive argument'
|
||||
out: item->delim = ' argument'
|
||||
TEST "wordlist replace, middle, remove" wordlist_replace 'foo.bar' 'baz barf gnarf' barf '' '' << END
|
||||
out: ' baz gnarf'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with configentry" configitem_simple_content_check $' \t\t key.foo \t\t=\tbar' << END
|
||||
out: item->line = ' key.foo = bar'
|
||||
out: item->key_size = '7'
|
||||
out: item->key = 'key.foo = bar'
|
||||
out: item->delim = '= bar'
|
||||
TEST "wordlist replace, middle, replace1" wordlist_replace 'foo.bar' 'baz barf gnarf' barf 'foof' '' << END
|
||||
out: ' baz foof gnarf'
|
||||
END
|
||||
|
||||
TEST "check content of configitem with configentry (redirect)" configitem_simple_content_check $' \t\t key.foo \t\t<\tkey.bar' << END
|
||||
out: item->line = ' key.foo < key.bar'
|
||||
out: item->key_size = '7'
|
||||
out: item->key = 'key.foo < key.bar'
|
||||
out: item->delim = '< key.bar'
|
||||
TEST "wordlist replace, middle, replace2" wordlist_replace 'foo.bar' 'baz barf gnarf' barf '' 'foof' << END
|
||||
out: ' baz foof gnarf'
|
||||
END
|
||||
|
||||
TEST "wordlist replace, first, insert before" wordlist_replace 'foo.bar' 'baz barf gnarf' baz 'first' 'baz' << END
|
||||
out: ' first baz barf gnarf'
|
||||
END
|
||||
|
||||
TEST "wordlist replace, first, replace1" wordlist_replace 'foo.bar' 'baz barf gnarf' baz 'first' '' << END
|
||||
out: ' first barf gnarf'
|
||||
END
|
||||
|
||||
TEST "wordlist replace, first, replace2" wordlist_replace 'foo.bar' 'baz barf gnarf' baz '' 'first' << END
|
||||
out: ' first barf gnarf'
|
||||
END
|
||||
|
||||
TEST "wordlist replace, last, insert after" wordlist_replace 'foo.bar' 'baz barf gnarf' gnarf 'gnarf' 'last' << END
|
||||
out: ' baz barf gnarf last'
|
||||
END
|
||||
|
||||
TEST "wordlist add 2 words" wordlist_add 'foo.bar' 'baz barf gnarf' first second << END
|
||||
out: ' baz barf gnarf first'
|
||||
out: ' baz barf gnarf first second'
|
||||
END
|
||||
|
||||
TEST "wordlist add same word" wordlist_add 'foo.bar' 'baz barf gnarf' same same << END
|
||||
out: ' baz barf gnarf same'
|
||||
out: ' baz barf gnarf same'
|
||||
END
|
||||
|
||||
TEST "wordlist add to empty list" wordlist_add 'foo.bar' '' first second << END
|
||||
out: ' first'
|
||||
out: ' first second'
|
||||
END
|
||||
|
||||
TEST "wordlist add to empty list, same" wordlist_add 'foo.bar' '' same same << END
|
||||
out: ' same'
|
||||
out: ' same'
|
||||
END
|
||||
|
||||
|
||||
TEST "wordlist get item from empty list should fail" wordlist_get_nth 'foo.bar' '' 0 << END
|
||||
out: 'NULL'
|
||||
END
|
||||
|
||||
TEST "wordlist get item past end should fail" wordlist_get_nth 'foo.bar' 'baz barf gnarf' 3 << END
|
||||
out: 'NULL'
|
||||
END
|
||||
|
||||
TEST "wordlist get first item" wordlist_get_nth 'foo.bar' 'baz barf gnarf' 0 << END
|
||||
out: 'baz'
|
||||
END
|
||||
|
||||
TEST "wordlist get last item" wordlist_get_nth 'foo.bar' 'baz barf; gnarf' 2 << END
|
||||
out: 'gnarf'
|
||||
END
|
||||
|
||||
TEST "wordlist get middle" wordlist_get_nth 'foo.bar' 'baz barf, gnarf' 1 << END
|
||||
out: 'barf'
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@ test_luid_SOURCES = $(tests_srcdir)/library/test-luid.c
|
|||
test_luid_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror
|
||||
test_luid_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm
|
||||
|
||||
check_PROGRAMS += test-interfaces
|
||||
test_interfaces_SOURCES = $(tests_srcdir)/backend/test-interfaces.c
|
||||
test_interfaces_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror
|
||||
test_interfaces_LDADD = liblumibackend.a liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl -lm
|
||||
|
||||
check_PROGRAMS += test-filedescriptors
|
||||
test_filedescriptors_SOURCES = $(tests_srcdir)/backend/test-filedescriptors.c
|
||||
test_filedescriptors_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror
|
||||
|
|
|
|||
|
|
@ -83,6 +83,36 @@ TEST ("lookup")
|
|||
}
|
||||
|
||||
|
||||
TEST ("change_value")
|
||||
{
|
||||
REQUIRE (argv[2]);
|
||||
REQUIRE (argv[3]);
|
||||
REQUIRE (argv[4]);
|
||||
|
||||
lumiera_config_init ("./");
|
||||
const char* value;
|
||||
|
||||
if (!lumiera_config_set (argv[2], argv[3]))
|
||||
printf ("failure setting first time '%s%s': %s\n", argv[2], argv[3], lumiera_error ());
|
||||
|
||||
if (lumiera_config_get (argv[2], &value))
|
||||
printf ("%s\n", value);
|
||||
else
|
||||
printf ("failure retrieving '%s': %s\n", argv[2], lumiera_error ());
|
||||
|
||||
if (!lumiera_config_set (argv[2], argv[4]))
|
||||
printf ("failure setting second time '%s%s': %s\n", argv[2], argv[4], lumiera_error ());
|
||||
|
||||
if (lumiera_config_get (argv[2], &value))
|
||||
printf ("%s\n", value);
|
||||
else
|
||||
printf ("failure retrieving '%s': %s\n", argv[2], lumiera_error ());
|
||||
|
||||
lumiera_config_destroy ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST ("basic_set_get")
|
||||
{
|
||||
REQUIRE (argv[2]);
|
||||
|
|
@ -258,6 +288,7 @@ TEST ("configitem_simple_ctor_dtor")
|
|||
lumiera_config_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TEST ("configitem_simple_content_check")
|
||||
{
|
||||
REQUIRE (argv[2]);
|
||||
|
|
@ -287,4 +318,95 @@ TEST ("configitem_simple_content_check")
|
|||
lumiera_config_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TEST ("wordlist_get_nth")
|
||||
{
|
||||
REQUIRE (argv[2]);
|
||||
REQUIRE (argv[3]);
|
||||
REQUIRE (argv[4]);
|
||||
|
||||
lumiera_config_init ("./");
|
||||
|
||||
if (!lumiera_config_wordlist_set (argv[2], &argv[3]))
|
||||
printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ());
|
||||
|
||||
const char* word = lumiera_config_wordlist_get_nth (argv[2], atoi (argv[4]));
|
||||
|
||||
printf ("'%s'\n", word?word:"NULL");
|
||||
|
||||
lumiera_config_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TEST ("wordlist_find")
|
||||
{
|
||||
REQUIRE (argv[2]);
|
||||
REQUIRE (argv[3]);
|
||||
REQUIRE (argv[4]);
|
||||
|
||||
lumiera_config_init ("./");
|
||||
|
||||
if (!lumiera_config_wordlist_set (argv[2], &argv[3]))
|
||||
printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ());
|
||||
|
||||
int n = lumiera_config_wordlist_find (argv[2], argv[4]);
|
||||
|
||||
printf ("'%d'\n", n);
|
||||
|
||||
lumiera_config_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TEST ("wordlist_replace")
|
||||
{
|
||||
REQUIRE (argv[2]);
|
||||
REQUIRE (argv[3]);
|
||||
REQUIRE (argv[4]);
|
||||
REQUIRE (argv[5]);
|
||||
REQUIRE (argv[6]);
|
||||
|
||||
lumiera_config_init ("./");
|
||||
|
||||
if (!lumiera_config_wordlist_set (argv[2], &argv[3]))
|
||||
printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ());
|
||||
|
||||
const char* wordlist = lumiera_config_wordlist_replace (argv[2], argv[4], *argv[5]?argv[5]:NULL, *argv[6]?argv[6]:NULL);
|
||||
|
||||
if (wordlist)
|
||||
printf ("'%s'\n", wordlist);
|
||||
else
|
||||
printf ("%s\n", lumiera_error ());
|
||||
|
||||
lumiera_config_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TEST ("wordlist_add")
|
||||
{
|
||||
REQUIRE (argv[2]);
|
||||
REQUIRE (argv[3]);
|
||||
REQUIRE (argv[4]);
|
||||
REQUIRE (argv[5]);
|
||||
|
||||
lumiera_config_init ("./");
|
||||
|
||||
if (!lumiera_config_wordlist_set (argv[2], &argv[3]))
|
||||
printf ("failed setting word '%s=%s': %s\n", argv[2], argv[3], lumiera_error ());
|
||||
|
||||
const char* wordlist = lumiera_config_wordlist_add (argv[2], argv[4]);
|
||||
if (wordlist)
|
||||
printf ("'%s'\n", wordlist);
|
||||
else
|
||||
printf ("%s\n", lumiera_error ());
|
||||
|
||||
wordlist = lumiera_config_wordlist_add (argv[2], argv[5]);
|
||||
if (wordlist)
|
||||
printf ("'%s'\n", wordlist);
|
||||
else
|
||||
printf ("%s\n", lumiera_error ());
|
||||
|
||||
lumiera_config_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TESTS_END
|
||||
|
|
|
|||
452
tests/backend/test-interfaces.c
Normal file
452
tests/backend/test-interfaces.c
Normal file
|
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
test-interfaces.c - test interfaces declaration and implementation
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "backend/interface.h"
|
||||
#include "backend/interfaceregistry.h"
|
||||
#include "backend/interfacedescriptor.h"
|
||||
#include "tests/test.h"
|
||||
|
||||
/*
|
||||
define 2 example interfaces
|
||||
*/
|
||||
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_testexample_one, 0,
|
||||
LUMIERA_INTERFACE_SLOT (void, foo1, (const char*)),
|
||||
LUMIERA_INTERFACE_SLOT (void, bar1, (const char*)),
|
||||
);
|
||||
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_testexample_two, 0,
|
||||
LUMIERA_INTERFACE_SLOT (void, foo2, (const char*)),
|
||||
LUMIERA_INTERFACE_SLOT (void, bar2, (const char*)),
|
||||
);
|
||||
|
||||
LUMIERA_INTERFACE_DECLARE (lumieraorg_testexample_void, 0
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
now the functions we want to bind to them
|
||||
*/
|
||||
|
||||
void
|
||||
testfunc (const char* message)
|
||||
{
|
||||
printf ("Called as '%s'\n", message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LumieraInterface
|
||||
testacquire (LumieraInterface self)
|
||||
{
|
||||
printf ("Acquire %s_%d_%s\n", self->interface, self->version, self->name);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testrelease (LumieraInterface self)
|
||||
{
|
||||
printf ("Release %s_%d_%s\n", self->interface, self->version, self->name);
|
||||
}
|
||||
|
||||
/*
|
||||
implementation of some example interfaces
|
||||
*/
|
||||
|
||||
LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0,
|
||||
lumieraorg_tests_descriptor,
|
||||
/*self reference, yay*/
|
||||
LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor),
|
||||
testacquire,
|
||||
testrelease,
|
||||
LUMIERA_INTERFACE_INLINE (name, "\073\003\054\127\344\046\324\321\221\262\232\026\376\123\125\243",
|
||||
const char*, (LumieraInterface iface),
|
||||
{return "Lumiera Test suite examples";}
|
||||
),
|
||||
LUMIERA_INTERFACE_INLINE (version, "\271\330\345\066\304\217\211\065\157\120\031\365\304\363\364\074",
|
||||
const char*, (LumieraInterface iface),
|
||||
{return "No Version";}
|
||||
),
|
||||
LUMIERA_INTERFACE_INLINE (author, "\367\160\342\065\147\007\237\371\141\335\371\131\025\030\257\232",
|
||||
const char*, (LumieraInterface iface),
|
||||
{return "Christian Thaeter <ct@pipapo.org>";}
|
||||
),
|
||||
LUMIERA_INTERFACE_INLINE (copyright, "\163\106\344\014\251\125\111\252\236\322\174\120\335\225\333\245",
|
||||
const char*, (LumieraInterface iface),
|
||||
{
|
||||
return
|
||||
"Copyright (C) Lumiera.org\n"
|
||||
" 2008 Christian Thaeter <ct@pipapo.org>";
|
||||
}
|
||||
),
|
||||
LUMIERA_INTERFACE_INLINE (license, "\343\031\207\122\225\217\014\163\015\023\243\101\165\377\222\350",
|
||||
const char*, (LumieraInterface iface),
|
||||
{
|
||||
return
|
||||
"This program is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License as published by\n"
|
||||
"the Free Software Foundation; either version 2 of the License, or\n"
|
||||
"(at your option) any later version.\n"
|
||||
"\n"
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
"GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
"You should have received a copy of the GNU General Public License\n"
|
||||
"along with this program; if not, write to the Free Software\n"
|
||||
"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA";
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
LUMIERA_EXPORT (interfaces_defined_here,
|
||||
LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_one, 0,
|
||||
lumieraorg_first_test,
|
||||
LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor),
|
||||
testacquire,
|
||||
testrelease,
|
||||
LUMIERA_INTERFACE_MAP (foo1, "\214\310\136\372\003\344\163\377\075\100\070\200\375\221\227\324",
|
||||
testfunc),
|
||||
LUMIERA_INTERFACE_MAP (bar1, "\262\253\067\211\157\052\212\140\114\334\231\250\340\075\214\030",
|
||||
testfunc)
|
||||
),
|
||||
LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_two, 0,
|
||||
lumieraorg_second_test,
|
||||
LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor),
|
||||
testacquire,
|
||||
testrelease,
|
||||
LUMIERA_INTERFACE_MAP (foo2, "\110\152\002\271\363\052\324\272\373\045\132\270\277\000\271\217",
|
||||
testfunc),
|
||||
LUMIERA_INTERFACE_MAP (bar2, "\376\042\027\336\355\113\132\233\350\312\170\077\377\370\356\167",
|
||||
testfunc)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
Now we rig a cross dependency test
|
||||
|
||||
we have 4 instances, the respective acquire/release operations set following up:
|
||||
|
||||
one depends on two and three
|
||||
two depends on one and four
|
||||
three depends on two and four
|
||||
four depends on one, two three
|
||||
|
||||
These all are empty interfaces with no slots
|
||||
*/
|
||||
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) one_keeps_two;
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) one_keeps_three;
|
||||
|
||||
LumieraInterface
|
||||
testacquire_one (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Acquire one %s_%d_%s", self->interface, self->version, self->name);
|
||||
one_keeps_two = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two);
|
||||
one_keeps_three = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_three);
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
testrelease_one (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Release one %s_%d_%s", self->interface, self->version, self->name);
|
||||
lumiera_interface_close ((LumieraInterface)one_keeps_two);
|
||||
lumiera_interface_close ((LumieraInterface)one_keeps_three);
|
||||
}
|
||||
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) two_keeps_one;
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) two_keeps_four;
|
||||
|
||||
LumieraInterface
|
||||
testacquire_two (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Acquire two %s_%d_%s", self->interface, self->version, self->name);
|
||||
two_keeps_one = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one);
|
||||
two_keeps_four = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four);
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
testrelease_two (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Release two %s_%d_%s", self->interface, self->version, self->name);
|
||||
lumiera_interface_close ((LumieraInterface)two_keeps_one);
|
||||
lumiera_interface_close ((LumieraInterface)two_keeps_four);
|
||||
}
|
||||
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) three_keeps_two;
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) three_keeps_four;
|
||||
|
||||
LumieraInterface
|
||||
testacquire_three (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Acquire three %s_%d_%s", self->interface, self->version, self->name);
|
||||
three_keeps_two = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two);
|
||||
three_keeps_four = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four);
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
testrelease_three (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Release three %s_%d_%s", self->interface, self->version, self->name);
|
||||
lumiera_interface_close ((LumieraInterface)three_keeps_two);
|
||||
lumiera_interface_close ((LumieraInterface)three_keeps_four);
|
||||
}
|
||||
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) four_keeps_one;
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) four_keeps_two;
|
||||
static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) four_keeps_three;
|
||||
|
||||
LumieraInterface
|
||||
testacquire_four (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Acquire four %s_%d_%s", self->interface, self->version, self->name);
|
||||
four_keeps_one = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one);
|
||||
four_keeps_two = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two);
|
||||
four_keeps_three = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_three);
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
testrelease_four (LumieraInterface self)
|
||||
{
|
||||
TRACE (tests, "Release four %s_%d_%s", self->interface, self->version, self->name);
|
||||
lumiera_interface_close ((LumieraInterface)four_keeps_one);
|
||||
lumiera_interface_close ((LumieraInterface)four_keeps_two);
|
||||
lumiera_interface_close ((LumieraInterface)four_keeps_three);
|
||||
}
|
||||
|
||||
|
||||
LUMIERA_EXPORT (dependencytests,
|
||||
LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_void, 0,
|
||||
lumieraorg_dependencytest_one,
|
||||
LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor),
|
||||
testacquire_one,
|
||||
testrelease_one
|
||||
),
|
||||
LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_void, 0,
|
||||
lumieraorg_dependencytest_two,
|
||||
LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor),
|
||||
testacquire_two,
|
||||
testrelease_two
|
||||
),
|
||||
LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_void, 0,
|
||||
lumieraorg_dependencytest_three,
|
||||
LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor),
|
||||
testacquire_three,
|
||||
testrelease_three
|
||||
),
|
||||
LUMIERA_INTERFACE_DEFINE (lumieraorg_testexample_void, 0,
|
||||
lumieraorg_dependencytest_four,
|
||||
LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_tests_descriptor),
|
||||
testacquire_four,
|
||||
testrelease_four
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
TESTS_BEGIN
|
||||
|
||||
TEST ("basic")
|
||||
{
|
||||
lumiera_interfaceregistry_init ();
|
||||
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here());
|
||||
|
||||
|
||||
/* some ugly lowlevel handling tests */
|
||||
|
||||
LumieraInterface handle1 =
|
||||
lumiera_interfaceregistry_interface_find ("lumieraorg_testexample_one", 0, "lumieraorg_first_test");
|
||||
|
||||
(LUMIERA_INTERFACE_CAST(lumieraorg_testexample_one, 0)handle1)->bar1 ("this is bar1");
|
||||
|
||||
|
||||
LUMIERA_INTERFACE_TYPE(lumieraorg_testexample_two, 0)* handle2 = LUMIERA_INTERFACE_CAST(lumieraorg_testexample_two, 0)
|
||||
lumiera_interfaceregistry_interface_find ("lumieraorg_testexample_two", 0, "lumieraorg_second_test");
|
||||
|
||||
handle2->foo2 ("this is foo2");
|
||||
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (interfaces_defined_here());
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
TEST ("open_close")
|
||||
{
|
||||
lumiera_interfaceregistry_init ();
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (interfaces_defined_here());
|
||||
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_one, 0) handle =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_one, 0, 0, lumieraorg_first_test);
|
||||
ENSURE (handle);
|
||||
|
||||
handle->bar1 ("this is bar1");
|
||||
|
||||
lumiera_interface_close ((LumieraInterface)handle);
|
||||
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (interfaces_defined_here());
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
TEST ("dependencies_one")
|
||||
{
|
||||
lumiera_interfaceregistry_init ();
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (dependencytests());
|
||||
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one);
|
||||
ENSURE (handle);
|
||||
|
||||
TRACE (tests, "Sucessfully opened");
|
||||
|
||||
lumiera_interface_close ((LumieraInterface)handle);
|
||||
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (dependencytests());
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TEST ("dependencies_two")
|
||||
{
|
||||
lumiera_interfaceregistry_init ();
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (dependencytests());
|
||||
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two);
|
||||
ENSURE (handle);
|
||||
|
||||
TRACE (tests, "Sucessfully opened");
|
||||
|
||||
lumiera_interface_close ((LumieraInterface)handle);
|
||||
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (dependencytests());
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
TEST ("dependencies_three")
|
||||
{
|
||||
lumiera_interfaceregistry_init ();
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (dependencytests());
|
||||
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_three);
|
||||
ENSURE (handle);
|
||||
|
||||
TRACE (tests, "Sucessfully opened");
|
||||
|
||||
lumiera_interface_close ((LumieraInterface)handle);
|
||||
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (dependencytests());
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
|
||||
TEST ("dependencies_four")
|
||||
{
|
||||
lumiera_interfaceregistry_init ();
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (dependencytests());
|
||||
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four);
|
||||
ENSURE (handle);
|
||||
|
||||
TRACE (tests, "Sucessfully opened");
|
||||
|
||||
lumiera_interface_close ((LumieraInterface)handle);
|
||||
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (dependencytests());
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST ("dependencies_all")
|
||||
{
|
||||
lumiera_interfaceregistry_init ();
|
||||
lumiera_interfaceregistry_bulkregister_interfaces (dependencytests());
|
||||
|
||||
TRACE (tests, "OPEN one");
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle_one =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one);
|
||||
ENSURE (handle_one);
|
||||
|
||||
TRACE (tests, "OPEN three");
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle_three =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_three);
|
||||
ENSURE (handle_three);
|
||||
|
||||
TRACE (tests, "OPEN two");
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle_two =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two);
|
||||
ENSURE (handle_two);
|
||||
|
||||
TRACE (tests, "OPEN four");
|
||||
LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) handle_four =
|
||||
LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four);
|
||||
ENSURE (handle_four);
|
||||
|
||||
TRACE (tests, "Sucessfully OPENED");
|
||||
|
||||
TRACE (tests, "CLOSE four");
|
||||
lumiera_interface_close ((LumieraInterface)handle_four);
|
||||
|
||||
TRACE (tests, "CLOSE two");
|
||||
lumiera_interface_close ((LumieraInterface)handle_two);
|
||||
|
||||
TRACE (tests, "CLOSE three");
|
||||
lumiera_interface_close ((LumieraInterface)handle_three);
|
||||
|
||||
TRACE (tests, "CLOSE one");
|
||||
lumiera_interface_close ((LumieraInterface)handle_one);
|
||||
|
||||
|
||||
lumiera_interfaceregistry_bulkremove_interfaces (dependencytests());
|
||||
lumiera_interfaceregistry_destroy ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST ("highlevel, plugin")
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
TESTS_END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -85,7 +85,46 @@ TEST ("nestedmutexsection")
|
|||
lumiera_mutex_destroy (&m, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
TEST ("chainedmutexsection")
|
||||
{
|
||||
lumiera_mutex m;
|
||||
lumiera_mutex_init (&m, "m_mutexsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
lumiera_mutex n;
|
||||
lumiera_mutex_init (&n, "n_mutexsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
LUMIERA_MUTEX_SECTION (NOBUG_ON, &m)
|
||||
{
|
||||
printf ("outer mutex locked section\n");
|
||||
|
||||
LUMIERA_MUTEX_SECTION_CHAIN (NOBUG_ON, &n)
|
||||
{
|
||||
printf ("inner but not outer mutex locked section\n");
|
||||
}
|
||||
}
|
||||
|
||||
lumiera_mutex_destroy (&n, &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_mutex_destroy (&m, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
TEST ("recursivemutexsection")
|
||||
{
|
||||
lumiera_mutex m;
|
||||
lumiera_recmutex_init (&m, "m_mutexsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
|
||||
LUMIERA_MUTEX_SECTION (NOBUG_ON, &m)
|
||||
{
|
||||
printf ("mutex locked once\n");
|
||||
|
||||
LUMIERA_MUTEX_SECTION (NOBUG_ON, &m)
|
||||
{
|
||||
printf ("mutex locked twice\n");
|
||||
}
|
||||
}
|
||||
|
||||
lumiera_mutex_destroy (&m, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
TEST ("rwlocksection")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
working example code for Lumiera's plugin system
|
||||
This directory contains example code which shows how to use specific features.
|
||||
All examples will be build and run as part of the testsuite
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# Copyright (C) Lumiera.org
|
||||
# 2007, Christian Thaeter <ct@pipapo.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
examples_srcdir = $(top_srcdir)/tests/plugin
|
||||
noinst_PROGRAMS += test-plugin
|
||||
|
||||
test_plugin_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Werror
|
||||
test_plugin_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror
|
||||
test_plugin_LDADD = liblumi.a $(NOBUGMT_LUMIERA_LIBS) -ldl
|
||||
test_plugin_SOURCES = $(examples_srcdir)/plugin_main.c
|
||||
|
||||
noinst_HEADERS += $(examples_srcdir)/hello_interface.h
|
||||
|
||||
check_LTLIBRARIES += example_plugin.la example_plugin_cpp.la
|
||||
example_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror
|
||||
example_plugin_la_SOURCES = $(examples_srcdir)/example_plugin.c
|
||||
# the -rpath option is required, prolly a automake bug?
|
||||
example_plugin_la_LDFLAGS = -avoid-version -module -rpath $(shell pwd)
|
||||
|
||||
example_plugin_cpp_la_CPPFLAGS = $(AM_CPPFLAGS) -Wall -Werror
|
||||
example_plugin_cpp_la_SOURCES = $(examples_srcdir)/example_plugin.cpp
|
||||
# the -rpath option is required, prolly a automake bug?
|
||||
example_plugin_cpp_la_LDFLAGS = -avoid-version -module -rpath $(shell pwd)
|
||||
Loading…
Reference in a new issue