diff --git a/Makefile.am b/Makefile.am index 068388274..8b31a802c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/SConstruct b/SConstruct index 26efb00e8..138b5ac7e 100644 --- a/SConstruct +++ b/SConstruct @@ -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']) diff --git a/admin/scons/Buildhelper.py b/admin/scons/Buildhelper.py index 38940424c..7eef32750 100644 --- a/admin/scons/Buildhelper.py +++ b/admin/scons/Buildhelper.py @@ -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 diff --git a/bin/.libs b/bin/.libs new file mode 120000 index 000000000..2e321a8e9 --- /dev/null +++ b/bin/.libs @@ -0,0 +1 @@ +../.libs \ No newline at end of file diff --git a/doc/devel/Doxyfile b/doc/devel/Doxyfile index 9b276233e..02d2d787c 100644 --- a/doc/devel/Doxyfile +++ b/doc/devel/Doxyfile @@ -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 diff --git a/doc/devel/Doxyfile.browse b/doc/devel/Doxyfile.browse new file mode 100644 index 000000000..25c664b83 --- /dev/null +++ b/doc/devel/Doxyfile.browse @@ -0,0 +1,1472 @@ +# Doxyfile 1.5.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Lumiera + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.1+pre + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = ../../src/ \ + ../../tests/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = warnings_browse.txt + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../../src/ \ + ../../tests/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.PY + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = lumiera:: \ + lumiera_ \ + lumi_ \ + LUMIERA_ + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html_browse + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Lumiera Doxygen docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hiererachy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = YES + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = YES + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = NO + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is enabled by default, which results in a transparent +# background. Warning: Depending on the platform used, enabling this option +# may lead to badly anti-aliased labels on the edges of a graph (i.e. they +# become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = NO + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/doc/devel/Doxyfile.pdf b/doc/devel/Doxyfile.pdf new file mode 100644 index 000000000..c59afa02d --- /dev/null +++ b/doc/devel/Doxyfile.pdf @@ -0,0 +1,1470 @@ +# Doxyfile 1.5.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Lumiera + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 3.0+alpha + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = NO + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = ../../src/ \ + ../../tests/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = YES + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= NO + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../../src/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.PY + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = lumiera:: \ + lumiera_ \ + LUMIERA_ + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = NO + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Lumiera Doxygen docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hiererachy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = YES + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = YES + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = NO + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is enabled by default, which results in a transparent +# background. Warning: Depending on the platform used, enabling this option +# may lead to badly anti-aliased labels on the edges of a graph (i.e. they +# become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = NO + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/doc/devel/config_guide.txt b/doc/devel/config_guide.txt index a4a5d711d..af9cd8d30 100644 --- a/doc/devel/config_guide.txt +++ b/doc/devel/config_guide.txt @@ -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 diff --git a/doc/devel/draw/io-subsystem-overview.svg b/doc/devel/draw/io-subsystem-overview.svg new file mode 100644 index 000000000..ab9d0ac66 --- /dev/null +++ b/doc/devel/draw/io-subsystem-overview.svg @@ -0,0 +1,2227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filesystem + File + Chunks + MMap + Index + + + path/foo.mov + + + blah/baz.mov + + + another.mov + + + + Many files link to one physical file on disk + Metadata + Each file is treated as consectutive sequence of equal sized chunks + Ranges which are aligned on chunk boundaries are mapped into memory, these may be overlapping + Indices are generated by indexing engines, there can more than one per file + Indices also point to generic per-frame metadata + + + + + + 011011000010001100011100111011100001100111000110010......... + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + 3 + 4 + 5 + 1 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + + + + + + + + + + + + + + + + + + + + 2 + 3 + 4 + 1 + 5 + 6 + 7 + 8 + 9 + + 10 + 11 + 12 + 13 + + + 14 + 15 + 16 + + Files can be hardlinked, opening hardlinked files ensures that only one filedescriptor is used for them. The last chunk may exceed the end of the file, when the file is opened for writing, then the file is temporary resized to the chunk end and truncated to the real size at close.Chunksizes are given when a file is opened (first time sets it), they are choosen by the application depening on the purpose of the operation, generally its desireable to roughly spawn some dozen frames or few seconds of footage play time. All IO operations (memory locking) are done in chunksize granularity. Mapping windows are in real much biggier than in this example, current defaults are 128MB for 32 bit systems and 2GB for 64 bit systems. These get automatically adapted depending on system load and usage. Higher level access goes over the indices. frames are acquired from then when needed and released to it when done. + diff --git a/doc/devel/nobug_flags.txt b/doc/devel/nobug_flags.txt index 325141acb..761e14d2f 100644 --- a/doc/devel/nobug_flags.txt +++ b/doc/devel/nobug_flags.txt @@ -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 diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index f37f51a57..62e744b47 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -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 diff --git a/src/backend/backend.c b/src/backend/backend.c index 024f7e6f8..a41675f3c 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -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 +#include //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 (); } diff --git a/src/backend/backend.h b/src/backend/backend.h index bd4c86815..ded220b6e 100644 --- a/src/backend/backend.h +++ b/src/backend/backend.h @@ -24,8 +24,9 @@ #include NOBUG_DECLARE_FLAG (backend); -NOBUG_DECLARE_FLAG (file_all); -NOBUG_DECLARE_FLAG (file); + +extern size_t lumiera_backend_pagesize; + int lumiera_backend_init (void); diff --git a/src/backend/configitem.c b/src/backend/configitem.c deleted file mode 100644 index 8015a6e20..000000000 --- a/src/backend/configitem.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - configitem.c - generalized hierachy of configuration items - - Copyright (C) Lumiera.org - 2008, Christian Thaeter - Simeon Voelkel - - 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 -#include - -/** - * @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: -*/ diff --git a/src/backend/enginefacade.cpp b/src/backend/enginefacade.cpp new file mode 100644 index 000000000..e081b116e --- /dev/null +++ b/src/backend/enginefacade.cpp @@ -0,0 +1,85 @@ +/* + EngineFacade - access point for communicating with the render engine + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + + +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 theDescriptor; + } + + + + + /** @internal intended for use by main(). */ + Subsys& + EngineFacade::getDescriptor() + { + return theDescriptor(); + } + + + +} // namespace backend diff --git a/src/backend/enginefacade.hpp b/src/backend/enginefacade.hpp new file mode 100644 index 000000000..ec14b139b --- /dev/null +++ b/src/backend/enginefacade.hpp @@ -0,0 +1,63 @@ +/* + ENGINEFACADE.hpp - access point for communicating with the render engine + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 diff --git a/src/backend/file.c b/src/backend/file.c index 9739e3a58..95b4474c4 100644 --- a/src/backend/file.c +++ b/src/backend/file.c @@ -24,23 +24,30 @@ #include "backend/file.h" #include "backend/filehandlecache.h" -#include "backend/filedescriptor.h" #include #include 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; } diff --git a/src/backend/file.h b/src/backend/file.h index bf5f11181..dd1188e02 100644 --- a/src/backend/file.h +++ b/src/backend/file.h @@ -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 diff --git a/src/backend/filedescriptor.c b/src/backend/filedescriptor.c index 5f6bb4f13..f2c35beee 100644 --- a/src/backend/filedescriptor.c +++ b/src/backend/filedescriptor.c @@ -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", ®istry, registry_mutex.rh); + lumiera_mutex_init (®istry_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 (®istry_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, ®istry_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"); diff --git a/src/backend/filedescriptor.h b/src/backend/filedescriptor.h index d91296956..a74e8c47d 100644 --- a/src/backend/filedescriptor.h +++ b/src/backend/filedescriptor.h @@ -24,6 +24,7 @@ #include "lib/mutex.h" #include "lib/psplay.h" +#include "lib/llist.h" #include @@ -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 diff --git a/src/backend/filehandle.c b/src/backend/filehandle.c index 60d54cf82..c0d136ec2 100644 --- a/src/backend/filehandle.c +++ b/src/backend/filehandle.c @@ -28,20 +28,26 @@ #include -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; +} diff --git a/src/backend/filehandle.h b/src/backend/filehandle.h index e1b02b2e4..d92410a78 100644 --- a/src/backend/filehandle.h +++ b/src/backend/filehandle.h @@ -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 diff --git a/src/backend/filehandlecache.c b/src/backend/filehandlecache.c index cf8d0a0e5..03abe08ae 100644 --- a/src/backend/filehandlecache.c +++ b/src/backend/filehandlecache.c @@ -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) { diff --git a/src/backend/filehandlecache.h b/src/backend/filehandlecache.h index f624caefe..41030425d 100644 --- a/src/backend/filehandlecache.h +++ b/src/backend/filehandlecache.h @@ -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. diff --git a/src/backend/mediaaccessfacade.hpp b/src/backend/mediaaccessfacade.hpp index 63741b02e..539d4141e 100644 --- a/src/backend/mediaaccessfacade.hpp +++ b/src/backend/mediaaccessfacade.hpp @@ -26,7 +26,7 @@ #include "common/singleton.hpp" -#include "common/error.hpp" +#include "include/error.hpp" diff --git a/src/backend/mmap.c b/src/backend/mmap.c new file mode 100644 index 000000000..292c58b65 --- /dev/null +++ b/src/backend/mmap.c @@ -0,0 +1,271 @@ +/* + mmap.c - memory mapped acces to files + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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 +#include +#include + +/** + * @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: +*/ diff --git a/src/backend/mmap.h b/src/backend/mmap.h index 608e40133..90e2006a2 100644 --- a/src/backend/mmap.h +++ b/src/backend/mmap.h @@ -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: diff --git a/src/backend/mmapcache.c b/src/backend/mmapcache.c new file mode 100644 index 000000000..ea1d7dac3 --- /dev/null +++ b/src/backend/mmapcache.c @@ -0,0 +1,171 @@ +/* + mmapcache.c - handle aging of mmap objects + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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: +*/ diff --git a/src/backend/mmapcache.h b/src/backend/mmapcache.h index ed2efcb43..c6e4a9e86 100644 --- a/src/backend/mmapcache.h +++ b/src/backend/mmapcache.h @@ -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 */ diff --git a/src/backend/mmapings.c b/src/backend/mmapings.c new file mode 100644 index 000000000..b36d77d62 --- /dev/null +++ b/src/backend/mmapings.c @@ -0,0 +1,159 @@ +/* + mmapings.c - manage ranges of mmaped areas on a filedescriptor + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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: +*/ diff --git a/src/backend/mmapings.h b/src/backend/mmapings.h index 234ab280b..17548f1a9 100644 --- a/src/backend/mmapings.h +++ b/src/backend/mmapings.h @@ -30,13 +30,15 @@ typedef lumiera_mmapings* LumieraMMapings; #include "backend/filedescriptor.h" #include "backend/mmap.h" +#include "backend/file.h" #include +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); }; /** diff --git a/src/backend/netnodefacade.cpp b/src/backend/netnodefacade.cpp new file mode 100644 index 000000000..df019fbaa --- /dev/null +++ b/src/backend/netnodefacade.cpp @@ -0,0 +1,84 @@ +/* + NetNodeFacade - access point for maintaining a renderfarm node + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + +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 theDescriptor; + } + + + + + /** @internal intended for use by main(). */ + Subsys& + NetNodeFacade::getDescriptor() + { + return theDescriptor(); + } + + + +} // namespace backend diff --git a/src/backend/netnodefacade.hpp b/src/backend/netnodefacade.hpp new file mode 100644 index 000000000..14f3113dc --- /dev/null +++ b/src/backend/netnodefacade.hpp @@ -0,0 +1,61 @@ +/* + NETNODEFACADE.hpp - access point for maintaining a renderfarm node + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 diff --git a/src/backend/resourcecollector.c b/src/backend/resourcecollector.c new file mode 100644 index 000000000..2e31c41c3 --- /dev/null +++ b/src/backend/resourcecollector.c @@ -0,0 +1,187 @@ +/* + resourcecollector.c - manage/collect resources when they get short + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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 + +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: +*/ diff --git a/src/backend/resourcecollector.h b/src/backend/resourcecollector.h new file mode 100644 index 000000000..703da8b7b --- /dev/null +++ b/src/backend/resourcecollector.h @@ -0,0 +1,169 @@ +/* + resourcecollector.h - manage/collect resources when they get short + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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_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: +*/ diff --git a/src/backend/scriptrunnerfacade.cpp b/src/backend/scriptrunnerfacade.cpp new file mode 100644 index 000000000..533ea3481 --- /dev/null +++ b/src/backend/scriptrunnerfacade.cpp @@ -0,0 +1,85 @@ +/* + ScriptRunnerFacade - access point for running a script within Lumiera application context + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + + +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 theDescriptor; + } + + + + + /** @internal intended for use by main(). */ + Subsys& + ScriptRunnerFacade::getDescriptor() + { + return theDescriptor(); + } + + + +} // namespace backend diff --git a/src/backend/scriptrunnerfacade.hpp b/src/backend/scriptrunnerfacade.hpp new file mode 100644 index 000000000..043d532d4 --- /dev/null +++ b/src/backend/scriptrunnerfacade.hpp @@ -0,0 +1,59 @@ +/* + SCRIPTRUNNERFACADE.hpp - access point for running a script within Lumiera application context + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 71291ef82..5e1275abf 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -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 \ diff --git a/src/common/configrules.cpp b/src/common/configrules.cpp index 02a0bfcb6..8d121532b 100644 --- a/src/common/configrules.cpp +++ b/src/common/configrules.cpp @@ -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 typeinfo; } - /** Singleton factory instance, parametrized to actual impl. type. */ + /** Singleton factory instance, parametrised to actual impl. type. */ SingletonSub ConfigRules::instance (typeinfo); diff --git a/src/common/configrules.hpp b/src/common/configrules.hpp index e80ccfa8a..7b015dfdd 100644 --- a/src/common/configrules.hpp +++ b/src/common/configrules.hpp @@ -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) virtual functions (implemented * by MockConfigRules) diff --git a/src/common/error.cpp b/src/common/error.cpp index 64dea31a5..e069fef5a 100644 --- a/src/common/error.cpp +++ b/src/common/error.cpp @@ -22,7 +22,7 @@ -#include "common/error.hpp" +#include "include/error.hpp" #include "common/util.hpp" #include @@ -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 (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 diff --git a/src/common/multithread.hpp b/src/common/multithread.hpp index 8cdbe8002..794d4a18d 100644 --- a/src/common/multithread.hpp +++ b/src/common/multithread.hpp @@ -26,7 +26,7 @@ #ifndef LUMIERA_MULTITHREAD_H #define LUMIERA_MULTITHREAD_H -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #include "common/util.hpp" diff --git a/src/common/p.hpp b/src/common/p.hpp index 0a303ace7..0a1deb5fc 100644 --- a/src/common/p.hpp +++ b/src/common/p.hpp @@ -53,13 +53,13 @@ #include -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 diff --git a/src/common/query.cpp b/src/common/query.cpp index 255061476..10b43e12e 100644 --- a/src/common/query.cpp +++ b/src/common/query.cpp @@ -23,7 +23,7 @@ #include "common/query.hpp" #include "common/util.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #include #include diff --git a/src/common/query.hpp b/src/common/query.hpp index db76259db..e0eac98e4 100644 --- a/src/common/query.hpp +++ b/src/common/query.hpp @@ -30,15 +30,16 @@ #include +#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; /** diff --git a/src/common/query/mockconfigrules.cpp b/src/common/query/mockconfigrules.cpp index 0ae7f29ed..62848245e 100644 --- a/src/common/query/mockconfigrules.cpp +++ b/src/common/query/mockconfigrules.cpp @@ -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; diff --git a/src/common/singletonfactory.hpp b/src/common/singletonfactory.hpp index 0f6a12755..8d7b7a4b9 100644 --- a/src/common/singletonfactory.hpp +++ b/src/common/singletonfactory.hpp @@ -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::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 diff --git a/src/common/singletonpolicies.hpp b/src/common/singletonpolicies.hpp index f0b448305..ce53e0109 100644 --- a/src/common/singletonpolicies.hpp +++ b/src/common/singletonpolicies.hpp @@ -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 @@ -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) diff --git a/src/common/singletonpreconfigure.hpp b/src/common/singletonpreconfigure.hpp index e9b12e3d6..188c67b30 100644 --- a/src/common/singletonpreconfigure.hpp +++ b/src/common/singletonpreconfigure.hpp @@ -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; diff --git a/src/common/singletonsubclass.hpp b/src/common/singletonsubclass.hpp index a7e800487..48586f0f6 100644 --- a/src/common/singletonsubclass.hpp +++ b/src/common/singletonsubclass.hpp @@ -45,8 +45,8 @@ #include -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 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::create (); } // covariance checked! virtual void destroy (I* pSi) { POL::destroy (static_cast (pSi)); } }; - - + + struct My_scoped_ptr : scoped_ptr ///< implementation detail: defeat static initialisation { using scoped_ptr::get; My_scoped_ptr() : scoped_ptr (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 class A, class I> - typename Adapter::My_scoped_ptr Adapter::link; // note: use special ctor (due to stati init order!) + typename Adapter::My_scoped_ptr Adapter::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 diff --git a/src/common/test/mockinjector.hpp b/src/common/test/mockinjector.hpp index 4daf78081..f9df2d102 100644 --- a/src/common/test/mockinjector.hpp +++ b/src/common/test/mockinjector.hpp @@ -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); } diff --git a/src/common/test/run.hpp b/src/common/test/run.hpp index b1dbd08b6..06b1cda95 100644 --- a/src/common/test/run.hpp +++ b/src/common/test/run.hpp @@ -28,7 +28,7 @@ #include "pre.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #include "common/test/suite.hpp" #include "common/util.hpp" diff --git a/src/common/test/suite.cpp b/src/common/test/suite.cpp index 37a303ef6..0f8036997 100644 --- a/src/common/test/suite.cpp +++ b/src/common/test/suite.cpp @@ -30,11 +30,11 @@ #include #include -#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" diff --git a/src/common/test/testoption.cpp b/src/common/test/testoption.cpp index c591e895d..d898eaef9 100644 --- a/src/common/test/testoption.cpp +++ b/src/common/test/testoption.cpp @@ -1,5 +1,5 @@ /* - Suite - handle cmdline for invoking Testsuite + TestOption - handle cmdline for invoking Testsuite Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -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 @@ -56,7 +56,7 @@ namespace test ("group,g", op::value()->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(), "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")) diff --git a/src/common/test/testoption.hpp b/src/common/test/testoption.hpp index 28a82ff55..0bdb9f616 100644 --- a/src/common/test/testoption.hpp +++ b/src/common/test/testoption.hpp @@ -24,7 +24,7 @@ #ifndef TESTHELPER_TESTOPTION_H #define TESTHELPER_TESTOPTION_H -#include "common/cmdline.hpp" +#include "lib/cmdline.hpp" #include #include @@ -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); diff --git a/src/common/util.hpp b/src/common/util.hpp index 00c7bb638..402cbb435 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -31,10 +31,10 @@ -namespace util - { +namespace util { + using std::string; - + template 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 @@ -65,7 +65,7 @@ namespace util { return !pCStr || 0 == std::strlen(pCStr); } - + /** cut a numeric value to be >=0 */ template @@ -100,7 +100,7 @@ namespace util } /** shortcut for brute-force containment test - * in any sequencial container */ + * in any sequential container */ template 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 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)); diff --git a/src/common/visitordispatcher.hpp b/src/common/visitordispatcher.hpp index 4ed6a52e2..34d166b33 100644 --- a/src/common/visitordispatcher.hpp +++ b/src/common/visitordispatcher.hpp @@ -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" diff --git a/src/common/visitorpolicies.hpp b/src/common/visitorpolicies.hpp index 829dd5546..a31b781a1 100644 --- a/src/common/visitorpolicies.hpp +++ b/src/common/visitorpolicies.hpp @@ -32,7 +32,7 @@ #ifndef LUMIERA_VISITORPOLICIES_H #define LUMIERA_VISITORPOLICIES_H -#include "common/error.hpp" +#include "include/error.hpp" namespace lumiera diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index ef0031754..3e712ce8a 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -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 = diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index c73e45977..83a2f80a0 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -33,7 +33,7 @@ #include "model/project.hpp" extern "C" { -#include "backend/interface.h" +#include "lumiera/interface.h" } NOBUG_CPP_DEFINE_FLAG(gui); diff --git a/src/gui/guifacade.hpp b/src/gui/guifacade.hpp new file mode 100644 index 000000000..3b1775e79 --- /dev/null +++ b/src/gui/guifacade.hpp @@ -0,0 +1,108 @@ +/* + GUIFACADE.hpp - access point for communicating with the Lumiera GTK GUI + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 diff --git a/src/gui/guinotificationfacade.cpp b/src/gui/guinotificationfacade.cpp new file mode 100644 index 000000000..181006de7 --- /dev/null +++ b/src/gui/guinotificationfacade.cpp @@ -0,0 +1,150 @@ +/* + GuiNotificationFacade - access point for pushing informations into the GUI + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + + +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 _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 "; + } + ) + , 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 diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index 80fe0fea9..8dc698969 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -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); diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index 6afe2c2a8..fcf81dab4 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -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, diff --git a/src/guistart.cpp b/src/guistart.cpp new file mode 100644 index 000000000..b86b05e2d --- /dev/null +++ b/src/guistart.cpp @@ -0,0 +1,189 @@ +/* + GuiStart - entry point for the lumiera GUI loaded as shared module + + Copyright (C) Lumiera.org + 2007-2008, Joel Holdsworth + Christian Thaeter + Hermann Vosseler + + 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 + +using std::string; + +#include /////////////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 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 \n" + " Christian Thaeter \n" + " Hermann Vosseler "; + } + ) + , 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 (termSig)); + } + ) + ) + ); + +} // extern "C" diff --git a/src/include/configfacade.hpp b/src/include/configfacade.hpp new file mode 100644 index 000000000..db30b9937 --- /dev/null +++ b/src/include/configfacade.hpp @@ -0,0 +1,73 @@ +/* + CONFIGFACADE - C++ convenience wrapper and startup of the config system + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + + +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 instance; + + private: + Config(); + ~Config(); + + friend class lumiera::singleton::StaticCreate; + + //////////////////TODO: define startup/shutdown and loading of the config interface + + }; + + + +} // namespace lumiera +#endif diff --git a/src/common/error.hpp b/src/include/error.hpp similarity index 95% rename from src/common/error.hpp rename to src/include/error.hpp index ffd344323..b1b94676c 100644 --- a/src/common/error.hpp +++ b/src/include/error.hpp @@ -25,13 +25,13 @@ #define LUMIERA_ERROR_HPP_ #include -#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 diff --git a/src/include/guinotificationfacade.h b/src/include/guinotificationfacade.h new file mode 100644 index 000000000..2898db538 --- /dev/null +++ b/src/include/guinotificationfacade.h @@ -0,0 +1,100 @@ +/* + GUINOTIFICATIONFACADE.hpp - access point for pushing informations into the GUI + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + + +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 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 diff --git a/src/include/lifecycle.h b/src/include/lifecycle.h new file mode 100644 index 000000000..b91ce5619 --- /dev/null +++ b/src/include/lifecycle.h @@ -0,0 +1,105 @@ +/* + LIFECYCLE.h - interface for registering and triggering lifecycle callbacks + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + + + +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 diff --git a/src/include/nobugcfg.h b/src/include/nobugcfg.h new file mode 100644 index 000000000..cfcedd6b7 --- /dev/null +++ b/src/include/nobugcfg.h @@ -0,0 +1,117 @@ +/* + NOBUGCFG.h - NoBug definitions and initialisation for the Proc-Layer + + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + Hermann Vosseler + + 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 definitions. 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 Logging Channels 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 +#include + + +#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 ========= */ diff --git a/src/include/symbol.hpp b/src/include/symbol.hpp new file mode 100644 index 000000000..b2b526e6a --- /dev/null +++ b/src/include/symbol.hpp @@ -0,0 +1,54 @@ +/* + SYMBOL.hpp - symbolic constant datatype + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 2ba729d73..efec8af18 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -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 diff --git a/src/lib/allocationcluster.cpp b/src/lib/allocationcluster.cpp index 306e4a659..ccd2b3804 100644 --- a/src/lib/allocationcluster.cpp +++ b/src/lib/allocationcluster.cpp @@ -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 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 (...) { diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index a44151957..881d9cd4b 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -52,7 +52,7 @@ #include #include "common/multithread.hpp" -#include "common/error.hpp" +#include "include/error.hpp" #include "lib/scopedholder.hpp" #include "lib/scopedholdertransfer.hpp" diff --git a/src/lib/appconfig.cpp b/src/lib/appconfig.cpp deleted file mode 100644 index ad114fb56..000000000 --- a/src/lib/appconfig.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - Appconfig - for global initialization and configuration - - Copyright (C) Lumiera.org - 2008, Hermann Vosseler - - 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)); -} diff --git a/src/lib/appconfig.hpp b/src/lib/appconfig.hpp deleted file mode 100644 index a69336d78..000000000 --- a/src/lib/appconfig.hpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - APPCONFIG.hpp - for global initialization and configuration - - Copyright (C) Lumiera.org - 2008, Hermann Vosseler - - 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 -#include -#include -#include -#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*); - - - 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 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 Configmap; - typedef scoped_ptr PConfig; - typedef scoped_ptr 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 diff --git a/src/common/cmdline.cpp b/src/lib/cmdline.cpp similarity index 91% rename from src/common/cmdline.cpp rename to src/lib/cmdline.cpp index eca0b18bb..f2105394a 100644 --- a/src/common/cmdline.cpp +++ b/src/lib/cmdline.cpp @@ -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 #include @@ -50,8 +50,8 @@ using boost::regex_search; namespace util { - /** create as a tokenized copy of the current commandline. - * Note that argv[0] is allways ignored. */ + /** create as a tokenised copy of the current commandline. + * Note that argv[0] is always ignored. */ Cmdline::Cmdline (int argc, const char** argv) : vector (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) diff --git a/src/common/cmdline.hpp b/src/lib/cmdline.hpp similarity index 98% rename from src/common/cmdline.hpp rename to src/lib/cmdline.hpp index 3f5455587..31d49acff 100644 --- a/src/common/cmdline.hpp +++ b/src/lib/cmdline.hpp @@ -30,8 +30,8 @@ -namespace util - { +namespace util { + using std::string; using std::vector; using std::ostream; diff --git a/src/lib/external/libgavl.cpp b/src/lib/external/libgavl.cpp index 740515052..a5711584d 100644 --- a/src/lib/external/libgavl.cpp +++ b/src/lib/external/libgavl.cpp @@ -21,7 +21,7 @@ * *****************************************************/ -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "lib/external/libgavl.hpp" #include "proc/control/stypemanager.hpp" diff --git a/src/lib/functorutil.hpp b/src/lib/functorutil.hpp new file mode 100644 index 000000000..ccbb69988 --- /dev/null +++ b/src/lib/functorutil.hpp @@ -0,0 +1,88 @@ +/* + FUNCTORUTIL.hpp - collection of helpers for dealing with functors and signals + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 + + + +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 + class CombineSequenced; + + template + struct CombineSequenced + { + typedef function Func; + + static RET + dispatch (Func first, Func second, ARG arg) + { + first (arg); + return second (arg); + } + }; + + + template< typename SIG + , class COM = CombineSequenced + > + class Dispatch + : public function + { + 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 + Dispatch + dispatchSequenced (function const& f1, + function const& f2) + { + return Dispatch (f1, f2); + } + + +} // namespace util + +#endif /*UTIL_HPP_*/ diff --git a/src/lib/lifecycleregistry.hpp b/src/lib/lifecycleregistry.hpp index 285c95fac..b6e744b02 100644 --- a/src/lib/lifecycleregistry.hpp +++ b/src/lib/lifecycleregistry.hpp @@ -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 #include #include -#include +#include #include #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 table_; LifecycleRegistry () {} - friend class Appconfig; + friend class AppState; }; diff --git a/src/lib/mrucache.h b/src/lib/mrucache.h index 08654754f..8a8c5fbe9 100644 --- a/src/lib/mrucache.h +++ b/src/lib/mrucache.h @@ -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) diff --git a/src/lib/ppmpl.h b/src/lib/ppmpl.h index edc7bec7c..f2cf20665 100644 --- a/src/lib/ppmpl.h +++ b/src/lib/ppmpl.h @@ -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_ diff --git a/src/lib/scopedholder.hpp b/src/lib/scopedholder.hpp index 0019b6966..986ba956b 100644 --- a/src/lib/scopedholder.hpp +++ b/src/lib/scopedholder.hpp @@ -57,7 +57,7 @@ #include -#include "common/error.hpp" +#include "include/error.hpp" diff --git a/src/lib/scopedholdertransfer.hpp b/src/lib/scopedholdertransfer.hpp index d894de114..75c67d8c7 100644 --- a/src/lib/scopedholdertransfer.hpp +++ b/src/lib/scopedholdertransfer.hpp @@ -25,7 +25,7 @@ #ifndef LIB_SCOPEDHOLDERVECTOR_H #define LIB_SCOPEDHOLDERVECTOR_H -#include "common/error.hpp" +#include "include/error.hpp" #include diff --git a/src/lumiera/DIR_INFO b/src/lumiera/DIR_INFO new file mode 100644 index 000000000..c78139d7e --- /dev/null +++ b/src/lumiera/DIR_INFO @@ -0,0 +1,7 @@ +The main application shell + +contains: + * the config system + * commandline parsing + * interfaces and plugin loading + * lua interpreter (planned) diff --git a/src/lumiera/Makefile.am b/src/lumiera/Makefile.am new file mode 100644 index 000000000..6f65747b3 --- /dev/null +++ b/src/lumiera/Makefile.am @@ -0,0 +1,72 @@ +# Copyright (C) Lumiera.org +# 2008, Christian Thaeter +# +# 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 diff --git a/src/lumiera/appstate.cpp b/src/lumiera/appstate.cpp new file mode 100644 index 000000000..916e0755c --- /dev/null +++ b/src/lumiera/appstate.cpp @@ -0,0 +1,325 @@ +/* + AppState - application initialisation and behaviour + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 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); + } + +} + diff --git a/src/lumiera/appstate.hpp b/src/lumiera/appstate.hpp new file mode 100644 index 000000000..5833b9fcc --- /dev/null +++ b/src/lumiera/appstate.hpp @@ -0,0 +1,142 @@ +/* + APPSTATE.hpp - application initialisation and behaviour + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 +#include +#include +#include + + + +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*); + + + 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 PLife; + typedef scoped_ptr PSub; + + PLife lifecycleHooks_; + PSub subsystems_; + + bool emergency_; + bool core_up_; + + friend class LifecycleHook; + + }; + + +} // namespace lumiera + +#endif diff --git a/src/backend/config.c b/src/lumiera/config.c similarity index 90% rename from src/backend/config.c rename to src/lumiera/config.c index cec0dbfd8..b4083655a 100644 --- a/src/backend/config.c +++ b/src/lumiera/config.c @@ -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 keydelim == '=' || *item->delim == '<', "default must be a configentry with key=value or keyline); + 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; } diff --git a/src/backend/config.h b/src/lumiera/config.h similarity index 97% rename from src/backend/config.h rename to src/lumiera/config.h index 445ed6e23..c9d7b957f 100644 --- a/src/backend/config.h +++ b/src/lumiera/config.h @@ -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 @@ -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); diff --git a/src/lumiera/config_interface.c b/src/lumiera/config_interface.c new file mode 100644 index 000000000..43b52bb3d --- /dev/null +++ b/src/lumiera/config_interface.c @@ -0,0 +1,164 @@ +/* + config_interface.c - Lumiera configuration interface implementation + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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: +*/ diff --git a/src/lumiera/config_interface.h b/src/lumiera/config_interface.h new file mode 100644 index 000000000..374af50c5 --- /dev/null +++ b/src/lumiera/config_interface.h @@ -0,0 +1,85 @@ +/* + config_interface.h - Lumiera configuration interface + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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: +*/ diff --git a/src/backend/config_lookup.c b/src/lumiera/config_lookup.c similarity index 98% rename from src/backend/config_lookup.c rename to src/lumiera/config_lookup.c index 357d845dc..efb33c6d8 100644 --- a/src/backend/config_lookup.c +++ b/src/lumiera/config_lookup.c @@ -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"); diff --git a/src/backend/config_lookup.h b/src/lumiera/config_lookup.h similarity index 99% rename from src/backend/config_lookup.h rename to src/lumiera/config_lookup.h index a0ec20dd5..cc6d921ee 100644 --- a/src/backend/config_lookup.h +++ b/src/lumiera/config_lookup.h @@ -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 diff --git a/src/backend/config_typed.c b/src/lumiera/config_typed.c similarity index 96% rename from src/backend/config_typed.c rename to src/lumiera/config_typed.c index 963090899..d320f66b0 100644 --- a/src/backend/config_typed.c +++ b/src/lumiera/config_typed.c @@ -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); } } diff --git a/src/backend/config_wordlist.c b/src/lumiera/config_wordlist.c similarity index 99% rename from src/backend/config_wordlist.c rename to src/lumiera/config_wordlist.c index 47232f483..5f9f089c5 100644 --- a/src/backend/config_wordlist.c +++ b/src/lumiera/config_wordlist.c @@ -23,7 +23,7 @@ #include "lib/safeclib.h" -#include "backend/config.h" +#include "lumiera/config.h" extern LumieraConfig lumiera_global_config; diff --git a/src/backend/configentry.c b/src/lumiera/configentry.c similarity index 98% rename from src/backend/configentry.c rename to src/lumiera/configentry.c index e2c846b12..f5d09d4f6 100644 --- a/src/backend/configentry.c +++ b/src/lumiera/configentry.c @@ -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// diff --git a/src/backend/configentry.h b/src/lumiera/configentry.h similarity index 98% rename from src/backend/configentry.h rename to src/lumiera/configentry.h index 61f5f5f73..0df7ecc59 100644 --- a/src/backend/configentry.h +++ b/src/lumiera/configentry.h @@ -31,7 +31,7 @@ typedef lumiera_configentry* LumieraConfigentry; //TODO: Lumiera header includes// -#include "backend/configitem.h" +#include "lumiera/configitem.h" //TODO: System includes// #include diff --git a/src/lumiera/configfacade.cpp b/src/lumiera/configfacade.cpp new file mode 100644 index 000000000..27e953acf --- /dev/null +++ b/src/lumiera/configfacade.cpp @@ -0,0 +1,97 @@ +/* + ConfigFacade - C++ convenience wrapper and startup of the config system + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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::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 diff --git a/src/lumiera/configitem.c b/src/lumiera/configitem.c new file mode 100644 index 000000000..3bdb9a8f8 --- /dev/null +++ b/src/lumiera/configitem.c @@ -0,0 +1,384 @@ +/* + configitem.c - generalized hierachy of configuration items + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + Simeon Voelkel + + 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/safeclib.h" + + +//TODO: Lumiera header includes// +#include "lumiera/config.h" +#include "lumiera/configitem.h" +#include "lumiera/configentry.h" + + +static LumieraConfigitem parse_directive (LumieraConfigitem self, char* itr); + +static LumieraConfigitem parse_section (LumieraConfigitem self, char* itr); + +static LumieraConfigitem parse_configentry (LumieraConfigitem self, char* itr); + + +#include +#include + + +/** + * @file + * create a configitem out of a single line. + * + */ + + +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"); + + 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 */ + self = parse_directive (self, itr); + } + else if (*itr == '[' ) + { + /* this is a section */ + self = parse_section (self, itr); + } + else + { + /* this is probably a configentry */ + self = parse_configentry (self, itr); + } + + return self; +} + + +static LumieraConfigitem +parse_directive (LumieraConfigitem self, char* itr) +{ + /* 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); + } + return self; +} + + +static LumieraConfigitem +parse_section (LumieraConfigitem self, char* itr) +{ + /* 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); + } + + return self; +} + + +static LumieraConfigitem +parse_configentry (LumieraConfigitem self, char* itr) +{ + /* 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: +*/ diff --git a/src/backend/configitem.h b/src/lumiera/configitem.h similarity index 91% rename from src/backend/configitem.h rename to src/lumiera/configitem.h index 979609c36..52fd95ed6 100644 --- a/src/backend/configitem.h +++ b/src/lumiera/configitem.h @@ -1,5 +1,5 @@ /* - configitem.h - generalized hierachy of configuration items + configitem.h - generalized hierarchy of configuration items Copyright (C) Lumiera.org 2008, Christian Thaeter @@ -33,7 +33,7 @@ typedef lumiera_configitem* LumieraConfigitem; struct lumiera_configitem_vtable; //TODO: Lumiera header includes// -#include "backend/config_lookup.h" +#include "lumiera/config_lookup.h" //TODO: System includes// @@ -42,7 +42,7 @@ struct lumiera_configitem_vtable; /** * @file - * configitems build a 3 level hierachy: + * configitems build a 3 level hierarchy: * * 1. file: * contain sections @@ -66,7 +66,7 @@ struct lumiera_configitem_vtable; //TODO: declarations go here// /** * @file - * configitems build a 3 level hierachy: + * configitems build a 3 level hierarchy: * * 1. file: * contain sections @@ -84,7 +84,7 @@ struct lumiera_configitem_vtable; * directives are only valid at the toplevel section [] * configurationentry: * 'key = value' or 'key < redirect' - * errorneous: + * erroneous: * any line which cant be parsed */ @@ -96,11 +96,11 @@ struct lumiera_configitem_vtable struct lumiera_configitem_struct { - llist link; // all lines on the same hierachy level are linked here (see childs) + llist link; // all lines on the same hierarchy level are linked here (see childs) LumieraConfigitem parent; // parent section - llist childs; // root node for all lines below this hierachy + llist childs; // root node for all lines below this hierarchy - llist lookup; // all lines with the same key are stacked up on the loockup + llist lookup; // all lines with the same key are stacked up on the lookup char* line; // raw line as read in allocated here trailing \n will be replaced with \0 char* key; // pointer into line to start of key diff --git a/src/lumiera/guifacade.cpp b/src/lumiera/guifacade.cpp new file mode 100644 index 000000000..e0620fe18 --- /dev/null +++ b/src/lumiera/guifacade.cpp @@ -0,0 +1,184 @@ +/* + GuiFacade - access point for communicating with the Lumiera GTK GUI + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 "gui/guifacade.hpp" +#include "include/guinotificationfacade.h" +#include "include/error.hpp" +#include "common/singleton.hpp" +#include "lib/functorutil.hpp" +#include "lumiera/instancehandle.hpp" + +#include +#include +#include + + +namespace gui { + + using std::string; + using boost::scoped_ptr; + using std::tr1::bind; + using std::tr1::placeholders::_1; + using lumiera::Subsys; + using lumiera::InstanceHandle; + using util::dispatchSequenced; + + + + struct GuiRunner + : public GuiFacade + { + typedef InstanceHandle GuiHandle; + + GuiHandle theGUI_; + + + GuiRunner (Subsys::SigTerm terminationHandle) + : theGUI_("lumieraorg_Gui", 1, 1, "lumieraorg_GuiStarterPlugin") // load GuiStarterPlugin + { + ASSERT (theGUI_); + if (!kickOff (terminationHandle)) + throw lumiera::error::Fatal("failed to bring up GUI",lumiera_error()); + } + + ~GuiRunner () { } + + + bool kickOff (Subsys::SigTerm& terminationHandle) + { + return theGUI_->kickOff (reinterpret_cast (&terminationHandle)) + && !lumiera_error_peek(); + } + }; + + + + + namespace { // implementation details : start GUI through GuiStarterPlugin + + scoped_ptr facade (0); + + class GuiSubsysDescriptor + : public lumiera::Subsys + { + operator string () const { return "Lumiera GTK GUI"; } + + bool + shouldStart (lumiera::Option& opts) + { + if (opts.isHeadless() || 0 < opts.getPort()) + { + INFO (lumiera, "*not* starting the GUI..."); + return false; + } + else + return true; + } + + bool + start (lumiera::Option&, Subsys::SigTerm termination) + { + //Lock guard (*this); + if (facade) return false; // already started + + facade.reset ( + new GuiRunner ( // trigger loading load the GuiStarterPlugin... + dispatchSequenced( closeOnTermination_ // on termination call this->closeGuiModule(*) first + , termination))); //...followed by invoking the given termSignal + return true; + } + + void + triggerShutdown () throw() + { + try { GuiNotification::facade().triggerGuiShutdown ("Application shutdown"); } + + catch (...){} + } + + bool + checkRunningState () throw() + { + //Lock guard (*this); + return (facade); + } + + void + closeGuiModule (lumiera::Error *) + { + //Lock guard (*this); + if (!facade) + { + WARN (operate, "Termination signal invoked, but GUI is currently closed. " + "Probably this is due to some broken startup logic and should be fixed."); + } + else + facade.reset (0); + } + + + Subsys::SigTerm closeOnTermination_; + + public: + GuiSubsysDescriptor() + : closeOnTermination_ (bind (&GuiSubsysDescriptor::closeGuiModule, this, _1)) + { } + + ~GuiSubsysDescriptor() + { + if (facade) + { + WARN (operate, "GUI subsystem terminates, but GuiFacade isn't properly closed. " + "Closing it forcedly; this indicates broken startup logic and should be fixed."); + try { facade.reset (0); } + catch(...) { WARN_IF (lumiera_error_peek(), operate, "Ignoring error: %s", lumiera_error()); } + } + } + }; + + lumiera::Singleton theDescriptor; + + } // (End) impl details + + + + + + + /** @internal intended for use by main(). */ + lumiera::Subsys& + GuiFacade::getDescriptor() + { + return theDescriptor(); + } + + + bool + GuiFacade::isUp () + { + return (facade); + } + + + +} // namespace gui diff --git a/src/lumiera/instancehandle.hpp b/src/lumiera/instancehandle.hpp new file mode 100644 index 000000000..753c1fbab --- /dev/null +++ b/src/lumiera/instancehandle.hpp @@ -0,0 +1,185 @@ +/* + INSTANCEHANDLE.hpp - automatically handling interface lifecycle + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 instancehandle.hpp + ** A handle template for automatically dealing with interface and plugin + ** registration and deregistration. By placing an instance of this template, + ** parametrised with the appropriate interface type, the respective interface + ** and instance is loaded and opened through the Lumiera Interface system. + ** It will be closed and unregistered automatically when the handle goes + ** out of scope. Additionally, access via an (existing) interface proxy + ** may be enabled and disabled alongside with the loading and unloading. + ** + ** @see gui::GuiFacade usage example + ** @see interface.h + ** @see interfaceproxy.cpp + */ + + +#ifndef LUMIERA_INSTANCEHANDLE_H +#define LUMIERA_INSTANCEHANDLE_H + + +#include "include/nobugcfg.h" + +extern "C" { +#include "lumiera/interface.h" +#include "lumiera/interfaceregistry.h" +} + +#include +//#include +#include + + + +namespace lumiera { + + using std::string; +// using boost::scoped_ptr; + + namespace { // implementation details + + /** takes a bunch of instance definitions, as typically created + * when defining interfaces for external use, and registers them + * with the InterfaceSystem. Then uses the data found in the + * \em first descriptor to open an instance handle. + */ + LumieraInterface + register_and_open (LumieraInterface* descriptors) + { + if (!descriptors) return NULL; + lumiera_interfaceregistry_bulkregister_interfaces (descriptors, NULL); + LumieraInterface masterI = descriptors[0]; + return lumiera_interface_open (masterI->interface, + masterI->version, + masterI->size, + masterI->name); + } + + /** do a lookup within the interfaceregistry + * using the name/version found within the interface + * handle, to ensure it is still valid and registered */ + bool + verify_validity (LumieraInterface ifa) + { + REQUIRE (ifa); + return (ifa == lumiera_interfaceregistry_interface_find (ifa->interface, + ifa->version, + ifa->name)); + } + + } // (End) impl details + + + + /** + * Handle tracking the registration of an interface, deregistering it on deletion. + * Depending on which flavour of the ctor is used, either (bulk) registration of interfaces + * or plugin loading is triggered. The interface type is defined by type parameter. + * @todo when provided with the type of an facade interface class, care for enabling/disabling + * access through the facade proxy singleton when opening/closing the registration. + */ + template< class I ///< fully mangled name of the interface type + , class FA = I ///< facade interface type to be used by clients + > + class InstanceHandle + : private boost::noncopyable + { + LumieraInterface* desc_; + I* instance_; + + typedef InstanceHandle _ThisType; + + public: + /** Set up an InstanceHandle representing a plugin. + * Should be placed at the client side. + * @param iName unmangled name of the interface + * @param version major version + * @param minminor minimum acceptable minor version number + * @param impName unmangled name of the instance (implementation) + */ + InstanceHandle (string const& iName, uint version, size_t minminor, string const& impName) + : desc_(0), + instance_(reinterpret_cast + (lumiera_interface_open (iName.c_str(), version, minminor, impName.c_str()))) + { } + + /** Set up an InstanceHandle managing the + * registration and deregistration of interface(s). + * Should be placed at the service providing side. + * @param descriptors zero terminated array of interface descriptors, + * usually available through lumiera_plugin_interfaces() + */ + InstanceHandle (LumieraInterface* descriptors) + : desc_(descriptors), + instance_(reinterpret_cast (register_and_open (desc_))) + { } + + ~InstanceHandle () + { + lumiera_interface_close (&instance_->interface_header_); + if (desc_) + lumiera_interfaceregistry_bulkremove_interfaces (desc_); + } + + + + /** act as smart pointer providing access through the facade. + * @todo implement the case where the Facade differs from I + * @note we don't provide operator* */ + FA * operator-> () const { return accessFacade(); } + + /** directly access the instance via the CLI interface */ + I& get () const { ENSURE(instance_); return *instance_; } + + + + typedef I* _ThisType::*unspecified_bool_type; + + /** implicit conversion to "bool" */ + operator unspecified_bool_type() const // never throws + { return isValid()? &_ThisType::instance_ : 0; } + + bool operator! () const { return !isValid(); } + + + private: + FA * + accessFacade() const + { + ENSURE (instance_); + return static_cast (instance_); /////////////////TODO: actually handle the case when the facade differs from the interface by using the proxy + } + + bool + isValid() const + { + return instance_ + && verify_validity (&instance_->interface_header_); + } + }; + + +} // namespace lumiera + +#endif diff --git a/src/backend/interface.c b/src/lumiera/interface.c similarity index 82% rename from src/backend/interface.c rename to src/lumiera/interface.c index 22e94cbcc..e8c633c7f 100644 --- a/src/backend/interface.c +++ b/src/lumiera/interface.c @@ -22,10 +22,10 @@ #include "lib/mutex.h" #include "lib/safeclib.h" -#include "backend/plugin.h" -#include "backend/interface.h" +#include "lumiera/plugin.h" +#include "lumiera/interface.h" -#include "backend/interfaceregistry.h" +#include "lumiera/interfaceregistry.h" #include @@ -37,6 +37,8 @@ * Interfaces can be opened multiple times and cross reference each other. */ +/* the mother of all interfaces */ +LumieraInterface lumiera_interface_interface; static LumieraInterfacenode lumiera_interface_open_interfacenode (LumieraInterfacenode self); @@ -201,7 +203,7 @@ lumiera_interface_open_interfacenode (LumieraInterfacenode self) { TRACE (interface, "Acquire %s", self->interface->name); collect_dependencies = self->deps?0:1; - self->interface = self->interface->acquire (self->interface); + self->interface = self->interface->acquire (self->interface, lumiera_interface_interface); } } else @@ -301,6 +303,41 @@ lumiera_interfacenode_close (LumieraInterfacenode self) } } +/** + * Definitinon of 'the mother of all interfaces' + * since this interface is singleton and required for any component to open any other + * interface this should get a very stable interface and likely never change. + */ +LUMIERA_EXPORT( + LUMIERA_INTERFACE_DEFINE (lumieraorg_interface, 0, + lumieraorg_interface, + NULL, + NULL, + NULL, + LUMIERA_INTERFACE_MAP (open, "\322\165\227\133\252\355\125\104\157\167\253\267\117\273\174\022", + lumiera_interface_open), + LUMIERA_INTERFACE_MAP (close, "\264\037\253\243\312\273\024\104\030\007\076\006\154\071\340\102", + lumiera_interface_close), + LUMIERA_INTERFACE_MAP (version, "\004\272\070\214\006\235\047\212\007\165\115\221\146\274\217\324", + lumiera_interface_version), + ) + ) + + +void +lumiera_interface_init (void) +{ + LUMIERA_INTERFACE_REGISTEREXPORTED; + lumiera_interface_interface = + lumiera_interface_open ("lumieraorg_interface", 0, 0, "lumieraorg_interface"); +} + +void +lumiera_interface_destroy (void) +{ + lumiera_interface_close (lumiera_interface_interface); + LUMIERA_INTERFACE_UNREGISTEREXPORTED; +} /* // Local Variables: diff --git a/src/backend/interface.h b/src/lumiera/interface.h similarity index 90% rename from src/backend/interface.h rename to src/lumiera/interface.h index e962a2d10..83d1a4e6b 100644 --- a/src/backend/interface.h +++ b/src/lumiera/interface.h @@ -290,9 +290,12 @@ LUMIERA_PLUGININTERFACE /** - * Create a plugin interface when being copiled as plugin + * Create a plugin interface when being compiled as plugin */ -#ifdef LUMIERA_PLUGIN +#ifdef LUMIERA_PLUGIN /* compile as plugin */ +#define LUMIERA_PLUGIN_INTERFACEHANDLE static LUMIERA_INTERFACE_HANDLE(lumieraorg_interface, 0) lumiera_interface_handle +#define LUMIERA_PLUGIN_STORE_INTERFACEHANDLE(name) lumiera_interface_handle = LUMIERA_INTERFACE_CAST (lumieraorg_interface, 0) name + #define LUMIERA_PLUGININTERFACE \ LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, \ lumieraorg_plugin, \ @@ -305,7 +308,19 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, ); #define LUMIERA_INTERFACE_REGISTEREXPORTED #define LUMIERA_INTERFACE_UNREGISTEREXPORTED -#else + +#define LUMIERA_INTERFACE_OPEN(interface, version, minminor, name) \ + LUMIERA_INTERFACE_CAST(interface, version) lumiera_interface_handle->open (#interface, version, minminor, #name) + +#define LUMIERA_INTERFACE_CLOSE(handle) \ + lumiera_interface_handle->close (&(handle)->interface_header_) + + +#else /* compile as builtin */ + +#define LUMIERA_PLUGIN_INTERFACEHANDLE static LUMIERA_INTERFACE_HANDLE(lumieraorg_interface, 0) lumiera_interface_handle +#define LUMIERA_PLUGIN_STORE_INTERFACEHANDLE(name) lumiera_interface_handle = LUMIERA_INTERFACE_CAST (lumieraorg_interface, 0) name + #define LUMIERA_PLUGININTERFACE /** * Register all exported interfaces when not a plugin @@ -319,9 +334,17 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, */ #define LUMIERA_INTERFACE_UNREGISTEREXPORTED \ lumiera_interfaceregistry_bulkremove_interfaces (lumiera_plugin_interfaces()) + +#define LUMIERA_INTERFACE_OPEN(interface, version, minminor, name) \ + LUMIERA_INTERFACE_CAST(interface, version) lumiera_interface_open (#interface, version, minminor, #name) + +#define LUMIERA_INTERFACE_CLOSE(handle) \ + lumiera_interface_close (&(handle)->interface_header_) + #endif + /** * create a handle for a interface (WIP) */ @@ -329,12 +352,6 @@ LUMIERA_INTERFACE_INSTANCE (lumieraorg__plugin, 0, #define LUMIERA_INTERFACE_HANDLE(interface, version) \ LUMIERA_INTERFACE_TYPE(interface, version)* -#define LUMIERA_INTERFACE_OPEN(interface, version, minminor, name) \ - LUMIERA_INTERFACE_CAST(interface, version) lumiera_interface_open (#interface, version, minminor, #name) - -#define LUMIERA_INTERFACE_CLOSE(handle) \ - lumiera_interface_close (&(handle)->interface_header_) - typedef struct lumiera_interfaceslot_struct lumiera_interfaceslot; typedef lumiera_interfaceslot* LumieraInterfaceslot; @@ -378,9 +395,12 @@ struct lumiera_interface_struct * Must be called before this interface is used. * might be nested. * @param self pointer to the interface to be acquired + * @param interfaces pointer to a 'interfaces' interface giving plugins access to + * opening and closing interfaces, this is already opened and if a plugin + * wants to use other interfaces it has to store this pointer * @return pointer to the interface or NULL on error */ - LumieraInterface (*acquire)(LumieraInterface self); + LumieraInterface (*acquire)(LumieraInterface self, LumieraInterface interfaces); /** * called when finished using this interface * must match the acquire calls @@ -394,20 +414,10 @@ struct lumiera_interface_struct #endif }; - -/** - * Plugin interface - */ -LUMIERA_INTERFACE_DECLARE (lumieraorg__plugin, 0, - LUMIERA_INTERFACE_SLOT (LumieraInterface*, plugin_interfaces, (void)), -); - - /* API to handle interfaces */ - /** * Open an interface by version and name. * Looks up the requested interface, possibly loading it from a plugin. @@ -437,6 +447,41 @@ lumiera_interface_close (LumieraInterface self); unsigned lumiera_interface_version (LumieraInterface self, const char* iname); +/** + * Define an interface for the above + */ +LUMIERA_INTERFACE_DECLARE (lumieraorg_interface, 0, + LUMIERA_INTERFACE_SLOT (LumieraInterface, + open, + (const char* interface, unsigned version, size_t minminorversion, const char* name)), + LUMIERA_INTERFACE_SLOT (void, close, (LumieraInterface self)), + LUMIERA_INTERFACE_SLOT (unsigned, version, (LumieraInterface self, const char* iname)), +); + +/** + * registering implementations of the above interface + */ +void +lumiera_interface_init (void); + +/** + * deregistering implementations of the above interface + */ +void +lumiera_interface_destroy (void); + + + + + +/** + * Plugin interface + */ +LUMIERA_INTERFACE_DECLARE (lumieraorg__plugin, 0, + LUMIERA_INTERFACE_SLOT (LumieraInterface*, plugin_interfaces, (void)), +); + + #endif /* LUMIERA_INTERFACE_H */ /* diff --git a/src/backend/interfacedescriptor.h b/src/lumiera/interfacedescriptor.h similarity index 96% rename from src/backend/interfacedescriptor.h rename to src/lumiera/interfacedescriptor.h index 29894c686..77ce43e73 100644 --- a/src/backend/interfacedescriptor.h +++ b/src/lumiera/interfacedescriptor.h @@ -21,7 +21,7 @@ #ifndef LUMIERA_INTERFACEDESCRIPTOR_H #define LUMIERA_INTERFACEDESCRIPTOR_H -#include "backend/interface.h" +#include "lumiera/interface.h" /** @@ -29,10 +29,10 @@ * The interface subsystem must be able to categorize implementations to present possible * upgrade paths to the user. This is done by the tagging it to a certain state in concert * with the version and the user supplied version compare function. The respective numbers - * are choosen in a way that a higher value indicates precedence when selecting an implementation. + * are chosen in a way that a higher value indicates precedence when selecting an implementation. * Note that 'BETA' is higher than 'DEPRECATED', we make the assumption that BETA is at least * maintained code and something gets deprecated for some reason. For common practice it is - * suggested to make a stable release before declaring its predcessor version as deprecated. + * suggested to make a stable release before declaring its predecessor version as deprecated. */ enum lumiera_interface_state { /** some known bugs exist which won't be fixed, don't use this */ @@ -73,7 +73,7 @@ LUMIERA_INTERFACE_DECLARE (lumieraorg_interfacedescriptor, 0, #if 0 /** - * For convinience, a copy'n'paste descriptor + * For convenience, a copy'n'paste descriptor */ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, /*IDENTIFIER*/, diff --git a/src/lumiera/interfaceproxy.cpp b/src/lumiera/interfaceproxy.cpp new file mode 100644 index 000000000..c6e96df8d --- /dev/null +++ b/src/lumiera/interfaceproxy.cpp @@ -0,0 +1,85 @@ +/* + InterfaceProxy - definition of forwarding proxies for the facade interfaces + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 "common/singletonsubclass.hpp" +#include "include/guinotificationfacade.h" +#include "common/util.hpp" +#include "include/error.hpp" + +extern "C" { +#include "lumiera/interface.h" +} + +using util::cStr; + + +namespace singleton = lumiera::singleton; + +namespace gui { + + class GuiNotificationInterfaceProxy + : public GuiNotification + { + LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 1) * interface_; + + GuiNotificationInterfaceProxy () + { + interface_ = LUMIERA_INTERFACE_OPEN (lumieraorg_GuiNotification, 1, 2, lumieraorg_GuiNotificationFacade); + if (!interface_) + throw lumiera::error::State ("unable to access GuiNotificationFacade"); + } + + friend class singleton::StaticCreate; + + + + /* ======== forwarding through interface ========== */ + + void + displayInfo (string const& text) + { + interface_->displayInfo (cStr(text)); + } + + void + triggerGuiShutdown (string const& cause) + { + interface_->triggerGuiShutdown (cStr(cause)); + } + + + }; + + namespace { + + singleton::UseSubclass typeinfo_proxyInstance_to_create; + } + + /** storage for the facade proxy factory used by client code to invoke through the interface */ + lumiera::SingletonSub GuiNotification::facade (typeinfo_proxyInstance_to_create); + + ///////////////////////////////////////TODO: this solution is not correct, because it doesn't detect when the interface is shut down! + + + +} // namespace gui diff --git a/src/backend/interfaceregistry.c b/src/lumiera/interfaceregistry.c similarity index 97% rename from src/backend/interfaceregistry.c rename to src/lumiera/interfaceregistry.c index 969ab23e0..52a40988a 100644 --- a/src/backend/interfaceregistry.c +++ b/src/lumiera/interfaceregistry.c @@ -29,8 +29,8 @@ -#include "backend/plugin.h" -#include "backend/interfaceregistry.h" +#include "lumiera/plugin.h" +#include "lumiera/interfaceregistry.h" /** * @file @@ -39,7 +39,7 @@ * by their name and major version. */ -NOBUG_DEFINE_FLAG_PARENT (interface_all, backend); +NOBUG_DEFINE_FLAG_PARENT (interface_all, lumiera_all); NOBUG_DEFINE_FLAG_PARENT (plugin, interface_all); NOBUG_DEFINE_FLAG_PARENT (interfaceregistry, interface_all); NOBUG_DEFINE_FLAG_PARENT (interface, interface_all); @@ -109,6 +109,8 @@ lumiera_interfaceregistry_init (void) LUMIERA_DIE (ERRNO); lumiera_recmutex_init (&lumiera_interface_mutex, "interfaceregistry", &NOBUG_FLAG(interfaceregistry)); + + lumiera_interface_init (); } @@ -117,6 +119,8 @@ lumiera_interfaceregistry_destroy (void) { TRACE (interfaceregistry); + lumiera_interface_destroy (); + if (lumiera_pluginregistry) psplay_delete (lumiera_pluginregistry); lumiera_pluginregistry = NULL; diff --git a/src/backend/interfaceregistry.h b/src/lumiera/interfaceregistry.h similarity index 93% rename from src/backend/interfaceregistry.h rename to src/lumiera/interfaceregistry.h index 54ede293a..425961fd4 100644 --- a/src/backend/interfaceregistry.h +++ b/src/lumiera/interfaceregistry.h @@ -24,8 +24,8 @@ #include "lib/mutex.h" #include "lib/psplay.h" -#include "backend/interface.h" -#include "backend/plugin.h" +#include "lumiera/interface.h" +#include "lumiera/plugin.h" #include @@ -33,7 +33,7 @@ /** * @file * Interface instances are published and activated by registering them - * into a gloabl registry, which is defined here. This instances are identified + * into a global registry, which is defined here. This instances are identified * by their name and major version. */ @@ -71,7 +71,7 @@ struct lumiera_interfacenode_struct LumieraInterfacenode lnk; /** allocated size of the following deps table */ size_t deps_size; - /** NULL terminated table of all dependenncies (interfaces opened on initialization) */ + /** NULL terminated table of all dependencies (interfaces opened on initialization) */ LumieraInterfacenode* deps; }; diff --git a/src/proc/nobugcfg.cpp b/src/lumiera/nobugcfg.cpp similarity index 90% rename from src/proc/nobugcfg.cpp rename to src/lumiera/nobugcfg.cpp index 7dc68a9bb..ecbde0e79 100644 --- a/src/proc/nobugcfg.cpp +++ b/src/lumiera/nobugcfg.cpp @@ -21,24 +21,26 @@ * *****************************************************/ -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #define NOBUG_INIT_DEFS_ -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #undef NOBUG_INIT_DEFS_ -namespace lumiera - { + + +namespace lumiera { + void - initialize_NoBug () + initialise_NoBug () { NOBUG_INIT; #ifdef DEBUG static uint callCount = 0; ASSERT ( 0 == callCount++ ); -#endif +#endif } } diff --git a/src/lumiera/option.cpp b/src/lumiera/option.cpp new file mode 100644 index 000000000..ef8225836 --- /dev/null +++ b/src/lumiera/option.cpp @@ -0,0 +1,163 @@ +/* + Option - handle cmdline for starting the Lumiera application + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 "lumiera/option.hpp" + +#include "include/error.hpp" +#include "common/util.hpp" + + + +typedef boost::program_options::options_description Syntax; +typedef boost::program_options::variables_map VarMap; + +namespace op = boost::program_options; + +using util::VectS; +using util::cStr; + + +namespace lumiera { + + /** set up an options parser to use the application commandline. + * Recognises the following options + * \code + * --help + * [--session] FILENAME + * --script FILENAME + * --headless + * --port # + * \endcode + * @todo describe the actual options + */ + Option::Option (util::Cmdline& cmdline) + : syntax("Lumiera, the non linear video editor. Supported parameters"), + parameters() + { + syntax.add_options() + ("help,h", "produce help message") + ("session,f", op::value(), + "session file to load (UNIMPLEMENTED)") + ("script,s", op::value(), + "execute the given LUA script (UNIMPLEMENTED)") + ("headless", op::bool_switch(), + "start without GUI") + ("port,p", op::value(), + "open renderfarm node at given port (UNIMPLEMENTED)") + ("define,def,D",op::value(), + "enter definition into config system (UNIMPLEMENTED)") + ; + + // the name of an session file to open... + op::positional_options_description posopt; + posopt.add("session", 1); // ... can be given as 1st positional parameter + + op::parsed_options parsed = + op::command_line_parser (cmdline) + .options (syntax) + .positional(posopt) + .allow_unregistered() + .run(); + + op::store (parsed, parameters); + op::notify(parameters); + + // remove all recognised options from original cmdline vector + cmdline = op::collect_unrecognized(parsed.options, op::include_positional); + + if (isHelp()) + { + std::cerr << *this; + exit(-1); + } + if (isConfigDefs()) + { + UNIMPLEMENTED ("feed definitions from commandline to Config system"); + } + } + + + + /** syntax help requested? */ + bool Option::isHelp () { return (parameters.count("help")); } + + /** should an existing session file be loaded? */ + bool Option::isOpenSession () { return (parameters.count ("session")); } + + /** additional Config defs to fed to config system? */ + bool Option::isConfigDefs () { return (parameters.count ("define")); } + + + /** @return the name of the session file to open */ + const string + Option::getSessName () + { + ASSERT (parameters.count ("session")); + return parameters["session"].as(); + } + + /** @return an (maybe empty) vector + * containing all specified scripts to run. */ + const VectS + Option::getScripts () + { + return parameters["script"].as(); + } + + /** @return an (maybe empty) vector + * containing any additional Config definitions to set. */ + const VectS + Option::getConfigDefs () + { + return parameters["define"].as(); + } + + /** @return \c true if --headless switch was given */ + bool + Option::isHeadless () + { + return parameters["headless"].as(); + } + + /** @return the port number for a render node server + * or 0 if --port was not specified */ + int + Option::getPort () + { + if (parameters.count ("port")) + return parameters["port"].as(); + else + return 0; + } + + + + ostream& + operator<< (ostream& os, const Option& ops) + { + return os << ops.syntax; + } + + + +} // namespace lumiera diff --git a/src/lumiera/option.hpp b/src/lumiera/option.hpp new file mode 100644 index 000000000..c44a6b35e --- /dev/null +++ b/src/lumiera/option.hpp @@ -0,0 +1,84 @@ +/* + OPTION.hpp - handle cmdline for starting the Lumiera application + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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_OPTION_H +#define LUMIERA_OPTION_H + +#include "lib/cmdline.hpp" + +#include +#include +#include +#include + + + +namespace lumiera { + + using std::string; + using std::ostream; + using util::VectS; + + + + /** + * Support for selecting and configuring testcases + * via commandline arguments. A preconfigured wrapper + * around boost::program_options, with the ability + * to tolerate unknown options. The commandline + * to be parsed is taken wrapped into a Cmdline + * instance; after parsing this commandline + * vector will contain only the remaining + * unrecognised parts. + */ + class Option : private boost::noncopyable + { + public: + Option (util::Cmdline& cmdline); + + const string getSessName(); + const VectS getScripts(); + const VectS getConfigDefs(); + int getPort(); + + bool isOpenSession (); + bool isConfigDefs(); + bool isHeadless(); + bool isHelp(); + + + private: + boost::program_options::options_description syntax; + boost::program_options::variables_map parameters; + + friend ostream& operator<< (ostream&, const Option&); + }; + + + /** for outputting the help messages. Forward accumulated + * help messages from all contained option definitions */ + ostream& operator<< (ostream& os, const Option& to); + + +} // namespace lumiera +#endif diff --git a/src/backend/plugin.c b/src/lumiera/plugin.c similarity index 99% rename from src/backend/plugin.c rename to src/lumiera/plugin.c index d5db02c48..30f664e11 100644 --- a/src/backend/plugin.c +++ b/src/lumiera/plugin.c @@ -25,9 +25,9 @@ #include "lib/mutex.h" #include "lib/error.h" -#include "backend/interfaceregistry.h" -#include "backend/config.h" -#include "backend/plugin.h" +#include "lumiera/interfaceregistry.h" +#include "lumiera/config.h" +#include "lumiera/plugin.h" #include diff --git a/src/backend/plugin.h b/src/lumiera/plugin.h similarity index 98% rename from src/backend/plugin.h rename to src/lumiera/plugin.h index 26451edac..f5a5ffc21 100644 --- a/src/backend/plugin.h +++ b/src/lumiera/plugin.h @@ -24,7 +24,7 @@ #include "lib/psplay.h" #include "lib/error.h" -#include "backend/interface.h" +#include "lumiera/interface.h" #include #include @@ -72,7 +72,7 @@ NOBUG_DECLARE_FLAG (plugin); struct lumiera_plugin_struct; typedef struct lumiera_plugin_struct lumiera_plugin; typedef lumiera_plugin* LumieraPlugin; -enum lumiera_plugin_type; + /** * Allocates an preinitializes a plugin structure @@ -89,7 +89,7 @@ lumiera_plugin_new (const char* name); * Stores any pending error (from loading) in self which clears out the LUMIERA_ERROR_PLUGIN_INIT error state * which was initialized by lumiera_plugin_new(), stores the handle and plugin pointers in the plugin struct. * @param self pointer to the plugin struct - * @param handle opaque handle refering to some plugin type specific data + * @param handle opaque handle referring to some plugin type specific data * @param plugin a lumieraorg__plugin interface which will be used to initialize this plugin */ LumieraPlugin diff --git a/src/backend/plugin_dynlib.c b/src/lumiera/plugin_dynlib.c similarity index 87% rename from src/backend/plugin_dynlib.c rename to src/lumiera/plugin_dynlib.c index 50030843c..52813e69c 100644 --- a/src/backend/plugin_dynlib.c +++ b/src/lumiera/plugin_dynlib.c @@ -18,7 +18,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "backend/plugin.h" +#include "lumiera/plugin.h" #include #include @@ -32,6 +32,7 @@ LumieraPlugin lumiera_plugin_load_DYNLIB (const char* name) { TRACE (plugin); + REQUIRE (name); LumieraPlugin self = lumiera_plugin_new (name); LumieraInterface plugin = NULL; @@ -46,6 +47,14 @@ lumiera_plugin_load_DYNLIB (const char* name) else LUMIERA_ERROR_SET (plugin, PLUGIN_OPEN); +#ifdef DEBUG + if (lumiera_error_peek()) + { + const char* problem = dlerror(); + WARN_IF (problem, plugin, "Problem opening shared object %s : %s", name, problem); + } +#endif + return lumiera_plugin_init (self, handle, plugin); } diff --git a/src/lumiera/subsys.cpp b/src/lumiera/subsys.cpp new file mode 100644 index 000000000..823b838e4 --- /dev/null +++ b/src/lumiera/subsys.cpp @@ -0,0 +1,64 @@ +/* + Subsys - interface for describing an application part to be handled by main() + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 "lumiera/subsys.hpp" + +#include "include/error.hpp" +//#include "common/util.hpp" + + +//using util::isnil; +//using util::cStr; + +namespace lumiera { + + + + + + Subsys::~Subsys() { } + + + + Subsys& + Subsys::depends (Subsys& prereq) + { + TODO ("anything else to care when defining a dependency on the prerequisite subsystem??");/////////////////////TODO + prereq_.push_back(&prereq); + return *this; + } + + + + bool + Subsys::isRunning() + { + //Lock guard (*this); + return checkRunningState(); + } + + + + + +} // namespace lumiera diff --git a/src/lumiera/subsys.hpp b/src/lumiera/subsys.hpp new file mode 100644 index 000000000..61f08d84b --- /dev/null +++ b/src/lumiera/subsys.hpp @@ -0,0 +1,129 @@ +/* + SUBSYS.hpp - interface for describing an application part to be handled by main() + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 subsys.hpp + ** Describing dependencies and lifecycle of the application's primary parts. + ** Within Lumiera's main(), a small number of well-known application subsystems + ** need to be started and maintained, observing some interrelations. + ** While the activation of the key components is controlled by options, maybe + ** some prerequisite subsystems need to be pulled up, and in case of an regular + ** or irregular exit of a given subsystem, the whole dependency graph needs + ** to be brought down in a clean manner. The purpose of lumiera::Subsys is + ** to maintain these in a self-explanatory script-like fashion within main(), + ** without forcing the individual subsystems into a fixed implementation scheme. + ** The only requirement is that for each subsystem there is sort-of an entry + ** point or facade object, providing a Subsys descriptor instance to be + ** used within main. + ** + ** @see lumiera::AppState + ** @see lumiera::Option + ** @see main.cpp + */ + + +#ifndef LUMIERA_SUBSYS_H +#define LUMIERA_SUBSYS_H + +#include "include/error.hpp" +#include "lumiera/option.hpp" + +#include +#include +#include +#include + + + +namespace lumiera { + + using std::string; + using boost::noncopyable; + using std::tr1::function; + + + + /** + * Dependencies and lifecycle of a partially independent Subsystem of the Application. + * Using such descriptors, AppState as activated from main() is able to pull up, + * maintain and shut down the primary parts of the Application. + */ + class Subsys + : private noncopyable + { + public: + typedef function SigTerm; + + virtual ~Subsys(); + + /** a human readable name */ + virtual operator string () const =0; + + + /** define a dependency to another Subsys + * required for running this subsystem */ + Subsys& depends (Subsys& prereq); + + /** @return true if Up */ + bool isRunning(); + + + /** query application option state to determine + * if this subsystem should be activated. */ + virtual bool shouldStart (lumiera::Option&) =0; + + + /** how to start up this subsystem. Failure to start up + * usually terminates the whole application. When this subsystem + * ceases to work, it must assure to activate the given signal. + * @param options may be influencing the operation mode + * @param termination to be signalled by the subsystem. + * @warning termination must be signalled reliably. + * @return \c true if actually started. */ + virtual bool start (lumiera::Option&, SigTerm) =0; + + + /** initiate termination of this subsystem. + * may be called repeatedly any time... + * @warning must not block nor throw. */ + virtual void triggerShutdown () throw() =0; + + + const std::vector + getPrerequisites () { return prereq_; } + + + private: + /** weather this subsystem is actually operational. + * When returning \c false here, the application may + * terminate at any point without further notice + * Note further, that a subsystem must not be in + * running state when signalling termination. */ + virtual bool checkRunningState() throw() =0; + + std::vector prereq_; + }; + + + +} // namespace lumiera + +#endif diff --git a/src/lumiera/subsystemrunner.hpp b/src/lumiera/subsystemrunner.hpp new file mode 100644 index 000000000..a04e4708d --- /dev/null +++ b/src/lumiera/subsystemrunner.hpp @@ -0,0 +1,186 @@ +/* + SUBSYSTEMRUNNER.hpp - helper for controlling execution of several dependant subsystems + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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_SUBSYSTEMRUNNER_H +#define LUMIERA_SUBSYSTEMRUNNER_H + +#include "include/error.hpp" +#include "common/util.hpp" +#include "lumiera/subsys.hpp" +#include "common/multithread.hpp" + +#include +#include + + +namespace lumiera { + + using std::tr1::bind; + using std::tr1::function; + using std::tr1::placeholders::_1; + using std::vector; + using util::cStr; + using util::isnil; + using util::and_all; + using util::for_each; + using util::removeall; + + namespace { + function + isRunning() { + return bind (&Subsys::isRunning, _1); + } + } + + + /***************************************************************************** + * Implementation helper for managing execution of a collection of subsystems, + * which may depend on one another and execute in parallel. Properties of the + * subsystems are available through Subsys object refs, which act as handle. + * In this context, "Subsystem" is an \em abstraction and doesn't necessarily + * correspond to a single component, interface or plugin. It may well be a + * complete layer of the application (e.g. the GUI). + * + * \par Protocol of operation + * The SubsystemRunner is to be configured with a lumiera::Option object first. + * Then, primary subsystems are \link #maybeRun provided \endlink for eventual + * startup, which may depend on conditions defined by the subsystem. When + * a component is actually to be pulled up, all of its prerequisite subsystems + * shall be started in advance. Problems while starting may result in throwing + * an exception, which is \em not handled here and aborts the whole operation. + * On startup, a signal slot is reserved for each subsystem to notify the + * SubsystemRunner on termination. It is the liability of the subsystems to + * ensure this signal is activated regardless of what actually causes the + * termination; failure to do so may deadlock the SubsystemRunner. + * + * Usually, the startup process is conducted from one (main) thread, which enters + * a blocking wait() after starting the subsystems. Awakened by some termination + * signal from one of the subsystems, termination of any remaining subsystems + * will be triggered. The wait() function returns after shutdown of all subsystems, + * signalling an emergency exit (caused by an exception) with its return value. + * + * @todo implement an object monitor primitive based on a mutex and a condition. Inherit from this privately and create local instances of the embedded Lock class to activate the locking and wait/notify + * @todo maybe use my refArray (see builder) to use Subsys& instead of Subsys* ?? + * + * @see lumiera::AppState + * @see lumiera::Subsys + * @see main.cpp + */ + class SubsystemRunner + { + Option& opts_; + volatile bool emergency_; + vector running_; + + function start_, + killIt_; + + + public: + + SubsystemRunner (Option& opts) + : opts_(opts) + , emergency_(false) + , start_(bind (&SubsystemRunner::triggerStartup, this,_1)) + , killIt_(bind (&Subsys::triggerShutdown, _1)) + { } + + void + maybeRun (Subsys& susy) + { + //Lock guard (*this); + + if (!susy.isRunning() && susy.shouldStart (opts_)) + triggerStartup (&susy); + if (susy.isRunning()) + running_.push_back (&susy); + } + + void + shutdownAll () + { + //Lock guard (*this); + for_each (running_, killIt_); + } + + bool + wait () + { + //Lock(*this).wait (&SubsystemRunner::allDead); + return isEmergencyExit(); + } + + bool isEmergencyExit () { return emergency_; } + void triggerEmergency (bool cond) { emergency_ |= cond; } + + + + private: + + void + triggerStartup (Subsys* susy) + { + ASSERT (susy); + INFO (operate, "Starting subsystem \"%s\"", cStr(*susy)); + + for_each (susy->getPrerequisites(), start_); + bool started = susy->start (opts_, bind (&SubsystemRunner::sigTerm, this, susy, _1)); + + if (started && !susy->isRunning()) + { + throw error::Logic("Subsystem "+string(*susy)+" failed to start"); + } + if (!and_all (susy->getPrerequisites(), isRunning() )) + { + susy->triggerShutdown(); + throw error::Logic("Unable to start all prerequisites of Subsystem "+string(*susy)); + } } + + void + sigTerm (Subsys* susy, Error* problem) ///< called from subsystem on termination + { + ASSERT (susy); + //Lock guard (*this); + triggerEmergency(problem); + ERROR_IF (susy->isRunning(), lumiera, "Subsystem '%s' signals termination, " + "without resetting running state", cStr(*susy)); + removeall (running_, susy); + shutdownAll(); + //guard.notify(); + } + + bool + allDead () + { + if (isEmergencyExit()) + ; //Lock(*this).setTimeout(EMERGENCYTIMEOUT); + + return isnil (running_); // end wait if no running subsystem left + } + + }; + + + +} // namespace lumiera +#endif diff --git a/src/main.cpp b/src/main.cpp index 0e04ef89f..03e266686 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,8 @@ main.cpp - start the Lumiera Application Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2007-2008, Joel Holdsworth + Christian Thaeter Hermann Vosseler This program is free software; you can redistribute it and/or @@ -21,26 +22,68 @@ */ -#include +#include "include/nobugcfg.h" +#include "include/error.hpp" +#include "lumiera/appstate.hpp" +#include "lumiera/option.hpp" -#include "proc/lumiera.hpp" +#include "backend/enginefacade.hpp" +#include "backend/netnodefacade.hpp" +#include "backend/scriptrunnerfacade.hpp" +#include "proc/facade.hpp" +#include "gui/guifacade.hpp" -using std::cout; -using std::endl; -using lumiera::Appconfig; +using util::Cmdline; +using lumiera::Subsys; +using lumiera::AppState; using lumiera::ON_GLOBAL_INIT; -using lumiera::ON_GLOBAL_SHUTDOWN; - -int main (int argc, char* argv[]) -{ - cout << "*** Lumiera NLE for Linux ***" << endl - << " Version: " << Appconfig::get("version") << "\n"; - - Appconfig::lifecycle (ON_GLOBAL_INIT); - - // great things are happening here.... - - Appconfig::lifecycle (ON_GLOBAL_SHUTDOWN); - return 0; +namespace { + Subsys& engine = backend::EngineFacade::getDescriptor(); + Subsys& netNode = backend::NetNodeFacade::getDescriptor(); + Subsys& script = backend::ScriptRunnerFacade::getDescriptor(); + Subsys& builder = proc::Facade::getBuilderDescriptor(); + Subsys& session = proc::Facade::getSessionDescriptor(); + Subsys& lumigui = gui::GuiFacade::getDescriptor(); +} + + + +int +main (int argc, const char* argv[]) +{ + NOTICE (lumiera, "*** Lumiera NLE for Linux ***"); + + AppState& application = AppState::instance(); + try + { + Cmdline args (argc,argv); + lumiera::Option options (args); + application.init (options); + + session.depends (builder); + netNode.depends (session); + netNode.depends (engine); +// lumigui.depends (session); //////TODO commented out in order to be able to start up a dummy GuiStarterPlugin +// lumigui.depends (engine); + script.depends (session); + script.depends (engine); + + application.maybeStart (session); + application.maybeStart (netNode); + application.maybeStart (lumigui); + application.maybeStart (script); + + return application.maybeWait(); + } + + + catch (lumiera::Error& problem) + { + return application.abort (problem); + } + catch (...) + { + return application.abort(); + } } diff --git a/src/plugin/helloplugin.c b/src/plugin/helloplugin.c deleted file mode 100644 index d75f55f94..000000000 --- a/src/plugin/helloplugin.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * hello.c - demonstrates how to build a standalone tool (C source) - * integrated into the SCons based build system of Lumiera - */ - -#include - -int main(int argc, char* argv[]) - { - printf("hello lumiera world"); - return 0; - } diff --git a/src/pre.hpp b/src/pre.hpp index ca948b7d6..d1495d952 100644 --- a/src/pre.hpp +++ b/src/pre.hpp @@ -45,7 +45,7 @@ #include #include -#include "proc/lumiera.hpp" +#include "proc/common.hpp" diff --git a/src/pre_a.hpp b/src/pre_a.hpp index 6174b83e8..2d032c03c 100644 --- a/src/pre_a.hpp +++ b/src/pre_a.hpp @@ -42,7 +42,7 @@ #include #include -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "proc/asset.hpp" diff --git a/src/proc/Makefile.am b/src/proc/Makefile.am index 580bb637e..3e25c2749 100644 --- a/src/proc/Makefile.am +++ b/src/proc/Makefile.am @@ -24,11 +24,11 @@ noinst_LIBRARIES += liblumiproc.a liblumiproc_a_CXXFLAGS = $(CXXFLAGS) -Wall liblumiproc_a_SOURCES = \ - $(liblumiproc_a_srcdir)/controllerfacade.cpp \ + $(liblumiproc_a_srcdir)/controllerfacade.cpp \ + $(liblumiproc_a_srcdir)/facade.cpp \ $(liblumiproc_a_srcdir)/state.cpp \ $(liblumiproc_a_srcdir)/asset.cpp \ - $(liblumiproc_a_srcdir)/assetmanager.cpp \ - $(liblumiproc_a_srcdir)/nobugcfg.cpp + $(liblumiproc_a_srcdir)/assetmanager.cpp @@ -218,6 +218,5 @@ noinst_HEADERS += \ $(liblumiproc_a_srcdir)/mobject/session.hpp \ $(liblumiproc_a_srcdir)/asset.hpp \ $(liblumiproc_a_srcdir)/assetmanager.hpp \ - $(liblumiproc_a_srcdir)/lumiera.hpp \ - $(liblumiproc_a_srcdir)/nobugcfg.hpp + $(liblumiproc_a_srcdir)/facade.cpp diff --git a/src/proc/asset.cpp b/src/proc/asset.cpp index 923b61248..e576b4b44 100644 --- a/src/proc/asset.cpp +++ b/src/proc/asset.cpp @@ -1,5 +1,5 @@ /* - Asset} - Superinterface: bookeeping view of "things" present in the session + Asset - Superinterface: bookkeeping view of "things" present in the session Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -40,8 +40,11 @@ using util::and_all; using util::cStr; -namespace asset - { +namespace asset { + + using ::NOBUG_FLAG(memory); + NOBUG_CPP_DEFINE_FLAG_PARENT(assetmem, memory); + Asset::Ident::Ident(const string& n, const Category& cat, const string& o, const uint ver) : name(util::sanitize (n)), @@ -92,7 +95,7 @@ namespace asset } /** - * whether this asset is swithced on and consequently included + * whether this asset is switched on and consequently included * in the fixture and participates in rendering. */ bool @@ -133,7 +136,7 @@ namespace asset other->unlink (this->id); } - /** release all links to other dependant + /** release all links to other dependent * asset objects held internally and advise all parent * assets to do so with the link to this asset. * @note we don't release upward links to parent assets, diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index 2ed5141c8..2298a9a01 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -1,5 +1,5 @@ /* - ASSET.hpp - Superinterface: bookeeping view of "things" present in the session + ASSET.hpp - Superinterface: bookkeeping view of "things" present in the session Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -30,7 +30,7 @@ ** ** Assets are handled by a hierarchy of interfaces. Below the top level Asset interface ** there are interfaces for various different Kinds of Assets, like asset::Media, - ** asset::Proc, etc. Code utilizing the specific properties of e.g. Media assets, will + ** asset::Proc, etc. Code utilising the specific properties of e.g. Media assets, will ** be implemented directly against the asset::Media interface. To make this feasible ** while at the same time being able to handle all asset Kinds in a uniform manner, ** we use a hierarchy of ID classes. These IDs are actually just thin wrappers around @@ -56,7 +56,8 @@ #include "proc/asset/category.hpp" -#include "common/error.hpp" +#include "include/nobugcfg.h" +#include "include/error.hpp" #include "common/p.hpp" #include @@ -75,8 +76,7 @@ using std::set; -namespace asset - { +namespace asset { using std::size_t; using std::tr1::shared_ptr; @@ -84,13 +84,15 @@ namespace asset using lumiera::P; + NOBUG_DECLARE_FLAG (assetmem); + /** * thin wrapper around a size_t hash ID * used as primary key for all Asset objects. - * The Templace parameter is intended for tagging + * The Template parameter is intended for tagging * the ID with type information, causing the - * compiler to select specialized behaviour + * compiler to select specialised behaviour * for the different kinds of Assets. * @see Asset * @see AssetManager#getID generating ID values @@ -119,15 +121,15 @@ namespace asset /** - * Superinterface describing especially bookeeping properties. + * Superinterface describing especially bookkeeping properties. * As of 09/2007, there are four Kinds of Assets, each * comprising a sub-Interface of the Asset Interface: *
  • asset::Media representing mediafiles
  • *
  • asset::Proc representing media data processing components (e.g. Effects)
  • - *
  • asset::Struct representing structural components used in the sesion (e.g. Tracks)
  • + *
  • asset::Struct representing structural components used in the session (e.g. Tracks)
  • *
  • asset::Meta representing meta objects created while editing (e.g. Automation)
  • *
- * And of course there are various concret Asset subclasses, like asset::Clip, + * And of course there are various concrete Asset subclasses, like asset::Clip, * asset::Effect, asset::Codec, asset::Track, asset::Dataset. * @note Assets objects have a strict unique identity and because of this are non-copyable. * You can not create an Asset derived object without registering it with the AssetManager @@ -149,7 +151,7 @@ namespace asset struct Ident : boost::totally_ordered { - /** element ID, comprehensible but sanitized. + /** element ID, comprehensible but sanitised. * The tuple (category, name, org) is unique. */ string name; @@ -161,7 +163,7 @@ namespace asset /** origin or authorship id. * Can be a project abbreviation, a package id or just the authors nickname or UID. - * This allows for the compnent name to be more generic (e.g. "blur"). + * This allows for the component name to be more generic (e.g. "blur"). * Default for all assets provided by the core Lumiera codebase is "lumi". */ const string org; diff --git a/src/proc/asset/category.cpp b/src/proc/asset/category.cpp index 3d178e549..ad2e22cf0 100644 --- a/src/proc/asset/category.cpp +++ b/src/proc/asset/category.cpp @@ -23,7 +23,7 @@ #include "proc/asset/category.hpp" #include "common/util.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #include diff --git a/src/proc/asset/db.hpp b/src/proc/asset/db.hpp index f35785e5e..136a9e4c9 100644 --- a/src/proc/asset/db.hpp +++ b/src/proc/asset/db.hpp @@ -28,7 +28,7 @@ #include "pre_a.hpp" #include "proc/asset.hpp" -#include "common/error.hpp" +#include "include/error.hpp" #include #include @@ -130,11 +130,11 @@ namespace asset } catch (lumiera::Error& EX) { - WARN (oper, "Problems while clearing Asset registry: %s", EX.what()); + WARN (operate, "Problems while clearing Asset registry: %s", EX.what()); } catch (...) { - ERROR (oper, "Serious trouble while clearing Asset registry."); + ERROR (operate, "Serious trouble while clearing Asset registry."); } } diff --git a/src/proc/asset/media.cpp b/src/proc/asset/media.cpp index 68fcb0b56..75f78ea31 100644 --- a/src/proc/asset/media.cpp +++ b/src/proc/asset/media.cpp @@ -29,7 +29,7 @@ #include "proc/mobject/session/clip.hpp" #include "proc/mobject/session/mobjectfactory.hpp" #include "common/util.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #include #include diff --git a/src/proc/asset/meta.cpp b/src/proc/asset/meta.cpp index ec58b493c..8d71b8a1b 100644 --- a/src/proc/asset/meta.cpp +++ b/src/proc/asset/meta.cpp @@ -24,7 +24,7 @@ #include "proc/assetmanager.hpp" #include "proc/asset/meta.hpp" #include "common/util.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" namespace asset diff --git a/src/proc/asset/proc.cpp b/src/proc/asset/proc.cpp index 61dd228b7..223d3616b 100644 --- a/src/proc/asset/proc.cpp +++ b/src/proc/asset/proc.cpp @@ -24,7 +24,7 @@ #include "proc/assetmanager.hpp" #include "proc/asset/proc.hpp" #include "common/util.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" namespace asset diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index 5813ce339..68764b008 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -31,7 +31,7 @@ #include "proc/asset/structfactoryimpl.hpp" #include "common/util.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" #include diff --git a/src/proc/asset/structfactoryimpl.hpp b/src/proc/asset/structfactoryimpl.hpp index c2f6f2ab7..249259a13 100644 --- a/src/proc/asset/structfactoryimpl.hpp +++ b/src/proc/asset/structfactoryimpl.hpp @@ -36,7 +36,7 @@ #include "proc/mobject/session.hpp" #include "common/configrules.hpp" -#include "common/error.hpp" +#include "include/error.hpp" #include "common/util.hpp" #include diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp index 3f62d2ecd..ec1e715f0 100644 --- a/src/proc/assetmanager.hpp +++ b/src/proc/assetmanager.hpp @@ -39,7 +39,7 @@ #include "pre_a.hpp" #include "proc/asset.hpp" -#include "common/error.hpp" +#include "include/error.hpp" #include "common/singleton.hpp" diff --git a/src/proc/lumiera.hpp b/src/proc/common.hpp similarity index 84% rename from src/proc/lumiera.hpp rename to src/proc/common.hpp index f9ce3b838..876f96fb6 100644 --- a/src/proc/lumiera.hpp +++ b/src/proc/common.hpp @@ -45,13 +45,13 @@ #include "common/p.hpp" #include "common/util.hpp" #include "common/lumitime.hpp" -#include "common/error.hpp" ///< pulls in NoBug via nobugcfg.hpp -#include "lib/appconfig.hpp" +#include "include/symbol.hpp" +#include "include/error.hpp" ///< pulls in NoBug via nobugcfg.h /** - * Namespace for globals. - * A small number of definitions and facilities of application wide relevance. + * Lumiera public interface. + * Global interfaces and facilities accessible from plugins and scripts. * It's probably a good idea to pull it in explicitly and to avoid nesting * implementation namespaces within \c lumiera:: */ @@ -64,7 +64,7 @@ namespace lumiera { /** - * Namespace for support and library code. + * Implementation namespace for support and library code. */ namespace lib { @@ -73,12 +73,14 @@ namespace lib { /** * The asset subsystem of the Proc-Layer. + * @todo refactor proc namespaces */ namespace asset { } /** * Proc-Layer dispatcher, controller and administrative facilities. + * @todo refactor proc namespaces */ namespace control { } @@ -88,6 +90,7 @@ namespace control { } * Backbone of the engine, render nodes base and cooperation. * A good deal of the active engine code is outside the scope of the * Proc-Layer, e.g. code located in backend services and plugins. + * @todo refactor proc namespaces */ namespace engine { } @@ -95,6 +98,8 @@ namespace engine { } /** * Media-Objects, edit operations and high-level session. + * @todo is this interface or implementation ?? + * @todo refactor proc namespaces */ namespace mobject { diff --git a/src/proc/control/stypemanager.cpp b/src/proc/control/stypemanager.cpp index d28ee3eb0..d2f798a8b 100644 --- a/src/proc/control/stypemanager.cpp +++ b/src/proc/control/stypemanager.cpp @@ -21,9 +21,10 @@ * *****************************************************/ -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "proc/control/stypemanager.hpp" #include "proc/control/styperegistry.hpp" +#include "include/lifecycle.h" namespace control { @@ -52,7 +53,7 @@ namespace control { STypeManager::reset() { reg_.reset(new Registry); - lumiera::Appconfig::lifecycle(ON_STREAMTYPES_RESET); + lumiera::LifecycleHook::trigger (ON_STREAMTYPES_RESET); } /** \par diff --git a/src/proc/engine/buffhandle.hpp b/src/proc/engine/buffhandle.hpp index 069b9f83e..a3d690398 100644 --- a/src/proc/engine/buffhandle.hpp +++ b/src/proc/engine/buffhandle.hpp @@ -39,7 +39,7 @@ #define ENGINE_BUFFHANDLE_H -#include "common/error.hpp" +#include "include/error.hpp" #include "common/streamtype.hpp" diff --git a/src/proc/engine/bufftable.hpp b/src/proc/engine/bufftable.hpp index ac1329265..67c565a4d 100644 --- a/src/proc/engine/bufftable.hpp +++ b/src/proc/engine/bufftable.hpp @@ -25,7 +25,7 @@ #define ENGINE_BUFFHTABLE_H -#include "common/error.hpp" +#include "include/error.hpp" #include "proc/engine/buffhandle.hpp" #include "proc/engine/procnode.hpp" diff --git a/src/proc/engine/processor.hpp b/src/proc/engine/processor.hpp index 3f0890c93..f9bb7b164 100644 --- a/src/proc/engine/processor.hpp +++ b/src/proc/engine/processor.hpp @@ -24,7 +24,7 @@ #ifndef ENGINE_PROCESSOR_H #define ENGINE_PROCESSOR_H -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "proc/state.hpp" diff --git a/src/proc/engine/procnode.hpp b/src/proc/engine/procnode.hpp index 9cf3a2ea8..4889c0041 100644 --- a/src/proc/engine/procnode.hpp +++ b/src/proc/engine/procnode.hpp @@ -42,7 +42,7 @@ #include "pre.hpp" -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "proc/state.hpp" #include "proc/mobject/parameter.hpp" diff --git a/src/proc/facade.cpp b/src/proc/facade.cpp new file mode 100644 index 000000000..f1fbdd239 --- /dev/null +++ b/src/proc/facade.cpp @@ -0,0 +1,131 @@ +/* + Facade - access point for communicating with the Proc-Interface + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 "proc/facade.hpp" +#include "common/singleton.hpp" + +#include + + +namespace proc { + + using std::string; + using lumiera::Subsys; + + + class BuilderSubsysDescriptor + : public Subsys + { + operator string () const { return "Builder"; } + + bool + shouldStart (lumiera::Option&) + { + TODO ("determine, if we need a Builder Thread"); + return false; + } + + bool + start (lumiera::Option&, Subsys::SigTerm termination) + { + UNIMPLEMENTED ("fire up a Builder in a separate Thread, and register shutdown hook"); + return false; + } + + void + triggerShutdown () throw() + { + UNIMPLEMENTED ("halt the Builder and cancel any build process"); /////TODO really cancel?? + } + + bool + checkRunningState () throw() + { + //Lock guard (*this); + TODO ("implement detecting running state"); + return false; + } + }; + + + + class SessionSubsysDescriptor + : public Subsys + { + operator string () const { return "Session"; } + + bool + shouldStart (lumiera::Option&) + { + TODO ("determine, if an existing Session schould be loaded"); + return false; + } + + bool + start (lumiera::Option&, Subsys::SigTerm termination) + { + UNIMPLEMENTED ("load an existing session as denoted by the options and register shutdown hook"); + return false; + } + + void + triggerShutdown () throw() + { + UNIMPLEMENTED ("initiate closing this Session"); + } + + bool + checkRunningState () throw() + { + //Lock guard (*this); + TODO ("implement detecting running state"); + return false; + } + }; + + namespace { + lumiera::Singleton theBuilderDescriptor; + lumiera::Singleton theSessionDescriptor; + } + + + + + /** @internal intended for use by main(). */ + Subsys& + Facade::getBuilderDescriptor() + { + return theBuilderDescriptor(); + } + + + /** @internal intended for use by main(). */ + Subsys& + Facade::getSessionDescriptor() + { + return theSessionDescriptor(); + } + + + +} // namespace proc diff --git a/src/proc/facade.hpp b/src/proc/facade.hpp new file mode 100644 index 000000000..be156533f --- /dev/null +++ b/src/proc/facade.hpp @@ -0,0 +1,73 @@ +/* + FACADE.hpp - access point for communicating with the Proc-Interface + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 PROC_INTERFACE_FACADE_H +#define PROC_INTERFACE_FACADE_H + + +#include "lumiera/subsys.hpp" + + + +namespace proc { + + + /********************************************************************* + * Global access point for loading and starting up the Lumiera GTK GUI + * and for defining the public interface(s) for addressing the GUI + * from Backend or Proc-Layer. + * + * If 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. + * + */ + struct Facade + { + /** provide a descriptor for lumiera::AppState, + * wired accordingly to allow main to fire off + * or halt the Builder thread within Proc. */ + static lumiera::Subsys& getBuilderDescriptor(); + + + /** provide a descriptor for lumiera::AppState, + * wired accordingly to allow main to load and + * save an existing session. */ + static lumiera::Subsys& getSessionDescriptor(); + + + //////////////////TODO: define the global access interfaces for the Proc-Layer + //////////////////TODO: provide a function for accessing this interface + //////////////////TODO: register similar proxy/facade interfaces for the GUI + + }; + + + +} // namespace proc +#endif diff --git a/src/proc/mobject/builder/buildertool.hpp b/src/proc/mobject/builder/buildertool.hpp index 1801bc2ef..6cdad7456 100644 --- a/src/proc/mobject/builder/buildertool.hpp +++ b/src/proc/mobject/builder/buildertool.hpp @@ -89,13 +89,13 @@ namespace mobject { * Base class of all BuilderTools, used according to the visitor pattern: * each Tool contains the concrete implementation for one task to be done * to the various MObject classes. The concrete builder tool implementation - * should not diretcly inherit from this base interface, but rather through - * an instantiation of the "Applicable" template parametrized with all + * should not directly inherit from this base interface, but rather through + * an instantiation of the "Applicable" template parametrised with all * concrete Buildable classes, for which it wants calls to be dispatched. * \par * In addition to lumiera::visitor::Tool, BuilderTool adds support for dealing * with objects normally handled by means of smart-pointers or similar - * wrappers, most notably mobject::Placement. The visitaion is initiated + * wrappers, most notably mobject::Placement. The visitation is initiated * by calling the stand-alone function \c (BuilderTool& tool, WRA& wrappedTargetObj) , * which forwards to the visitation mechanism supported by the type contained * in the wrapper, but stores away a pointer to the wrapped object, which can diff --git a/src/proc/mobject/builder/common.hpp b/src/proc/mobject/builder/common.hpp new file mode 100644 index 000000000..36993fa03 --- /dev/null +++ b/src/proc/mobject/builder/common.hpp @@ -0,0 +1,40 @@ +/* + COMMON.hpp - common definitions for the Builder subsystem + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + 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 MOBJECT_BUILDER_COMMON_H +#define MOBJECT_BUILDER_COMMON_H + +#include "include/nobugcfg.h" + + +namespace mobject { + namespace builder { + + + NOBUG_DECLARE_FLAG (buildermem); + + + } // namespace builder + +} // namespace mobject +#endif diff --git a/src/proc/mobject/builderfacade.cpp b/src/proc/mobject/builderfacade.cpp index 149862f98..175aa2b24 100644 --- a/src/proc/mobject/builderfacade.cpp +++ b/src/proc/mobject/builderfacade.cpp @@ -21,10 +21,15 @@ * *****************************************************/ +#include "proc/mobject/builder/common.hpp" #include "proc/mobject/builderfacade.hpp" -namespace mobject - { +namespace mobject { + + namespace builder { + using ::NOBUG_FLAG(memory); + NOBUG_CPP_DEFINE_FLAG_PARENT(buildermem, memory); + } /** diff --git a/src/proc/mobject/builderfacade.hpp b/src/proc/mobject/builderfacade.hpp index 59023853c..98197ec13 100644 --- a/src/proc/mobject/builderfacade.hpp +++ b/src/proc/mobject/builderfacade.hpp @@ -24,19 +24,19 @@ #ifndef MOBJECT_BUILDERFACADE_H #define MOBJECT_BUILDERFACADE_H +#include "proc/mobject/builder/common.hpp" #include "proc/engine/renderengine.hpp" -namespace mobject - { +namespace mobject { /** * Provides unified access to the builder functionality. * While individual components of the builder subsystem may be called - * if necessary or suitable, it is usually better to do all extern invocations - * via the high level methods of this Facade. + * if necessary or suitable, it is usually better to do all external + * invocations via the high level methods of this Facade. */ class BuilderFacade { diff --git a/src/proc/mobject/mobject.cpp b/src/proc/mobject/mobject.cpp index cd6c0011b..022c3f9ff 100644 --- a/src/proc/mobject/mobject.cpp +++ b/src/proc/mobject/mobject.cpp @@ -27,6 +27,10 @@ namespace mobject { + using ::NOBUG_FLAG(memory); + NOBUG_CPP_DEFINE_FLAG_PARENT(mobjectmem, memory); + + /** Storage for the (single, static) MObject factory object. */ session::MObjectFactory MObject::create; diff --git a/src/proc/mobject/mobject.hpp b/src/proc/mobject/mobject.hpp index eb481489f..9770590e3 100644 --- a/src/proc/mobject/mobject.hpp +++ b/src/proc/mobject/mobject.hpp @@ -27,7 +27,7 @@ #include "pre.hpp" -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "proc/mobject/builder/buildertool.hpp" #include "proc/mobject/placement.hpp" #include "proc/asset.hpp" // TODO finally not needed? @@ -47,7 +47,10 @@ using proc_interface::AssetManager; namespace mobject { using lumiera::P; - + + NOBUG_DECLARE_FLAG (mobjectmem); + + namespace session { class MObjectFactory; diff --git a/src/proc/mobject/session/defsmanager.cpp b/src/proc/mobject/session/defsmanager.cpp index 538e8c9a8..456ff4b0d 100644 --- a/src/proc/mobject/session/defsmanager.cpp +++ b/src/proc/mobject/session/defsmanager.cpp @@ -24,7 +24,7 @@ #include "proc/mobject/session/defsmanager.hpp" #include "proc/mobject/session/defsregistry.hpp" #include "common/configrules.hpp" -#include "common/error.hpp" +#include "include/error.hpp" #include diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index 75068ec92..2973b85e7 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -173,7 +173,7 @@ namespace mobject }; - // static vars to organize one Table Slot per type.... + // static vars to organise one Table Slot per type.... template size_t Slot::index (0); diff --git a/src/proc/mobject/session/fixture.cpp b/src/proc/mobject/session/fixture.cpp index 19ba84970..88329075d 100644 --- a/src/proc/mobject/session/fixture.cpp +++ b/src/proc/mobject/session/fixture.cpp @@ -22,7 +22,7 @@ #include "proc/mobject/session/fixture.hpp" -#include "proc/nobugcfg.hpp" +#include "include/nobugcfg.h" namespace mobject { diff --git a/src/proc/mobject/session/locatingpin.hpp b/src/proc/mobject/session/locatingpin.hpp index ecd82ab30..799255589 100644 --- a/src/proc/mobject/session/locatingpin.hpp +++ b/src/proc/mobject/session/locatingpin.hpp @@ -42,7 +42,7 @@ #define MOBJECT_SESSION_LOCATINGPIN_H -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include #include diff --git a/src/proc/mobject/session/segment.hpp b/src/proc/mobject/session/segment.hpp index 4d978f810..72b25fcbc 100644 --- a/src/proc/mobject/session/segment.hpp +++ b/src/proc/mobject/session/segment.hpp @@ -26,7 +26,7 @@ #include -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "proc/mobject/explicitplacement.hpp" diff --git a/src/proc/mobject/session/sessionimpl.cpp b/src/proc/mobject/session/sessionimpl.cpp index e8f8c1e21..defcf7116 100644 --- a/src/proc/mobject/session/sessionimpl.cpp +++ b/src/proc/mobject/session/sessionimpl.cpp @@ -23,7 +23,7 @@ #include "proc/mobject/session/sessionimpl.hpp" #include "proc/mobject/placement.hpp" -#include "common/error.hpp" +#include "include/error.hpp" namespace mobject { diff --git a/src/proc/mobject/session/sessmanagerimpl.cpp b/src/proc/mobject/session/sessmanagerimpl.cpp index 7ac96bee4..647ee1682 100644 --- a/src/proc/mobject/session/sessmanagerimpl.cpp +++ b/src/proc/mobject/session/sessmanagerimpl.cpp @@ -22,7 +22,7 @@ /** @file sessmanagerimpl.cpp - ** Implemention of the Session management functions. + ** Implementation of the Session management functions. ** The Class SessManager is declared alongside with mobject::Session, ** because it serves as smart ptr-to-Impl at the same time. Effectively, ** the session manager owns the current session object and only grants @@ -40,16 +40,14 @@ #include "proc/mobject/session/sessionimpl.hpp" #include "proc/mobject/session/defsmanager.hpp" //#include "proc/mobject/session/defsregistry.hpp" -#include "common/error.hpp" +#include "include/error.hpp" using boost::scoped_ptr; -namespace mobject - { - namespace session - { +namespace mobject { + namespace session { LUMIERA_ERROR_DEFINE (CREATE_SESSION, "unable to create basic session"); @@ -71,8 +69,8 @@ namespace mobject } catch (...) { - ERROR (oper, "Unrecoverable Failure while creating the empty default session."); - throw lumiera::error::Fatal ( "Failure while creating the basic session object. Sysstem halted." + ERROR (operate, "Unrecoverable Failure while creating the empty default session."); + throw lumiera::error::Fatal ( "Failure while creating the basic session object. System halted." , LUMIERA_ERROR_CREATE_SESSION ); } @@ -86,7 +84,7 @@ namespace mobject * Session manger instance is created. It can be used to load an * existing session; otherwise an empty default Session an a * Defaults manager (Config Query system) is created at first - * \link #operator-> access \endlink to the sesion object. + * \link #operator-> access \endlink to the session object. */ SessManagerImpl::SessManagerImpl () throw() : pDefs_ (0), @@ -105,7 +103,7 @@ namespace mobject /** @note this operation is atomic and either succeeds or - * failes completely, in which case the current session + * fails completely, in which case the current session * remains unaltered. * @todo for this to work, we need to change the implementation of * AssetManager so support this kind of transactional switch! diff --git a/src/proc/nobugcfg.hpp b/src/proc/nobugcfg.hpp deleted file mode 100644 index edb079d05..000000000 --- a/src/proc/nobugcfg.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - NOBUGCFG.hpp - NoBug definitions and initialisation for the Proc-Layer - - - Copyright (C) Lumiera.org - 2008, Christian Thaeter - Hermann Vosseler - - 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.hpp - ** This header is for including and configuring NoBug. - ** The idea is that configuration and some globally used flag - ** declarations are to be kept in one central location. Normally, - ** this header will be included via some of the basic headers like - ** error.hpp, which in turn gets included by proc/lumiera.hpp - ** - ** @par Besides the usual guarded declarations, this header contains - ** one section with the corresponding definitions. This section - ** is to be included once by some translation unit (currently this is - ** nobugcfg.cpp) in order to generate the necessary definitions. - ** - ** @note this header assures automatic initialisation of NoBug - ** by placing a static ctor call. - ** - */ - - -#ifndef NOBUGCFG_H /* ============= Part 1: DECLARATIONS ======== */ -#define NOBUGCFG_H - -#include -#include -#include "lib/appconfig.hpp" -#include "common/error.hpp" ///< make assertions throw instead of abort() - - - /* declare flags used throughout the code base... */ - NOBUG_DECLARE_FLAG(config); - NOBUG_DECLARE_FLAG(oper); - NOBUG_DECLARE_FLAG(test); - NOBUG_DECLARE_FLAG(singleton); - NOBUG_DECLARE_FLAG(assetmem); - NOBUG_DECLARE_FLAG(mobjectmem); - NOBUG_DECLARE_FLAG(buildermem); - - -namespace lumiera { - void initialize_NoBug (); - namespace { - LifecycleHook schedule_ (ON_BASIC_INIT, &initialize_NoBug); -} } -#endif /*NOBUGCFG_H ======= (End) Part 1: DECLARATIONS ======== */ - - - - - - -#ifdef NOBUG_INIT_DEFS_ /*========== Part 2: DEFINITIONS ========= */ - - - /* flags used throughout the code base... */ - NOBUG_CPP_DEFINE_FLAG(config); - NOBUG_CPP_DEFINE_FLAG(oper); - NOBUG_CPP_DEFINE_FLAG(test); - NOBUG_CPP_DEFINE_FLAG_LIMIT(singleton, LOG_WARNING); - NOBUG_CPP_DEFINE_FLAG_LIMIT(assetmem, LOG_WARNING); - NOBUG_CPP_DEFINE_FLAG_LIMIT(mobjectmem, LOG_WARNING); - NOBUG_CPP_DEFINE_FLAG_LIMIT(buildermem, LOG_INFO); - - - - -#endif /*NOBUG_INIT_DEFS_ ==== (End) Part 2: DEFINITIONS ========= */ diff --git a/src/proc/state.hpp b/src/proc/state.hpp index cd98a39b8..9f7ee9788 100644 --- a/src/proc/state.hpp +++ b/src/proc/state.hpp @@ -27,7 +27,7 @@ #include "pre.hpp" -#include "proc/lumiera.hpp" +#include "proc/common.hpp" #include "common/frameid.hpp" #include "proc/engine/buffhandle.hpp" diff --git a/src/tool/try.cpp b/src/tool/try.cpp index 5d1034645..d6b3a95b9 100644 --- a/src/tool/try.cpp +++ b/src/tool/try.cpp @@ -15,7 +15,7 @@ #include -//#include "proc/nobugcfg.hpp" +//#include "include/nobugcfg.h" #include //#include @@ -41,7 +41,11 @@ main (int argc, char* argv[]) NOBUG_INIT; cout << "\n.gulp.\n"; - + + int * p = 0; + + int oh = *p; + return 0; } diff --git a/tests/20resourcecollector.tests b/tests/20resourcecollector.tests new file mode 100644 index 000000000..bab637815 --- /dev/null +++ b/tests/20resourcecollector.tests @@ -0,0 +1,22 @@ +TESTING "Resourcecollector" ./test-resourcecollector + + +TEST "basic register, destroy" basic < - -#include "lib/plugin.h" -#include "hello_interface.h" - -LUMIERA_ERROR_DEFINE(FAILURE, "test failure"); - -int -main(int argc, char** argv) -{ - NOBUG_INIT; - - if (argc < 2) - return -1; - - lumiera_init_plugin (); - /* - we have a plugin 'hello_1' which provides us 2 hello interfaces, one for english and one for german output, - open both try them, close them. - */ - - TODO("macros, doing casting and typing"); - - if( !strcmp(argv[1],"C")) - { - LUMIERA_INTERFACE_TYPE(hello, 1)* hello_de = - (LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin", "german_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1))); - - if (!hello_de) LUMIERA_DIE (FAILURE); - - hello_de->hello(); - hello_de->goodbye(argv[1]); - - LUMIERA_INTERFACE_TYPE(hello, 1)* hello_en = - (LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin", "english_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1))); - - if (!hello_en) LUMIERA_DIE (FAILURE); - - hello_en->hello(); - hello_en->goodbye(argv[1]); - - lumiera_interface_close (hello_en); - lumiera_interface_close (hello_de); - } - - if( !strcmp(argv[1],"C++")) - { - /* same again for a plugin written in C++ */ - LUMIERA_INTERFACE_TYPE(hello, 1)* hello_de = - (LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin_cpp", "german_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1))); - - if (!hello_de) LUMIERA_DIE (FAILURE); - - hello_de->hello(); - hello_de->goodbye(argv[1]); - - LUMIERA_INTERFACE_TYPE(hello, 1)* hello_en = - (LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin_cpp", "english_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1))); - - if (!hello_en) LUMIERA_DIE (FAILURE); - - hello_en->hello(); - hello_en->goodbye(argv[1]); - - lumiera_interface_close (hello_en); - lumiera_interface_close (hello_de); - } - - return 0; -} diff --git a/tests/backend/test-filedescriptors.c b/tests/backend/test-filedescriptors.c index 745c4087b..65a1fd33c 100644 --- a/tests/backend/test-filedescriptors.c +++ b/tests/backend/test-filedescriptors.c @@ -20,6 +20,7 @@ */ #include "lib/safeclib.h" +#include "lumiera/config.h" #include "backend/backend.h" #include "backend/filedescriptor.h" @@ -29,28 +30,39 @@ TESTS_BEGIN TEST ("acquire_existing") { + lumiera_config_init ("./"); lumiera_backend_init (); - LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY); + llist node; + llist_init (&node); + LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY, &node); if (descriptor) { - lumiera_filedescriptor_release (descriptor); + lumiera_filedescriptor_release (descriptor, ",tmp_testfile", &node); lumiera_backend_destroy (); + lumiera_config_destroy (); return 0; } else return 1; } + TEST ("acquire_existing_again") { + lumiera_config_init ("./"); lumiera_backend_init (); - LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY); + llist node; + llist_init (&node); + LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY, &node); if (descriptor) { - LumieraFiledescriptor descriptor2 = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY); - lumiera_filedescriptor_release (descriptor2); - lumiera_filedescriptor_release (descriptor); + llist node2; + llist_init (&node2); + LumieraFiledescriptor descriptor2 = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY, &node2); + lumiera_filedescriptor_release (descriptor2, ",tmp_testfile", &node2); + lumiera_filedescriptor_release (descriptor, ",tmp_testfile", &node); lumiera_backend_destroy (); + lumiera_config_destroy (); return 0; } else @@ -59,24 +71,32 @@ TEST ("acquire_existing_again") TEST ("acquire_existing_3files") { + lumiera_config_init ("./"); lumiera_backend_init (); - LumieraFiledescriptor descriptor1 = lumiera_filedescriptor_acquire (",tmp_testfile1", LUMIERA_FILE_READONLY); + llist node1; + llist_init (&node1); + LumieraFiledescriptor descriptor1 = lumiera_filedescriptor_acquire (",tmp_testfile1", LUMIERA_FILE_READONLY, &node1); - LumieraFiledescriptor descriptor2 = lumiera_filedescriptor_acquire (",tmp_testfile2", LUMIERA_FILE_READONLY); + llist node2; + llist_init (&node2); + LumieraFiledescriptor descriptor2 = lumiera_filedescriptor_acquire (",tmp_testfile2", LUMIERA_FILE_READONLY, &node2); - LumieraFiledescriptor descriptor3 = lumiera_filedescriptor_acquire (",tmp_testfile3", LUMIERA_FILE_READONLY); + llist node3; + llist_init (&node3); + LumieraFiledescriptor descriptor3 = lumiera_filedescriptor_acquire (",tmp_testfile3", LUMIERA_FILE_READONLY, &node3); if (descriptor1) - lumiera_filedescriptor_release (descriptor1); + lumiera_filedescriptor_release (descriptor1, ",tmp_testfile1", &node1); if (descriptor2) - lumiera_filedescriptor_release (descriptor2); + lumiera_filedescriptor_release (descriptor2, ",tmp_testfile2", &node2); if (descriptor3) - lumiera_filedescriptor_release (descriptor3); + lumiera_filedescriptor_release (descriptor3, ",tmp_testfile3", &node3); if (descriptor1 && descriptor2 && descriptor3) { lumiera_backend_destroy (); + lumiera_config_destroy (); return 0; } else @@ -85,12 +105,16 @@ TEST ("acquire_existing_3files") TEST ("acquire_create") { + lumiera_config_init ("./"); lumiera_backend_init (); - LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_CREATE); + llist node; + llist_init (&node); + LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_CREATE, &node); if (descriptor) { - lumiera_filedescriptor_release (descriptor); + lumiera_filedescriptor_release (descriptor, ",tmp_testfile", &node); lumiera_backend_destroy (); + lumiera_config_destroy (); return 0; } else @@ -99,17 +123,22 @@ TEST ("acquire_create") TEST ("acquire_create_dir") { + lumiera_config_init ("./"); lumiera_backend_init (); + llist node; + llist_init (&node); LumieraFiledescriptor descriptor = - lumiera_filedescriptor_acquire (",tmp_testdir/nested/,tmp_testfile", LUMIERA_FILE_CREATE); + lumiera_filedescriptor_acquire (",tmp_testdir/nested/,tmp_testfile", LUMIERA_FILE_CREATE, &node); if (descriptor) { - lumiera_filedescriptor_release (descriptor); + lumiera_filedescriptor_release (descriptor, ",tmp_testdir/nested/,tmp_testfile", &node); lumiera_backend_destroy (); + lumiera_config_destroy (); return 0; } else return 1; } + TESTS_END diff --git a/tests/backend/test-filehandles.c b/tests/backend/test-filehandles.c index 17c237d4f..cec01a152 100644 --- a/tests/backend/test-filehandles.c +++ b/tests/backend/test-filehandles.c @@ -21,6 +21,7 @@ #include "lib/llist.h" #include "lib/safeclib.h" +#include "backend/config.h" #include "backend/backend.h" #include "backend/filehandlecache.h" @@ -30,6 +31,7 @@ TESTS_BEGIN TEST ("basic") { + lumiera_config_init ("./"); lumiera_backend_init (); LumieraFile file = lumiera_file_new (",tmp_testfile", LUMIERA_FILE_CREATE); @@ -45,11 +47,13 @@ TEST ("basic") lumiera_file_delete (file); lumiera_backend_destroy (); + lumiera_config_destroy (); } TEST ("more") { + lumiera_config_init ("./"); lumiera_backend_init (); LumieraFile files[100]; @@ -82,6 +86,7 @@ TEST ("more") } lumiera_backend_destroy (); + lumiera_config_destroy (); } TESTS_END diff --git a/tests/backend/test-filemmap.c b/tests/backend/test-filemmap.c new file mode 100644 index 000000000..6e7710520 --- /dev/null +++ b/tests/backend/test-filemmap.c @@ -0,0 +1,325 @@ +/* + test-files.c - test file management + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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 + +#include "lib/llist.h" + +#include "backend/config.h" +#include "backend/backend.h" +#include "backend/file.h" +#include "backend/filedescriptor.h" +#include "backend/mmapings.h" +#include "backend/mmap.h" + +#include "tests/test.h" + +#include +#include +#include + +TESTS_BEGIN + +/* + The first two are not really tests, but some code to check for + filesystem and kernel semantics which might be moved elsewhere someday +*/ +TEST ("mmap_semantic") +{ + int fd = open (",mmaptest", O_RDWR|O_CREAT, 0666); + printf ("got fd %d\n", fd); + printf ("error %s\n", strerror (errno)); + ftruncate (fd, 8192); + + void* addr = mmap (NULL, + 8192, + PROT_WRITE, + MAP_SHARED, + fd, + 0); + + printf ("mapped at %p\n", addr); + printf ("error %s\n", strerror (errno)); + + int i = 0; + while (++i && ! errno) + { + addr = mmap (NULL, + 4096, + PROT_READ|PROT_WRITE, + MAP_SHARED, + fd, + 0); + + printf ("mapped %d again %p\n", i, addr); + printf ("error %s\n", strerror (errno)); + } +} + +TEST ("fd_semantic") +{ + mkdir (",testdir", 0777); errno = 0; + + int i = 0; + while (++i && ! errno) + { + char name[256]; + + sprintf (name, ",testdir/file_%d", i); + int fd = open (name, O_RDWR|O_CREAT, 0666); + printf ("#%d opened %d\n", i, fd); + printf ("error %s\n", strerror (errno)); + + void* addr = mmap (NULL, + 8192, + PROT_WRITE, + MAP_SHARED, + fd, + 0); + printf ("mapped at %p\n", addr); + + close (fd); + } + +} + + +TEST ("mmap_missing_chunksize") +{ + lumiera_config_init ("./"); + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-filemmap", LUMIERA_FILE_CREATE); + + LumieraMMapings mmaps = lumiera_file_mmapings (file); + + if (!mmaps) + fprintf (stderr, "%s\n", lumiera_error()); + + lumiera_file_delete (file); + + lumiera_backend_destroy (); + lumiera_config_destroy (); +} + + +TEST ("mmap_forget_releasing") +{ + lumiera_config_init ("./"); + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-filemmap", LUMIERA_FILE_CREATE); + lumiera_file_chunksize_set (file, 4096); + + LumieraMMapings mmaps = lumiera_file_mmapings (file); + + llist user; + llist_init (&user); + + LumieraMMap mmap = lumiera_mmapings_mmap_acquire (mmaps, file, &user, 0, 100); + + (void) mmap; //lumiera_mmapings_release_mmap (mmaps, &user, mmap); + + lumiera_file_delete (file); + + lumiera_backend_destroy (); + lumiera_config_destroy (); +} + + +TEST ("mmap_simple") +{ + lumiera_config_init ("./"); + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-filemmap", LUMIERA_FILE_CREATE); + lumiera_file_chunksize_set (file, 4096); + + LumieraMMapings mmaps = lumiera_file_mmapings (file); + + llist user; + llist_init (&user); + LumieraMMap mmap = lumiera_mmapings_mmap_acquire (mmaps, file, &user, 0, 100); + + lumiera_mmapings_release_mmap (mmaps, &user, mmap); + + lumiera_file_delete (file); + + /* check that the file got truncated to the desired size */ + struct stat st; + stat (",tmp-filemmap", &st); + ENSURE (st.st_size == 100); + + lumiera_backend_destroy (); + lumiera_config_destroy (); +} + + + +TEST ("mmap_checkout_twice") +{ + lumiera_config_init ("./"); + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-filemmap", LUMIERA_FILE_CREATE); + lumiera_file_chunksize_set (file, 4096); + + LumieraMMapings mmaps = lumiera_file_mmapings (file); + + llist user; + llist_init (&user); + LumieraMMap mmap = lumiera_mmapings_mmap_acquire (mmaps, file, &user, 0, 100); + + llist user2; + llist_init (&user2); + LumieraMMap mmap2 = lumiera_mmapings_mmap_acquire (mmaps, file, &user2, 0, 100); + + ENSURE (lumiera_mmap_address (mmap) == lumiera_mmap_address (mmap2)); + + lumiera_mmapings_release_mmap (mmaps, &user, mmap); + + lumiera_mmapings_release_mmap (mmaps, &user2, mmap2); + + lumiera_file_delete (file); + + /* check that the file got truncated to the desired size */ + struct stat st; + stat (",tmp-filemmap", &st); + ENSURE (st.st_size == 100); + + lumiera_backend_destroy (); + lumiera_config_destroy (); +} + + + +TEST ("mmap_checkout_again") +{ + lumiera_config_init ("./"); + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-filemmap", LUMIERA_FILE_CREATE); + lumiera_file_chunksize_set (file, 4096); + + LumieraMMapings mmaps = lumiera_file_mmapings (file); + + llist user; + llist_init (&user); + LumieraMMap mmap = lumiera_mmapings_mmap_acquire (mmaps, file, &user, 0, 100); + lumiera_mmapings_release_mmap (mmaps, &user, mmap); + + llist user2; + llist_init (&user2); + LumieraMMap mmap2 = lumiera_mmapings_mmap_acquire (mmaps, file, &user2, 0, 100); + lumiera_mmapings_release_mmap (mmaps, &user2, mmap2); + + lumiera_file_delete (file); + + /* check that the file got truncated to the desired size */ + struct stat st; + stat (",tmp-filemmap", &st); + ENSURE (st.st_size == 100); + + lumiera_backend_destroy (); + lumiera_config_destroy (); +} + + + +TEST ("mmap_grow_existing_file") +{ + lumiera_config_init ("./"); + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-filemmap", LUMIERA_FILE_READWRITE); + + lumiera_file_chunksize_set (file, 4096); + + LumieraMMapings mmaps = lumiera_file_mmapings (file); + + llist user; + llist_init (&user); + + LumieraMMap mmap = lumiera_mmapings_mmap_acquire (mmaps, file, &user, 0, 100); + lumiera_mmapings_release_mmap (mmaps, &user, mmap); + + lumiera_file_delete (file); + + /* check that the file got truncated to the desired size */ + struct stat st; + stat (",tmp-filemmap", &st); + ENSURE (st.st_size == 100); + + lumiera_backend_destroy (); + lumiera_config_destroy (); +} + + +TEST ("mmap_readonly_file") +{ + lumiera_config_init ("./"); + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-filemmap", LUMIERA_FILE_READONLY); + + lumiera_file_chunksize_set (file, 4096); + + LumieraMMapings mmaps = lumiera_file_mmapings (file); + + llist user; + llist_init (&user); + + LumieraMMap mmap = lumiera_mmapings_mmap_acquire (mmaps, file, &user, 0, 100); + lumiera_mmapings_release_mmap (mmaps, &user, mmap); + + lumiera_file_delete (file); + + /* check that the file got truncated to the desired size */ + struct stat st; + stat (",tmp-filemmap", &st); + ENSURE (st.st_size == 100); + + lumiera_backend_destroy (); + lumiera_config_destroy (); +} + + + + + +#if 0 +TEST ("refactored_usage") +{ + LumieraFile file = lumiera_file_new ("filename", mode); + + LumieraFrameIndex index = lumiera_frameindex_new ("indexfilename", file /*, indexing engine*/); + + LumieraFrame frame = lumiera_frameindex_frame (index, 123); + + //TAG+HINTS could be NEXT|PREV|EXACT|NEAREST|HARD|SOFT + + lumiera_frame_prefetch (index, 123); + + + lumiera_frame_release (frame); + + lumiera_frameindex_delete (index); + + lumiera_file_free (file); +} +#endif + + +TESTS_END diff --git a/tests/backend/test-resourcecollector.c b/tests/backend/test-resourcecollector.c new file mode 100644 index 000000000..c0e8380a9 --- /dev/null +++ b/tests/backend/test-resourcecollector.c @@ -0,0 +1,74 @@ +/* + test-resourcecollector.c - test the resource collector + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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/resourcecollector.h" + +#include "tests/test.h" + +#include +#include + +static enum lumiera_resource_try +test_memory_handler (enum lumiera_resource_try itr, void* data, void* context) +{ + switch (itr) + { + case LUMIERA_RESOURCE_UNREGISTER: + printf ("unregistering memory handler\n"); + break; + + default: + printf ("memory handler got called\n"); + return LUMIERA_RESOURCE_ALL; + } + + return LUMIERA_RESOURCE_NONE; +} + + + + +TESTS_BEGIN + +TEST ("basic") +{ + lumiera_resourcecollector_register_handler (LUMIERA_RESOURCE_MEMORY, test_memory_handler, NULL); + lumiera_resourcecollector_destroy (); +} + +TEST ("memory_collection_mockup") +{ + REQUIRE (argv[2]); + + lumiera_resourcecollector_register_handler (LUMIERA_RESOURCE_MEMORY, test_memory_handler, NULL); + + size_t size = 1000; + enum lumiera_resource_try iteration = LUMIERA_RESOURCE_ONE; + int trying = atoi (argv[2]); + do { + --trying; + } while (trying && lumiera_resourcecollector_run (LUMIERA_RESOURCE_MEMORY, &iteration, &size)); + + lumiera_resourcecollector_destroy (); +} + + +TESTS_END diff --git a/tests/common/Makefile.am b/tests/common/Makefile.am index 06a7be493..16c163f08 100644 --- a/tests/common/Makefile.am +++ b/tests/common/Makefile.am @@ -20,17 +20,18 @@ testcommon_srcdir = $(top_srcdir)/tests/common check_PROGRAMS += test-common test_common_CPPFLAGS = $(AM_CPPFLAGS) -Wall -I$(testcommon_srcdir) -test_common_LDADD = \ - liblumiprocmobjectbuilder.a \ - liblumiprocmobjectsession.a \ - liblumiprocmobject.a \ - liblumiprocengine.a \ - liblumiproccontrol.a \ - liblumiproc.a \ - liblumiprocasset.a \ - liblumibackend.a \ - liblumicommon.a \ - liblumiera.a \ +test_common_LDADD = \ + liblumiprocmobjectbuilder.a \ + liblumiprocmobjectsession.a \ + liblumiprocmobject.a \ + liblumiprocengine.a \ + liblumiproccontrol.a \ + liblumiproc.a \ + liblumiprocasset.a \ + liblumibackend.a \ + liblumicommon.a \ + liblumieracore.a \ + liblumiera.a \ $(NOBUGMT_LUMIERA_LIBS) -ldl -lboost_program_options-mt -lboost_regex-mt test_common_SOURCES = \ diff --git a/tests/common/appconfigtest.cpp b/tests/common/appconfigtest.cpp index c51b413bc..08683fa3b 100644 --- a/tests/common/appconfigtest.cpp +++ b/tests/common/appconfigtest.cpp @@ -1,5 +1,5 @@ /* - Appconfig(Test) - accessing the allways-available Appconfig singleton + Appconfig(Test) - accessing the always-available AppState singleton Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -25,15 +25,13 @@ #include "common/test/run.hpp" #include "common/util.hpp" -#include "lib/appconfig.hpp" +#include "lumiera/appstate.hpp" -namespace lumiera - { - namespace test - { +namespace lumiera { + namespace test { class Appconfig_test : public Test @@ -41,13 +39,14 @@ namespace lumiera virtual void run (Arg arg) { testAccess("version"); + UNIMPLEMENTED ("reorganise config access for C++"); } - /** @test accessing a value from lumiera::Appconfig */ + /** @test accessing a value from lumiera::AppState */ void testAccess (const string& key) { - string ver = lumiera::Appconfig::get(key); - ASSERT ( !util::isnil(ver)); +// string ver = lumiera::AppState::get(key); +// ASSERT ( !util::isnil(ver)); } }; diff --git a/tests/common/customsharedptrtest.cpp b/tests/common/customsharedptrtest.cpp index e32fa6b22..bab7cfaa1 100644 --- a/tests/common/customsharedptrtest.cpp +++ b/tests/common/customsharedptrtest.cpp @@ -1,5 +1,5 @@ /* - CustomSharedPtr(Test) - refcounting, equality and comparisons + CustomSharedPtr(Test) - ref counting, equality and comparisons Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -174,16 +174,15 @@ namespace asset P pX1; // Base: shared_ptr P > pX2; // Base: P P > pX3; // Base: shared_ptr - P > pLo;// Base: shared_ptr (quite a nonsene, but well...) + P > pLo;// Base: shared_ptr (quite a nonsense, but well...) P pLoL; // Base: std::string P pLoLoL; // Base: shared_ptr - ASSERT (INSTANCEOF (P, &pX)); ASSERT (INSTANCEOF (shared_ptr, &pX)); ASSERT ( INSTANCEOF (shared_ptr, &pX1)); // ASSERT (!INSTANCEOF (shared_ptr, &pX1)); // doesn't compile (no RTTI) -- that's correct -// ASSERT (!INSTANCEOF (P, &pX1)); +// ASSERT (!INSTANCEOF (P, &pX1)); // similar, type mismatch detected by compiler ASSERT ( INSTANCEOF (shared_ptr, &pX2)); // ASSERT (!INSTANCEOF (shared_ptr, &pX2)); @@ -209,8 +208,8 @@ namespace asset pX = pX1; // OK: pointee subtype... pX = pX2; // invokes shared_ptr::operator= (shared_ptr const&) pX = pX3; -// pX = pLo; // similar, but long* not asignable to X* -// pX = pLoL; // similar, but string* not asignable to X* +// pX = pLo; // similar, but long* not assignable to X* +// pX = pLoL; // similar, but string* not assignable to X* // pX = pLoLoL; // same... // you won't be able to do much with the "LoLo"-Types, // as their types and pointee types's relations don't match @@ -295,7 +294,7 @@ namespace asset ASSERT (!(pXX <= pX5)); ASSERT (!(pXX >= pX5)); - ASSERT ( (pX5 == pX6)); // compare two empty ptrs: "equal, aequivalent but not orderable" + ASSERT ( (pX5 == pX6)); // compare two empty ptrs: "equal, equivalent but not orderable" ASSERT (!(pX5 != pX6)); ASSERT (!(pX5 < pX6)); ASSERT (!(pX5 > pX6)); diff --git a/tests/common/exceptionerrortest.cpp b/tests/common/exceptionerrortest.cpp index e1c133e4f..9ce45a1c8 100644 --- a/tests/common/exceptionerrortest.cpp +++ b/tests/common/exceptionerrortest.cpp @@ -23,7 +23,7 @@ #include "lib/error.h" -#include "common/error.hpp" +#include "include/error.hpp" #include "common/test/run.hpp" #include "common/util.hpp" @@ -182,7 +182,7 @@ namespace lumiera * this should result in the global unknown() handler to be called, * so usually it will terminate the testrun. * @note inside error.hpp, an initialisation hook has been installed into - * Appconfig, causing our own unknown() handler to be installed and + * AppState, causing our own unknown() handler to be installed and * invoked, which gives additional diagnostics.*/ void terminateUnknown () throw() { diff --git a/tests/common/lifecycletest.cpp b/tests/common/lifecycletest.cpp index 21a33dce5..113c1c162 100644 --- a/tests/common/lifecycletest.cpp +++ b/tests/common/lifecycletest.cpp @@ -1,5 +1,5 @@ /* - LifeCycle(Test) - checking the lifecycle callback hooks provided by Appconfig + LifeCycle(Test) - checking the lifecycle callback hooks provided by AppState Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -25,7 +25,7 @@ #include "common/test/run.hpp" #include "common/util.hpp" -#include "lib/appconfig.hpp" +#include "lumiera/appstate.hpp" @@ -44,7 +44,7 @@ namespace lumiera Symbol MY_MAGIC_MEGA_EVENT = "dial M for murder"; - namespace // register them to be invoced by lifecycle event id + namespace // register them to be invoked by lifecycle event id { LifecycleHook _schedule1 (ON_BASIC_INIT, &basicInitHook); LifecycleHook _schedule2 (MY_MAGIC_MEGA_EVENT, &myCallback); @@ -64,7 +64,7 @@ namespace lumiera ASSERT (1 == basicInit, "the basic-init callback has been invoked more than once"); ASSERT (!customCallback); - Appconfig::lifecycle (MY_MAGIC_MEGA_EVENT); + AppState::lifecycle (MY_MAGIC_MEGA_EVENT); ASSERT ( 1 == customCallback); } diff --git a/tests/common/mainsuite.cpp b/tests/common/mainsuite.cpp index 455bfd98e..92db417e3 100644 --- a/tests/common/mainsuite.cpp +++ b/tests/common/mainsuite.cpp @@ -1,5 +1,5 @@ /* - mainsuite.cpp - "the" Lumiera self test suite + mainsuite.cpp - execute a suite of test objects, possibly filtered by category Copyright (C) Lumiera.org 2008, Christian Thaeter @@ -23,15 +23,16 @@ #include "common/test/suite.hpp" #include "common/test/testoption.hpp" -#include "lib/appconfig.hpp" +#include "lumiera/appstate.hpp" +#include "include/lifecycle.h" -using lumiera::Appconfig; +using lumiera::AppState; using lumiera::ON_GLOBAL_INIT; using lumiera::ON_GLOBAL_SHUTDOWN; /** run all tests or any single test specified in the first - * cmd line argument. + * command line argument. * Note: to ease debugging, we don't catch any exceptions. */ int main (int argc, const char* argv[]) @@ -39,13 +40,13 @@ int main (int argc, const char* argv[]) util::Cmdline args (argc,argv); test::TestOption optparser (args); test::Suite suite (optparser.getTestgroup()); - Appconfig::lifecycle(ON_GLOBAL_INIT); + AppState::lifecycle(ON_GLOBAL_INIT); if (optparser.getDescribe()) suite.describe(); else suite.run (args); - Appconfig::lifecycle(ON_GLOBAL_SHUTDOWN); + AppState::lifecycle(ON_GLOBAL_SHUTDOWN); return 0; } diff --git a/tests/common/meta/configflagstest.cpp b/tests/common/meta/configflagstest.cpp index 34b54be48..d7383615b 100644 --- a/tests/common/meta/configflagstest.cpp +++ b/tests/common/meta/configflagstest.cpp @@ -24,7 +24,7 @@ /** @file configflagstest.cpp ** \par build a type representing a single configuration defined by a set of flags ** - ** The semi-automatic assembly of processing node invocation code utilizes some + ** The semi-automatic assembly of processing node invocation code utilises some ** metaprogramming to generate a factory, which in turn produces node wiring objects ** according to the configuration to be used for the corresponding ProcNode. This relies on ** generating a distinct type based on a given set of configuration flags, @@ -128,7 +128,7 @@ namespace lumiera { * all possible defined specialisations of some template based on * such configuration-tuples. This allows us to assemble the glue code * for pulling data from processing nodes out of small building blocks - * in all possible configuraions. + * in all possible configurations. */ class ConfigFlags_test : public Test { @@ -280,7 +280,7 @@ namespace lumiera { /** @test use the ConfigSelector template to build a set of factories, - * based on a set of configurations. Then invoke the apropriate + * based on a set of configurations. Then invoke the appropriate * factory by specifying the configuration bit code */ void check_ConfigSelector() diff --git a/tests/common/query/queryutilstest.cpp b/tests/common/query/queryutilstest.cpp index fc5e914a9..b641d9d0a 100644 --- a/tests/common/query/queryutilstest.cpp +++ b/tests/common/query/queryutilstest.cpp @@ -24,7 +24,7 @@ #include "common/test/run.hpp" #include "common/util.hpp" -#include "common/cmdline.hpp" +#include "lib/cmdline.hpp" #include "common/query.hpp" #include "query/querydiagnostics.hpp" diff --git a/tests/common/singletonsubclasstest.cpp b/tests/common/singletonsubclasstest.cpp index cdbdd6934..ac3cbd3f0 100644 --- a/tests/common/singletonsubclasstest.cpp +++ b/tests/common/singletonsubclasstest.cpp @@ -83,7 +83,7 @@ namespace lumiera /******************************************************************* - * @test spezialized variant of the Singleton Factory, for creating + * @test specialised variant of the Singleton Factory, for creating * subclasses (implementation classes) without coupling the * caller to the concrete class type. * Expected results: an instance of the subclass is created. @@ -106,7 +106,7 @@ namespace lumiera singleton::UseSubclass typeinfo; // define an instance of the Singleton factory, - // spezialized to create the concrete Type passed in + // Specialised to create the concrete Type passed in SingletonSubclassFactory instance (typeinfo); // Now use the Singleton factory... diff --git a/tests/common/singletontestmocktest.cpp b/tests/common/singletontestmocktest.cpp index 2be296bb1..700398471 100644 --- a/tests/common/singletontestmocktest.cpp +++ b/tests/common/singletontestmocktest.cpp @@ -57,11 +57,11 @@ namespace lumiera TestSingletonO(Symbol ty="TestSingletonO") : callCnt (0), typid(ty), msg ("%s::doIt() call=%d\n") { - TRACE (singleton, "ctor %s", typid); + TRACE (test, "ctor %s", typid); } virtual ~TestSingletonO() { - TRACE (singleton, "dtor %s", typid); + TRACE (test, "dtor %s", typid); } void doIt () diff --git a/tests/common/test/cmdlinewrappertest.cpp b/tests/common/test/cmdlinewrappertest.cpp index f5d1eaf25..e99e2bd8c 100644 --- a/tests/common/test/cmdlinewrappertest.cpp +++ b/tests/common/test/cmdlinewrappertest.cpp @@ -22,7 +22,7 @@ #include "common/test/run.hpp" -#include "common/cmdline.hpp" +#include "lib/cmdline.hpp" #include "common/util.hpp" #include diff --git a/tests/components/Makefile.am b/tests/components/Makefile.am index 43503640a..98e7d5214 100644 --- a/tests/components/Makefile.am +++ b/tests/components/Makefile.am @@ -27,9 +27,10 @@ test_components_LDADD = \ liblumiprocmobjectsession.a \ liblumiprocasset.a \ liblumiprocmobject.a \ - liblumiera.a \ liblumicommon.a \ + liblumieracore.a \ liblumibackend.a \ + liblumiera.a \ $(NOBUGMT_LUMIERA_LIBS) -ldl -lboost_program_options-mt -lboost_regex-mt test_components_SOURCES = \ diff --git a/tests/components/proc/asset/makecliptest.cpp b/tests/components/proc/asset/makecliptest.cpp index 136abf05d..78ab35073 100644 --- a/tests/components/proc/asset/makecliptest.cpp +++ b/tests/components/proc/asset/makecliptest.cpp @@ -35,11 +35,10 @@ using std::string; using std::tr1::static_pointer_cast; //TODO only temporarily; -namespace asset - { - namespace test - { +namespace asset { + namespace test { + using mobject::NOBUG_FLAG(mobjectmem); diff --git a/tests/components/proc/engine/bufftabletest.cpp b/tests/components/proc/engine/bufftabletest.cpp index 420d30636..436285c95 100644 --- a/tests/components/proc/engine/bufftabletest.cpp +++ b/tests/components/proc/engine/bufftabletest.cpp @@ -22,7 +22,7 @@ #include "common/test/run.hpp" -#include "common/error.hpp" +#include "include/error.hpp" #include "proc/engine/procnode.hpp" #include "proc/engine/bufftable.hpp" diff --git a/tests/components/proc/mobject/session/testsession1.hpp b/tests/components/proc/mobject/session/testsession1.hpp index d9c422f2f..bb8745851 100644 --- a/tests/components/proc/mobject/session/testsession1.hpp +++ b/tests/components/proc/mobject/session/testsession1.hpp @@ -26,7 +26,7 @@ #include "proc/mobject/session.hpp" -#include "common/error.hpp" +#include "include/error.hpp" //#include "common/factory.hpp" //#include "common/util.hpp" diff --git a/tests/lumiera/DIR_INFO b/tests/lumiera/DIR_INFO new file mode 100644 index 000000000..5dbe3e850 --- /dev/null +++ b/tests/lumiera/DIR_INFO @@ -0,0 +1 @@ +tests for the main lumiera loader diff --git a/tests/lumiera/hello_interface.h b/tests/lumiera/hello_interface.h new file mode 100644 index 000000000..9cb25246f --- /dev/null +++ b/tests/lumiera/hello_interface.h @@ -0,0 +1,16 @@ +#include "lumiera/interface.h" + +/* + one interface which can greet in different languages +*/ +LUMIERA_INTERFACE_DECLARE (lumieraorg_testhello, 0, + LUMIERA_INTERFACE_SLOT (void, hello, (void)), + LUMIERA_INTERFACE_SLOT (void, goodbye, (const char*)), +); + +/* + and now one which will be used to test if interfaces can open and call each other +*/ +LUMIERA_INTERFACE_DECLARE (lumieraorg_testtest, 0, + LUMIERA_INTERFACE_SLOT (void, testit, (void)), +); diff --git a/tests/backend/test-config.c b/tests/lumiera/test-config.c similarity index 99% rename from tests/backend/test-config.c rename to tests/lumiera/test-config.c index 120fc57d7..cf215b7f2 100644 --- a/tests/backend/test-config.c +++ b/tests/lumiera/test-config.c @@ -21,8 +21,8 @@ */ #include "lib/safeclib.h" -#include "backend/config.h" -#include "backend/configitem.h" +#include "lumiera/config.h" +#include "lumiera/configitem.h" #include "tests/test.h" diff --git a/tests/backend/test-interfaces.c b/tests/lumiera/test-interfaces.c similarity index 94% rename from tests/backend/test-interfaces.c rename to tests/lumiera/test-interfaces.c index a087da735..d85cf99dd 100644 --- a/tests/backend/test-interfaces.c +++ b/tests/lumiera/test-interfaces.c @@ -19,13 +19,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "backend/interface.h" -#include "backend/interfaceregistry.h" -#include "backend/interfacedescriptor.h" -#include "backend/config.h" +#include "lumiera/interface.h" +#include "lumiera/interfaceregistry.h" +#include "lumiera/interfacedescriptor.h" +#include "lumiera/config.h" +#include "lumiera/config_interface.h" #include "tests/test.h" -#include "tests/backend/hello_interface.h" +#include "tests/lumiera/hello_interface.h" /* define 2 example interfaces @@ -58,8 +59,9 @@ testfunc (const char* message) LumieraInterface -testacquire (LumieraInterface self) +testacquire (LumieraInterface self, LumieraInterface interface) { + (void) interface; printf ("Acquire %s_%d_%s\n", self->interface, self->version, self->name); return self; } @@ -165,8 +167,9 @@ static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) one_keeps_two; static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) one_keeps_three; LumieraInterface -testacquire_one (LumieraInterface self) +testacquire_one (LumieraInterface self, LumieraInterface interface) { + (void) interface; TRACE (tests, "Acquire one %s_%d_%s", self->interface, self->version, self->name); one_keeps_two = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two); one_keeps_three = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_three); @@ -185,8 +188,9 @@ static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) two_keeps_one; static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) two_keeps_four; LumieraInterface -testacquire_two (LumieraInterface self) +testacquire_two (LumieraInterface self, LumieraInterface interface) { + (void) interface; TRACE (tests, "Acquire two %s_%d_%s", self->interface, self->version, self->name); two_keeps_one = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one); two_keeps_four = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four); @@ -205,8 +209,9 @@ static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) three_keeps_two; static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) three_keeps_four; LumieraInterface -testacquire_three (LumieraInterface self) +testacquire_three (LumieraInterface self, LumieraInterface interface) { + (void) interface; TRACE (tests, "Acquire three %s_%d_%s", self->interface, self->version, self->name); three_keeps_two = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two); three_keeps_four = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_four); @@ -226,8 +231,9 @@ static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) four_keeps_two; static LUMIERA_INTERFACE_HANDLE(lumieraorg_testexample_void, 0) four_keeps_three; LumieraInterface -testacquire_four (LumieraInterface self) +testacquire_four (LumieraInterface self, LumieraInterface interface) { + (void) interface; TRACE (tests, "Acquire four %s_%d_%s", self->interface, self->version, self->name); four_keeps_one = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_one); four_keeps_two = LUMIERA_INTERFACE_OPEN (lumieraorg_testexample_void, 0, 0, lumieraorg_dependencytest_two); @@ -493,7 +499,7 @@ TEST ("plugin_examplepluginc") lumiera_interfaceregistry_init (); lumiera_plugin_discover (lumiera_plugin_load, lumiera_plugin_register); - TODO ("macro to derrive minminor version from a slot"); + TODO ("macro to derive minminor version from a slot"); LUMIERA_INTERFACE_HANDLE(lumieraorg_testhello, 0) german = LUMIERA_INTERFACE_OPEN (lumieraorg_testhello, 0, 0, lumieraorg_hello_german); @@ -514,6 +520,25 @@ TEST ("plugin_examplepluginc") lumiera_config_destroy (); } +TEST ("plugin_examplepluginc_nested") +{ + lumiera_config_init ("./"); + lumiera_interfaceregistry_init (); + lumiera_plugin_discover (lumiera_plugin_load, lumiera_plugin_register); + lumiera_config_interface_init (); + + LUMIERA_INTERFACE_HANDLE(lumieraorg_testtest, 0) test = + LUMIERA_INTERFACE_OPEN (lumieraorg_testtest, 0, 0, lumieraorg_test_both); + + test->testit (); + + LUMIERA_INTERFACE_CLOSE (test); + + lumiera_config_interface_destroy (); + lumiera_interfaceregistry_destroy (); + lumiera_config_destroy (); +} + TESTS_END diff --git a/tests/backend/example_plugin.c b/tests/plugin/example_plugin.c similarity index 68% rename from tests/backend/example_plugin.c rename to tests/plugin/example_plugin.c index 66a93c838..ee48fc828 100644 --- a/tests/backend/example_plugin.c +++ b/tests/plugin/example_plugin.c @@ -1,41 +1,102 @@ +/* + example_plugin - example plugin for testing the interface/plugin system + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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 "hello_interface.h" -#include "backend/interfacedescriptor.h" +#include "lumiera/interfacedescriptor.h" +#include "lumiera/config_interface.h" -int myopen(void) +#include "tests/lumiera/hello_interface.h" + + +LUMIERA_PLUGIN_INTERFACEHANDLE; + +LumieraInterface +myopen (LumieraInterface self, LumieraInterface interfaces) { - printf("opened\n"); - return 0; + LUMIERA_PLUGIN_STORE_INTERFACEHANDLE (interfaces); + + fprintf (stderr, "opened %p global interfaces %p\n", self, interfaces); + return self; } -int myclose(void) +void +myclose (LumieraInterface self) { - printf("closed\n"); - return 0; + fprintf (stderr, "closed %p\n", self); } -void hallo(void) +void hallo (void) { - printf("Hallo Welt!\n"); + printf ("Hallo Welt!\n"); } -void tschuess(const char* m) +void tschuess (const char* m) { - printf("Tschuess %s\n", m); + printf ("Tschuess %s\n", m); } -void hello(void) +void hello (void) { - printf("Hello World!\n"); + printf ("Hello World!\n"); } -void bye(const char* m) +void bye (const char* m) { - printf("Bye %s\n", m); + printf ("Bye %s\n", m); } +void yeahbabe (void) +{ + LUMIERA_INTERFACE_HANDLE (lumieraorg_testhello, 0) german = + LUMIERA_INTERFACE_OPEN (lumieraorg_testhello, 0, 0, lumieraorg_hello_german); + + LUMIERA_INTERFACE_HANDLE (lumieraorg_testhello, 0) english = + LUMIERA_INTERFACE_OPEN (lumieraorg_testhello, 0, 0, lumieraorg_hello_english); + + LUMIERA_INTERFACE_HANDLE (lumieraorg_configuration, 0) config = + LUMIERA_INTERFACE_OPEN (lumieraorg_configuration, 0, 0, lumieraorg_configuration); + + const char* path; + if (config->wordlist_get ("config.path", &path)) + printf ("config path is: %s\n", path); + if (config->wordlist_get ("plugin.path", &path)) + printf ("plugin path is: %s\n", path); + + LUMIERA_INTERFACE_CLOSE (config); + + german->hello (); + english->hello (); + english->goodbye ("World!"); + german->goodbye ("Welt!"); + + LUMIERA_INTERFACE_CLOSE (german); + LUMIERA_INTERFACE_CLOSE (english); +} + + + LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor, NULL, NULL, NULL, @@ -107,8 +168,8 @@ LUMIERA_EXPORT( LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, lumieraorg_hello_german, LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), - NULL, - NULL, + myopen, + myclose, LUMIERA_INTERFACE_MAP (hello, "\167\012\306\023\031\151\006\362\026\003\125\017\170\022\100\333", hallo), LUMIERA_INTERFACE_MAP (goodbye, "\324\267\214\166\340\213\155\053\157\125\064\264\167\235\020\223", @@ -117,11 +178,19 @@ LUMIERA_EXPORT( LUMIERA_INTERFACE_DEFINE (lumieraorg_testhello, 0, lumieraorg_hello_english, LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), - NULL, - NULL, + myopen, + myclose, LUMIERA_INTERFACE_MAP (hello, "\326\247\370\247\032\103\223\357\262\007\356\042\051\330\073\116", hello), LUMIERA_INTERFACE_MAP (goodbye, "\365\141\371\047\101\230\050\106\071\231\022\235\325\112\354\241", bye) + ), + LUMIERA_INTERFACE_DEFINE (lumieraorg_testtest, 0, + lumieraorg_test_both, + LUMIERA_INTERFACE_REF (lumieraorg_interfacedescriptor, 0, lumieraorg_exampleplugin_descriptor), + myopen, + myclose, + LUMIERA_INTERFACE_MAP (testit, "\101\060\122\277\370\023\164\257\347\247\164\325\157\266\323\370", + yeahbabe) ) ) diff --git a/tests/backend/example_plugin.cpp b/tests/plugin/example_plugin.cpp similarity index 100% rename from tests/backend/example_plugin.cpp rename to tests/plugin/example_plugin.cpp diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 01c9a849d..806303db6 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -1364,6 +1364,29 @@ For this Lumiera design, we could consider making GOP just another raw media dat &rarr;see in [[Wikipedia|http://en.wikipedia.org/wiki/Group_of_pictures]] +
+
All communication between Proc-Layer and GUI has to be routed through the respective LayerSeparationInterfaces. Following a fundamental design decision within Lumiera, these interface are //intended to be language agnostic// &mdash; forcing them to stick to the least common denominator. Which creates the additional problem of how to create a smooth integration without forcing the architecture into functional decomposition style. To solve this problem, we rely on the well known solution of using a __business facade__ and delegation proxies.
+Thus, the Proc-Layer exposes (one or several) facade interfaces for the GUI to use it's functionality, and similarily the GUI provides a [[notification facade|GuiNotificationFacade]] for pushing back status information created as result of the edit operations, the build process and the render tasks.
+
+!anatomy of the Proc/GUI interface
+* the GuiFacade is used as a general lifecycle facade to start up the GUI and to set up the LayerSeparationInterfaces.
+* GuiFacade is implemented by a class //in core// and exposes a notification proxy implementing GuiNotificationFacade, which actually is wired through the InterfaceSystem to forward to the corresponding implementation facade object within the GUI
+* similarly, starting the fundamental subsystems within proc installs Interfaces into the InterfaceSystem and exposes them through proxy objects
+
+
+
+
+
Considering how to interface to and integrate with the GUI Layer. Running the GUI is //optional,// but it requires to be [[started up|GuiStart]], installing the necessary LayerSeparationInterfaces.
+
+
+
Starting up the GUI is optional and is considered part of the Application start/stop and lifecycle.
+* main and AppState activate the lifecyle methods on the ~GuiSubsysDescriptor
+* loading a GuiStarterPlugin creates an instance of the notification interface within the InterfaceSystem
+* its implementation (within GuiStarterPlugin) is linked against the GuiNotificationFacade, i.e. the actual implementation. This link is hard wired.
+* the process of loading this GuiStarterPlugin creates an interface ref on the calling side, which is made available through the usual singleton factory embedded within the GuiNotificationFacade interface. {{red{TODO current solution doesn't handle shutdown correctly}}}
+* activating this singleton factory yields the (single) instance of the forwarding proxy, which calls through this interface ref.
+
+
While the low-level model holds the data used for carrying out the actual media data processing (=rendering), the high-level model is what the user works upon when performing edit operations through the GUI (or script driven in &raquo;headless mode&laquo;). Its building blocks and combination rules determine largely what structures can be created within the [[Session]].
 On the whole, it is a collection of [[media objects|MObjects]] stuck together and arranged by [[placements|Placement]].
@@ -1401,7 +1424,7 @@ Besides routing to a global pipe, wiring plugs can also connect to the source po
 Finally, this example shows an ''automation'' data set controlling some parameter of an effect contained in one of the global pipes. From the effect's POV, the automation is simply a ParamProvider, i.e a function yielding a scalar value over time. The automation data set may be implemented as a bézier curve, or by a mathematical function (e.g. sine or fractal pseudo random) or by some captured and interpolated data values. Interestingly, in this example the automation data set has been placed relatively to the meta clip (albeit on another track), thus it will follow and adjust when the latter is moved.
 
-
+
This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Lumiera Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -1421,6 +1444,7 @@ Finally, this example shows an ''automation'' data set controlling some paramete
 * working out the [[basic building situations|BuilderPrimitives]] and [[mechanics of rendering|RenderMechanics]]
 * how to classify and [[describe media stream types|StreamType]] and how to [[use them|StreamTypeUse]]
 * the relation of [[Project, Timelines and Sequences|TimelineSequences]]
+* how to [[start the GUI|GuiStart]] and how to [[communicate|GuiCommunication]]
 
@@ -1777,6 +1801,20 @@ From experiences with other middle scale projects, I prefer having the test code [img[Example: Interfaces/Namespaces of the ~Session-Subsystems|uml/fig130053.png]]
+
+
Lumiera uses a 3-layered architecture. Separation between layers is crucial. Any communication between the layers regarding the normal operation of the application should //at least be initiated// through ''Layer abstraction interfaces''. This is a low-impact version of layering, because, aside from this triggering, direct cooperation of parts within the single Lumiera process is allowed, under the condition that is is implemented using additional abstractions (interfaces with implementation level granularity). We stick to the policy of //disallowing direct coupling of implementations located in different layers.//
+
+To implement such a structure, each layer separation interface actually is comprised of several parts:
+* an CLI interface to be installed into the InterfaceSystem
+* a facade interface defining the respective abstractions in terms of the implementation language (C or C++)
+* a implementation object on the service proiding side which is directly addressed by the implementation instantiated within the InterfaceSystem
+* a proxy object on the client side, which usually is given inline alongside with the CLI interface definition.
+
+!opening and closing
+Handling the lifecycle can be tricky, because client- and service-side need to carry out the opening and closing operations in sync and observing a specific call order to ensure calls get blocked already on the client side unless the whole interface compound is really up and running. To add to this complexity, plugins and built-in interfaces are handled differently regarding the question who is in charge of the lifecycle: interfaces are installed on the service side, whereas the loading of plugins is triggered from client side by requesting the plugin from the loader.
+Anyway, interfaces are resources which best should be managed automatically. At least within the C++ part of the application we can ensure this by using a handle class. This way the handling of plugins and interfaces can be unified; the only remaining difference is on what side (client or service provider side) the handle is instantiated, with the appropriate ctor parameters.
+
+
Opening and accessing media files on disk poses several problems, most of which belong to the domain of Lumiera's data backend. Here, we focus on the questions related to making media data available to the EDL and the render engine. Each media will be represented by an MediaAsset object, which indeed could be a compound object (in case of MultichannelMedia). Building this asset object thus includes getting informations from the real file on disk. For delegating this to the backend, we use the following query interface:
 * {{{queryFile(char* name)}}} requests accessing the file and yields some (opaque) handle when successful.
@@ -2810,7 +2848,7 @@ Besides, they provide an important __inward interface__ for the [[ProcNode]]s, w
 
 
-
+
The Render Engine is the part of the application doing the actual video calculations. Its operations are guided by the Objects and Parameters edited by the user in [[the EDL|EDL]] and it retrieves the raw audio and video data from the [[Data backend|backend.html]]. Because the inner workings of the Render Engine are closely related to the structures used in the EDL, this design covers [[the aspect of objects placed into the EDL|MObjects]] as well.
 <<<
 ''Status'': started out as design draft in summer '07, Ichthyo is now in the middle of a implementing the foundations and main structures in C++
@@ -2818,6 +2856,7 @@ Besides, they provide an important __inward interface__ for the [[ProcNode]]s, w
 * [[Builder]] implementation is on the way (&rarr;[[more|BuilderPrimitives]])
 * made a first draft of how to wire and operate procesing nodes (&rarr;[[more|RenderMechanics]])
 * working out the relation of [[Project, Timelines and Sequences|TimelineSequences]]
+* first attempts to [[integrate with the GUI|GuiIntegration]]
 <<<
 
 !Summary