Merge branch 'sharedlib' of git.lumiera.org:/git/lumiera/ct into gui

Conflicts:

	src/gui/Makefile.am
This commit is contained in:
Joel Holdsworth 2008-12-16 20:44:33 +00:00
commit 8b5733c293
192 changed files with 12177 additions and 1565 deletions

View file

@ -47,6 +47,7 @@ include $(top_srcdir)/src/proc/Makefile.am
include $(top_srcdir)/src/common/Makefile.am
include $(top_srcdir)/src/lib/Makefile.am
include $(top_srcdir)/src/backend/Makefile.am
include $(top_srcdir)/src/lumiera/Makefile.am
# tools
include $(top_srcdir)/src/tool/Makefile.am

View file

@ -27,6 +27,7 @@ OPTIONSCACHEFILE = 'optcache'
CUSTOPTIONSFILE = 'custom-options'
SRCDIR = 'src'
BINDIR = 'bin'
LIBDIR = '.libs'
TESTDIR = 'tests'
ICONDIR = 'icons'
VERSION = '0.1+pre.01'
@ -65,14 +66,17 @@ def setupBasicEnvironment():
)
handleVerboseMessages(env)
env.Append ( CCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honor CFLAGS, only CCFLAGS
env.Append ( CCCOM=' -std=gnu99')
env.Append ( SHCCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honour CFLAGS, only CCFLAGS
env.Replace( VERSION=VERSION
, SRCDIR=SRCDIR
, BINDIR=BINDIR
, LIBDIR=LIBDIR
, ICONDIR=ICONDIR
, CPPPATH=["#"+SRCDIR] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['-DLUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines
, CCFLAGS='-Wall ' # -fdiagnostics-show-option
, CCFLAGS='-Wall ' # -fdiagnostics-show-option
, CFLAGS='-std=gnu99'
)
RegisterIcon_Builder(env,SVGRENDERER)
handleNoBugSwitches(env)
@ -87,6 +91,8 @@ def setupBasicEnvironment():
# setup search path for Lumiera plugins
appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR\\"'
,'LUMIERA_PLUGIN_PATH=\\"$DESTDIR/lib/lumiera\\"')
appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR\\"'
,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera\\"')
prepareOptionsHelp(opts,env)
opts.Save(OPTIONSCACHEFILE, env)
@ -121,10 +127,10 @@ def handleVerboseMessages(env):
""" toggle verbose build output """
if not env['VERBOSE']:
# SetOption('silent', True)
env['CCCOMSTR'] = " Compiling $SOURCE"
env['CXXCOMSTR'] = " Compiling++ $SOURCE"
env['LINKCOMSTR'] = " Linking --> $TARGET"
env['LDMODULECOMSTR'] = " creating module [ $TARGET ]"
env['CCCOMSTR'] = env['SHCCCOMSTR'] = " Compiling $SOURCE"
env['CXXCOMSTR'] = env['SHCXXCOMSTR'] = " Compiling++ $SOURCE"
env['LINKCOMSTR'] = " Linking --> $TARGET"
env['LDMODULECOMSTR'] = " creating module [ $TARGET ]"
@ -139,8 +145,8 @@ def defineCmdlineOptions():
('ARCHFLAGS', 'Set architecture-specific compilation flags (passed literally to gcc)','')
,EnumOption('BUILDLEVEL', 'NoBug build level for debugging', 'ALPHA',
allowed_values=('ALPHA', 'BETA', 'RELEASE'))
,BoolOption('DEBUG', 'Build with debugging information and no optimizations', False)
,BoolOption('OPTIMIZE', 'Build with strong optimization (-O3)', False)
,BoolOption('DEBUG', 'Build with debugging information and no optimisations', False)
,BoolOption('OPTIMIZE', 'Build with strong optimisation (-O3)', False)
,BoolOption('VALGRIND', 'Run Testsuite under valgrind control', True)
,BoolOption('VERBOSE', 'Print full build commands', False)
,('TESTSUITES', 'Run only Testsuites matching the given pattern', '')
@ -149,8 +155,9 @@ def defineCmdlineOptions():
# allowed_values=('auto', 'i386', 'i686', 'x86_64' ), ignorecase=2)
,PathOption('DESTDIR', 'Installation dir prefix', '/usr/local')
,PathOption('PKGLIBDIR', 'Installation dir for plugins, defaults to DESTDIR/lib/lumiera', '',PathOption.PathAccept)
,PathOption('PKGDATADIR', 'Installation dir for default config, usually DESTDIR/share/lumiera', '',PathOption.PathAccept)
,PathOption('SRCTAR', 'Create source tarball prior to compiling', '..', PathOption.PathAccept)
,PathOption('DOCTAR', 'Create tarball with dev documentaionl', '..', PathOption.PathAccept)
,PathOption('DOCTAR', 'Create tarball with developer documentation', '..', PathOption.PathAccept)
)
return opts
@ -306,18 +313,25 @@ def defineBuildTargets(env, artifacts):
objback = srcSubtree(env,'$SRCDIR/backend')
objproc = srcSubtree(env,'$SRCDIR/proc')
objlib = ( srcSubtree(env,'$SRCDIR/common')
objlib = ( srcSubtree(env,'$SRCDIR/lumiera')
+ srcSubtree(env,'$SRCDIR/common')
+ srcSubtree(env,'$SRCDIR/lib')
)
objplug = srcSubtree(env,'$SRCDIR/plugin', isShared=True)
core = ( env.StaticLibrary('$BINDIR/lumiback.la', objback)
+ env.StaticLibrary('$BINDIR/lumiproc.la', objproc)
+ env.StaticLibrary('$BINDIR/lumiera.la', objlib)
core = ( env.SharedLibrary('$LIBDIR/lumiback', objback, SHLIBPREFIX='')
+ env.SharedLibrary('$LIBDIR/lumiproc', objproc, SHLIBPREFIX='')
+ env.SharedLibrary('$LIBDIR/lumiera', objlib, SHLIBPREFIX='')
)
artifacts['lumiera'] = env.Program('$BINDIR/lumiera', ['$SRCDIR/main.cpp'], LIBS=core)
artifacts['corelib'] = core
artifacts['lumiera'] = env.Program('$BINDIR/lumiera', ['$SRCDIR/main.cpp']+ core )
artifacts['plugins'] = env.LoadableModule('$BINDIR/lumiera-plugin', objplug)
# temporary solution to build the GuiStarterPlugin (TODO: implement plugin building as discussed on November meeting)
envplug = env.Clone()
envplug.Append(CPPPATH='$SRCDIR/plugin', CPPDEFINES='LUMIERA_PLUGIN')
guistarterplugin = env.LoadableModule('#$BINDIR/guistart',
envplug.SharedObject('$SRCDIR/guistart.cpp'), LIBS=core, SHLIBPREFIX='')
artifacts['plugins'] = guistarterplugin
# the Lumiera GTK GUI
envgtk = env.Clone().mergeConf(['gtkmm-2.4','cairomm-1.0','gdl-1.0','librsvg-2.0','xv','xext','sm'])
@ -366,6 +380,7 @@ def defineInstallTargets(env, artifacts):
""" define some artifacts to be installed into target locations.
"""
env.Install(dir = '$DESTDIR/bin', source=artifacts['lumiera'])
env.Install(dir = '$DESTDIR/lib', source=artifacts['corelib'])
env.Install(dir = '$DESTDIR/lib', source=artifacts['plugins'])
env.Install(dir = '$DESTDIR/bin', source=artifacts['tools'])

View file

@ -40,7 +40,7 @@ def isCleanupOperation(env):
def isHelpRequest():
""" this is a hack: SCons does all configure tests even if only
the helpmessage is requested. SCons doesn't export the
the help message is requested. SCons doesn't export the
help option for retrieval by env.GetOption(),
so we scan the commandline directly.
"""
@ -48,8 +48,8 @@ def isHelpRequest():
def srcSubtree(env,tree,isShared=False,builder=None, **args):
""" convienience wrapper: scans the given subtree, which is
def srcSubtree(env,tree,isShared=True,builder=None, **args):
""" convenience wrapper: scans the given subtree, which is
relative to the current SConscript, find all source files and
declare them as Static or SharedObjects for compilation
"""
@ -68,7 +68,7 @@ SRCPATTERNS = ['*.c','*.cpp','*.cc']
def scanSubtree(roots, patterns=SRCPATTERNS):
""" first expand (possible) wildcards and filter out non-dirs.
Then scan the given subtree for source filesnames
Then scan the given subtree for source filenames
(python generator function)
"""
for root in globRootdirs(roots):
@ -116,7 +116,7 @@ def getDirname(dir):
def RegisterIcon_Builder(env, renderer):
""" Registeres Custom Builders for generating and installing Icons.
""" Registers Custom Builders for generating and installing Icons.
Additionally you need to build the tool (rsvg-convert.c)
used to generate png from the svg source using librsvg.
"""
@ -157,7 +157,7 @@ def Tarball(env,location,dirs,suffix=''):
suffix: (optional) suffix to include in the tar name
dirs: directories to include in the tar
This is a bit of a hack, because we want to be able to include arbitrary dirctories,
This is a bit of a hack, because we want to be able to include arbitrary directories,
without creating new dependencies on those dirs. Esp. we want to tar the source tree
prior to compiling. Solution is
- use the Command-Builder, but pass all target specifications as custom build vars

1
bin/.libs Symbolic link
View file

@ -0,0 +1 @@
../.libs

View file

@ -70,10 +70,10 @@ SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = YES
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
GENERATE_DEPRECATEDLIST= NO
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
@ -94,8 +94,7 @@ WARN_LOGFILE = warnings.txt
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../../src/ \
../../tests/
INPUT = ../../src/
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.cc \
@ -154,7 +153,7 @@ FILTER_SOURCE_FILES = NO
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES

1472
doc/devel/Doxyfile.browse Normal file

File diff suppressed because it is too large Load diff

1470
doc/devel/Doxyfile.pdf Normal file

File diff suppressed because it is too large Load diff

View file

@ -78,3 +78,36 @@ Sensible defaults are initialized at installation time.
plugin.path
I/O Backend
-----------
File handling
~~~~~~~~~~~~~
How many filehandles the backend shall use [approx 2/3 of all available]
backend.file.max_handles
Memory mapped Files
~~~~~~~~~~~~~~~~~~~
Address space limit (memory mapping)
Defaults:
3GiB on 32 bit arch
192TiB on 64 bit arch
backend.mmap.as_limit
Default start size for mmaping windows.
128MB on 32 bit arch
2GB on 64 bit arch
backend.mmap.window_size
How many memory mappings shall be established at most
Default 60000
backend.mmap.max_maps

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 93 KiB

View file

@ -20,7 +20,10 @@ all # global logging
filedescriptor # internal filedescriptors
filehandle # posix filehandles
filehandlecache # mrucache for filehandles
map_all # file mapping subsystem
mmap_all # file mapping subsystem
mmap # mmap objects
mmapings # mmap range containers
mmapcache # mmap range containers
cache_all # caching subsystem
scheduler_all # all scheduler
threads # threadpool management

View file

@ -18,7 +18,7 @@
liblumibackend_a_srcdir = $(top_srcdir)/src/backend
noinst_LIBRARIES += liblumibackend.a
liblumibackend_a_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_PLUGIN_PATH="\"$(pkglibdir)\""
liblumibackend_a_CPPFLAGS = $(AM_CPPFLAGS)
liblumibackend_a_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror
liblumibackend_a_SOURCES = \
@ -27,17 +27,15 @@ liblumibackend_a_SOURCES = \
$(liblumibackend_a_srcdir)/file.c \
$(liblumibackend_a_srcdir)/filehandle.c \
$(liblumibackend_a_srcdir)/filedescriptor.c \
$(liblumibackend_a_srcdir)/resourcecollector.c \
$(liblumibackend_a_srcdir)/mmap.c \
$(liblumibackend_a_srcdir)/mmapings.c \
$(liblumibackend_a_srcdir)/mmapcache.c \
$(liblumibackend_a_srcdir)/filehandlecache.c \
$(liblumibackend_a_srcdir)/interface.c \
$(liblumibackend_a_srcdir)/interfaceregistry.c \
$(liblumibackend_a_srcdir)/plugin.c \
$(liblumibackend_a_srcdir)/plugin_dynlib.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)/config_lookup.c
$(liblumibackend_a_srcdir)/enginefacade.cpp \
$(liblumibackend_a_srcdir)/mediaaccessfacade.cpp \
$(liblumibackend_a_srcdir)/scriptrunnerfacade.cpp \
$(liblumibackend_a_srcdir)/netnodefacade.cpp
noinst_HEADERS += \
@ -47,12 +45,7 @@ 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)/plugin.h \
$(liblumibackend_a_srcdir)/config.h \
$(liblumibackend_a_srcdir)/configentry.h \
$(liblumibackend_a_srcdir)/configitem.h \
$(liblumibackend_a_srcdir)/config_lookup.h
$(liblumibackend_a_srcdir)/resourcecollector.h \
$(liblumibackend_a_srcdir)/mmap.h \
$(liblumibackend_a_srcdir)/mmapings.h \
$(liblumibackend_a_srcdir)/mmapcache.h

View file

@ -19,13 +19,35 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/safeclib.h"
#include "backend/backend.h"
#include "lumiera/config.h"
#include "backend/filehandlecache.h"
#include "backend/filedescriptor.h"
#include "backend/mmapcache.h"
#include <unistd.h>
#include <sys/resource.h>
//NOBUG_DEFINE_FLAG_PARENT (backend, lumiera); TODO
NOBUG_DEFINE_FLAG (backend);
NOBUG_DEFINE_FLAG_PARENT (file_all, backend);
NOBUG_DEFINE_FLAG_PARENT (filehandle, file_all);
NOBUG_DEFINE_FLAG_PARENT (mmapings, mmap_all);
NOBUG_DECLARE_FLAG (file);
NOBUG_DECLARE_FLAG (mmap_all);
NOBUG_DECLARE_FLAG (mmap);
NOBUG_DECLARE_FLAG (mmapings);
NOBUG_DECLARE_FLAG (mmapcache);
size_t lumiera_backend_pagesize;
int
lumiera_backend_init (void)
@ -33,14 +55,52 @@ lumiera_backend_init (void)
NOBUG_INIT_FLAG (backend);
NOBUG_INIT_FLAG (file_all);
NOBUG_INIT_FLAG (file);
NOBUG_INIT_FLAG (filehandle);
NOBUG_INIT_FLAG (mmap_all);
NOBUG_INIT_FLAG (mmap);
NOBUG_INIT_FLAG (mmapings);
NOBUG_INIT_FLAG (mmapcache);
TRACE (backend);
lumiera_filedescriptor_registry_init ();
int max_entries = 10; TODO("determine by sysconf (_SC_OPEN_MAX) minus some (big) safety margin "
"add some override to run tests with few filehandles");
lumiera_backend_pagesize = sysconf(_SC_PAGESIZE);
TODO ("add config options to override following defaults");
const char* filehandles = lumiera_tmpbuf_snprintf (SIZE_MAX,
"backend.file.max_handles = %d",
/* roughly 2/3 of all availables filehandles are managed by the backend */
(sysconf (_SC_OPEN_MAX)-10)*2/3);
lumiera_config_setdefault (filehandles);
long long max_entries;
lumiera_config_number_get ("backend.file.max_handles", &max_entries);
lumiera_filehandlecache_new (max_entries);
#if SIZE_MAX <= 4294967295UL
lumiera_config_setdefault ("backend.mmap.as_limit = 3221225469");
#else
lumiera_config_setdefault ("backend.mmap.as_limit = 211106232532992");
#endif
struct rlimit as_rlimit;
getrlimit (RLIMIT_AS, &as_rlimit);
long long as_limit = (long long)as_rlimit.rlim_cur;
if (as_rlimit.rlim_cur == RLIM_INFINITY)
{
lumiera_config_number_get ("backend.mmap.as_limit", &as_limit);
}
else
{
INFO (backend, "address space limited to %luMiB", as_rlimit.rlim_cur/1024/1024);
}
lumiera_mmapcache_new (as_limit);
return 0;
}
@ -48,6 +108,7 @@ void
lumiera_backend_destroy (void)
{
TRACE (backend);
lumiera_filedescriptor_registry_destroy ();
lumiera_mmapcache_delete ();
lumiera_filehandlecache_delete ();
lumiera_filedescriptor_registry_destroy ();
}

View file

@ -24,8 +24,9 @@
#include <nobug.h>
NOBUG_DECLARE_FLAG (backend);
NOBUG_DECLARE_FLAG (file_all);
NOBUG_DECLARE_FLAG (file);
extern size_t lumiera_backend_pagesize;
int
lumiera_backend_init (void);

View file

@ -1,405 +0,0 @@
/*
configitem.c - generalized hierachy of configuration items
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
Simeon Voelkel <simeon_voelkel@arcor.de>
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/llist.h"
#include "lib/safeclib.h"
//TODO: Lumiera header includes//
#include "backend/config.h"
#include "backend/configitem.h"
#include "backend/configentry.h"
//TODO: internal/static forward declarations//
//TODO: System includes//
#include <ctype.h>
#include <stdint.h>
/**
* @file
*
*/
//code goes here//
LumieraConfigitem
lumiera_configitem_init (LumieraConfigitem self)
{
TRACE (config_item);
REQUIRE (self);
llist_init (&self->link);
self->parent = NULL;
llist_init (&self->childs);
llist_init (&self->lookup);
self->line = NULL;
self->key = NULL;
self->key_size = 0;
self->delim = NULL;
self->vtable = NULL;
return self;
}
LumieraConfigitem
lumiera_configitem_destroy (LumieraConfigitem self, LumieraConfigLookup lookup)
{
TRACE (config_item);
if (self)
{
LLIST_WHILE_HEAD (&self->childs, node)
lumiera_configitem_delete ((LumieraConfigitem) node, lookup);
ENSURE (llist_is_empty (&self->childs), "destructor didn't remove childs");
if (self->vtable && self->vtable->destroy)
self->vtable->destroy (self);
if (!llist_is_empty (&self->lookup))
lumiera_config_lookup_remove (lookup, self);
llist_unlink (&self->link);
lumiera_free (self->line);
}
return self;
}
LumieraConfigitem
lumiera_configitem_new (const char* line)
{
TRACE (config_item, "%s", line);
lumiera_configitem tmp;
lumiera_configitem_init (&tmp);
lumiera_configitem_parse (&tmp, line);
LumieraConfigitem self = tmp.vtable && tmp.vtable->new
? tmp.vtable->new (&tmp)
: lumiera_configitem_move (lumiera_malloc (sizeof (*self)), &tmp);
return self;
}
void
lumiera_configitem_delete (LumieraConfigitem self, LumieraConfigLookup lookup)
{
TRACE (config_item);
lumiera_free (lumiera_configitem_destroy (self, lookup));
}
LumieraConfigitem
lumiera_configitem_set_value (LumieraConfigitem self, const char* delim_value)
{
REQUIRE (self->key);
REQUIRE (self->delim);
char* line = lumiera_tmpbuf_snprintf (SIZE_MAX, "%.*s%s", self->delim - self->line, self->line, delim_value);
lumiera_configitem_parse (self, line);
return self;
}
LumieraConfigitem
lumiera_configitem_move (LumieraConfigitem self, LumieraConfigitem source)
{
TRACE (config_item);
REQUIRE (self);
REQUIRE (source);
llist_init (&self->link);
llist_insertlist_next (&self->link, &source->link);
self->parent = source->parent;
llist_init (&self->childs);
llist_insertlist_next (&self->childs, &source->childs);
llist_init (&self->lookup);
llist_insertlist_next (&self->lookup, &source->lookup);
self->line = source->line;
source->line = NULL;
self->key = source->key;
self->key_size = source->key_size;
self->delim = source->delim;
self->vtable = source->vtable;
return self;
}
LumieraConfigitem
lumiera_configitem_parse (LumieraConfigitem self, const char* line)
{
TRACE (config_item);
lumiera_free (self->line);
self->line = lumiera_strndup (line, SIZE_MAX);
FIXME ("MOCKUP START");
TODO ("parsing here");
/*
HOWTO parse (for simav)
in self->line liegt jetzt der 'rohe' string
parsen setzt folgende werte in self: .key, .key_size, .delim und vtable. den rest macht dann die 'new' funktion aus der vtable
es geht jetzt da drum rauszufinden ob diese zeile einses der folgenden sachen ist:
(ich zeig hier nur die grundsyntax, das parsen sollte auch entartete situationen behandeln, insbesondere leerzeichen/tabulatoren an allen moeglichen stellen)
auserdem sollt hier alles soweit wie moeglich validiert werden z.b. keys auf erlaubte zeichen gescheckt (siehe die _tr function)
section:
'[prefix suffix]'
.key == prefix
.delim == das leerzeichen (oder tab) vor suffix oder aufs abschliessende ] wenn kein suffix
kommentar:
leere zeile, zeile nur aus leerzeichen und tabulatoren, leerzeichen und tabulatoren gefolgt von # bis zum zeilenende
alles ausser vtable auf NULL
direktive:
'@direktive argumente'
.key == @
.delim == leerzeichen oder tab vor argumente, NULL wenn keine argumente
configentry:
'key = value'
.key == key begin
.delim == '='
'key < redirect'
.key == key begin
.delim == '>'
*/
/*
* What should be working (for cehteh) or not yet..
*
* die Elemente sollten bereits richtig unterschieden werden, die {} sind noch zu füllen.
*
* */
char* itr = self->line;
/*skip leading whitespaces*/
while (*itr && isspace (*itr))
itr++;
/*decide what this line represents*/
if (!*itr || *itr == '#' )
{
/*this is an empty line or a a comment*/
}
else if (*itr == '@' )
{
/*this is a directive*/
/*itr points now to @*/
self->key = itr;
/*check whether there are illegal whitespaces after @*/
itr++;
if (*itr && !isspace(*itr))
{
/*now look for the end of the directive and set the keysize*/
self->key_size = strspn (itr, LUMIERA_CONFIG_KEY_CHARS);
itr += self->key_size;
/*we need a key with a length greather than zero and
* either end of line
* or whitespace after key */
if ( self->key_size && ( !*itr || (*itr && isspace(*itr)) ))
{
/*look for given arguments*/
/*skip blanks*/
while (*itr && isspace (*itr))
itr++;
if (*itr)
{
/*there are arguments given, thus set delim*/
self->delim = itr - 1;
}
else
{
/*no arguments were given*/
self->delim = NULL;
}
}
else
{
/*malformed lines shall be treated like if they were comments*/
self->key = NULL;
self->key_size = 0;
LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX);
}
}
else
{
/*there occurred already an error right after the @!*/
/*malformed lines shall be treated like if they were comments*/
self->key = NULL;
self->key_size = 0;
LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX);
}
}
else if (*itr == '[' )
{
/*this is a section*/
/*skip blanks before prefix*/
itr++;
while (*itr && isspace(*itr))
itr++;
/*itr points now to the begin of the key*/
self->key = itr;
/*now look for the end of the key and set the keysize*/
self->key_size = strspn (itr, LUMIERA_CONFIG_KEY_CHARS);
itr += self->key_size;
/*if the line ends ends with prefix] delim points to ]
* and not the last (blank) character before the final square bracket*/
if (self->key_size && *itr && *itr == ']')
{
self->delim = itr;
TODO("self->vtable = &lumiera_configsection_funcs;");
}
else if (self->key_size && *itr && isspace(*itr))
{
/* skip blanks until we reach the suffix or the final square bracket*/
while (*itr && isspace(*itr))
itr++;
if (*itr && *itr == ']')
{
/*final square bracket reached, so place delim one char before the
* actual position which must be a whitespace: no extra check necessary*/
self->delim = itr - 1;
TODO("self->vtable = &lumiera_configsection_funcs;");
}
else if (*itr)
{
TODO("check wheter suffix is made of legal characters");
/*delim points to the last whitespace before the actual position;
* no extra check needed*/
self->delim = itr - 1;
TODO("self->vtable = &lumiera_configsection_funcs;");
}
else
{
/*malformed section line, treat this line like a comment*/
self->key = NULL;
self->key_size = 0;
LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX);
}
}
else
{
/*error: either *itr is false, points neither to a blank nor to a closed square
* bracket or the key_size is zero*/
/*treat this line like a comment*/
self->key = NULL;
self->key_size = 0;
LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX);
}
}
else
{
/*this is probably a configentry*/
/*itr points now to the first not-whitespace-character*/
self->key = itr;
/*now look for the end of the key and set the keysize*/
self->key_size = strspn (itr, LUMIERA_CONFIG_KEY_CHARS);
/* skip blanks */
itr += self->key_size;
while (*itr && isspace (*itr))
itr++;
if (self->key_size && *itr == '=')
{
/*this configentry assigns a value to a key*/
self->delim = itr;
self->vtable = &lumiera_configentry_funcs;
}
else if (self->key_size && *itr == '<')
{
/*this configentry is a redirect*/
self->delim = itr;
self->vtable = &lumiera_configentry_funcs;
}
else
{
/*this is not a valid configentry; treat this line like a comment*/
self->key = NULL;
self->key_size = 0;
LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX);
}
}
return self;
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -0,0 +1,85 @@
/*
EngineFacade - access point for communicating with the render engine
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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/enginefacade.hpp"
#include "common/singleton.hpp"
#include <string>
namespace backend {
using std::string;
using lumiera::Subsys;
class EngineSubsysDescriptor
: public Subsys
{
operator string () const { return "Engine"; }
bool
shouldStart (lumiera::Option&)
{
TODO ("determine, if renderengine should be started");
return false;
}
bool
start (lumiera::Option&, Subsys::SigTerm termination)
{
UNIMPLEMENTED ("pull up renderengine and register shutdown hook");
return false;
}
void
triggerShutdown () throw()
{
UNIMPLEMENTED ("initiate halting the engine");
}
bool
checkRunningState () throw()
{
//Lock guard (*this);
TODO ("implement detecting running state");
return false;
}
};
namespace {
lumiera::Singleton<EngineSubsysDescriptor> theDescriptor;
}
/** @internal intended for use by main(). */
Subsys&
EngineFacade::getDescriptor()
{
return theDescriptor();
}
} // namespace backend

View file

@ -0,0 +1,63 @@
/*
ENGINEFACADE.hpp - access point for communicating with the render engine
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 BACKEND_INTERFACE_ENGINEFACADE_H
#define BACKEND_INTERFACE_ENGINEFACADE_H
#include "lumiera/subsys.hpp"
namespace backend {
/******************************************************************
* Interface to the backend layer (render engine subsystem):
* Global access point for starting the render engine subsystem and
* for defining the public interface(s) for talking with the engine.
*
* While the engine is partially implemented relying on Proc-Layer
* operations, the general access point and the playback/render
* controller is considered part of the backend. This results in
* a "W"-shaped control flow: from GUI to backend to proc to
* backend, feeding resulting data to output.
*
*/
struct EngineFacade
{
/** provide a descriptor for lumiera::AppState,
* wired accordingly to allow main to pull up and
* shut down the renderengine. */
static lumiera::Subsys& getDescriptor();
//////////////////TODO: define the global access interface for the engine
//////////////////TODO: provide a function for accessing this interface
};
} // namespace backend
#endif

View file

@ -24,23 +24,30 @@
#include "backend/file.h"
#include "backend/filehandlecache.h"
#include "backend/filedescriptor.h"
#include <limits.h>
#include <unistd.h>
NOBUG_DEFINE_FLAG_PARENT (file, file_all);
LUMIERA_ERROR_DEFINE(FILE_CHANGED, "File changed unexpected");
LUMIERA_ERROR_DEFINE (FILE_CHANGED, "File changed unexpected");
LUMIERA_ERROR_DEFINE (FILE_NOCHUNKSIZE, "Chunksize not set");
LumieraFile
lumiera_file_init (LumieraFile self, const char* name, int flags)
{
TRACE (file);
if (!(self->descriptor = lumiera_filedescriptor_acquire (name, flags)))
return NULL;
self->name = lumiera_strndup (name, PATH_MAX);
if (self)
{
llist_init (&self->node);
if (!(self->descriptor = lumiera_filedescriptor_acquire (name, flags, &self->node)))
return NULL;
self->name = lumiera_strndup (name, PATH_MAX);
}
return self;
}
@ -49,7 +56,8 @@ LumieraFile
lumiera_file_destroy (LumieraFile self)
{
TRACE (file);
lumiera_filedescriptor_release (self->descriptor);
lumiera_filedescriptor_release (self->descriptor, self->name, &self->node);
lumiera_free (self->name);
return self;
}
@ -60,7 +68,13 @@ lumiera_file_new (const char* name, int flags)
{
TRACE (file);
LumieraFile self = lumiera_malloc (sizeof (lumiera_file));
return lumiera_file_init (self, name, flags);
if (!lumiera_file_init (self, name, flags))
{
lumiera_free (self);
self = NULL;
}
return self;
}
void
@ -79,42 +93,7 @@ lumiera_file_handle_acquire (LumieraFile self)
REQUIRE (self->descriptor);
REQUIRE (lumiera_fhcache);
LUMIERA_MUTEX_SECTION (file, &self->descriptor->lock)
{
if (!self->descriptor->handle)
/* no handle yet, get a new one */
lumiera_filehandlecache_handle_acquire (lumiera_fhcache, self->descriptor);
else
lumiera_filehandlecache_checkout (lumiera_fhcache, self->descriptor->handle);
if (self->descriptor->handle->fd == -1)
{
int fd;
fd = open (self->name, self->descriptor->flags & LUMIERA_FILE_MASK);
if (fd == -1)
{
LUMIERA_ERROR_SET (file, ERRNO);
}
else
{
struct stat st;
if (fstat (fd, &st) == -1)
{
close (fd);
LUMIERA_ERROR_SET (file, ERRNO);
}
else if (self->descriptor->stat.st_dev != st.st_dev || self->descriptor->stat.st_ino != st.st_ino)
{
close (fd);
/* Woops this is not the file we expected to use */
LUMIERA_ERROR_SET (file, FILE_CHANGED);
}
}
self->descriptor->handle->fd = fd;
}
}
return self->descriptor->handle->fd;
return lumiera_filedescriptor_handle_acquire (self->descriptor);
}
@ -122,9 +101,36 @@ void
lumiera_file_handle_release (LumieraFile self)
{
TRACE (file);
REQUIRE (self);
REQUIRE (self->descriptor);
REQUIRE (lumiera_fhcache);
LUMIERA_MUTEX_SECTION (file, &self->descriptor->lock)
{
lumiera_filehandlecache_checkin (lumiera_fhcache, self->descriptor->handle);
}
return lumiera_filedescriptor_handle_release (self->descriptor);
}
size_t
lumiera_file_chunksize_set (LumieraFile self, size_t chunksize)
{
if (chunksize && !self->descriptor->mmapings)
self->descriptor->mmapings = lumiera_mmapings_new (self, chunksize);
return self->descriptor->mmapings->chunksize;
}
size_t
lumiera_file_chunksize_get (LumieraFile self)
{
return self->descriptor->mmapings->chunksize;
}
LumieraMMapings
lumiera_file_mmapings (LumieraFile self)
{
if (!self->descriptor->mmapings)
LUMIERA_ERROR_SET (file, FILE_NOCHUNKSIZE);
return self->descriptor->mmapings;
}

View file

@ -30,6 +30,7 @@
NOBUG_DECLARE_FLAG (file);
LUMIERA_ERROR_DECLARE(FILE_CHANGED);
LUMIERA_ERROR_DECLARE(FILE_NOCHUNKSIZE);
/**
* @file
@ -47,9 +48,17 @@ typedef struct lumiera_file_struct lumiera_file;
typedef lumiera_file* LumieraFile;
#include "backend/filehandle.h"
#include "backend/filedescriptor.h"
#include "backend/filehandle.h"
#include "backend/mmapings.h"
/**
* File modes:
* LUMIERA_FILE_READONLY existing file for reading only
* LUMIERA_FILE_READWRITE existing file for reading and writing
* LUMIERA_FILE_CREATE non-existing file for reading and writing
* LUMIERA_FILE_RECREATE remove and recreated existing, file for reading and writing
*/
#define LUMIERA_FILE_READONLY (O_RDONLY | O_LARGEFILE | O_NOATIME)
#define LUMIERA_FILE_READWRITE (O_RDWR | O_LARGEFILE | O_NOATIME)
#define LUMIERA_FILE_CREATE (O_RDWR | O_LARGEFILE | O_NOATIME | O_CREAT | O_EXCL)
@ -60,38 +69,46 @@ typedef lumiera_file* LumieraFile;
struct lumiera_file_struct
{
/* all files of one descriptor */
llist node;
char* name;
LumieraFiledescriptor descriptor;
};
/**
* Initialize a file structure.
* @param self pointer to the file structure
* @param name filename
* @param flags open flags
* @return self
* @return self or NULL in case of an error
*/
LumieraFile
lumiera_file_init (LumieraFile self, const char* name, int flags);
/**
* Destroy a file structure.
* frees all associated resources, releases the filedescriptor etc.
* @param self file structure to be destroyed
* @param chunksize allocation/mmaping granularity, must be 2's exponent of pagesize
* only used at the first access to a file and ignored for subsequnet accesses
* @return self
*/
LumieraFile
lumiera_file_destroy (LumieraFile self);
/**
* Allocate a new file structure.
* @param name filename
* @param flags open flags
* @return new file structure
* @return new file structure or NULL in case of an error
*/
LumieraFile
lumiera_file_new (const char* name, int flags);
/**
* Frees a file structure.
* @param self file structure to be freed
@ -99,6 +116,7 @@ lumiera_file_new (const char* name, int flags);
void
lumiera_file_delete (LumieraFile self);
/**
* Get a POSIX filehandle for a file.
* Filehandles are opened on demand and must be acquired for use.
@ -112,6 +130,7 @@ lumiera_file_delete (LumieraFile self);
int
lumiera_file_handle_acquire (LumieraFile self);
/**
* Put filehandle back into cache aging.
* @param self file which handle to be released
@ -119,5 +138,33 @@ lumiera_file_handle_acquire (LumieraFile self);
void
lumiera_file_handle_release (LumieraFile self);
/**
* Query the underlying mmapings object from a file
* The MMapings only exists after a chunksize got set with lumiera_file_chunksize_set()
* @param self the file to query
* @return Handle to the MMapings object or NULL on error (setting the error state)
*/
LumieraMMapings
lumiera_file_mmapings (LumieraFile self);
/**
* Set the chunksize for mapping operations
* @param chunksize allocation/mmaping granularity, must be 2's exponent of pagesize
* only used at the first access to a file and ignored for subsequent accesses
* @return the effective chunksize used for the file
*/
size_t
lumiera_file_chunksize_set (LumieraFile self, size_t chunksize);
/**
* Get the chunksize for mapping operations
* @return the effective chunksize used for the file
*/
size_t
lumiera_file_chunksize_get (LumieraFile self);
#endif

View file

@ -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 NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER};
static lumiera_mutex registry_mutex;
static int
@ -73,7 +73,8 @@ cmp_fn (const void* keya, const void* keyb)
static void
delete_fn (PSplaynode node)
{
lumiera_filedescriptor_delete ((LumieraFiledescriptor) node);
TODO ("figure name out? or is the handle here always closed");
lumiera_filedescriptor_delete ((LumieraFiledescriptor) node, NULL);
}
@ -96,10 +97,7 @@ lumiera_filedescriptor_registry_init (void)
if (!registry)
LUMIERA_DIE (NO_MEMORY);
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", &registry, registry_mutex.rh);
lumiera_mutex_init (&registry_mutex, "filedescriptor_registry", &NOBUG_FLAG (filedescriptor));
}
void
@ -108,9 +106,7 @@ lumiera_filedescriptor_registry_destroy (void)
TRACE (filedescriptor);
REQUIRE (!psplay_nelements (registry));
RESOURCE_FORGET (filedescriptor, registry_mutex.rh);
TODO ("LumieraMutex lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag);");
lumiera_mutex_destroy (&registry_mutex, &NOBUG_FLAG (filedescriptor));
if (registry)
psplay_destroy (registry);
@ -119,10 +115,11 @@ lumiera_filedescriptor_registry_destroy (void)
LumieraFiledescriptor
lumiera_filedescriptor_acquire (const char* name, int flags)
lumiera_filedescriptor_acquire (const char* name, int flags, LList filenode)
{
TRACE (filedescriptor, "%s", name);
REQUIRE (registry, "not initialized");
REQUIRE (llist_is_empty (filenode));
LumieraFiledescriptor dest = NULL;
@ -135,6 +132,7 @@ lumiera_filedescriptor_acquire (const char* name, int flags)
{
if (errno == ENOENT && flags&O_CREAT)
{
errno = 0;
char* dir = lumiera_tmpbuf_strndup (name, PATH_MAX);
char* slash = dir;
while ((slash = strchr (slash+1, '/')))
@ -150,7 +148,8 @@ lumiera_filedescriptor_acquire (const char* name, int flags)
}
int fd;
INFO (filedescriptor, "try creating file: %s", name);
fd = creat (name, 0777);
TODO ("creat mode from config");
fd = creat (name, 0666);
if (fd == -1)
{
LUMIERA_ERROR_SET (filedescriptor, ERRNO);
@ -171,19 +170,14 @@ lumiera_filedescriptor_acquire (const char* name, int flags)
if (!dest)
{
TRACE (filedescriptor, "Descriptor not found");
dest = lumiera_filedescriptor_new (&fdesc);
if (!dest)
goto error;
psplay_insert (registry, &dest->node, 100);
}
else
{
TRACE (filedescriptor, "Descriptor already existing");
++dest->refcount;
}
llist_insert_head (&dest->files, filenode);
error: ;
}
@ -192,11 +186,78 @@ lumiera_filedescriptor_acquire (const char* name, int flags)
void
lumiera_filedescriptor_release (LumieraFiledescriptor self)
lumiera_filedescriptor_release (LumieraFiledescriptor self, const char* name, LList filenode)
{
TRACE (filedescriptor, "%p", self);
if (!--self->refcount)
lumiera_filedescriptor_delete (self);
TRACE (filedescriptor);
if (filenode)
LUMIERA_MUTEX_SECTION (filedescriptor, &self->lock)
{
REQUIRE (llist_is_member (&self->files, filenode));
llist_unlink (filenode);
}
if (llist_is_empty (&self->files))
lumiera_filedescriptor_delete (self, name);
}
int
lumiera_filedescriptor_handle_acquire (LumieraFiledescriptor self)
{
TRACE (filedescriptor);
int fd = -1;
LUMIERA_MUTEX_SECTION (filedescriptor, &self->lock)
{
if (!self->handle)
/* no handle yet, get a new one */
lumiera_filehandlecache_handle_acquire (lumiera_fhcache, self);
else
lumiera_filehandlecache_checkout (lumiera_fhcache, self->handle);
fd = lumiera_filehandle_handle (self->handle);
}
return fd;
}
void
lumiera_filedescriptor_handle_release (LumieraFiledescriptor self)
{
TRACE (filedescriptor);
REQUIRE (self->handle);
LUMIERA_MUTEX_SECTION (filedescriptor, &self->lock)
lumiera_filehandlecache_checkin (lumiera_fhcache, self->handle);
}
const char*
lumiera_filedescriptor_name (LumieraFiledescriptor self)
{
REQUIRE (!llist_is_empty (&self->files));
return ((LumieraFile)(llist_head (&self->files)))->name;
}
int
lumiera_filedescriptor_flags (LumieraFiledescriptor self)
{
return self->flags;
}
int
lumiera_filedescriptor_samestat (LumieraFiledescriptor self, struct stat* stat)
{
if (self->stat.st_dev == stat->st_dev && self->stat.st_ino == stat->st_ino)
return 1;
return 0;
}
@ -209,9 +270,11 @@ lumiera_filedescriptor_new (LumieraFiledescriptor template)
psplaynode_init (&self->node);
self->stat = template->stat;
self->realsize = template->stat.st_size;
self->flags = template->flags;
self->refcount = 1;
self->handle = 0;
self->handle = NULL;
self->mmapings = NULL;
llist_init (&self->files);
lumiera_mutex_init (&self->lock, "filedescriptor", &NOBUG_FLAG (filedescriptor));
@ -220,18 +283,27 @@ lumiera_filedescriptor_new (LumieraFiledescriptor template)
void
lumiera_filedescriptor_delete (LumieraFiledescriptor self)
lumiera_filedescriptor_delete (LumieraFiledescriptor self, const char* name)
{
TRACE (filedescriptor, "%p", self);
TRACE (filedescriptor, "%p %s", self, name);
LUMIERA_MUTEX_SECTION (filedescriptor, &registry_mutex)
{
REQUIRE (self->refcount == 0);
REQUIRE (llist_is_empty (&self->files));
psplay_remove (registry, &self->node);
TODO ("destruct other members (WIP)");
if (self->handle && name && ((self->flags & O_RDWR) == O_RDWR))
{
TRACE (filedescriptor, "truncate %s to %lld", name, self->realsize);
lumiera_filehandlecache_checkout (lumiera_fhcache, self->handle);
ftruncate (lumiera_filehandle_handle (self->handle), self->realsize);
lumiera_filehandlecache_checkin (lumiera_fhcache, self->handle);
}
lumiera_mmapings_delete (self->mmapings);
TODO ("release filehandle");

View file

@ -24,6 +24,7 @@
#include "lib/mutex.h"
#include "lib/psplay.h"
#include "lib/llist.h"
#include <sys/types.h>
@ -36,6 +37,7 @@ typedef lumiera_filedescriptor* LumieraFiledescriptor;
#include "backend/filehandle.h"
#include "backend/file.h"
#include "backend/mmapings.h"
/**
* @file
@ -43,20 +45,34 @@ typedef lumiera_filedescriptor* LumieraFiledescriptor;
* Filedescriptors are the underlying working horse in accessing files.
* All information associated with managing a file is kept here.
*/
struct lumiera_filedescriptor_struct
{
psplaynode node; /* node for the lookup tree */
struct stat stat; /* create after first open, maintained metadata */
int flags; /* open flags, must be masked for reopen */
lumiera_mutex lock; /* locks operations on this file descriptor */
unsigned refcount; /* reference counter, all users sans registry */
/** node for the lookup tree */
psplaynode node;
/** create after first open, maintained metadata */
struct stat stat;
/**
* files which are written are rounded up to the next chunk boundary
* by the mmaping backend and will be ftruncated to the realsize on close.
*/
off_t realsize;
/** open flags, must be masked for reopen */
int flags;
/** locks operations on this file descriptor */
lumiera_mutex lock;
/** Associated posix filehandle */
LumieraFilehandle handle;
//LumieraFileMap mappings;
//LumieraWriteBuffer writebuffer;
/** established memory mappings */
LumieraMMapings mmapings;
/** list of all attached 'file' structures, that are the names of the files */
llist files;
};
/**
@ -83,16 +99,31 @@ lumiera_filedescriptor_registry_destroy (void);
* @return descriptor on success or NULL on error
*/
LumieraFiledescriptor
lumiera_filedescriptor_acquire (const char* name, int flags);
lumiera_filedescriptor_acquire (const char* name, int flags, LList filenode);
/**
* Release a filedescriptor.
* @param self filedescriptor to be released
* @param file the file struct which initiated the release
*/
void
lumiera_filedescriptor_release (LumieraFiledescriptor self);
lumiera_filedescriptor_release (LumieraFiledescriptor self, const char* name, LList filenode);
int
lumiera_filedescriptor_handle_acquire (LumieraFiledescriptor self);
void
lumiera_filedescriptor_handle_release (LumieraFiledescriptor self);
const char*
lumiera_filedescriptor_name (LumieraFiledescriptor self);
int
lumiera_filedescriptor_flags (LumieraFiledescriptor self);
int
lumiera_filedescriptor_samestat (LumieraFiledescriptor self, struct stat* stat);
/**
* Allocate a new filedescriptor cloned from a template
@ -108,6 +139,6 @@ lumiera_filedescriptor_new (LumieraFiledescriptor template);
* @param self the filedescriptor to be deleted
*/
void
lumiera_filedescriptor_delete (LumieraFiledescriptor self);
lumiera_filedescriptor_delete (LumieraFiledescriptor self, const char* name);
#endif

View file

@ -28,20 +28,26 @@
#include <unistd.h>
NOBUG_DEFINE_FLAG_PARENT (filehandle, file_all);
LumieraFilehandle
lumiera_filehandle_init (LumieraFilehandle self, LumieraFiledescriptor desc)
{
TRACE (filehandle, "%p", self);
if (self)
{
llist_init (&self->cachenode);
self->fd = -1;
self->use_cnt = 1;
self->descriptor = desc;
}
return self;
}
LumieraFilehandle
lumiera_filehandle_new ()
lumiera_filehandle_new (LumieraFiledescriptor desc)
{
LumieraFilehandle self = lumiera_malloc (sizeof (lumiera_filehandle));
TRACE (filehandle, "%p", self);
llist_init (&self->cachenode);
self->fd = -1;
self->use_cnt = 1;
self->descriptor = NULL;
return self;
LumieraFilehandle self = lumiera_malloc (sizeof (*self));
return lumiera_filehandle_init (self, desc);
}
@ -55,8 +61,6 @@ lumiera_filehandle_destroy_node (LList node)
if (self->fd >= 0)
close (self->fd);
self->fd = -1;
self->descriptor = NULL;
return self;
}
@ -68,3 +72,37 @@ lumiera_filehandle_get (LumieraFilehandle self)
return -1;
}
int
lumiera_filehandle_handle (LumieraFilehandle self)
{
TRACE (filehandle);
int fd = -1;
if (self->fd == -1)
{
fd = open (lumiera_filedescriptor_name (self->descriptor), lumiera_filedescriptor_flags (self->descriptor) & LUMIERA_FILE_MASK);
if (fd == -1)
{
LUMIERA_ERROR_SET (filehandle, ERRNO);
}
else
{
struct stat st;
if (fstat (fd, &st) == -1)
{
close (fd);
LUMIERA_ERROR_SET (filehandle, ERRNO);
}
else if (!lumiera_filedescriptor_samestat (self->descriptor, &st))
{
close (fd);
/* Woops this is not the file we expected to use */
LUMIERA_ERROR_SET (filehandle, FILE_CHANGED);
}
}
self->fd = fd;
}
return self->fd;
}

View file

@ -29,12 +29,15 @@ typedef lumiera_filehandle* LumieraFilehandle;
#include "backend/filedescriptor.h"
NOBUG_DECLARE_FLAG (filehandle);
/**
* @file
* Filehandles.
* Filehandles manage the underlying POSIX filehandle for a filedescriptor.
* Since we want to support handling of more files than POSIX filehandles are available on a common system
* the filehandles are opened, cached and closed on demand, see 'filehandlecache'.
* Access to filehandles is locked from elsewhere (filedescriptor, filehandlecache)
*/
@ -50,11 +53,21 @@ struct lumiera_filehandle_struct
};
/**
* Allocate a new filehandle structure.
* Initialize filehandle structure.
* @param self filehandle sttructure to be initialized
* @param descriptor on which this filehandle will be attached
* @return new filehandle structure
*/
LumieraFilehandle
lumiera_filehandle_new ();
lumiera_filehandle_init (LumieraFilehandle self, LumieraFiledescriptor descriptor);
/**
* Allocate a new filehandle structure.
* @param descriptor on which this filehandle will be attached
* @return new filehandle structure
*/
LumieraFilehandle
lumiera_filehandle_new (LumieraFiledescriptor descriptor);
/**
@ -66,4 +79,8 @@ lumiera_filehandle_new ();
void*
lumiera_filehandle_destroy_node (LList node);
int
lumiera_filehandle_handle (LumieraFilehandle self);
#endif

View file

@ -74,6 +74,7 @@ lumiera_filehandlecache_handle_acquire (LumieraFilehandlecache self, LumieraFile
{
/* pop a filehandle from cache */
ret = lumiera_mrucache_pop (&self->cache);
ret = lumiera_filehandle_init (lumiera_mrucache_pop (&self->cache), desc);
if (self->available < 0)
/* try to free overallocated filehandles */
self->available -= self->available + lumiera_mrucache_age (&self->cache, -self->available);
@ -81,14 +82,13 @@ lumiera_filehandlecache_handle_acquire (LumieraFilehandlecache self, LumieraFile
else
{
/* allocate new filehandle if we are below the limit or no cached handles are available (overallocating) */
ret = lumiera_filehandle_new ();
NOTICE (filehandlecache, "overallocating filehandle");
ret = lumiera_filehandle_new (desc);
if (!ret)
LUMIERA_ERROR_SET (filehandlecache, FILEHANDLECACHE_NOHANDLE);
else
--self->available;
}
ret->use_cnt = 1;
ret->descriptor = desc;
desc->handle = ret;
++self->checked_out;
}
@ -116,6 +116,7 @@ lumiera_filehandlecache_checkout (LumieraFilehandlecache self, LumieraFilehandle
return handle;
}
void
lumiera_filehandlecache_checkin (LumieraFilehandlecache self, LumieraFilehandle handle)
{

View file

@ -78,14 +78,6 @@ lumiera_filehandlecache_delete (void);
LumieraFilehandle
lumiera_filehandlecache_handle_acquire (LumieraFilehandlecache self, LumieraFiledescriptor desc);
/**
* Add filehande back to cache, the filehandle becomes subject of aging.
* @param self pointer to the cache
* @param handle filehandle to be put back
*/
void
lumiera_filehandlecache_add_filehandle (LumieraFilehandlecache self, LumieraFilehandle handle);
/**
* Remove a filehandle from cache aging
* Filehandles which are subject of cache aging must be checked out before they can be used.

View file

@ -26,7 +26,7 @@
#include "common/singleton.hpp"
#include "common/error.hpp"
#include "include/error.hpp"

271
src/backend/mmap.c Normal file
View file

@ -0,0 +1,271 @@
/*
mmap.c - memory mapped acces to files
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/safeclib.h"
#include "backend/mmap.h"
#include "backend/mmapcache.h"
#include "lumiera/config.h"
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
/**
* @file
*
*/
NOBUG_DEFINE_FLAG_PARENT (mmap_all, backend);
NOBUG_DEFINE_FLAG_PARENT (mmap, mmap_all);
LUMIERA_ERROR_DEFINE (MMAP_NWRITE, "Backing file not writeable");
LUMIERA_ERROR_DEFINE (MMAP_SPACE, "Address space exhausted");
/**
* global mmap registry/cache
*
*/
LumieraMMap
lumiera_mmap_init (LumieraMMap self, LumieraFile file, off_t start, size_t size)
{
TRACE (mmap);
REQUIRE (self);
REQUIRE (file);
REQUIRE (start >= 0);
REQUIRE (size);
static int once = 0;
if (!once)
{
once = 1;
/**
* default size for the mmaping window
* 128MB on 32 bit arch
* 2GB on 64 bit arch
*/
#if SIZE_MAX <= 4294967295U
lumiera_config_setdefault ("backend.mmap.window_size = 134217728");
#else
lumiera_config_setdefault ("backend.mmap.window_size = 2147483648");
#endif
}
long long mmap_window_size = 0;
lumiera_config_number_get ("backend.mmap.window_size", &mmap_window_size);
LumieraFiledescriptor descriptor = file->descriptor;
int fd = lumiera_file_handle_acquire (file);
TRACE (mmap, "got fd %d", fd);
if (fd == -1)
goto efile;
void* addr = (void*)-1;
off_t begin = 0;
size_t length = 0;
size_t chunksize = lumiera_file_chunksize_get (file);
/**
* Maintaining the right[tm] mmaping size is a bit tricky:
* - We have the default mmap_window_size which will be backed off when address space gets exhausted
* - When a biggier size is requested we have to fullfill it
* - The last mmaped chunk of a file can be as small as possible when the file is readonly
* - When the file is writeable, the last chunk should be rounded up to chunksize
* - All boundaries will be aligned up/down to chunk boundaries
* - Requests beyond the file end must ftruncate and map additional pages
* - Create the 'refmap' which contains a refounter per chunk
**/
/**
* Recovering address space strategies:
* mmap() will fail when too much memory got mmaped after some time which is then
* recovered in the following way
* 1. create a new mmap while the cachelimit is not reached.
* 2. All unused mmaps are kept in a mrucache, drop the oldest one.
* mmap() still fails..
* 3.a When the intented mmaping size is the same as mmap_window_size then reduce (/2) the window size and retry.
* 3.b When the intented mmaping size was biggier than mmap_window_size then free more mmaps from the cache.
* 4 When the cache is empty (that means all mmaps in use), scan the mmaps in use if they can be reduced
* mmap_window_size is already reduced now (half of refmap free from either end)
**/
enum {
FIRST_TRY,
DROP_FROM_CACHE,
REDUCE_WINDOW,
REDUCE_IN_USE,
GIVE_UP
} strategy = FIRST_TRY;
while (addr == (void*)-1)
{
TODO ("check if current mmaped size exceeds configured as_size (as_size be smaller than retrieved from getrlimit())");
switch (strategy++)
{
case FIRST_TRY:
TRACE (mmap, "FIRST_TRY");
/* align begin and end to chunk boundaries */
begin = start & ~(chunksize-1);
length = ((start+size+chunksize-1) & ~(chunksize-1)) - begin;
if (begin+(off_t)length > descriptor->stat.st_size)
{
/* request past the end */
if ((descriptor->flags & O_ACCMODE) == O_RDWR)
{
/* extend file (writeable) */
if (ftruncate (fd, begin+length) == -1)
{
LUMIERA_ERROR_SET (mmap, ERRNO);
goto etruncate;
};
descriptor->stat.st_size = begin+length;
descriptor->realsize = start+size;
}
}
else if (length < (size_t)mmap_window_size)
length = mmap_window_size;
if ((descriptor->flags & O_ACCMODE) == O_RDONLY)
{
/* The last mmaped chunk of a file can be as small as possible when the file is readonly */
length = start+size - begin;
}
break;
case DROP_FROM_CACHE:
TRACE (mmap, "drop a mapping from cache");
UNIMPLEMENTED ("mmap cache drop");
break;
case REDUCE_WINDOW:
NOTICE (mmap, "mmaping window reduced to NN MB");
UNIMPLEMENTED ("mmap window reduce");
break;
case REDUCE_IN_USE:
NOTICE (mmap, "reduce mmapings in use");
UNIMPLEMENTED ("mmapings in use reduce");
break;
case GIVE_UP:
LUMIERA_ERROR_SET (mmap, MMAP_SPACE);
goto espace;
}
addr = mmap (NULL,
length,
(descriptor->flags & O_ACCMODE) == O_RDONLY ? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED,
fd,
begin);
INFO_IF (addr==(void*)-1, mmap, "mmap failed %s", strerror (errno));
ENSURE (errno == 0 || errno == ENOMEM, "unexpected mmap error %s", strerror (errno));
}
llist_init (&self->cachenode);
llist_init (&self->searchnode);
self->start = begin;
self->size = length;
self->address = addr;
self->refmap = lumiera_calloc ((length-1)/chunksize+1, sizeof (unsigned short));
self->refcnt = 1;
lumiera_mmapcache_announce (lumiera_mcache, self);
lumiera_file_handle_release (file);
return self;
espace:
etruncate:
efile:
lumiera_file_handle_release (file);
lumiera_free (self);
return NULL;
}
LumieraMMap
lumiera_mmap_new (LumieraFile file, off_t start, size_t size)
{
TRACE (mmap);
LumieraMMap self = lumiera_mmapcache_mmap_acquire (lumiera_mcache);
if (lumiera_mmap_init (self, file, start, size))
return self;
else
{
lumiera_free (self);
return NULL;
}
}
void
lumiera_mmap_delete (LumieraMMap self)
{
TRACE (mmap);
if (self)
{
lumiera_mmapcache_forget (lumiera_mcache, self);
/* The matching mappings->lock must be hold or being unrelevant (mappings destructor) here, we can't asset this from here, good luck */
llist_unlink (&self->searchnode);
TRACE (mmap, "unmap at %p with size %zd", self->address, self->size);
munmap (self->address, self->size);
lumiera_free (self->refmap);
lumiera_free (self);
}
}
void*
lumiera_mmap_destroy_node (LList node)
{
TRACE (mmap);
REQUIRE (llist_is_empty (node));
LumieraMMap self = (LumieraMMap)node;
lumiera_mmapcache_forget (lumiera_mcache, self);
llist_unlink (&self->searchnode); TODO ("must lock mmapings -> deadlock");
munmap (self->address, self->size);
lumiera_free (self->refmap);
return self;
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -29,6 +29,7 @@ typedef struct lumiera_mmap_struct lumiera_mmap;
typedef lumiera_mmap* LumieraMMap;
#include "backend/file.h"
#include "backend/filedescriptor.h"
@ -37,6 +38,7 @@ typedef lumiera_mmap* LumieraMMap;
NOBUG_DECLARE_FLAG (mmap);
/**
* @file
* MMap objects cover a memory maped range in a file
@ -53,31 +55,44 @@ struct lumiera_mmap_struct
/** used for the mrucache when checked in the cache OR for attaching owners when checked out **/
llist cachenode;
/** all mmaps of a file are chained in this list, used to find ranges **/
/** all mmaps of a filedescriptor are chained in this list, used to find ranges **/
llist searchnode;
off_t start;
size_t size;
void* address;
/** array with refcounters per page **/
unsigned short* refmap;
/** accumulated references, this is 0 when checked into the cache **/
unsigned long refcnt;
/** 0 when this mmap is in cache, else the count of attached owners **/
unsigned use_cnt;
//RESOURCE_HANDLE (rh);
/** array with refcounters per chunk **/
unsigned short* refmap; // TODO flexible array?
};
LumieraMMap
lumiera_mmap_init (LumieraMMap self, LumieraFile file, LList acquirer, off_t start, size_t size, size_t chunksize);
lumiera_mmap_init (LumieraMMap self, LumieraFile file, off_t start, size_t size);
LumieraMMap
lumiera_mmap_new (LumieraFile file, LList acquirer, off_t start, size_t size, size_t chunksize);
lumiera_mmap_new (LumieraFile file, off_t start, size_t size);
static inline void*
lumiera_mmap_address (LumieraMMap self)
{
return self->address;
}
void
lumiera_mmap_delete (LumieraMMap self);
void*
lumiera_mmap_destroy_node (LList node);
#endif
/*
// Local Variables:

171
src/backend/mmapcache.c Normal file
View file

@ -0,0 +1,171 @@
/*
mmapcache.c - handle aging of mmap objects
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/safeclib.h"
#include "backend/mmapcache.h"
/**
* @file
*
*/
NOBUG_DEFINE_FLAG_PARENT (mmapcache, mmap_all);
LumieraMMapcache lumiera_mcache = NULL;
void
lumiera_mmapcache_new (size_t limit)
{
TRACE (mmapcache);
lumiera_mcache = lumiera_malloc (sizeof (*lumiera_mcache));
lumiera_mrucache_init (&lumiera_mcache->cache, lumiera_mmap_destroy_node);
lumiera_mcache->limit = limit;
lumiera_mcache->total = 0;
lumiera_mcache->cached = 0;
lumiera_mutex_init (&lumiera_mcache->lock, "mmapcache", &NOBUG_FLAG (mmapcache));
}
void
lumiera_mmapcache_delete (void)
{
TRACE (mmapcache);
if (lumiera_mcache)
{
REQUIRE (lumiera_mcache->total == lumiera_mcache->cached, "MMaps still checked out at shutdown");
lumiera_mrucache_destroy (&lumiera_mcache->cache);
lumiera_mutex_destroy (&lumiera_mcache->lock, &NOBUG_FLAG (mmapcache));
free (lumiera_mcache);
lumiera_mcache = NULL;
}
}
void*
lumiera_mmapcache_mmap_acquire (LumieraMMapcache self)
{
TRACE (mmapcache);
void* map = NULL;
LUMIERA_MUTEX_SECTION (mmapcache, &self->lock)
{
map = lumiera_mrucache_pop (&self->cache);
}
if (!map)
{
map = lumiera_malloc (sizeof (*self));
TRACE (mmapcache, "allocated new mmap");
}
else
{
TRACE (mmapcache, "poped mmap from cache");
}
return map;
}
void
lumiera_mmapcache_announce (LumieraMMapcache self, LumieraMMap map)
{
TRACE (mmapcache);
LUMIERA_MUTEX_SECTION (mmapcache, &self->lock)
{
self->total += map->size;
}
}
void
lumiera_mmapcache_forget (LumieraMMapcache self, LumieraMMap map)
{
TRACE (mmapcache);
LUMIERA_MUTEX_SECTION (mmapcache, &self->lock)
{
if (!llist_is_empty (&map->cachenode))
{
TODO ("cached stats");
REQUIRE (llist_is_member (&self->cache.cache_list, &map->cachenode), "Map object not in cache");
llist_unlink (&map->cachenode);
}
self->total -= map->size;
}
}
#if 0
int
lumiera_mmapcache_age (LumieraMMapcache self)
{
TRACE (mmapcache);
int ret = 0;
LUMIERA_MUTEX_SECTION (mmapcache, &self->lock)
{
ret = lumiera_mrucache_age (&self->cache, 10); TODO ("age nelem == 20%(configureable) of the cache");
}
return ret;
}
#endif
LumieraMMap
lumiera_mmapcache_checkout (LumieraMMapcache self, LumieraMMap handle)
{
TRACE (mmapcache);
LUMIERA_MUTEX_SECTION (mmapcache, &self->lock)
{
TODO ("cached stats");
lumiera_mrucache_checkout (&self->cache, &handle->cachenode);
++handle->refcnt;
}
return handle;
}
void
lumiera_mmapcache_checkin (LumieraMMapcache self, LumieraMMap handle)
{
TRACE (mmapcache);
LUMIERA_MUTEX_SECTION (mmapcache, &self->lock)
{
TODO ("cached stats");
--handle->refcnt;
lumiera_mrucache_checkin (&self->cache, &handle->cachenode);
}
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -47,7 +47,6 @@ struct lumiera_mmapcache_struct
size_t total;
size_t cached;
lumiera_mutex lock;
RESOURCE_HANDLE (rh);
};
extern LumieraMMapcache lumiera_mcache;
@ -73,9 +72,9 @@ lumiera_mmapcache_delete (void);
* when mmaped_limit is reached, the oldest mmap object gets dropped else a new allocated object
* is returned
* @param self pointer to the cache
* @return the new mmap
* @return the new uninitialized mmap
*/
LumieraMMap
void*
lumiera_mmapcache_mmap_acquire (LumieraMMapcache self);
@ -91,8 +90,7 @@ lumiera_mmapcache_announce (LumieraMMapcache self, LumieraMMap map);
/**
* Remove a mmap object from the cache quotas.
* Update the statistics kept in the cache,
* called by mmap's destructor only
* Update the statistics kept in the cache, remove it from the cache.
* @param self pointer to the cache
* @param map object to be removed
*/

159
src/backend/mmapings.c Normal file
View file

@ -0,0 +1,159 @@
/*
mmapings.c - manage ranges of mmaped areas on a filedescriptor
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/mmapings.h"
#include "backend/mmapcache.h"
/**
* @file
*
*/
LumieraMMapings
lumiera_mmapings_init (LumieraMMapings self, LumieraFile file, size_t chunksize)
{
TRACE (mmapings);
REQUIRE (!file->descriptor->mmapings);
llist_init (&self->mmaps);
self->descriptor = file->descriptor;
self->chunksize = chunksize;
lumiera_mutex_init (&self->lock, "mmapings", &NOBUG_FLAG(mmapings));
return self;
}
LumieraMMapings
lumiera_mmapings_destroy (LumieraMMapings self)
{
TRACE (mmapings);
if (!self)
return NULL;
LLIST_WHILE_TAIL (&self->mmaps, node)
{
LumieraMMap mmap = LLIST_TO_STRUCTP (node, lumiera_mmap, searchnode);
lumiera_mmap_delete (mmap);
}
lumiera_mutex_destroy (&self->lock, &NOBUG_FLAG(mmapings));
return self;
}
LumieraMMapings
lumiera_mmapings_new (LumieraFile file, size_t chunksize)
{
LumieraMMapings self = lumiera_malloc (sizeof (*self));
return lumiera_mmapings_init (self, file, chunksize);
}
void
lumiera_mmapings_delete (LumieraMMapings self)
{
TRACE (mmapings);
free (lumiera_mmapings_destroy (self));
}
LumieraMMap
lumiera_mmapings_mmap_acquire (LumieraMMapings self, LumieraFile file, LList acquirer, off_t start, size_t size)
{
TRACE (mmapings);
LumieraMMap ret = NULL;
LUMIERA_MUTEX_SECTION (mmapings, &self->lock)
{
REQUIRE (llist_is_empty (acquirer));
/* find first matching mmap, crude way */
LLIST_FOREACH (&self->mmaps, node)
{
TODO ("improve this selection algorithm, choose mmaps by size, move mfu to head etc");
LumieraMMap mmap = LLIST_TO_STRUCTP (node, lumiera_mmap, searchnode);
if (mmap->size >= size && mmap->start <= start && mmap->start+mmap->size >= start+size)
{
ret = mmap;
break;
}
}
/* found? */
if (ret)
{
if (!ret->refcnt)
/* in cache, needs to me checked out */
lumiera_mmapcache_checkout (lumiera_mcache, ret);
}
else
{
/* create new mmap */
TRACE (mmapings, "mmap not found, creating", mmap);
ret = lumiera_mmap_new (file, start, size);
llist_insert_head (&self->mmaps, &ret->searchnode);
TODO ("sort search list?");
}
llist_insert_head (&ret->cachenode, acquirer);
}
return ret;
}
void
lumiera_mmapings_release_mmap (LumieraMMapings self, LList acquirer, LumieraMMap map)
{
TRACE (mmapings);
LUMIERA_MUTEX_SECTION (mmapings, &self->lock)
{
llist_unlink (acquirer);
if (llist_is_empty (&map->cachenode))
{
TRACE (mmapings, "checkin");
lumiera_mmapcache_checkin (lumiera_mcache, map);
}
}
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -30,13 +30,15 @@ typedef lumiera_mmapings* LumieraMMapings;
#include "backend/filedescriptor.h"
#include "backend/mmap.h"
#include "backend/file.h"
#include <nobug.h>
NOBUG_DECLARE_FLAG (mmapings);
/**
* @file
* Keeps all mmaped areas
* Manage the mmap objects of a file
*
*/
@ -45,9 +47,6 @@ struct lumiera_mmapings_struct
/** mmaped ranges are kept in an list sorted by the size of the mmaping, might be improved to a tree someday **/
llist mmaps;
/** sum of all mmaped areas, areas might be overlapping **/
// size_t vsz;
/**
* chunkssize is the smallest granularity which is used for mmapping files, it
* should reflect the intended file usage, that is 'pagesize' for small or non growing
@ -57,7 +56,6 @@ struct lumiera_mmapings_struct
LumieraFiledescriptor descriptor;
lumiera_mutex lock;
RESOURCE_HANDLE (rh);
};
/**

View file

@ -0,0 +1,84 @@
/*
NetNodeFacade - access point for maintaining a renderfarm node
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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/netnodefacade.hpp"
#include "common/singleton.hpp"
#include <string>
namespace backend {
using std::string;
using lumiera::Subsys;
class NetNodeSubsysDescriptor
: public Subsys
{
operator string () const { return "Renderfarm node"; }
bool
shouldStart (lumiera::Option&)
{
TODO ("determine, if render node service should be provided");
return false;
}
bool
start (lumiera::Option&, SigTerm termination)
{
UNIMPLEMENTED ("open a render node server port and register shutdown hook");
return false;
}
void
triggerShutdown () throw()
{
UNIMPLEMENTED ("initiate shutting down the render node");
}
bool
checkRunningState () throw()
{
//Lock guard (*this);
TODO ("implement detecting running state");
return false;
}
};
namespace {
lumiera::Singleton<NetNodeSubsysDescriptor> theDescriptor;
}
/** @internal intended for use by main(). */
Subsys&
NetNodeFacade::getDescriptor()
{
return theDescriptor();
}
} // namespace backend

View file

@ -0,0 +1,61 @@
/*
NETNODEFACADE.hpp - access point for maintaining a renderfarm node
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 BACKEND_INTERFACE_NETNODEFACADE_H
#define BACKEND_INTERFACE_NETNODEFACADE_H
#include "lumiera/subsys.hpp"
namespace backend {
/******************************************************************
* Interface to the backend layer (renderfarm node):
* Global access point for starting a server listening on a TCP port
* and accepting render tasks. Possibly such a server could also
* use the backend file/media access functions to provide a media
* data access service.
*
* @todo define the services provided by such a node.
*
*/
struct NetNodeFacade
{
/** provide a descriptor for lumiera::AppState,
* wired accordingly to allow main to start and stop
* a node server accepting render / file jobs via network. */
static lumiera::Subsys& getDescriptor();
//////////////////TODO: define the global access interface for a renderfarm node server
//////////////////TODO: provide a function for accessing this interface
};
} // namespace backend
#endif

View file

@ -0,0 +1,187 @@
/*
resourcecollector.c - manage/collect resources when they get short
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/llist.h"
#include "lib/mutex.h"
#include "lib/safeclib.h"
#include "resourcecollector.h"
#include <unistd.h>
NOBUG_DEFINE_FLAG_PARENT (resourcecollector, backend);
llist lumiera_resourcecollector_registry[LUMIERA_RESOURCE_END];
lumiera_mutex lumiera_resourcecollector_lock;
static pthread_once_t lumiera_resourcecollector_once = PTHREAD_ONCE_INIT;
struct lumiera_resourcehandler_struct
{
llist node;
lumiera_resource_handler_fn handler;
void* data;
};
static void
lumiera_resourcecollector_init_ (void)
{
NOBUG_INIT_FLAG (resourcecollector);
TRACE (resourcecollector);
for (int i = 0; i < LUMIERA_RESOURCE_END; ++i)
llist_init (&lumiera_resourcecollector_registry[i]);
lumiera_mutex_init (&lumiera_resourcecollector_lock, "resourcecollector", &NOBUG_FLAG(resourcecollector));
}
void
lumiera_resourcecollector_destroy (void)
{
TRACE (resourcecollector);
for (int i = 0; i < LUMIERA_RESOURCE_END; ++i)
LLIST_WHILE_HEAD (&lumiera_resourcecollector_registry[i], head)
lumiera_resourcehandler_unregister ((LumieraResourcehandler)head);
lumiera_mutex_destroy (&lumiera_resourcecollector_lock, &NOBUG_FLAG(resourcecollector));
}
int
lumiera_resourcecollector_run (enum lumiera_resource which, enum lumiera_resource_try* iteration, void* context)
{
TRACE (resourcecollector);
pthread_once (&lumiera_resourcecollector_once, lumiera_resourcecollector_init_);
LUMIERA_MUTEX_SECTION (resourcecollector, &lumiera_resourcecollector_lock)
{
for (enum lumiera_resource_try progress = LUMIERA_RESOURCE_NONE; progress < *iteration; ++*iteration)
{
if (*iteration < LUMIERA_RESOURCE_PANIC)
{
LLIST_FOREACH (&lumiera_resourcecollector_registry[which], node)
{
LumieraResourcehandler self = (LumieraResourcehandler) node;
progress = self->handler (*iteration, self->data, context);
if (*iteration < LUMIERA_RESOURCE_ALL)
{
if (progress >= *iteration)
{
llist_insert_next (node, &lumiera_resourcecollector_registry[which]);
break;
}
}
}
}
else
{
ERROR (resourcecollector, "PANIC, Not enough resources %d", which);
for (int i = 0; i < LUMIERA_RESOURCE_END; ++i)
LLIST_FOREACH (&lumiera_resourcecollector_registry[i], node)
{
LumieraResourcehandler self = (LumieraResourcehandler) node;
progress = self->handler (LUMIERA_RESOURCE_PANIC, self->data, NULL);
}
_exit (EXIT_FAILURE);
}
}
}
return 1;
}
LumieraResourcehandler
lumiera_resourcecollector_register_handler (enum lumiera_resource resource, lumiera_resource_handler_fn handler, void* data)
{
pthread_once (&lumiera_resourcecollector_once, lumiera_resourcecollector_init_);
TRACE (resourcecollector);
LumieraResourcehandler self = lumiera_malloc (sizeof (*self));
llist_init (&self->node);
self->handler = handler;
self->data = data;
LUMIERA_MUTEX_SECTION (resourcecollector, &lumiera_resourcecollector_lock)
{
llist_insert_tail (&lumiera_resourcecollector_registry[resource], &self->node);
}
return self;
}
void
lumiera_resourcehandler_unregister (LumieraResourcehandler self)
{
TRACE (resourcecollector);
if (self)
{
LUMIERA_MUTEX_SECTION (resourcecollector, &lumiera_resourcecollector_lock)
{
llist_unlink (&self->node);
self->handler (LUMIERA_RESOURCE_UNREGISTER, self->data, NULL);
}
lumiera_free (self);
}
}
LumieraResourcehandler
lumiera_resourcecollector_handler_find (enum lumiera_resource resource, lumiera_resource_handler_fn handler, void* data)
{
TRACE (resourcecollector);
LumieraResourcehandler self = NULL;
LUMIERA_MUTEX_SECTION (resourcecollector, &lumiera_resourcecollector_lock)
{
LLIST_FOREACH (&lumiera_resourcecollector_registry[resource], node)
{
self = (LumieraResourcehandler) node;
if (((LumieraResourcehandler)node)->handler == handler && ((LumieraResourcehandler)node)->data == data)
{
self = (LumieraResourcehandler)node;
break;
}
}
}
return self;
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -0,0 +1,169 @@
/*
resourcecollector.h - manage/collect resources when they get short
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_RESOURCECOLLECTOR_H
#define LUMIERA_RESOURCECOLLECTOR_H
#include <nobug.h>
NOBUG_DECLARE_FLAG (resourcecollector);
/**
* Resources known to the resource collector
*/
enum lumiera_resource
{
/** memory blocks, context is a pointer to the size_t required **/
LUMIERA_RESOURCE_MEMORY,
/** OS filehandles **/
LUMIERA_RESOURCE_FILEHANDLE,
/** mmaped regions **/
LUMIERA_RESOURCE_MMAP,
/** disk space for the storage area, context is a pointer to the filename indication the device **/
LUMIERA_RESOURCE_DISKSTORAGE,
/** disk bandwidth for the storage area, context is a pointer to the filename indication the device **/
LUMIERA_RESOURCE_STORAGEBANDWIDTH,
/** disk space for the caching area, context is a pointer to the filename indication the device **/
LUMIERA_RESOURCE_DISKCACHE,
/** disk bandwidth for the caching area, context is a pointer to the filename indication the device **/
LUMIERA_RESOURCE_CACHEBANDWIDTH,
LUMIERA_RESOURCE_END /* last entry */
};
/**
* Iteration indicator
* Resource collection works iteratively freeing more and more resources.
* Handlers do not need to obey the request and shall return LUMIERA_RESOURCE_NONE
* which will then continue with the next handler.
* This goes through all available handlers until one returns a higher or same value
* than the current iteration to indicate that it freed enough resources to continue the task.
* Then control is passed back to the calling loop which retries the resource allocation.
* LUMIERA_RESOURCE_PANIC is somewhat special since it will always call all registered handlers
* for all resources, not only the queried one and finally _exit() the application.
* The exact amounts of resources to be freed for ONE, SOME and MANY in intentionally
* kept vague the handlers are free to interpret this in some sensible way.
*/
enum lumiera_resource_try
{
/** No op, returned by a handler when it did nothing **/
LUMIERA_RESOURCE_NONE,
/** try to free one or really few of this resources **/
LUMIERA_RESOURCE_ONE,
/** try to free a small reasonable implementation defined amount of resources **/
LUMIERA_RESOURCE_SOME,
/** try to free a biggier implementation defined amount of resources **/
LUMIERA_RESOURCE_MANY,
/** free as much as possible **/
LUMIERA_RESOURCE_ALL,
/** die! **/
LUMIERA_RESOURCE_PANIC,
/** When a handler gets unregistered it wull be called with this value to give it a chance to clean up the user 'data' **/
LUMIERA_RESOURCE_UNREGISTER
};
/**
* The type for the resource collector handler functions.
* Handlers are always run with a global resourcecollector mutex locked, the user does not need to
* care about syncronization.
* @param itr the current iteration try in freeing resources
* @param data user supplied data at registration time for the handler
* @param context context pointer for this collection run, might be NULL (at least for UNREGISTER and PANIC)
* @return indication what the the handler really did (LUMIERA_RESOURCE_NONE when it didn't obey the request)
*/
typedef enum lumiera_resource_try (*lumiera_resource_handler_fn)(enum lumiera_resource_try itr, void* data, void* context);
typedef struct lumiera_resourcehandler_struct lumiera_resourcehandler;
typedef lumiera_resourcehandler* LumieraResourcehandler;
/**
* Destroy the resource collector registry.
* Unregisters and deletes all handlers.
* Note that there is no resourcecollector_init() function, initialization is automatic on first use.
*/
void
lumiera_resourcecollector_destroy (void);
/**
* Try to free resources.
*
* @param which The kind of resource to be acquired
* @param iteration a pointer to a local iterator, initialized with the start
* value for the loop
* @param context NULL or some context dependent data for the needed resource
* this is a pointer to a size_t for MEMORY and a pointer to a filename
* (to find out about the device) for STORAGE and CACHE resources
* @return either returns 1 or calls _exit()
*
* @example
* void* data;
* size_t size = 1000;
* enum lumiera_resource_try iteration = LUMIERA_RESOURCE_ONE;
* do {
* data = malloc (size);
* } while (!data && lumiera_resourcecollector_run (LUMIERA_RESOURCE_MEMORY, &iteration, &size));
*/
int
lumiera_resourcecollector_run (enum lumiera_resource which, enum lumiera_resource_try* iteration, void* context);
/**
* Registers a new collector handler
* @param resource resource for which this handler shall be registered
* @param handler pointer to the handler function
* @param data opaque user-data pointer which will be passed to the handler
* @return pointer to the internal handler structure. This can be used to unregister the handler.
*/
LumieraResourcehandler
lumiera_resourcecollector_register_handler (enum lumiera_resource resource, lumiera_resource_handler_fn handler, void* data);
/**
* Unregisters a collector handle
* Removes the handler from the registry and calls it once with LUMIERA_RESOURCE_UNREGISTER
* to give it a chance to free the user supplied data. Must not be called after lumiera_resourcecollector_destroy()
* @param self pointer to internal handler structure, obtained from register_handler() or handler_find(), might be NULL
*/
void
lumiera_resourcehandler_unregister (LumieraResourcehandler self);
/**
* Looks up a handler.
* Used to find a registered handler when the return value of register_handler() was unpractical to store.
* @param resource resource for which this handler was registered
* @param handler pointer to the handler function, same as used for registering
* @param data opaque user-data pointer, same as used for registering
* @return pointer to the internal handler structure or NULL if no handler was found
*/
LumieraResourcehandler
lumiera_resourcecollector_handler_find (enum lumiera_resource resource, lumiera_resource_handler_fn handler, void* data);
#endif
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -0,0 +1,85 @@
/*
ScriptRunnerFacade - access point for running a script within Lumiera application context
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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/scriptrunnerfacade.hpp"
#include "common/singleton.hpp"
#include <string>
namespace backend {
using std::string;
using lumiera::Subsys;
class ScriptRunnerSubsysDescriptor
: public Subsys
{
operator string () const { return "Script runner"; }
bool
shouldStart (lumiera::Option&)
{
TODO ("determine, if a script should be executed");
return false;
}
bool
start (lumiera::Option&, SigTerm termination)
{
UNIMPLEMENTED ("start the script as defined by the options and register script abort/exit hook");
return false;
}
void
triggerShutdown () throw()
{
UNIMPLEMENTED ("halt any running script");
}
bool
checkRunningState () throw()
{
//Lock guard (*this);
TODO ("implement detecting running state");
return false;
}
};
namespace {
lumiera::Singleton<ScriptRunnerSubsysDescriptor> theDescriptor;
}
/** @internal intended for use by main(). */
Subsys&
ScriptRunnerFacade::getDescriptor()
{
return theDescriptor();
}
} // namespace backend

View file

@ -0,0 +1,59 @@
/*
SCRIPTRUNNERFACADE.hpp - access point for running a script within Lumiera application context
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 BACKEND_INTERFACE_SCRIPTRUNNERFACADE_H
#define BACKEND_INTERFACE_SCRIPTRUNNERFACADE_H
#include "lumiera/subsys.hpp"
namespace backend {
/***********************************************************************
* Interface to the backend layer (script runner):
* Global access point for starting a script within Lumiera application
* context.
*
* @todo build the (LUA,C)-script runner.
*
*/
struct ScriptRunnerFacade
{
/** provide a descriptor for lumiera::AppState,
* wired accordingly to allow main to start a script and to
* (prematurely) abort a running script. */
static lumiera::Subsys& getDescriptor();
//////////////////TODO: define the access interface for starting a (LUA, C, ...)-script
//////////////////TODO: provide a function for accessing this interface
};
} // namespace backend
#endif

View file

@ -27,7 +27,6 @@ liblumicommon_a_SOURCES = \
$(liblumicommon_a_srcdir)/lumitime.cpp \
$(liblumicommon_a_srcdir)/util.cpp \
$(liblumicommon_a_srcdir)/visitor.cpp \
$(liblumicommon_a_srcdir)/cmdline.cpp \
$(liblumicommon_a_srcdir)/configrules.cpp \
$(liblumicommon_a_srcdir)/error.cpp \
$(liblumicommon_a_srcdir)/query.cpp \
@ -38,7 +37,6 @@ liblumicommon_a_SOURCES = \
noinst_HEADERS += \
$(liblumicommon_a_srcdir)/cmdline.hpp \
$(liblumicommon_a_srcdir)/factory.hpp \
$(liblumicommon_a_srcdir)/frameid.hpp \
$(liblumicommon_a_srcdir)/singleton.hpp \
@ -49,7 +47,6 @@ noinst_HEADERS += \
$(liblumicommon_a_srcdir)/visitordispatcher.hpp \
$(liblumicommon_a_srcdir)/visitorpolicies.hpp \
$(liblumicommon_a_srcdir)/configrules.hpp \
$(liblumicommon_a_srcdir)/error.hpp \
$(liblumicommon_a_srcdir)/multithread.hpp \
$(liblumicommon_a_srcdir)/p.hpp \
$(liblumicommon_a_srcdir)/query.hpp \

View file

@ -24,7 +24,7 @@
#include "common/configrules.hpp"
#include "common/query/mockconfigrules.hpp"
//#include "common/util.hpp"
#include "proc/nobugcfg.hpp"
#include "include/nobugcfg.h"
@ -40,14 +40,14 @@ namespace lumiera
} // namespace query
namespace
{
namespace {
/** type of the actual ConfigRules implementation to use */
singleton::UseSubclass<query::MockConfigRules> typeinfo;
}
/** Singleton factory instance, parametrized to actual impl. type. */
/** Singleton factory instance, parametrised to actual impl. type. */
SingletonSub<ConfigRules> ConfigRules::instance (typeinfo);

View file

@ -31,7 +31,7 @@
** preconfigured Map.
**
** Fully implementing this facility would require the participating objects to register capabilities
** they want to provide, together with functors carrying out the neccessary configuration steps.
** they want to provide, together with functors carrying out the necessary configuration steps.
** All details and consequences of this approach still have to be worked out...
**
** @note this is rather a scrapbook and in flux... don't take this code too literal!
@ -79,7 +79,7 @@ namespace lumiera
//
// stream(T, mpeg) :- type(T, track), type(P, pipe), resolve(P, stream(P,mpeg)), place_to(P, T).
//
// The type guard is inserted auomatically, while the predicate implementations for
// The type guard is inserted automatically, while the predicate implementations for
// find/1, make/1, stream/2, and place_to/2 are to be provided by the target types.
//
// As a example, the goal ":-retrieve(T, stream(T,mpeg))." would search a Track object, try to
@ -102,7 +102,7 @@ namespace lumiera
};
/**
* the "backside" interface towards the classes participating
* the "back side" interface towards the classes participating
* in the configuration system (the config system will be
* delivering instances of these classes for a given query).
* This one currently is just brainstorming. The idea is that
@ -127,7 +127,7 @@ namespace lumiera
};
/**
* the "frontside" interface: the Proc-Layer code can
* the "front side" interface: the Proc-Layer code can
* use this QueryHandler to retrieve instances of the
* type TY fulfilling the given Query. To start with,
* we use a mock implementation.
@ -167,7 +167,7 @@ namespace lumiera
* thus inheriting from the Handler classes for each type. In
* the (future) version using YAP Prolog, this will drive the
* generation and registration of the necessary predicate
* implementations for each concrete type, using the speicalisations
* implementations for each concrete type, using the specialisations
* given alongside with the types. For now it just serves to generate
* the necessary resolve(Query<TY>) virtual functions (implemented
* by MockConfigRules)

View file

@ -22,7 +22,7 @@
#include "common/error.hpp"
#include "include/error.hpp"
#include "common/util.hpp"
#include <exception>
@ -33,29 +33,33 @@ using util::isnil;
using std::exception;
namespace lumiera
{
namespace error
{
namespace lumiera {
namespace error {
/** the message shown to the user per default
* if an exception reaches one of the top-level
* catch clauses.
* @todo to be localized
* @todo to be localised
*/
inline const string default_usermsg (Error* exception_obj) throw()
inline const string
default_usermsg (Error* exception_obj) throw()
{
return string("Sorry, Lumiera encountered an internal error. (")
+ typeid(*exception_obj).name() + ")";
}
inline const char*
default_or_given (const char* id)
{
return id? id : LUMIERA_ERROR_STATE;
}
/* constants to be used as error IDs */
LUMIERA_ERROR_DEFINE (LOGIC , "internal logic broken");
LUMIERA_ERROR_DEFINE (FATAL , "floundered");
LUMIERA_ERROR_DEFINE (CONFIG , "misconfiguration");
LUMIERA_ERROR_DEFINE (STATE , "unforseen state");
LUMIERA_ERROR_DEFINE (STATE , "unforeseen state");
LUMIERA_ERROR_DEFINE (INVALID , "invalid input or parameters");
LUMIERA_ERROR_DEFINE (EXTERNAL , "failure in external service");
LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure");
@ -70,7 +74,7 @@ namespace lumiera
/** @note we set the C-style errorstate as a side effect */
Error::Error (string description, const char* id) throw()
: std::exception (),
id_ (id),
id_ (error::default_or_given (id)),
msg_ (error::default_usermsg (this)),
desc_ (description),
cause_ ("")
@ -82,7 +86,7 @@ namespace lumiera
Error::Error (std::exception& cause,
string description, const char* id) throw()
: std::exception (),
id_ (id),
id_ (error::default_or_given (id)),
msg_ (error::default_usermsg (this)),
desc_ (description),
cause_ (extractCauseMsg(cause))
@ -99,8 +103,8 @@ namespace lumiera
desc_ (ref.desc_),
cause_ (extractCauseMsg(ref))
{ }
/** Description of the problem, including the internal char constant
* in accordance to Lumiera's error identification scheme.
@ -119,7 +123,7 @@ namespace lumiera
return what_.c_str();
}
/** @internal get at the description message of the
* first exception encountered in a chain of exceptions
*/
@ -138,29 +142,8 @@ namespace lumiera
// unknown other exception type
return cause.what ();
}
/* -- originally, I wanted to chain the exception objects themselfs.
but this doesn't work; we'd need to clone the "cause" error object,
because it can be destroyed when leaving the original
handler by throwing a new exception.
Anyways, not needed at the moment; maybe later? 8/2007
const exception&
Error::rootCause () const throw()
{
const exception * root(this);
if (this->cause)
if (Error* err = dynamic_cast<Error*> (this->cause))
root = &err->rootCause ();
else
root = this->cause;
ENSURE (root);
ENSURE (root!=this || !cause);
return *root;
}
*/
@ -182,7 +165,7 @@ namespace lumiera
std::terminate();
}
void assertion_terminate (const string& location)
{
throw Fatal (location, LUMIERA_ERROR_ASSERTION)
@ -196,6 +179,11 @@ namespace lumiera
std::set_unexpected (lumiera_unexpectedException);
}
namespace {
LifecycleHook schedule_ (ON_BASIC_INIT, &install_unexpectedException_handler);
}
} // namespace error
} // namespace lumiera

View file

@ -26,7 +26,7 @@
#ifndef LUMIERA_MULTITHREAD_H
#define LUMIERA_MULTITHREAD_H
#include "proc/nobugcfg.hpp"
#include "include/nobugcfg.h"
#include "common/util.hpp"

View file

@ -53,13 +53,13 @@
#include <tr1/memory>
namespace lumiera
{
namespace lumiera {
using std::tr1::shared_ptr;
using std::tr1::weak_ptr;
/**
* customized refcounting smart pointer template, built upon
* Customised refcounting smart pointer template, built upon
* std::tr1::shared_ptr, but forwarding type relationships and
* ordering operators to the pointee objects.
* @param TAR the visible pointee type

View file

@ -23,7 +23,7 @@
#include "common/query.hpp"
#include "common/util.hpp"
#include "proc/nobugcfg.hpp"
#include "include/nobugcfg.h"
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>

View file

@ -30,15 +30,16 @@
#include <boost/format.hpp>
#include "include/symbol.hpp"
namespace lumiera {
namespace lumiera
{
using std::string;
using boost::format;
/* ==== comon definitions for rule based queries ==== */
/* ==== common definitions for rule based queries ==== */
typedef const char * const Symbol;
/**

View file

@ -28,7 +28,7 @@
#include "proc/asset/pipe.hpp"
#include "proc/nobugcfg.hpp"
#include "include/nobugcfg.h"
#include "common/util.hpp"
using util::isnil;
@ -88,7 +88,7 @@ namespace lumiera
void
MockTable::fill_mock_table ()
{
INFO (config, "creating mock answers for some config queries...");
INFO (config, "creating mock answers for some hard wired config queries...");
isInit_ = true; // allow re-entrance
typedef const ProcPatt cPP;

View file

@ -38,7 +38,7 @@ This code is heavily inspired by
#include "common/singletonpolicies.hpp" // several Policies usable together with SingletonFactory
#include "common/util.hpp"
#include "proc/nobugcfg.hpp"
#include "include/nobugcfg.h"
@ -94,12 +94,10 @@ namespace lumiera
/** @internal helper used to delegate destroying the single instance
* to the Create policy, at the same time allowing the Life policy
* to control the point in the Application lifecycle when the
* destruction of this instance occures.
* destruction of this instance occurs.
*/
static void destroy()
{
TRACE (singleton, "Singleton: triggering destruction");
REQUIRE (!isDead_);
Create<SI>::destroy (pInstance_);
pInstance_ = 0;
@ -133,7 +131,7 @@ namespace lumiera
///// the object may already have been released when the runtime system calls the
///// destructors of static objects at shutdown.
///// It seems this would either cost us much of the flexibility or get complicated
///// to a point where we could as well implement our own Depenency Injection Manager.
///// to a point where we could as well implement our own Dependency Injection Manager.
} // namespace lumiera
#endif

View file

@ -35,7 +35,7 @@ This code is heavily inspired by
#define LUMIERA_SINGLETONPOLICIES_H
#include "common/multithread.hpp"
#include "common/error.hpp"
#include "include/error.hpp"
#include <vector>
@ -95,7 +95,7 @@ namespace lumiera
* the provided deleter function(s) at application shutdown,
* relying on the runtime system calling destructors of static
* objects. Because this Policy class can be shared between
* several Singletons, we need to memoize all registered
* several Singletons, we need to memorise all registered
* deleter functions for calling them at shutdown.
*/
static void scheduleDelete (DelFunc kill_the_singleton)

View file

@ -61,7 +61,7 @@ namespace lumiera
/* ********************************************************************** */
/* Forward declarations of all Classes we want to specialize the template */
/* Forward declarations of all Classes we want to specialise the template */
/* ********************************************************************** */
namespace test
@ -87,8 +87,7 @@ namespace backend_interface
/* Specialisation Definitions */
/* ************************** */
namespace lumiera
{
namespace lumiera {
using test::MockInjector;

View file

@ -45,8 +45,8 @@
#include <typeinfo>
namespace lumiera
{
namespace lumiera {
using boost::scoped_ptr;
@ -54,7 +54,7 @@ namespace lumiera
{
/**
* Helper template to use the general policy classes of the lumiera::Singleton,
* but change the way they are parametrized on-the-fly.
* but change the way they are parametrised on-the-fly.
*/
template<template<class> class POL, class I>
struct Adapter
@ -63,7 +63,7 @@ namespace lumiera
struct Link
{
virtual ~Link() {}
virtual I* create () = 0; ///< @note compiler will check the actual type is asignable...
virtual I* create () = 0; ///< @note compiler will check the actual type is assignable...
virtual void destroy (I* pSi) = 0;
};
@ -73,14 +73,14 @@ namespace lumiera
virtual S* create () { return POL<S>::create (); } // covariance checked!
virtual void destroy (I* pSi) { POL<S>::destroy (static_cast<S*> (pSi)); }
};
struct My_scoped_ptr : scoped_ptr<Link> ///< implementation detail: defeat static initialisation
{
using scoped_ptr<Link>::get;
My_scoped_ptr() : scoped_ptr<Link> (get()? get() : 0) {} ///< bypass if already configured
};
/** we configure this link \e later, when the singleton factory
* is actually created, to point at the desired implementation subclass.
*/
@ -94,9 +94,9 @@ namespace lumiera
static void destroy (II* pSi) { link->destroy (pSi); }
};
};
template<template<class> class A, class I>
typename Adapter<A,I>::My_scoped_ptr Adapter<A,I>::link; // note: use special ctor (due to stati init order!)
typename Adapter<A,I>::My_scoped_ptr Adapter<A,I>::link; // note: use special ctor (due to static init order!)
/** type-information used to configure the factory instance
@ -115,7 +115,7 @@ namespace lumiera
* a subclass or wrap the product in some way. For the user code, it should behave
* exactly like the standard SingletonFactory. The configuration of the product
* actually to be created is delayed until the ctor call, so it can be hidden
* away to the implementaton of a class using the SingletonFactory.
* away to the implementation of a class using the SingletonFactory.
*
* @see configrules.cpp usage example
*/
@ -134,10 +134,10 @@ namespace lumiera
{
public:
/** The singleton-factory ctor configures what concrete type to create.
* It takes type information passed as dummy parameter and installes
* It takes type information passed as dummy parameter and installs
* a trampoline object in the static field of class Adapter to perform
* the necessary up/downcasts. This allows to use whatever policy
* class ist wanted, but parametrizes this policy template with
* class is desired, but parametrises this policy template with
* the concrete type to be created. (only the "create" policy
* needs to know the actual class, because it allocates storage)
*/
@ -156,11 +156,11 @@ namespace lumiera
"If using several instances of the sub-class-creating "
"singleton factory, all *must* be configured to create "
"objects of exactly the same implementation type!");
#endif
#endif
}
};
/**
* Default Singleton configuration (subclass creating factory)
* @note all Policy template parameters taking default values

View file

@ -64,8 +64,8 @@ namespace lumiera
void injectSubclass (SI* mockobj)
{
TRACE_IF (mockobj, singleton, "Singleton: installing Mock object");
TRACE_IF (!mockobj, singleton, "Singleton: removing Mock object");
TRACE_IF (mockobj, test, "Singleton: installing Mock object");
TRACE_IF (!mockobj, test, "Singleton: removing Mock object");
mock_.reset (mockobj);
}

View file

@ -28,7 +28,7 @@
#include "pre.hpp"
#include "proc/nobugcfg.hpp"
#include "include/nobugcfg.h"
#include "common/test/suite.hpp"
#include "common/util.hpp"

View file

@ -30,11 +30,11 @@
#include <sstream>
#include <boost/algorithm/string.hpp>
#include "proc/nobugcfg.hpp"
#include "common/cmdline.hpp"
#include "include/nobugcfg.h"
#include "lib/cmdline.hpp"
#include "common/test/suite.hpp"
#include "common/test/run.hpp"
#include "common/error.hpp"
#include "include/error.hpp"
#include "common/util.hpp"

View file

@ -1,5 +1,5 @@
/*
Suite - handle cmdline for invoking Testsuite
TestOption - handle cmdline for invoking Testsuite
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -24,7 +24,7 @@
#include "common/test/testoption.hpp"
#include "common/test/suite.hpp"
#include "common/error.hpp"
#include "include/error.hpp"
@ -40,7 +40,7 @@ namespace test
/** set up an options parser to use the current commandline.
* reconizes the following options
* Recognises the following options
* \code
* --help
* --group <groupID>
@ -56,7 +56,7 @@ namespace test
("group,g", op::value<string>()->default_value(Suite::ALLGROUP),
"the group (selection) of testcases to execute")
("describe", op::bool_switch(),
"ennumerate all testcases in this Suite in a format usable with ./test.sh.")
"enumerate all testcases in this Suite in a format usable with ./test.sh.")
("id", op::value<VectS>(),
"an individual testcase to be called.\nIf not specified, run all.")
;
@ -75,7 +75,7 @@ namespace test
op::store (parsed, parameters);
op::notify(parameters);
// remove all recognized options from original cmdline vector
// remove all recognised options from original cmdline vector
cmdline = op::collect_unrecognized(parsed.options, op::include_positional);
if (parameters.count("help"))

View file

@ -24,7 +24,7 @@
#ifndef TESTHELPER_TESTOPTION_H
#define TESTHELPER_TESTOPTION_H
#include "common/cmdline.hpp"
#include "lib/cmdline.hpp"
#include <string>
#include <iostream>
@ -48,7 +48,7 @@ namespace test
* to be parsed is taken wrapped into a Cmdline
* instance; after parsing this commandline
* vector will contain only the remaining
* unrecognized parts.
* unrecognised parts.
*/
class TestOption : private boost::noncopyable
{
@ -66,8 +66,8 @@ namespace test
};
/** for outputting the help messages. Forward accummulated
* help messages from all contained option defintions */
/** for outputting the help messages. Forward accumulated
* help messages from all contained option definitions */
ostream& operator<< (ostream& os, const TestOption& to);

View file

@ -31,10 +31,10 @@
namespace util
{
namespace util {
using std::string;
template <class NUM>
inline int
@ -43,7 +43,7 @@ namespace util
return (n==0)? 0 :((n<0)? -1:+1 );
}
/** a family of util functions providing a "no value whatsoever" test.
Works on strings and all STL containers, includes NULL test for pointers */
template <class CONT>
@ -65,7 +65,7 @@ namespace util
{
return !pCStr || 0 == std::strlen(pCStr);
}
/** cut a numeric value to be >=0 */
template <typename NUM>
@ -100,7 +100,7 @@ namespace util
}
/** shortcut for brute-force containment test
* in any sequencial container */
* in any sequential container */
template <typename SEQ>
inline bool
contains (SEQ& cont, typename SEQ::const_reference val)
@ -112,7 +112,7 @@ namespace util
}
/** shortcut for removing all copies of an Element
* in any sequencial collection */
* in any sequential collection */
template <typename SEQ>
inline typename SEQ::iterator
removeall (SEQ& coll, typename SEQ::value_type& val)
@ -187,7 +187,7 @@ namespace util
/** produce an identifier based on the given string.
* remove non-standard-chars, reduce sequences of punctuation
* and whitespace to single underscores. The sanitized string
* and whitespace to single underscores. The sanitised string
* will start with an alphanumeric character.
*
* @par Example Conversions
@ -215,7 +215,7 @@ namespace util
{
return org.c_str();
}
} // namespace util
@ -223,7 +223,7 @@ namespace util
/* === some common macro definitions === */
/** supress "warning: unused variable" on vars, which are
/** suppress "warning: unused variable" on vars, which are
* introduced into a scope because of some sideeffect, i.e. Locking
*/
#define SIDEEFFECT __attribute__ ((unused));

View file

@ -25,7 +25,7 @@
#ifndef LUMIERA_VISITORDISPATCHER_H
#define LUMIERA_VISITORDISPATCHER_H
#include "common/error.hpp"
#include "include/error.hpp"
#include "common/util.hpp"
#include "common/singleton.hpp"
#include "common/multithread.hpp"

View file

@ -32,7 +32,7 @@
#ifndef LUMIERA_VISITORPOLICIES_H
#define LUMIERA_VISITORPOLICIES_H
#include "common/error.hpp"
#include "include/error.hpp"
namespace lumiera

View file

@ -20,14 +20,15 @@ lumigui_srcdir = $(top_srcdir)/src/gui
#lumigui_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror
lumigui_CPPFLAGS = $(AM_CPPFLAGS) \
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
lumigui_CPPFLAGS = $(AM_CPPFLAGS) \
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
$(LUMIERA_GUI_CFLAGS)
bin_PROGRAMS += lumigui
<<<<<<< HEAD:src/gui/Makefile.am
lumigui_SOURCES = \
$(lumigui_srcdir)/gtk-lumiera.cpp \
$(lumigui_srcdir)/gtk-lumiera.hpp \
@ -97,6 +98,77 @@ lumigui_SOURCES = \
$(lumigui_srcdir)/output/gdkdisplayer.cpp \
$(lumigui_srcdir)/output/gdkdisplayer.hpp \
$(lumigui_srcdir)/output/xvdisplayer.cpp \
=======
lumigui_SOURCES = \
$(lumigui_srcdir)/gtk-lumiera.cpp \
$(lumigui_srcdir)/gtk-lumiera.hpp \
$(lumigui_srcdir)/window-manager.cpp \
$(lumigui_srcdir)/window-manager.hpp \
$(lumigui_srcdir)/workspace/actions.cpp \
$(lumigui_srcdir)/workspace/actions.hpp \
$(lumigui_srcdir)/workspace/workspace-window.cpp \
$(lumigui_srcdir)/workspace/workspace-window.hpp \
$(lumigui_srcdir)/dialogs/dialog.hpp \
$(lumigui_srcdir)/dialogs/render.cpp \
$(lumigui_srcdir)/dialogs/render.hpp \
$(lumigui_srcdir)/dialogs/preferences-dialog.cpp \
$(lumigui_srcdir)/dialogs/preferences-dialog.hpp \
$(lumigui_srcdir)/dialogs/sequence-name.cpp \
$(lumigui_srcdir)/dialogs/sequence-name.hpp \
$(lumigui_srcdir)/panels/panel.cpp \
$(lumigui_srcdir)/panels/panel.hpp \
$(lumigui_srcdir)/panels/timeline-panel.cpp \
$(lumigui_srcdir)/panels/timeline-panel.hpp \
$(lumigui_srcdir)/panels/viewer-panel.cpp \
$(lumigui_srcdir)/panels/viewer-panel.hpp \
$(lumigui_srcdir)/panels/assets-panel.cpp \
$(lumigui_srcdir)/panels/assets-panel.hpp \
$(lumigui_srcdir)/widgets/video-display-widget.cpp \
$(lumigui_srcdir)/widgets/video-display-widget.hpp \
$(lumigui_srcdir)/widgets/timeline-widget.cpp \
$(lumigui_srcdir)/widgets/timeline-widget.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-view-window.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-view-window.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-header-container.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-header-container.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-body.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-body.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-ruler.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-ruler.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-tool.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-tool.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-track.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-track.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-clip-track.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-clip-track.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-group-track.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-group-track.hpp \
$(lumigui_srcdir)/widgets/timeline/timeline-clip.cpp \
$(lumigui_srcdir)/widgets/timeline/timeline-clip.hpp \
$(lumigui_srcdir)/model/project.cpp \
$(lumigui_srcdir)/model/project.hpp \
$(lumigui_srcdir)/model/track-base.cpp \
$(lumigui_srcdir)/model/track-base.hpp \
$(lumigui_srcdir)/model/sequence.cpp \
$(lumigui_srcdir)/model/sequence.hpp \
$(lumigui_srcdir)/model/track.cpp \
$(lumigui_srcdir)/model/track.hpp \
$(lumigui_srcdir)/model/clip-track.cpp \
$(lumigui_srcdir)/model/clip-track.hpp \
$(lumigui_srcdir)/model/group-track.cpp \
$(lumigui_srcdir)/model/group-track.hpp \
$(lumigui_srcdir)/model/clip.cpp \
$(lumigui_srcdir)/model/clip.hpp \
$(lumigui_srcdir)/output/displayer.cpp \
$(lumigui_srcdir)/output/displayer.hpp \
$(lumigui_srcdir)/output/gdkdisplayer.cpp \
$(lumigui_srcdir)/output/gdkdisplayer.hpp \
$(lumigui_srcdir)/output/xvdisplayer.cpp \
>>>>>>> 9a1a1890e27942a7f45a3593f525c55cb5e8d8cb:src/gui/Makefile.am
$(lumigui_srcdir)/output/xvdisplayer.hpp
lumigui_LDFLAGS =

View file

@ -33,7 +33,7 @@
#include "model/project.hpp"
extern "C" {
#include "backend/interface.h"
#include "lumiera/interface.h"
}
NOBUG_CPP_DEFINE_FLAG(gui);

108
src/gui/guifacade.hpp Normal file
View file

@ -0,0 +1,108 @@
/*
GUIFACADE.hpp - access point for communicating with the Lumiera GTK GUI
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file guifacade.hpp
** Interface for the GUI loader and for accessing the GUI interface from the
** lower layers of Lumiera. While part of the public interface of the Lumiera GUI,
** the implementation of this facility is part of the core application (and not
** contained within the GUI dynamic module), because it's job is to load and
** activate this module and to startup the GUI.
**
** @see lumiera::AppState
** @see lumiera::Option
** @see guifacade.cpp
** @see main.cpp
*/
#ifndef GUI_FACADE_H
#define GUI_FACADE_H
#include "lumiera/subsys.hpp"
extern "C" {
#include "lumiera/interface.h"
}
namespace gui {
/*********************************************************************
* Global access point for loading and starting up the Lumiera GTK GUI
* and for controlling the GUI lifecycle. The implementation part of
* this class also is responsible for making the "business" interface
* of the GUI available, i.e. gui::GuiNotification
*
* When running Lumiera with a GUI is required (the default case),
* it is loaded as dynamic module, thus defining the interface(s)
* for any further access. After successfully loading and starting
* the GUI, this gui::Facade is wired internally with this interface
* such as to allow transparent access from within the core. This
* startup sequence includes providing the GUI with similar facade
* access via interface handles for communication with Backend and
* Proc-Layer.
*
* @note this facade is intended to be used by Lumiera main solely.
* client code should always use the "business" interface(s).
*
*/
class GuiFacade
{
public:
/** provide a descriptor for lumiera::AppState,
* wired accordingly to allow main to load,
* start and stop the Lumiera GTK GUI. */
static lumiera::Subsys& getDescriptor();
/** weather the GUI has been started and all interfaces are opened */
static bool isUp();
/* ===== control interface for the GuiStarterPlugin ======= */
/** start the actual GUI thread(s), after successfully loading
* the GuiStarterPlugin, that is. The implementation of this function
* must ensure to invoke the given termination signal reliably after
* shutting down the GUI, otherwise the application will hang on exit.
* @internal this function is invoked automatically during the GUI
* loading and startup process. Don't call it manually.
*/
virtual bool kickOff (lumiera::Subsys::SigTerm&) =0;
protected:
virtual ~GuiFacade() {}
};
/** interface of the GuiStarterPlugin */
LUMIERA_INTERFACE_DECLARE (lumieraorg_Gui, 1,
LUMIERA_INTERFACE_SLOT (bool, kickOff, (void*))
);
} // namespace gui
#endif

View file

@ -0,0 +1,150 @@
/*
GuiNotificationFacade - access point for pushing informations into the GUI
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 "include/guinotificationfacade.h"
#include "common/singleton.hpp"
#include "include/nobugcfg.h"
#include "common/util.hpp"
extern "C" {
#include "lumiera/interfacedescriptor.h"
}
#include <string>
namespace gui {
using std::string;
using util::cStr;
namespace { // facade implementation details
struct GuiNotificationFacade
: public GuiNotification
{
void
displayInfo (string const& text)
{
INFO (operate, "@GUI: display '%s' as notification message.", cStr(text));
}
void
triggerGuiShutdown (string const& cause)
{
NOTICE (operate, "@GUI: shutdown triggered with explanation '%s'....", cStr(cause));
}
};
lumiera::Singleton<GuiNotificationFacade> _facade;
/* ================== define an lumieraorg_GuiNotification instance ======================= */
LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0
,lumieraorg_GuiNotificationFacade_descriptor
, NULL, NULL, NULL
, LUMIERA_INTERFACE_INLINE (name, "\044\117\156\365\344\056\362\220\166\350\320\214\115\221\302\177",
const char*, (LumieraInterface iface),
{ return "GuiNotification"; }
)
, LUMIERA_INTERFACE_INLINE (brief, "\160\240\102\325\175\145\270\140\350\241\163\303\331\343\253\142",
const char*, (LumieraInterface iface),
{ return "GUI Interface: push state update and notification of events into the GUI"; }
)
, LUMIERA_INTERFACE_INLINE (homepage, "\217\232\066\101\042\116\054\217\070\233\253\241\166\145\234\133",
const char*, (LumieraInterface iface),
{ return "http://www.lumiera.org/develompent.html" ;}
)
, LUMIERA_INTERFACE_INLINE (version, "\350\365\121\052\037\022\300\021\171\357\017\367\270\071\266\376",
const char*, (LumieraInterface iface),
{ return "0.1~pre"; }
)
, LUMIERA_INTERFACE_INLINE (author, "\117\007\006\234\153\206\000\344\303\043\027\261\045\320\166\133",
const char*, (LumieraInterface iface),
{ return "Hermann Vosseler"; }
)
, LUMIERA_INTERFACE_INLINE (email, "\356\243\022\137\345\275\016\034\337\144\031\260\303\050\140\327",
const char*, (LumieraInterface iface),
{ return "Ichthyostega@web.de"; }
)
, LUMIERA_INTERFACE_INLINE (copyright, "\365\220\260\051\267\345\330\046\145\134\331\320\115\157\332\356",
const char*, (LumieraInterface iface),
{
return
"Copyright (C) Lumiera.org\n"
" 2008 Hermann Vosseler <Ichthyostega@web.de>";
}
)
, LUMIERA_INTERFACE_INLINE (license, "\155\335\361\364\221\012\115\325\306\046\153\152\002\117\075\077",
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_INTERFACE_INLINE (state, "\227\170\230\144\310\330\131\175\367\152\327\324\113\275\223\245",
int, (LumieraInterface iface),
{return LUMIERA_INTERFACE_EXPERIMENTAL; }
)
, LUMIERA_INTERFACE_INLINE (versioncmp, "\253\066\335\233\025\161\135\347\377\156\121\135\347\313\130\014",
int, (const char* a, const char* b),
{return 0;} ////////////////////////////////////////////TODO define version ordering
)
);
LUMIERA_INTERFACE_INSTANCE (lumieraorg_GuiNotification, 1
,lumieraorg_GuiNotificationFacade
, LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_GuiNotificationFacade_descriptor)
, NULL /* on open */
, NULL /* on close */
, LUMIERA_INTERFACE_INLINE (displayInfo, "\366\075\213\163\207\040\221\233\010\366\174\374\317\126\331\205",
void, (const char* text),
{ return _facade().displayInfo(text); }
)
, LUMIERA_INTERFACE_INLINE (triggerGuiShutdown, "\267\043\244\065\107\314\370\175\063\330\264\257\302\146\326\303",
void, (const char* cause),
{ return _facade().triggerGuiShutdown(cause); }
)
);
} // (END) facade implementation details
} // namespace gui

View file

@ -38,7 +38,8 @@ Track::Track() :
buttonBar.append(lockButton);
buttonBar.set_toolbar_style(TOOLBAR_ICONS);
buttonBar.set_icon_size(WindowManager::MenuIconSize);
//buttonBar.set_icon_size(WindowManager::MenuIconSize);
//TODO uncommented for now, doesn't compile on etch. 12/15/08 ichthyo
headerWidget.pack_start(titleBox, PACK_SHRINK);
headerWidget.pack_start(buttonBar, PACK_SHRINK);

View file

@ -209,7 +209,7 @@ Actions::on_menu_help_about()
//dialog.set_program_name(AppTitle);
dialog.set_version(AppVersion);
//dialog.set_version(Appconfig::get("version"));
//dialog.set_version(AppState::get("version"));
dialog.set_copyright(AppCopyright);
dialog.set_website(AppWebsite);
dialog.set_authors(StringArrayHandle(AppAuthors,

189
src/guistart.cpp Normal file
View file

@ -0,0 +1,189 @@
/*
GuiStart - entry point for the lumiera GUI loaded as shared module
Copyright (C) Lumiera.org
2007-2008, Joel Holdsworth <joel@airwebreathe.org.uk>
Christian Thaeter <ct@pipapo.org>
Hermann Vosseler <Ichthyostega@web.de>
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.
* *****************************************************/
/** @file guistart.cpp
** Start up the Lumiera GTK GUI when loading it as dynamic module.
** This plugin is linked together with the Lumiera GUI code; when loaded as
** Lumiera plugin, it allows to kick off the main GUI thread and thus to bring up
** the GUI. The loading and shutdown process is carried out by gui::GuiFacade and
** controlled by lumiera::AppState, which in turn is activated by Lumiera main().
**
** After successfully loading this module, a call to #kickOff is expected to be
** issued, passing a termination signal (callback) to be executed when the GUI
** terminates. This call returns immediately, after spawning off the main thread
** and setting up the termination callback accordingly. Additionally, it cares
** for opening the primary "business" interface of the GUI, i.e. the interface
** gui::GuiNotification.
**
** @see lumiera::AppState
** @see gui::GuiFacade
** @see guifacade.cpp
** @see ///////////////////////////////////TODO: add link to the gui main routine here!
*/
#include "gui/guifacade.hpp"
#include "lumiera/subsys.hpp"
#include "common/singleton.hpp"
extern "C" {
#include "lumiera/interface.h"
#include "lumiera/interfacedescriptor.h"
}
#include <string>
using std::string;
#include <iostream> /////////////TODO
using std::cout; //////////////TODO
using lumiera::Subsys;
using gui::LUMIERA_INTERFACE_INAME(lumieraorg_Gui, 1);
namespace gui {
namespace { // implementation details
/**
* Implement the necessary steps for starting up the GUI main thread
*/
struct GuiFacadeImpl
: public GuiFacade
{
bool kickOff (Subsys::SigTerm& terminationHandle)
{
cout << " *** Ha Ha Ha\n"
<< " this is the GuiStarterPlugin speaking!\n"
<< " now, the Lumiera GUI should be spawned....\n"
<< " but actually nothing happens!!!!!!!!!!!!!!\n\n";
terminationHandle(0); // signal immediate shutdown without error
return true;
}
};
lumiera::Singleton<GuiFacadeImpl> facade_;
} // (End) impl details
} // namespace gui
extern "C" { /* ================== define an lumieraorg_Gui instance ======================= */
LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0
,lumieraorg_GuiStarterPlugin_descriptor
, NULL, NULL, NULL
, LUMIERA_INTERFACE_INLINE (name, "\126\247\365\337\126\254\173\037\130\310\337\345\200\347\323\136",
const char*, (LumieraInterface iface),
{ return "GuiStarterPlugin"; }
)
, LUMIERA_INTERFACE_INLINE (brief, "\056\346\322\365\344\104\232\232\355\213\367\056\301\144\051\021",
const char*, (LumieraInterface iface),
{ return "entry point to start up the Lumiera GTK GUI contained in this dynamic module"; }
)
, LUMIERA_INTERFACE_INLINE (homepage, "\357\056\117\165\320\066\273\130\113\100\367\022\221\350\236\256",
const char*, (LumieraInterface iface),
{ return "http://www.lumiera.org/develompent.html" ;}
)
, LUMIERA_INTERFACE_INLINE (version, "\013\117\366\210\070\320\274\076\253\230\032\116\271\161\027\354",
const char*, (LumieraInterface iface),
{ return "0.1~pre"; }
)
, LUMIERA_INTERFACE_INLINE (author, "\371\262\024\273\170\105\163\261\351\240\051\003\153\040\256\155",
const char*, (LumieraInterface iface),
{ return "Joel Holdsworth, Christian Thaeter, Hermann Vosseler"; }
)
, LUMIERA_INTERFACE_INLINE (email, "\353\242\247\130\056\242\314\145\053\162\003\060\200\357\303\214",
const char*, (LumieraInterface iface),
{ return "Lumiera@lists.lumiera.org"; }
)
, LUMIERA_INTERFACE_INLINE (copyright, "\172\325\335\304\015\222\377\372\343\151\255\020\030\103\320\101",
const char*, (LumieraInterface iface),
{
return
"Copyright (C) Lumiera.org\n"
"2007-2008, Joel Holdsworth <joel@airwebreathe.org.uk>\n"
" Christian Thaeter <ct@pipapo.org>\n"
" Hermann Vosseler <Ichthyostega@web.de>";
}
)
, LUMIERA_INTERFACE_INLINE (license, "\016\264\202\005\160\305\033\227\037\077\143\363\263\011\167\257",
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_INTERFACE_INLINE (state, "\006\070\035\065\267\073\016\107\376\027\355\035\135\176\107\064",
int, (LumieraInterface iface),
{return LUMIERA_INTERFACE_EXPERIMENTAL; }
)
, LUMIERA_INTERFACE_INLINE (versioncmp, "\224\077\275\040\357\244\311\244\112\030\042\163\061\166\245\325",
int, (const char* a, const char* b),
{return 0;} ////////////////////////////////////////////TODO define version ordering
)
);
LUMIERA_EXPORT( /* ===================== PLUGIN EXPORTS ================================== */
LUMIERA_INTERFACE_DEFINE (lumieraorg_Gui, 1
,lumieraorg_GuiStarterPlugin
, LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_GuiStarterPlugin_descriptor)
, NULL /* on open */
, NULL /* on close */
, LUMIERA_INTERFACE_INLINE (kickOff, "\255\142\006\244\057\170\152\312\301\372\220\323\230\026\200\065",
bool, (void* termSig),
{
return gui::facade_().kickOff (
*reinterpret_cast<Subsys::SigTerm *> (termSig));
}
)
)
);
} // extern "C"

View file

@ -0,0 +1,73 @@
/*
CONFIGFACADE - C++ convenience wrapper and startup of the config system
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file configfacade.hpp
** The lumiera::Config wrapper class addresses two issues.
** First, it registers startup and shutdown hooks to bring up the config system
** as early as possible. Later, on application main initialisation, the global
** config interface is opened and wrapped for convenient access from C++ code.
**
** @see config.h
** @see lumiera::AppState
** @see main.cpp
*/
#ifndef INTERFACE_CONFIGFACADE_H
#define INTERFACE_CONFIGFACADE_H
#include "common/singleton.hpp"
#include <string>
namespace lumiera {
using std::string;
/*********************************************************************
* C++ wrapper for convenient access to the Lumiera config system.
*/
struct Config
{
static const string get (string const& key);
static lumiera::Singleton<Config> instance;
private:
Config();
~Config();
friend class lumiera::singleton::StaticCreate<Config>;
//////////////////TODO: define startup/shutdown and loading of the config interface
};
} // namespace lumiera
#endif

View file

@ -25,13 +25,13 @@
#define LUMIERA_ERROR_HPP_
#include <string>
#include "proc/nobugcfg.hpp"
#include "lib/appconfig.hpp"
#include "include/nobugcfg.h"
#include "include/lifecycle.h"
#include "lib/error.h"
namespace lumiera
{
namespace lumiera {
using std::string;
@ -152,13 +152,8 @@ namespace lumiera
/** install our own handler for undeclared exceptions. Will be
* called automatically ON_BASIC_INIT when including errror.hpp
* @note it's OK this is defined multiple times...
* @see appconfig.hpp */
* called automatically ON_BASIC_INIT when linking error.cpp */
void install_unexpectedException_handler ();
namespace {
LifecycleHook schedule_ (ON_BASIC_INIT, &install_unexpectedException_handler);
}
} // namespace error

View file

@ -0,0 +1,100 @@
/*
GUINOTIFICATIONFACADE.hpp - access point for pushing informations into the GUI
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file guifacade.hpp
** Interface for the GUI loader and for accessing the GUI interface from the
** lower layers of Lumiera. While part of the public interface of the Lumiera GUI,
** the implementation of this facility is part of the core application (and not
** contained within the GUI dynamic module), because it's job is to load and
** activate this module and to startup the GUI.
**
** @see lumiera::AppState
** @see lumiera::Option
** @see guifacade.cpp
** @see main.cpp
*/
#ifndef GUI_GUINOTIFICATION_H
#define GUI_GUINOTIFICATION_H
#ifdef __cplusplus /* ============== C++ Interface ================= */
#include "common/singletonsubclass.hpp"
#include <string>
namespace gui {
using std::string;
/*********************************************************************
* Global access point to push state update and notification of events
* from the lower layers into the Lumiera GUI. Typically, this happens
* asynchronously and triggered by events within the lower layers.
*
* This is a layer separation facade interface. Clients should use
* the embedded #facade factory, which yields a proxy routing any
* calls through the lumieraorg_GuiNotification interface
* @throws lumiera::error::State when interface is not opened
*/
class GuiNotification
{
public:
static lumiera::SingletonSub<GuiNotification> facade;
/** push a user visible notification text */
virtual void displayInfo (string const& text) =0;
/** causes the GUI to shut down unconditionally
* @param cause user visible explanation of the
* reason causing this shutdown */
virtual void triggerGuiShutdown (string const& cause) =0;
protected:
virtual ~GuiNotification() {}
};
} // namespace gui
extern "C" {
#endif /* =========================== CLI Interface ================= */
#include "lumiera/interface.h"
LUMIERA_INTERFACE_DECLARE (lumieraorg_GuiNotification, 1,
LUMIERA_INTERFACE_SLOT (void, displayInfo, (const char*)),
LUMIERA_INTERFACE_SLOT (void, triggerGuiShutdown, (const char*)),
);
#ifdef __cplusplus
}
#endif
#endif

105
src/include/lifecycle.h Normal file
View file

@ -0,0 +1,105 @@
/*
LIFECYCLE.h - interface for registering and triggering lifecycle callbacks
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file lifecycle.h
** Interface for registering and triggering application lifecycle event callbacks.
** This service is a facade for and implemented by lumiera::AppState.
** By placing a static LifecycleHook variable or by calling LifecycleHook::add,
** a callback can be registered to be executed on a specific application lifecycle
** event. Examples being #ON_BASIC_INIT, #ON_GLOBAL_INIT. Other subsystems may
** register additional events for more specific purpose.
**
** @see lumiera::AppState
** @see main.cpp
*/
#ifndef LUMIERA_LIFECYCLE_H
#define LUMIERA_LIFECYCLE_H
#ifdef __cplusplus
#include "include/symbol.hpp"
#include <boost/noncopyable.hpp>
namespace lumiera {
extern Symbol ON_BASIC_INIT; ///< automatic static init. treated specially
extern Symbol ON_GLOBAL_INIT; ///< to be triggered in main() @note no magic!
extern Symbol ON_GLOBAL_SHUTDOWN; ///< to be triggered at the end of main() @note no magic!
extern Symbol ON_EMERGENCY; ///< activated on shutdown after premature failure of a subsystem
// client code is free to register and use additional lifecycle events
/**
* define and register a callback for a specific lifecycle event.
* The purpose of this class is to be defined as a static variable in the implementation
* of some subsystem (i.e. in the cpp file), providing the ctor with the pointer to a
* callback function. Thus the callback gets enrolled when the corresponding object file
* is loaded. The event ON_BASIC_INIT is handled specifically, firing off the referred
* callback function as soon as possible. All other labels are just arbitrary (string)
* constants and it is necessary that "someone" cares to fire off the lifecycle events
* at the right place. For example, lumiera-main (and the test runner) calls
* \c AppState::instance().execute(ON_GLOBAL_INIT) (and..SHUTDOWN)
* @note duplicate or repeated calls with the same callback are NOP
*/
class LifecycleHook
: private boost::noncopyable
{
public:
typedef void (*Hook)(void);
LifecycleHook (Symbol eventLabel, Hook callbackFun);
/** alternative, static interface for registering a callback */
static void add (Symbol eventLabel, Hook callbackFun);
/** trigger lifecycle callbacks registered under the given label */
static void trigger (Symbol eventLabel);
};
} // namespace lumiera
#else /* =========== C interface ====================== */
extern const char * lumiera_ON_BASIC_INIT;
extern const char * lumiera_ON_GLOBAL_INIT;
extern const char * lumiera_ON_GLOBAL_SHUTDOWN;
void lumiera_LifecycleHook_add (const char* eventLabel, void callbackFun(void));
void lumiera_Lifecycle_trigger (const char* eventLabel);
#endif
#endif

117
src/include/nobugcfg.h Normal file
View file

@ -0,0 +1,117 @@
/*
NOBUGCFG.h - NoBug definitions and initialisation for the Proc-Layer
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file nobugcfg.h
** This header is for including and configuring NoBug.
** The idea is that configuration and some commonly used flag
** declarations are to be kept in one central location. Subsystems
** are free to define and use additional flags for local use. Typically,
** this header will be included via some of the basic headers like error.hpp,
** which in turn gets included e.g. by proc/common.hpp
**
** This header can thus be assumed to be effectively global. It should contain
** only declarations of global relevance, as any change causes the whole project
** to be rebuilt. Moreover, for C++ this header assures automatic initialisation
** of NoBug by placing a static ctor call.
**
** Besides the usual guarded declarations, this header contains one section
** with the corresponding <b>definitions</b>. This section is to be included once
** by some translation unit (currently this is lumiera/nobugcfg.cpp) in order to
** generate the necessary definitions.
**
** @par Logging configuration
** By default, logging is configured such as to emit a small number of informative
** messages on the starting terminal and to report fatal errors. But besides the
** usual fine-grained tracing messages, we define a small number of distinct
** thematic <b>Logging Channels</b> providing a consistent high-level view of
** what is going on with regards to a specific aspect of the application
** - \c operate documents a high-level overall view of what the application \em does
** - \c render focuses on the working of the render engine (without logging each frame)
** - \c config shows anything of relevance regarding the configured state of App and session
** - \c memory allows to diagnose a high-level view of memory management
**
** Any log level can be overridden by an environment variable, for example
** \code NOBUG_LOG='operate:INFO' ./lumiera \endcode
**
** @todo logging to files?
*/
#ifndef NOBUGCFG_H /* ============= Part 1: DECLARATIONS ======== */
#define NOBUGCFG_H
#include <syslog.h>
#include <nobug.h>
#ifdef __cplusplus /* ============= C++ ================ */
#include "include/lifecycle.h"
#include "include/error.hpp" ///< make assertions throw instead of abort()
namespace lumiera {
void initialise_NoBug ();
namespace {
LifecycleHook trigger_it_ (ON_BASIC_INIT, &initialise_NoBug);
} }
#endif /* =====================(End) C++ ================ */
/* declare flags used throughout the code base */
NOBUG_DECLARE_FLAG (all);
NOBUG_DECLARE_FLAG (lumiera_all);
NOBUG_DECLARE_FLAG (lumiera); ///< master log, informative console output
NOBUG_DECLARE_FLAG (operate); ///< logging channel reporting what the application does
NOBUG_DECLARE_FLAG (render); ///< logging channel focusing on the render engine's workings
NOBUG_DECLARE_FLAG (config); ///< logging channel covering application and session configuration
NOBUG_DECLARE_FLAG (memory); ///< logging channel covering memory management issues
NOBUG_DECLARE_FLAG (test);
#endif /*NOBUGCFG_H ======= (End) Part 1: DECLARATIONS ======== */
#ifdef NOBUG_INIT_DEFS_ /*========== Part 2: DEFINITIONS ========= */
/* flags used throughout the code base... */
NOBUG_CPP_DEFINE_FLAG (all);
NOBUG_CPP_DEFINE_FLAG_PARENT (lumiera_all, all);
NOBUG_CPP_DEFINE_FLAG_PARENT (lumiera, lumiera_all);
NOBUG_CPP_DEFINE_FLAG_PARENT (config, lumiera);
NOBUG_CPP_DEFINE_FLAG_PARENT (operate, lumiera);
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (render, lumiera, LOG_WARNING);
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (memory, lumiera, LOG_WARNING);
NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (test, all, LOG_ERR);
#endif /*NOBUG_INIT_DEFS_ ==== (End) Part 2: DEFINITIONS ========= */

54
src/include/symbol.hpp Normal file
View file

@ -0,0 +1,54 @@
/*
SYMBOL.hpp - symbolic constant datatype
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file symbol.hpp
** WIP placeholder definition for a planned Symbol datatype.
**
** @todo the (currently just planned as of 11/08) rules based configuration
** in the Proc-Layer a explicit Symbol datatype will probably very helpful.
** For now we just a typedef is sufficient. A real Symbol datatype should
** - be definable by string constant
** - integrate smoothly with std::string
** - provide a unique numeric index for each distinct Symbol
** - automatically maintain a symbol table at runtime to support this
** - provide some magic (macros) allowing to build distinct types based on symbols.
**
** @see configrules.hpp
** @see query.hpp
*/
#ifndef LUMIERA_SYMBOL_H
#define LUMIERA_SYMBOL_H
namespace lumiera {
typedef const char * const Symbol; //TODO define a real Symbol class, i.e. same literal string==same pointer,
} // namespace lumiera
#endif

View file

@ -31,25 +31,24 @@ liblumiera_a_SOURCES = \
$(liblumiera_a_srcdir)/psplay.c \
$(liblumiera_a_srcdir)/mrucache.c \
$(liblumiera_a_srcdir)/time.c \
$(liblumiera_a_srcdir)/allocationcluster.cpp\
$(liblumiera_a_srcdir)/allocationcluster.cpp \
$(liblumiera_a_srcdir)/external/libgavl.cpp \
$(liblumiera_a_srcdir)/appconfig.cpp
$(liblumiera_a_srcdir)/cmdline.cpp
noinst_HEADERS += \
$(liblumiera_a_srcdir)/error.h \
$(liblumiera_a_srcdir)/mutex.h \
$(liblumiera_a_srcdir)/rwlock.h \
$(liblumiera_a_srcdir)/condition.h \
$(liblumiera_a_srcdir)/luid.h \
$(liblumiera_a_srcdir)/safeclib.h \
$(liblumiera_a_srcdir)/cuckoo.h \
$(liblumiera_a_srcdir)/psplay.h \
$(liblumiera_a_srcdir)/mrucache.h \
$(liblumiera_a_srcdir)/time.h \
$(liblumiera_a_srcdir)/ppmpl.h \
$(liblumiera_a_srcdir)/appconfig.hpp \
noinst_HEADERS += \
$(liblumiera_a_srcdir)/error.h \
$(liblumiera_a_srcdir)/mutex.h \
$(liblumiera_a_srcdir)/rwlock.h \
$(liblumiera_a_srcdir)/condition.h \
$(liblumiera_a_srcdir)/luid.h \
$(liblumiera_a_srcdir)/safeclib.h \
$(liblumiera_a_srcdir)/cuckoo.h \
$(liblumiera_a_srcdir)/psplay.h \
$(liblumiera_a_srcdir)/mrucache.h \
$(liblumiera_a_srcdir)/time.h \
$(liblumiera_a_srcdir)/ppmpl.h \
$(liblumiera_a_srcdir)/allocationcluster.hpp \
$(liblumiera_a_srcdir)/scopedholdertransfer.hpp \
$(liblumiera_a_srcdir)/scopedholder.hpp \
$(liblumiera_a_srcdir)/external/libgavl.hpp \
$(liblumiera_a_srcdir)/scopedholder.hpp \
$(liblumiera_a_srcdir)/external/libgavl.hpp \
$(liblumiera_a_srcdir)/lifecycleregistry.hpp

View file

@ -22,7 +22,7 @@
#include "lib/allocationcluster.hpp"
#include "common/error.hpp"
#include "include/error.hpp"
#include "common/util.hpp"
using util::isnil;
@ -163,7 +163,7 @@ namespace lib {
*/
AllocationCluster::AllocationCluster()
{
TRACE (buildermem, "new AllocationCluster");
TRACE (memory, "new AllocationCluster");
}
@ -177,7 +177,7 @@ namespace lib {
{
Thread::Lock<AllocationCluster> guard SIDEEFFECT
TRACE (buildermem, "shutting down AllocationCluster");
TRACE (memory, "shutting down AllocationCluster");
for (size_t i = typeHandlers_.size(); 0 < i; --i)
if (handler(i))
handler(i)->purge();
@ -187,7 +187,7 @@ namespace lib {
}
catch (lumiera::Error & ex)
{
WARN (oper, "Exception while closing AllocationCluster: %s",ex.what());
WARN (operate, "Exception while closing AllocationCluster: %s",ex.what());
}
catch (...)
{

View file

@ -52,7 +52,7 @@
#include <boost/noncopyable.hpp>
#include "common/multithread.hpp"
#include "common/error.hpp"
#include "include/error.hpp"
#include "lib/scopedholder.hpp"
#include "lib/scopedholdertransfer.hpp"

View file

@ -1,140 +0,0 @@
/*
Appconfig - for global initialization and configuration
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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/appconfig.hpp"
#include "common/error.hpp"
#include "common/util.hpp"
using util::isnil;
using util::cStr;
namespace lumiera
{
#ifndef LUMIERA_VERSION
#define LUMIERA_VERSION 0++devel
#endif
Symbol ON_BASIC_INIT ("ON_BASIC_INIT");
Symbol ON_GLOBAL_INIT ("ON_GLOBAL_INIT");
Symbol ON_GLOBAL_SHUTDOWN ("ON_GLOBAL_SHUTDOWN");
/** perform initialization triggered on first access.
* Will execute the ON_BASIC_INIT hook, but under typical
* circumstances this is a NOP, because when callbacks are
* added to this hook, the Appconfig singleton instance has
* already been created. For this reason, there is special
* treatment for the ON_BASIC_INIT in LifecycleHook::add,
* causing the provided callbacks to be fired immediately.
* (btw, this is nothing to be worried of, because from
* client codes POV it just behaves like intended).
*/
Appconfig::Appconfig()
: configParam_ (new Configmap),
lifecycleHooks_(new LifecycleRegistry)
{
lifecycleHooks_->execute (ON_BASIC_INIT); // note in most cases a NOP
(*configParam_)["version"] = STRINGIFY (LUMIERA_VERSION);
}
const string &
Appconfig::get (const string & key)
{
try
{
const string& val = (*instance().configParam_)[key];
WARN_IF ( isnil(val), config, "undefined config parameter \"%s\" requested.", key.c_str());
return val;
}
catch (...)
{
ERROR (config, "error while accessing configuration parameter \"%s\".", key.c_str());
static string NOTFOUND ("");
return NOTFOUND;
} }
void
Appconfig::lifecycle (Symbol event_label)
{
instance().lifecycleHooks_->execute(event_label);
}
// ==== implementation LifecycleHook class =======
typedef LifecycleRegistry::Hook Callback;
LifecycleHook::LifecycleHook (Symbol eventLabel, Callback callbackFun)
{
this->add (eventLabel,callbackFun);
}
LifecycleHook&
LifecycleHook::add (Symbol eventLabel, Callback callbackFun)
{
bool isNew = Appconfig::instance().lifecycleHooks_->enroll (eventLabel,callbackFun);
if (isNew && !strcmp(ON_BASIC_INIT, eventLabel))
callbackFun(); // when this code executes,
// then per definition we are already post "basic init"
// (which happens in the Appconfig ctor); thus fire it immediately
return *this;
}
} // namespace lumiera
// ==== implementation C interface =======
void
lumiera_LifecycleHook_add (const char* eventLabel, void callbackFun(void))
{
lumiera::LifecycleHook (eventLabel, callbackFun);
}
void
lumiera_Lifecycle_execute (const char* eventLabel)
{
lumiera::Appconfig::lifecycle (eventLabel);
}
const char*
lumiera_Appconfig_get (const char* key)
{
return cStr (lumiera::Appconfig::get(key));
}

View file

@ -1,158 +0,0 @@
/*
APPCONFIG.hpp - for global initialization and configuration
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file appconfig.hpp
** Registering and managing some application-global services.
** Besides \link Appconfig::get querying \endlink for some
** "Application property" constants, there is a mechanism for
** registering and firing off application lifecycle event hooks.
** The implementation of some subsystem can define a static instance
** variable of class LifecycleHook, which will place the provided
** callback function into a central registry accessable through
** the Appconfig singleton instance.
**
** @see lumiera.cpp
** @see nobugcfg.cpp
** @see sessmanagerimpl.cpp
*/
#ifndef LUMIERA_APPCONFIG_H
#define LUMIERA_APPCONFIG_H
#include <map>
#include <string>
#include <boost/scoped_ptr.hpp>
#include <boost/noncopyable.hpp>
#include "lib/lifecycleregistry.hpp"
namespace lumiera
{
using std::string;
using boost::scoped_ptr;
using boost::noncopyable;
/**
* Singleton to hold inevitable global flags and constants
* and for performing early (static) global initialization tasks.
* Appconfig services are available already from static
* initialsation code.
* @warning don't use Appconfig in destuctors.
*/
class Appconfig
: private noncopyable
{
private:
/** perform initialization on first access.
* @see #instance()
*/
Appconfig ();
~Appconfig () throw() {}; ///< deletion prohibited
friend void boost::checked_delete<Appconfig>(Appconfig*);
public:
/** get the (single) Appconfig instance.
* Implemented as Meyers singleton.
* @warning don't use it after the end of main()!
*/
static Appconfig& instance()
{
static scoped_ptr<Appconfig> theApp_ (0);
if (!theApp_) theApp_.reset (new Appconfig ());
return *theApp_;
}
/** access the configuation value for a given key.
* @return empty string for unknown keys, config value else */
static const string & get (const string& key); // never throws
/** fire off all lifecycle callbacks
* registered under the given label */
static void lifecycle (Symbol eventLabel);
// note: if necessary, we can add support
// for querying the current lifecycle phase...
private:
typedef std::map<string,string> Configmap;
typedef scoped_ptr<Configmap> PConfig;
typedef scoped_ptr<LifecycleRegistry> PLife;
PConfig configParam_;
PLife lifecycleHooks_;
friend class LifecycleHook;
};
extern Symbol ON_BASIC_INIT; ///< automatic static init. treated specially
extern Symbol ON_GLOBAL_INIT; ///< to be triggered in main() @note no magic!
extern Symbol ON_GLOBAL_SHUTDOWN; ///< to be triggered at the end of main() @note no magic!
// client code is free to register and use additional lifecycle events
/**
* define and register a callback for some lifecycle event.
* The purpose of this class is to be defined as a static variable
* in the implementation of some subsystem (i.e. in the cpp file),
* providing the ctor with the pointer to a callback function.
* Thus the callback gets enrolled when the corresponding object
* file is loaded. The event ON_BASIC_INIT is handled specifically,
* firing off the referred callback function as soon as possible.
* All other lables are just arbitrary (string) constants and it
* is necessary that "someone" cares to fire off the lifcycle events
* at the right place. For example, lumiera-main (and the test runner)
* calls \c Appconfig::instance().execute(ON_GLOBAL_INIT) (and..SHUTDOWN)
* @note duplicate or repeated calls with the same callback are a NOP
*/
class LifecycleHook
: private noncopyable
{
public:
LifecycleHook (Symbol eventLabel, LifecycleRegistry::Hook callbackFun);
LifecycleHook& add (Symbol eventLabel, LifecycleRegistry::Hook callbackFun); ///< for chained calls (add multiple callbacks)
};
} // namespace lumiera
extern "C" { //TODO provide a separate header if some C code happens to need this...
void lumiera_LifecycleHook_add (const char* eventLabel, void callbackFun(void));
void lumiera_Lifecycle_execute (const char* eventLabel);
const char* lumiera_Appconfig_get (const char* key);
}
#endif

View file

@ -22,9 +22,9 @@
#include "common/cmdline.hpp"
#include "lib/cmdline.hpp"
#include "common/util.hpp"
#include "proc/nobugcfg.hpp"
#include "include/nobugcfg.h"
#include <boost/regex.hpp>
#include <boost/algorithm/string/split.hpp>
@ -50,8 +50,8 @@ using boost::regex_search;
namespace util
{
/** create as a tokenized <i>copy</i> of the current commandline.
* Note that argv[0] is allways ignored. */
/** create as a tokenised <i>copy</i> of the current commandline.
* Note that argv[0] is always ignored. */
Cmdline::Cmdline (int argc, const char** argv)
: vector<string> (noneg(argc-1))
{
@ -63,7 +63,7 @@ namespace util
}
/** create by tokenizing a string
/** create by tokenising a string
* (e.g. "fake" cmdline, separated by whitespace)
*/
Cmdline::Cmdline (const string cmdline)

View file

@ -30,8 +30,8 @@
namespace util
{
namespace util {
using std::string;
using std::vector;
using std::ostream;

View file

@ -21,7 +21,7 @@
* *****************************************************/
#include "proc/lumiera.hpp"
#include "proc/common.hpp"
#include "lib/external/libgavl.hpp"
#include "proc/control/stypemanager.hpp"

88
src/lib/functorutil.hpp Normal file
View file

@ -0,0 +1,88 @@
/*
FUNCTORUTIL.hpp - collection of helpers for dealing with functors and signals
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 FUNCTORUTIL_H_
#define FUNCTORUTIL_H_
#include <tr1/functional>
namespace util { ////////////TODO: refactor it. But probably not directly into namespace lib. Needs some more consideration though
using std::tr1::function;
using std::tr1::bind;
using std::tr1::placeholders::_1;
/** "Combiner" which calls two functions one after another
* returning the result of the second invocation. */
template<typename SIG>
class CombineSequenced;
template<typename ARG, typename RET>
struct CombineSequenced<RET(ARG)>
{
typedef function<RET(ARG)> Func;
static RET
dispatch (Func first, Func second, ARG arg)
{
first (arg);
return second (arg);
}
};
template< typename SIG
, class COM = CombineSequenced<SIG>
>
class Dispatch
: public function<SIG>
{
typedef typename COM::Func Func;
public:
Dispatch (Func const& f1,
Func const& f2)
: Func (bind (&COM::dispatch, f1, f2, _1))
{ }
};
/** convenience shortcut to call two functors in sequence.
* @return a Dispatch functor object which incorporates the
* functors as copy and on invocation calls the first
* function and then returns the result of the second */
template<typename SIG>
Dispatch<SIG>
dispatchSequenced (function<SIG> const& f1,
function<SIG> const& f2)
{
return Dispatch<SIG> (f1, f2);
}
} // namespace util
#endif /*UTIL_HPP_*/

View file

@ -23,45 +23,43 @@
/** @file lifecycleregistry.hpp
** Helper for registering lifecycle event callbacks, which are
** provided as a global service by lumiera::Appconfig. This service
** allows to enroll functions under a given label and then to call
** provided as a global service by lumiera::AppState. This service
** allows to enrol functions under a given label and then to call
** all those registered functions.
** @note this is in fact an event mechanism, and if we start using
** more than just this basic functionallity, we should switch to
** more than just this basic functionality, we should switch to
** boost::signals. (which has the downside of being an binary
** dependency).
**
** @see appconfig.hpp
** @see appstate.hpp
*/
#ifndef LUMIERA_LIFECYCLE_H
#define LUMIERA_LIFECYCLE_H
#ifndef LUMIERA_LIFECYCLEREGISTRY_H
#define LUMIERA_LIFECYCLEREGISTRY_H
#include <map>
#include <set>
#include <string>
#include <boost/function.hpp>
#include <tr1/functional>
#include <boost/noncopyable.hpp>
#include "common/util.hpp"
namespace lumiera
{
namespace lumiera {
using boost::noncopyable;
using boost::function;
using std::tr1::function;
using util::contains;
using std::string;
typedef const char * const Symbol; //TODO define a real Symbol class, i.e. same literal string==same pointer,
// so we don't have to store string keys in the map...
/**
* Registry of callback functions accessable by a label (ID)
* Registry of callback functions accessible by a label (ID)
* provided at registration. Registered functions will be added
* to a list, which can be triggered via label. Used by Appconfig
* to a list, which can be triggered via label. Used by AppState
* to implement the lumiera lifecycle (init, shutdown) hooks.
*/
class LifecycleRegistry
@ -73,6 +71,7 @@ namespace lumiera
typedef Callbacks::iterator Iter;
/** @note only one copy of each distinct callback remembered */
bool enroll (const string label, Hook toCall)
{
return table_[label]
@ -94,7 +93,7 @@ namespace lumiera
std::map<const string, Callbacks> table_;
LifecycleRegistry () {}
friend class Appconfig;
friend class AppState;
};

View file

@ -30,7 +30,7 @@
* @file
* Most recent used cache
* Elements (addressed by a LList node) are either checked in the cache and thereby subject of aging
* or checked out under control of the user. Most operations require that the chache is locked. This locking
* or checked out under control of the user. Most operations require that the cache is locked. This locking
* must be done from elsewhere.
*/
@ -63,7 +63,7 @@ lumiera_mrucache_init (LumieraMruCache self, lumiera_cache_destructor_fn destruc
/**
* Destroy a cache.
* frees all checked in items.
* calls the registered destructor and frees all checked in items.
* @param self cache to be destroyed
* @return self
*/
@ -133,7 +133,8 @@ static inline void
lumiera_mrucache_checkout (LumieraMruCache self, LList node)
{
REQUIRE (self);
REQUIRE (node && llist_is_member (&self->cache_list, node)); /* speedup loop warning :P, this check is costly */
/* speedup loop warning :P, this check is costly */
REQUIRE (node && llist_is_member (&self->cache_list, node), "Node not in cache");
llist_unlink (node);
--self->cached;
}
@ -144,7 +145,7 @@ lumiera_mrucache_checkout (LumieraMruCache self, LList node)
* This function is used to get a new element by deleting the oldest least used one from the cache.
* The cache must be locked for this operation.
* @param self cache
* @return pointer to the uninitialized memory ready for being reused
* @return pointer to the uninitialized memory ready for being reused or NULL when no element was available
*/
static inline void*
lumiera_mrucache_pop (LumieraMruCache self)

View file

@ -69,7 +69,55 @@
#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_FOREACH15(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH16(p, __VA_ARGS__)
#define PPMPL_FOREACH16(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH17(p, __VA_ARGS__)
#define PPMPL_FOREACH17(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH18(p, __VA_ARGS__)
#define PPMPL_FOREACH18(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH19(p, __VA_ARGS__)
#define PPMPL_FOREACH19(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH20(p, __VA_ARGS__)
#define PPMPL_FOREACH20(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH21(p, __VA_ARGS__)
#define PPMPL_FOREACH21(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH22(p, __VA_ARGS__)
#define PPMPL_FOREACH22(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH23(p, __VA_ARGS__)
#define PPMPL_FOREACH23(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH24(p, __VA_ARGS__)
#define PPMPL_FOREACH24(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH25(p, __VA_ARGS__)
#define PPMPL_FOREACH25(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH26(p, __VA_ARGS__)
#define PPMPL_FOREACH26(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH27(p, __VA_ARGS__)
#define PPMPL_FOREACH27(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH28(p, __VA_ARGS__)
#define PPMPL_FOREACH28(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH29(p, __VA_ARGS__)
#define PPMPL_FOREACH29(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH30(p, __VA_ARGS__)
#define PPMPL_FOREACH30(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH31(p, __VA_ARGS__)
#define PPMPL_FOREACH31(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH32(p, __VA_ARGS__)
#define PPMPL_FOREACH32(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH33(p, __VA_ARGS__)
#define PPMPL_FOREACH33(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH34(p, __VA_ARGS__)
#define PPMPL_FOREACH34(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH35(p, __VA_ARGS__)
#define PPMPL_FOREACH35(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH36(p, __VA_ARGS__)
#define PPMPL_FOREACH36(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH37(p, __VA_ARGS__)
#define PPMPL_FOREACH37(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH38(p, __VA_ARGS__)
#define PPMPL_FOREACH38(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH39(p, __VA_ARGS__)
#define PPMPL_FOREACH39(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH40(p, __VA_ARGS__)
#define PPMPL_FOREACH40(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH41(p, __VA_ARGS__)
#define PPMPL_FOREACH41(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH42(p, __VA_ARGS__)
#define PPMPL_FOREACH42(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH43(p, __VA_ARGS__)
#define PPMPL_FOREACH43(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH44(p, __VA_ARGS__)
#define PPMPL_FOREACH44(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH45(p, __VA_ARGS__)
#define PPMPL_FOREACH45(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH46(p, __VA_ARGS__)
#define PPMPL_FOREACH46(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH47(p, __VA_ARGS__)
#define PPMPL_FOREACH47(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH48(p, __VA_ARGS__)
#define PPMPL_FOREACH48(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH49(p, __VA_ARGS__)
#define PPMPL_FOREACH49(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH50(p, __VA_ARGS__)
#define PPMPL_FOREACH50(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH51(p, __VA_ARGS__)
#define PPMPL_FOREACH51(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH52(p, __VA_ARGS__)
#define PPMPL_FOREACH52(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH53(p, __VA_ARGS__)
#define PPMPL_FOREACH53(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH54(p, __VA_ARGS__)
#define PPMPL_FOREACH54(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH55(p, __VA_ARGS__)
#define PPMPL_FOREACH55(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH56(p, __VA_ARGS__)
#define PPMPL_FOREACH56(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH57(p, __VA_ARGS__)
#define PPMPL_FOREACH57(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH58(p, __VA_ARGS__)
#define PPMPL_FOREACH58(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH59(p, __VA_ARGS__)
#define PPMPL_FOREACH59(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH60(p, __VA_ARGS__)
#define PPMPL_FOREACH60(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH61(p, __VA_ARGS__)
#define PPMPL_FOREACH61(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH62(p, __VA_ARGS__)
#define PPMPL_FOREACH62(p, h, ...) PPMPL_FOREACH##p##h PPMPL_FOREACH63(p, __VA_ARGS__)
#define PPMPL_FOREACH63(p, h, ...) PPMPL_FOREACH##p##h
#define PPMPL_FOREACH_
#define PPMPL_FOREACH_P1_
#define PPMPL_FOREACH_P2_
@ -99,7 +147,55 @@
#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_15(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_16(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_16(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_17(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_17(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_18(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_18(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_19(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_19(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_20(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_20(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_21(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_21(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_22(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_22(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_23(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_23(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_24(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_24(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_25(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_25(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_26(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_26(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_27(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_27(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_28(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_28(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_29(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_29(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_30(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_30(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_31(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_31(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_32(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_32(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_33(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_33(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_34(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_34(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_35(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_35(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_36(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_36(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_37(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_37(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_38(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_38(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_39(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_39(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_40(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_40(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_41(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_41(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_42(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_42(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_43(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_43(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_44(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_44(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_45(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_45(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_46(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_46(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_47(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_47(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_48(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_48(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_49(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_49(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_50(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_50(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_51(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_51(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_52(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_52(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_53(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_53(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_54(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_54(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_55(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_55(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_56(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_56(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_57(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_57(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_58(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_58(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_59(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_59(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_60(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_60(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_61(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_61(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_62(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_62(p, h, ...) PPMPL_FOREACH_L1##p##h PPMPL_FOREACH_L1_63(p, __VA_ARGS__)
#define PPMPL_FOREACH_L1_63(p, h, ...) PPMPL_FOREACH_L1##p##h
#define PPMPL_FOREACH_L1_
#define PPMPL_FOREACH_L1_P1_
#define PPMPL_FOREACH_L1_P2_
@ -129,7 +225,55 @@
#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_15(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_16(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_16(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_17(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_17(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_18(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_18(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_19(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_19(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_20(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_20(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_21(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_21(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_22(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_22(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_23(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_23(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_24(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_24(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_25(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_25(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_26(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_26(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_27(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_27(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_28(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_28(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_29(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_29(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_30(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_30(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_31(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_31(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_32(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_32(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_33(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_33(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_34(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_34(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_35(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_35(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_36(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_36(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_37(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_37(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_38(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_38(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_39(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_39(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_40(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_40(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_41(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_41(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_42(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_42(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_43(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_43(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_44(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_44(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_45(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_45(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_46(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_46(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_47(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_47(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_48(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_48(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_49(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_49(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_50(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_50(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_51(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_51(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_52(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_52(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_53(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_53(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_54(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_54(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_55(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_55(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_56(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_56(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_57(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_57(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_58(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_58(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_59(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_59(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_60(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_60(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_61(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_61(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_62(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_62(p, h, ...) PPMPL_FOREACH_L2##p##h PPMPL_FOREACH_L2_63(p, __VA_ARGS__)
#define PPMPL_FOREACH_L2_63(p, h, ...) PPMPL_FOREACH_L2##p##h
#define PPMPL_FOREACH_L2_
#define PPMPL_FOREACH_L2_P1_
#define PPMPL_FOREACH_L2_P2_

View file

@ -57,7 +57,7 @@
#include <boost/scoped_ptr.hpp>
#include "common/error.hpp"
#include "include/error.hpp"

View file

@ -25,7 +25,7 @@
#ifndef LIB_SCOPEDHOLDERVECTOR_H
#define LIB_SCOPEDHOLDERVECTOR_H
#include "common/error.hpp"
#include "include/error.hpp"
#include <memory>

7
src/lumiera/DIR_INFO Normal file
View file

@ -0,0 +1,7 @@
The main application shell
contains:
* the config system
* commandline parsing
* interfaces and plugin loading
* lua interpreter (planned)

72
src/lumiera/Makefile.am Normal file
View file

@ -0,0 +1,72 @@
# 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.
lumiera_srcdir = $(top_srcdir)/src/lumiera
noinst_LIBRARIES += liblumieracore.a
liblumieracore_a_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_PLUGIN_PATH="\"$(pkglibdir)\"" -DLUMIERA_CONFIG_PATH="\"$(pkgdatadir)/config\""
liblumieracore_a_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror
liblumieracore_a_SOURCES = \
$(lumiera_srcdir)/config.c \
$(lumiera_srcdir)/config_typed.c \
$(lumiera_srcdir)/config_wordlist.c \
$(lumiera_srcdir)/configentry.c \
$(lumiera_srcdir)/configitem.c \
$(lumiera_srcdir)/config_lookup.c \
$(lumiera_srcdir)/config_interface.c \
$(lumiera_srcdir)/interface.c \
$(lumiera_srcdir)/interfaceregistry.c \
$(lumiera_srcdir)/plugin.c \
$(lumiera_srcdir)/plugin_dynlib.c \
$(lumiera_srcdir)/guifacade.cpp \
$(lumiera_srcdir)/configfacade.cpp \
$(lumiera_srcdir)/appstate.cpp \
$(lumiera_srcdir)/option.cpp \
$(lumiera_srcdir)/subsys.cpp \
$(lumiera_srcdir)/interfaceproxy.cpp \
$(lumiera_srcdir)/nobugcfg.cpp
bin_PROGRAMS += lumiera
lumiera_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_CONFIG_PATH="\"$(pkgdatadir)/config\""
lumiera_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror
lumiera_LDADD = liblumieracore.a liblumibackend.a liblumiproc.a liblumiera.a liblumicommon.a \
$(LUMIERA_PLUGIN_LIBS) $(NOBUGMT_LUMIERA_LIBS) -lboost_program_options-mt -lboost_regex-mt
lumiera_SOURCES = \
$(top_srcdir)/src/guistart.cpp \
$(top_srcdir)/src/main.cpp
noinst_HEADERS += \
$(lumiera_srcdir)/interface.h \
$(lumiera_srcdir)/interfaceregistry.h \
$(lumiera_srcdir)/interfacedescriptor.h \
$(lumiera_srcdir)/plugin.h \
$(lumiera_srcdir)/config.h \
$(lumiera_srcdir)/configentry.h \
$(lumiera_srcdir)/configitem.h \
$(lumiera_srcdir)/config_lookup.h \
$(lumiera_srcdir)/config_interface.h \
$(lumiera_srcdir)/subsys.hpp \
$(lumiera_srcdir)/appstate.hpp \
$(lumiera_srcdir)/option.hpp \
$(lumiera_srcdir)/subsystemrunner.hpp \
$(lumiera_srcdir)/instancehandle.hpp

325
src/lumiera/appstate.cpp Normal file
View file

@ -0,0 +1,325 @@
/*
AppState - application initialisation and behaviour
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 "include/error.hpp"
#include "include/lifecycle.h"
#include "lumiera/appstate.hpp"
#include "lib/lifecycleregistry.hpp"
#include "lumiera/subsystemrunner.hpp"
extern "C" {
#include "lumiera/config_interface.h"
#include "lumiera/interface.h"
#include "lumiera/interfaceregistry.h"
#include "lumiera/plugin.h"
}
#include "common/util.hpp"
#include "include/configfacade.hpp" //////////TODO: temp hack to force configfacade.o to be linked in
using util::cStr;
namespace lumiera {
namespace { // implementation details
inline void
log_and_clear_unexpected_errorstate ()
{
if (const char * errorstate = lumiera_error ())
ERROR (NOBUG_ON, "*** Unexpected error: %s\n Triggering emergency exit.", errorstate);
} }
/** perform initialisation triggered on first access.
* Will execute the ON_BASIC_INIT hook, but under typical
* circumstances this is a NOP, because when callbacks are
* added to this hook, the AppState singleton instance has
* already been created. For this reason, there is special
* treatment for the ON_BASIC_INIT in LifecycleHook::add,
* causing the provided callbacks to be fired immediately.
* (btw, this is nothing to be worried of, because from
* client codes POV it just behaves like intended).
*/
AppState::AppState()
: lifecycleHooks_(new LifecycleRegistry)
, subsystems_(0)
, emergency_(false)
, core_up_ (false)
{
lifecycleHooks_->execute (ON_BASIC_INIT); // note in most cases a NOP
}
AppState&
AppState::instance() // Meyer's singleton
{
static scoped_ptr<AppState> theApp_ (0);
if (!theApp_) theApp_.reset (new AppState ());
return *theApp_;
}
void
AppState::lifecycle (Symbol event_label)
{
instance().lifecycleHooks_->execute(event_label);
}
// ===== Implementation startup and shutdown sequence for main() ========
#define _THROW_IF \
if (lumiera_error_peek()) \
throw error::Fatal (lumiera_error());
void
AppState::init (Option& options)
{
TRACE (lumiera, "initialising application core...");
lumiera_interfaceregistry_init ();
_THROW_IF
TODO ("use a plugindb instead of loading all plugins at once");
lumiera_plugin_discover (lumiera_plugin_load, lumiera_plugin_register);
_THROW_IF
lumiera_config_interface_init ();
_THROW_IF
core_up_= true;
AppState::lifecycle (ON_GLOBAL_INIT);
_THROW_IF
subsystems_.reset (new SubsystemRunner (options));
TRACE (lumiera, "Lumiera core started successfully.");
}
void
AppState::maybeStart (lumiera::Subsys& subsys)
{
TRACE (lumiera, "maybe startup %s...?", cStr(subsys));
ASSERT (subsystems_);
subsystems_->maybeRun (subsys);
}
typedef AppState::ExitCode ExitCode;
/** @par
* This function is executed at the end of main(), after the necessary subsystems
* have been started, typically in separate threads. Thus, the main thread will
* enter a blocking wait, until all activated subsystems have signalled shutdown.
* After returning, we can proceed with the normal shutdown sequence.
*
* The SubsystemRunner ensures that in case of a premature failure of one subsystem,
* the termination of all other subsystems is initiated; when detecting this case,
* the emergency exit sequence is called. Any error which can't be handled within
* this scheme, should be thrown as exception, in which case the abort handler
* is activated.
*/
ExitCode
AppState::maybeWait()
{
if (subsystems_)
{
emergency_ |= subsystems_->wait();
subsystems_.reset(0);
}
NOTICE (lumiera, "Shutting down Lumiera...");
if (emergency_)
{
ERROR (operate, "Triggering emergency exit...");
lifecycle (ON_EMERGENCY);
return CLEAN_EMERGENCY_EXIT;
}
else
{
lifecycle (ON_GLOBAL_SHUTDOWN);
return NORMAL_EXIT;
}
}
ExitCode
AppState::abort (lumiera::Error& problem)
{
INFO (operate, "Address of Config Facade = %x", &lumiera::Config::instance()); //////////TODO: a temp hack to force configfacade.cpp to be linked into lumiera exe.
ERROR (operate, "Aborting Lumiera after unhandled error: %s", cStr(problem.what()));
log_and_clear_unexpected_errorstate();
try
{
if (subsystems_)
{
subsystems_->triggerEmergency(true);
subsystems_->shutdownAll();
}
return maybeWait ();
}
catch (...)
{
return abort();
}
}
ExitCode
AppState::abort () throw()
{
log_and_clear_unexpected_errorstate();
if (emergency_)
{
lifecycle (ON_EMERGENCY);
return FAILED_EMERGENCY_EXIT;
}
else
{
lifecycle (ON_GLOBAL_SHUTDOWN);
return CLEAN_EXIT_AFTER_ERROR;
}
}
/** anything which should be closed as late as possible and after
* the normal shutdown sequence can be placed into the AppState dtor.
* But note though, when the application is halted unconditionally,
* not dtors will be executed.
*/
AppState::~AppState()
{
if (core_up_)
try
{
TRACE (lumiera, "shutting down basic application layer...");
lumiera_config_interface_destroy ();
lumiera_interfaceregistry_destroy ();
}
catch (...)
{
log_and_clear_unexpected_errorstate();
} }
// ==== implementation LifecycleHook class =======
typedef LifecycleRegistry::Hook Callback;
LifecycleHook::LifecycleHook (Symbol eventLabel, Callback callbackFun)
{
add (eventLabel,callbackFun);
}
void
LifecycleHook::add (Symbol eventLabel, Callback callbackFun)
{
bool isNew = AppState::instance().lifecycleHooks_->enroll (eventLabel,callbackFun);
if (isNew && !strcmp(ON_BASIC_INIT, eventLabel))
callbackFun(); // when this code executes,
// then per definition we are already post "basic init"
// (which happens in the AppState ctor); thus fire it immediately
}
void
LifecycleHook::trigger (Symbol eventLabel)
{
AppState::lifecycle (eventLabel);
}
Symbol ON_BASIC_INIT ("ON_BASIC_INIT");
Symbol ON_GLOBAL_INIT ("ON_GLOBAL_INIT");
Symbol ON_GLOBAL_SHUTDOWN ("ON_GLOBAL_SHUTDOWN");
Symbol ON_EMERGENCY ("ON_EMERGENCY");
} // namespace lumiera
extern "C" { /* ==== implementation C interface for lifecycle hooks ======= */
extern const char * lumiera_ON_BASIC_INIT = lumiera::ON_BASIC_INIT;
extern const char * lumiera_ON_GLOBAL_INIT = lumiera::ON_GLOBAL_INIT;
extern const char * lumiera_ON_GLOBAL_SHUTDOWN = lumiera::ON_GLOBAL_SHUTDOWN;
extern const char * lumiera_ON_EMERGENCY = lumiera::ON_EMERGENCY;
void
lumiera_LifecycleHook_add (const char* eventLabel, void callbackFun(void))
{
lumiera::LifecycleHook (eventLabel, callbackFun);
}
void
lumiera_Lifecycle_trigger (const char* eventLabel)
{
lumiera::AppState::lifecycle (eventLabel);
}
}

142
src/lumiera/appstate.hpp Normal file
View file

@ -0,0 +1,142 @@
/*
APPSTATE.hpp - application initialisation and behaviour
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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.
*/
/** @file appstate.hpp
** Registering and managing some application-global services.
** Besides encapsulating the logic for starting up the fundamental parts
** of the application, there is a mechanism for registering and firing off
** application lifecycle event callbacks.
**
** @see LifecycleHook
** @see main.cpp
** @see nobugcfg.h
*/
#ifndef LUMIERA_APPSTATE_H
#define LUMIERA_APPSTATE_H
#include "include/symbol.hpp"
#include "lumiera/option.hpp"
#include "lumiera/subsys.hpp"
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <string>
#include <map>
namespace lumiera {
using std::string;
using boost::scoped_ptr;
using boost::noncopyable;
class LifecycleRegistry;
class SubsystemRunner;
/**
* Singleton to hold global flags directing the overall application behaviour,
* for triggering lifecycle events and performing early initialisation tasks.
* AppState services are available already from static initialisation code.
* @warning don't use AppState in destructors.
*/
class AppState
: private noncopyable
{
private:
AppState ();
~AppState ();
friend void boost::checked_delete<AppState>(AppState*);
public:
/** get the (single) AppState instance.
* @warning don't use it after the end of main()! */
static AppState& instance();
/** fire off all lifecycle callbacks
* registered under the given label */
static void lifecycle (Symbol eventLabel);
/** evaluate the result of option parsing and maybe additional configuration
* such as to be able to determine the further behaviour of the application.
* Set the internal state within this object accordingly. */
void init (lumiera::Option& options);
/** building on the state determined by #evaluate, decide if the given Subsys
* needs to be pulled up and, if necessary, register the Subsys and its
* prerequisites to be maintained throughout the application's lifetime. */
void maybeStart (lumiera::Subsys&);
enum ExitCode {
NORMAL_EXIT,
CLEAN_EXIT_AFTER_ERROR,
CLEAN_EMERGENCY_EXIT,
FAILED_EMERGENCY_EXIT
};
/** put the main thread of the application into a wait state, if some subsystem(s)
* registered with #maybeStart still need to be maintained. On termination of
* one of those components, tear down the remaining components and initiate
* a normal or emergency shutdown of the application, depending on the
* triggering component's mode of termination (exit or exception).
* @return global application exit code */
ExitCode maybeWait();
/** initiate the controlled error shutdown sequence
* @param problem causing exception */
ExitCode abort (lumiera::Error& problem);
/** initiate an fatal emergency shutdown,
* caused by an unforeseen error condition */
ExitCode abort () throw();
private:
typedef scoped_ptr<LifecycleRegistry> PLife;
typedef scoped_ptr<SubsystemRunner> PSub;
PLife lifecycleHooks_;
PSub subsystems_;
bool emergency_;
bool core_up_;
friend class LifecycleHook;
};
} // namespace lumiera
#endif

View file

@ -24,7 +24,7 @@
//TODO: Lumiera header includes//
#include "backend/config.h"
#include "lumiera/config.h"
//TODO: internal/static forward declarations//
@ -39,8 +39,8 @@
*
*/
NOBUG_DEFINE_FLAG_PARENT (config_all, backend);
NOBUG_DEFINE_FLAG_PARENT (config, config_all);
NOBUG_DEFINE_FLAG_PARENT (config_all, lumiera_all);
NOBUG_DEFINE_FLAG_PARENT (configsys, config_all);
NOBUG_DEFINE_FLAG_PARENT (config_typed, config_all);
NOBUG_DEFINE_FLAG_PARENT (config_file, config_all);
NOBUG_DEFINE_FLAG_PARENT (config_item, config_all);
@ -53,7 +53,7 @@ LUMIERA_ERROR_DEFINE (CONFIG_NO_ENTRY, "no configuration entry");
/**
* defaults for the configuraton system itself
* defaults for the configuration system itself
*/
const char* lumiera_config_defaults[] =
{
@ -93,12 +93,12 @@ LumieraConfig lumiera_global_config = NULL;
int
lumiera_config_init (const char* path)
{
TRACE (config);
TRACE (configsys);
REQUIRE (!lumiera_global_config, "Configuration subsystem already initialized");
REQUIRE (path);
NOBUG_INIT_FLAG (config_all);
NOBUG_INIT_FLAG (config);
NOBUG_INIT_FLAG (configsys);
NOBUG_INIT_FLAG (config_typed);
NOBUG_INIT_FLAG (config_file);
NOBUG_INIT_FLAG (config_item);
@ -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_mutex_init (&lumiera_global_config->lock, "config mutex", &NOBUG_FLAG (config));
lumiera_mutex_init (&lumiera_global_config->lock, "config mutex", &NOBUG_FLAG (configsys));
lumiera_config_setdefault (lumiera_tmpbuf_snprintf (SIZE_MAX, "config.path = %s", path));
@ -127,10 +127,10 @@ lumiera_config_init (const char* path)
void
lumiera_config_destroy ()
{
TRACE (config);
TRACE (configsys);
if (lumiera_global_config)
{
lumiera_mutex_destroy (&lumiera_global_config->lock, &NOBUG_FLAG (config));
lumiera_mutex_destroy (&lumiera_global_config->lock, &NOBUG_FLAG (configsys));
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);
@ -139,7 +139,7 @@ lumiera_config_destroy ()
lumiera_global_config = NULL;
}
else
WARN (config, "Tried to destroy non initialized config subsystem");
WARN (configsys, "Tried to destroy non initialized config subsystem");
}
@ -147,7 +147,7 @@ int
lumiera_config_load (const char* file)
{
(void) file;
TRACE (config);
TRACE (configsys);
UNIMPLEMENTED();
return -1;
}
@ -156,7 +156,7 @@ lumiera_config_load (const char* file)
int
lumiera_config_save ()
{
TRACE (config);
TRACE (configsys);
UNIMPLEMENTED();
return -1;
}
@ -166,7 +166,7 @@ int
lumiera_config_purge (const char* filename)
{
(void) filename;
TRACE (config);
TRACE (configsys);
UNIMPLEMENTED();
return -1;
@ -176,7 +176,7 @@ lumiera_config_purge (const char* filename)
const char*
lumiera_config_get (const char* key, const char** value)
{
TRACE (config);
TRACE (configsys);
REQUIRE (key);
REQUIRE (value);
@ -193,10 +193,10 @@ lumiera_config_get (const char* key, const char** value)
{
char* env = lumiera_tmpbuf_snprintf (2048, "LUMIERA_%s", tr_key);
*value = getenv(env);
*value = getenv (env);
if (*value)
{
NOTICE (config, "envvar override for config %s = %s", env, *value);
NOTICE (configsys, "envvar override for config %s = %s", env, *value);
}
else
{
@ -208,12 +208,12 @@ lumiera_config_get (const char* key, const char** value)
*value = item->delim+1;
}
else
LUMIERA_ERROR_SET (config, CONFIG_NO_ENTRY);
LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY);
}
}
else
{
LUMIERA_ERROR_SET (config, CONFIG_SYNTAX_KEY);
LUMIERA_ERROR_SET (configsys, CONFIG_SYNTAX_KEY);
}
return *value;
@ -223,7 +223,7 @@ lumiera_config_get (const char* key, const char** value)
const char*
lumiera_config_get_default (const char* key, const char** value)
{
TRACE (config);
TRACE (configsys);
REQUIRE (key);
REQUIRE (value);
@ -245,7 +245,7 @@ lumiera_config_get_default (const char* key, const char** value)
LumieraConfigitem
lumiera_config_set (const char* key, const char* delim_value)
{
TRACE (config);
TRACE (configsys);
LumieraConfigitem item = lumiera_config_lookup_item_find (&lumiera_global_config->keys, key);
if (item && item->parent != &lumiera_global_config->defaults)
@ -287,12 +287,12 @@ lumiera_config_set (const char* key, const char* delim_value)
LumieraConfigitem
lumiera_config_setdefault (const char* line)
{
TRACE (config);
TRACE (configsys);
REQUIRE (line);
LumieraConfigitem item = NULL;
LUMIERA_MUTEX_SECTION (config, &lumiera_global_config->lock)
LUMIERA_MUTEX_SECTION (configsys, &lumiera_global_config->lock)
{
const char* key = line;
while (*key && isspace (*key))
@ -308,7 +308,7 @@ lumiera_config_setdefault (const char* line)
{
ENSURE (item->delim, "default must be a configentry with key=value or key<delegate syntax");
ENSURE (*item->delim == '=' || *item->delim == '<', "default must be a configentry with key=value or key<delegate syntax");
TRACE (config, "registering default: '%s'", item->line);
TRACE (configsys, "registering default: '%s'", item->line);
llist_insert_head (&lumiera_global_config->defaults.childs, &item->link);
item->parent = &lumiera_global_config->defaults;
@ -345,7 +345,7 @@ int
lumiera_config_reset (const char* key)
{
(void) key;
TRACE (config);
TRACE (configsys);
UNIMPLEMENTED();
return -1;
}
@ -357,7 +357,7 @@ lumiera_config_info (const char* key, const char** filename, unsigned* line)
(void) key;
(void) filename;
(void) line;
TRACE (config);
TRACE (configsys);
UNIMPLEMENTED();
return -1;
}

View file

@ -33,7 +33,7 @@ struct lumiera_config_struct;
/* master config subsystem debug flag */
NOBUG_DECLARE_FLAG (config_all);
/* config subsystem internals */
NOBUG_DECLARE_FLAG (config);
NOBUG_DECLARE_FLAG (configsys);
/* high level typed interface operations */
NOBUG_DECLARE_FLAG (config_typed);
/* file operations */
@ -51,8 +51,8 @@ LUMIERA_ERROR_DECLARE (CONFIG_NO_ENTRY);
//TODO: Lumiera header includes//
#include "backend/config_lookup.h"
#include "backend/configitem.h"
#include "lumiera/config_lookup.h"
#include "lumiera/configitem.h"
//TODO: System includes//
#include <nobug.h>
@ -86,7 +86,7 @@ typedef lumiera_config* LumieraConfig;
/* TODO: add here as 'LUMIERA_CONFIG_TYPE(name, ctype)' the _get/_set prototypes are declared automatically below, you still have to implement them in config.c */
#define LUMIERA_CONFIG_TYPES \
LUMIERA_CONFIG_TYPE(link, const char*) \
LUMIERA_CONFIG_TYPE(number, signed long long) \
LUMIERA_CONFIG_TYPE(number, long long) \
LUMIERA_CONFIG_TYPE(real, long double) \
LUMIERA_CONFIG_TYPE(string, const char*) \
LUMIERA_CONFIG_TYPE(wordlist, const char*) \
@ -95,7 +95,7 @@ typedef lumiera_config* LumieraConfig;
// * does only initialize the variables, so that they get valid values, but does not allocate them as they will be allocated before as they are singleton.
// * lumiera_config_init (const char* searchpath) searchpath is a buildin-default, can be changed via configure and can be appended and overridden by using a flag, e.g. {{{ --config-path-append="" }}} or {{{ --config-path="" }}}
// * lumiera_config_init (const char* searchpath) searchpath is a builtin-default, can be changed via configure and can be appended and overridden by using a flag, e.g. {{{ --config-path-append="" }}} or {{{ --config-path="" }}}
/**
* Initialize the configuration subsystem.
@ -240,7 +240,7 @@ lumiera_config_wordlist_get_nth (const char* key, unsigned nth, const char* deli
* @param key key under which this wordlist is stored
* @param value word to find
* @param delims a string literal listing all characters which are treated as delimiters
* @return index of the first occurence of the word or -1 in case of failure
* @return index of the first occurrence of the word or -1 in case of failure
*/
int
lumiera_config_wordlist_find (const char* key, const char* value, const char* delims);

View file

@ -0,0 +1,164 @@
/*
config_interface.c - Lumiera configuration interface 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.
*/
//TODO: Support library includes//
//TODO: Lumiera header includes//
#include "lumiera/config_interface.h"
#include "lumiera/config.h"
//TODO: internal/static forward declarations//
//TODO: System includes//
LUMIERA_EXPORT(
LUMIERA_INTERFACE_DEFINE (lumieraorg_configuration, 0,
lumieraorg_configuration,
NULL,
NULL,
NULL,
LUMIERA_INTERFACE_MAP (load, "\177\002\314\014\245\001\056\246\317\203\322\346\114\061\262\366",
lumiera_config_load),
LUMIERA_INTERFACE_MAP (save, "\271\141\152\017\060\312\103\343\342\063\007\142\374\201\163\334",
lumiera_config_save),
LUMIERA_INTERFACE_MAP (purge, "\321\275\170\140\010\075\323\340\371\050\345\131\267\070\076\130",
lumiera_config_purge),
LUMIERA_INTERFACE_MAP (dump, "\317\357\304\076\137\035\100\023\130\021\327\253\314\237\311\045",
lumiera_config_dump),
LUMIERA_INTERFACE_INLINE (setdefault, "\344\337\116\131\101\037\175\227\310\151\216\240\125\316\241\115",
int, (const char* line),
{return !!lumiera_config_setdefault (line);}
),
LUMIERA_INTERFACE_MAP (reset, "\337\143\274\052\364\362\256\353\165\161\352\267\026\204\154\231",
lumiera_config_reset),
LUMIERA_INTERFACE_MAP (info, "\355\305\326\372\236\302\122\253\114\024\376\010\326\055\132\130",
lumiera_config_info),
LUMIERA_INTERFACE_MAP (wordlist_get_nth, "\151\224\043\353\244\134\360\125\361\352\236\267\225\371\020\173",
lumiera_config_wordlist_get_nth),
LUMIERA_INTERFACE_MAP (wordlist_find, "\276\103\153\017\257\171\300\277\311\352\027\054\174\017\321\213",
lumiera_config_wordlist_find),
LUMIERA_INTERFACE_INLINE (wordlist_replace, "\365\115\171\203\374\371\236\246\212\021\121\003\161\364\060\011",
int, (const char* key,
const char* value,
const char* subst1,
const char* subst2,
const char* delims),
{return !!lumiera_config_wordlist_replace (key, value, subst1, subst2, delims);}
),
LUMIERA_INTERFACE_INLINE (wordlist_add, "\133\255\034\074\300\073\374\067\241\145\302\067\256\301\206\034",
int, (const char* key, const char* value, const char* delims),
{return !!lumiera_config_wordlist_add (key, value, delims);}
),
LUMIERA_INTERFACE_INLINE (link_get, "\062\177\332\266\004\256\323\102\252\064\153\054\313\151\124\361",
int, (const char* key, const char** value),
{return !!lumiera_config_link_get (key, value);}
),
LUMIERA_INTERFACE_INLINE (link_set, "\303\273\325\021\071\344\270\041\342\341\233\072\262\216\333\100",
int, (const char* key, const char** value),
{return !!lumiera_config_link_set (key, value);}
),
LUMIERA_INTERFACE_INLINE (number_get, "\300\070\066\026\154\053\052\176\212\021\376\240\314\224\235\300",
int, (const char* key, long long* value),
{return !!lumiera_config_number_get (key, value);}
),
LUMIERA_INTERFACE_INLINE (number_set, "\231\142\147\006\243\203\002\354\152\237\147\074\115\363\345\127",
int, (const char* key, long long* value),
{return !!lumiera_config_number_set (key, value);}
),
LUMIERA_INTERFACE_INLINE (real_get, "\356\335\127\112\365\220\056\000\051\077\247\013\046\210\164\120",
int, (const char* key, long double* value),
{return !!lumiera_config_real_get (key, value);}
),
LUMIERA_INTERFACE_INLINE (real_set, "\205\011\020\140\014\112\134\076\232\352\246\025\274\227\347\047",
int, (const char* key, long double* value),
{return !!lumiera_config_real_set (key, value);}
),
LUMIERA_INTERFACE_INLINE (string_get, "\215\104\350\103\163\245\065\235\373\237\364\155\312\225\027\304",
int, (const char* key, const char** value),
{return !!lumiera_config_string_get (key, value);}
),
LUMIERA_INTERFACE_INLINE (string_set, "\014\003\357\020\117\035\073\353\302\026\231\351\037\051\163\346",
int, (const char* key, const char** value),
{return !!lumiera_config_string_set (key, value);}
),
LUMIERA_INTERFACE_INLINE (wordlist_get, "\000\276\355\321\257\366\166\247\246\141\224\304\142\306\047\131",
int, (const char* key, const char** value),
{return !!lumiera_config_wordlist_get (key, value);}
),
LUMIERA_INTERFACE_INLINE (wordlist_set, "\340\352\216\303\161\056\354\264\121\162\003\061\345\001\306\265",
int, (const char* key, const char** value),
{return !!lumiera_config_wordlist_set (key, value);}
),
LUMIERA_INTERFACE_INLINE (word_get, "\057\337\302\110\276\332\307\172\035\012\246\315\370\203\226\135",
int, (const char* key, const char** value),
{return !!lumiera_config_word_get (key, value);}
),
LUMIERA_INTERFACE_INLINE (word_set, "\151\276\334\165\173\165\333\224\076\264\352\371\205\174\105\013",
int, (const char* key, const char** value),
{return !!lumiera_config_word_set (key, value);}
),
LUMIERA_INTERFACE_INLINE (bool_get, "\204\254\234\117\147\323\210\236\102\234\123\323\124\221\305\234",
int, (const char* key, int* value),
{return !!lumiera_config_bool_get (key, value);}
),
LUMIERA_INTERFACE_INLINE (bool_set, "\215\151\207\006\032\117\354\053\311\035\261\141\120\117\310\007",
int, (const char* key, int* value),
{return !!lumiera_config_bool_set (key, value);}
),
)
);
#ifndef LUMIERA_PLUGIN
#include "lumiera/interfaceregistry.h"
void
lumiera_config_interface_init (void)
{
LUMIERA_INTERFACE_REGISTEREXPORTED;
}
void
lumiera_config_interface_destroy (void)
{
LUMIERA_INTERFACE_UNREGISTEREXPORTED;
}
#endif
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -0,0 +1,85 @@
/*
config_interface.h - Lumiera configuration interface
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_CONFIG_INTERFACE_H
#define LUMIERA_CONFIG_INTERFACE_H
//TODO: Support library includes//
#include "lumiera/interface.h"
//TODO: Forward declarations//
/**
* @file
* Declares the interface for the lumiera configuration system
*/
void
lumiera_config_interface_init (void);
void
lumiera_config_interface_destroy (void);
/*
Note that some interfaces return ints rather than underlying opaque pointers, this is then the truth value of the pointer
*/
LUMIERA_INTERFACE_DECLARE (lumieraorg_configuration, 0,
LUMIERA_INTERFACE_SLOT (int, load, (const char* file)),
LUMIERA_INTERFACE_SLOT (int, save, (void)),
LUMIERA_INTERFACE_SLOT (int, purge, (const char* filename)),
LUMIERA_INTERFACE_SLOT (void, dump, (FILE* out)),
LUMIERA_INTERFACE_SLOT (int, setdefault, (const char* line)),
LUMIERA_INTERFACE_SLOT (int, reset, (const char* key)),
LUMIERA_INTERFACE_SLOT (int, info, (const char* key, const char** filename, unsigned* line)),
LUMIERA_INTERFACE_SLOT (const char*, wordlist_get_nth, (const char* key, unsigned nth, const char* delims)),
LUMIERA_INTERFACE_SLOT (int, wordlist_find, (const char* key, const char* value, const char* delims)),
LUMIERA_INTERFACE_SLOT (int, wordlist_replace,
(const char* key, const char* value, const char* subst1, const char* subst2, const char* delims)),
LUMIERA_INTERFACE_SLOT (int, wordlist_add, (const char* key, const char* value, const char* delims)),
LUMIERA_INTERFACE_SLOT (int, link_get, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, link_set, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, number_get, (const char* key, long long* value)),
LUMIERA_INTERFACE_SLOT (int, number_set, (const char* key, long long* value)),
LUMIERA_INTERFACE_SLOT (int, real_get, (const char* key, long double* value)),
LUMIERA_INTERFACE_SLOT (int, real_set, (const char* key, long double* value)),
LUMIERA_INTERFACE_SLOT (int, string_get, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, string_set, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, wordlist_get, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, wordlist_set, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, word_get, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, word_set, (const char* key, const char** value)),
LUMIERA_INTERFACE_SLOT (int, bool_get, (const char* key, int* value)),
LUMIERA_INTERFACE_SLOT (int, bool_set, (const char* key, int* value)),
);
#endif
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -20,8 +20,8 @@
*/
#include "lib/safeclib.h"
#include "backend/config_lookup.h"
#include "backend/config.h"
#include "lumiera/config_lookup.h"
#include "lumiera/config.h"
/* we only use one fatal error for now, when allocation in the config system fail, something else is pretty wrong */
LUMIERA_ERROR_DEFINE (CONFIG_LOOKUP, "config lookup failure");

View file

@ -33,7 +33,7 @@ typedef struct lumiera_config_lookupentry_struct lumiera_config_lookupentry;
typedef lumiera_config_lookupentry* LumieraConfigLookupentry;
#include "backend/configitem.h"
#include "lumiera/configitem.h"
#include <nobug.h>

View file

@ -24,7 +24,7 @@
//TODO: Lumiera header includes//
#include "backend/config.h"
#include "lumiera/config.h"
//TODO: internal/static forward declarations//
extern LumieraConfig lumiera_global_config;
@ -82,7 +82,7 @@ lumiera_config_number_get (const char* key, long long* value)
}
}
else
LUMIERA_ERROR_SET (config, CONFIG_NO_ENTRY);
LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY);
}
}
@ -208,7 +208,7 @@ lumiera_config_string_get (const char* key, const char** value)
*value = scan_string (raw_value);
}
else
LUMIERA_ERROR_SET (config, CONFIG_NO_ENTRY);
LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY);
}
}
@ -253,7 +253,7 @@ lumiera_config_wordlist_get (const char* key, const char** value)
*value = raw_value;
}
else
LUMIERA_ERROR_SET (config, CONFIG_NO_ENTRY);
LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY);
TODO ("remove the ERROR_SET because config_get sets it already? also in all other getters in this file");
}
@ -322,7 +322,7 @@ lumiera_config_word_get (const char* key, const char** value)
*value = scan_word (raw_value);
}
else
LUMIERA_ERROR_SET (config, CONFIG_NO_ENTRY);
LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY);
}
}

View file

@ -23,7 +23,7 @@
#include "lib/safeclib.h"
#include "backend/config.h"
#include "lumiera/config.h"
extern LumieraConfig lumiera_global_config;

View file

@ -23,7 +23,7 @@
#include "lib/safeclib.h"
//TODO: Lumiera header includes//
#include "backend/configentry.h"
#include "lumiera/configentry.h"
//TODO: internal/static forward declarations//

View file

@ -31,7 +31,7 @@ typedef lumiera_configentry* LumieraConfigentry;
//TODO: Lumiera header includes//
#include "backend/configitem.h"
#include "lumiera/configitem.h"
//TODO: System includes//
#include <nobug.h>

View file

@ -0,0 +1,97 @@
/*
ConfigFacade - C++ convenience wrapper and startup of the config system
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 "include/nobugcfg.h"
#include "include/lifecycle.h"
#include "include/configfacade.hpp"
extern "C" { // TODO: can't include "lumiera/config.h" from C++ code, because it uses an identifier "new"
/** Initialise the configuration subsystem.
* Must be called exactly once prior to any use
* @param path search path for config files.
*/
int lumiera_config_init (const char* path);
/** Destroys the configuration subsystem.
* Subsequent calls are no-op. */
void
lumiera_config_destroy ();
}
#ifndef LUMIERA_CONFIG_PATH
#error LUMIERA_CONFIG_PATH not defined
#endif
namespace lumiera {
namespace {
void
pull_up_ConfigSystem ()
{
TRACE (lumiera, "booting up config system");
Config::instance();
}
LifecycleHook trigger__ (ON_BASIC_INIT, &pull_up_ConfigSystem);
}
/** storage for the single system-wide config facade instance */
Singleton<Config> Config::instance;
Config::Config ()
{
lumiera_config_init (LUMIERA_CONFIG_PATH);
INFO (config, "Config system ready.");
TODO ("wire Config facade to config interface");
}
Config::~Config()
{
lumiera_config_destroy();
TRACE (lumiera, "config system closed.");
}
const string
Config::get (string const& key)
{
UNIMPLEMENTED ("config facade access to config value");
return string("warwohlnix");
}
} // namespace lumiera

Some files were not shown because too many files have changed in this diff Show more