From c7466293124aa6590e8591b8a403ac443c44c292 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 14 Sep 2007 19:18:11 +0200 Subject: [PATCH 1/5] util for sanitizing a string, making it usable as identifier --- SConstruct | 2 +- src/common/singleton.hpp | 2 +- src/common/util.cpp | 72 +++++++++++++++++++ src/common/util.hpp | 30 ++++++-- tests/50components.tests | 21 +++++- .../common/sanitizedidentifiertest.cpp | 10 ++- .../common/test/cmdlinewrappertest.cpp | 2 +- 7 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 src/common/util.cpp diff --git a/SConstruct b/SConstruct index b9ac74167..126e40a8d 100644 --- a/SConstruct +++ b/SConstruct @@ -62,7 +62,7 @@ def setupBasicEnvironment(): , BINDIR=BINDIR , CPPPATH=["#"+SRCDIR] # used to find includes, "#" means always absolute to build-root , CPPDEFINES=['-DCINELERRA_VERSION='+VERSION ] # note: it's a list to append further defines - , CCFLAGS='-Wall' + , CCFLAGS='-Wall ' # -fdiagnostics-show-option ) handleNoBugSwitches(env) diff --git a/src/common/singleton.hpp b/src/common/singleton.hpp index 9a7e70365..5c9018f78 100644 --- a/src/common/singleton.hpp +++ b/src/common/singleton.hpp @@ -75,7 +75,7 @@ namespace cinelerra { if (!pInstance_) { - ThreadLock guard; + ThreadLock guard SIDEEFFECT; if (!pInstance_) { if (isDead_) diff --git a/src/common/util.cpp b/src/common/util.cpp new file mode 100644 index 000000000..28958ade9 --- /dev/null +++ b/src/common/util.cpp @@ -0,0 +1,72 @@ +/* + util.cpp - helper functions implementation + + Copyright (C) CinelerraCV + 2007, 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 "common/util.hpp" + +#include +#include +#include + +using boost::algorithm::trim_right_copy_if; +using boost::algorithm::is_any_of; +using boost::algorithm::is_alnum; +using boost::algorithm::is_space; + + +namespace util + { + + typedef boost::function ChPredicate; + ChPredicate operator! (ChPredicate p) { return ! boost::bind(p,_1); } + + // character classes used for sanitizing strings + ChPredicate isValid (is_alnum() || is_any_of("-_.:+$'()@")); + ChPredicate isPunct (is_space() || is_any_of(",;#*~´`?\\=/&%![]{}")); + + + string + sanitize (const string& org) + { + string res (trim_right_copy_if(org, !isValid )); + string::iterator j = res.begin(); + string::const_iterator i = org.begin(); + string::const_iterator e = i + (res.length()); + while ( i != e ) + { + while ( i != e && !isValid (*i) ) ++i; + while ( i != e && isValid (*i) ) *(j++) = *(i++); + if ( i != e && isPunct (*i) ) + { + *j++ = '_'; + do ++i; + while ( i != e && isPunct (*i)); + } + } + res.erase(j,res.end()); + return res; + } + + + +} // namespace util + diff --git a/src/common/util.hpp b/src/common/util.hpp index dca8158ee..479142069 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -89,14 +89,25 @@ namespace util /** produce an identifier based on the given string. - * remove non-standard-chars, reduce punctuation to underscores + * remove non-standard-chars, reduce sequences of punctuation + * and whitespace to single underscores. The sanitized string + * will start with an alphanumeric character. + * + * @par Example Conversions +\verbatim + "Word" --> 'Word' + "a Sentence" --> 'a_Sentence' + "trailing Withespace \t \n" --> 'trailing_Withespace' + "with a lot \nof Whitespace" --> 'with_a_lot_of_Whitespace' + "with\"much (punctuation)[]!" --> 'withmuch_(punctuation)' + "§&Ω%€ leading garbarge" --> 'leading_garbarge' + "mixed Ω garbarge" --> 'mixed_garbarge' + "Bääääh!!" --> 'Bh' +\endverbatim */ - inline string - sanitize (const string& org) - { - UNIMPLEMENTED ("sanitize String"); - return org; ///////////////////////////TODO - } + string sanitize (const string& org); + + /** convienience shortcut: conversion to c-String via string. @@ -113,6 +124,11 @@ namespace util /* some common macro definitions */ +/** supress "warning: unused variable" on vars, which + * are introduced into a scope because of some sideeffect, i.e. Locking + */ +#define SIDEEFFECT __attribute__ ((unused)); + /** this macro wraps its parameter into a cstring literal */ #define STRINGIFY(TOKEN) __STRNGFY(TOKEN) #define __STRNGFY(TOKEN) #TOKEN diff --git a/tests/50components.tests b/tests/50components.tests index 81f64062f..9b134ed6c 100644 --- a/tests/50components.tests +++ b/tests/50components.tests @@ -41,8 +41,12 @@ out: 2|ä| out: 3|+| out: 4|€| out: -->oo _O()O_ ä + € -out: wrapping cmdline:... -out: --> +out: wrapping cmdline:Ω ooΩ oΩo Ωoo... +out: 0|Ω| +out: 1|ooΩ| +out: 2|oΩo| +out: 3|Ωoo| +out: -->Ω ooΩ oΩo Ωoo out: Standard Cmdlineformat:one two END @@ -135,7 +139,18 @@ out: --> remaining=SingleTestID spam --eggs END -PLANNED "SanitizedIdentifier_test" SanitizedIdentifier_test < 'Word' +out: 'a Sentence' --> 'a_Sentence' +out: 'trailing Withespace +out: ' --> 'trailing_Withespace' +out: 'with a lot +out: of Whitespace' --> 'with_a_lot_of_Whitespace' +out: 'with"much (punctuation)[]!' --> 'withmuch_(punctuation)' +out: '§&Ω%€ leading garbarge' --> 'leading_garbarge' +out: 'mixed Ω garbarge' --> 'mixed_garbarge' +out: 'Bääääh!!' --> 'Bh' +out: '§&Ω%€' --> '' END diff --git a/tests/components/common/sanitizedidentifiertest.cpp b/tests/components/common/sanitizedidentifiertest.cpp index 709879606..938f5cbe4 100644 --- a/tests/components/common/sanitizedidentifiertest.cpp +++ b/tests/components/common/sanitizedidentifiertest.cpp @@ -44,13 +44,17 @@ namespace util { print_clean ("Word"); print_clean ("a Sentence"); - print_clean ("with a lot \nof Whitespace"); - print_clean ("with\"much (punctuation)!"); + print_clean ("trailing Withespace\n \t"); + print_clean ("with a \t lot\n of Whitespace"); + print_clean ("with\"much (punctuation)[]!"); + print_clean ("§&Ω%€ leading garbarge"); + print_clean ("mixed Ω garbarge"); print_clean ("Bääääh!!"); + print_clean ("§&Ω%€"); } /** @test print the original and the sanitized string */ - void print_clean (const string& org) + void print_clean (const string org) { cout << "'" << org << "' --> '" << sanitize(org) << "'\n"; } diff --git a/tests/components/common/test/cmdlinewrappertest.cpp b/tests/components/common/test/cmdlinewrappertest.cpp index 66547535f..5dfaf6af7 100644 --- a/tests/components/common/test/cmdlinewrappertest.cpp +++ b/tests/components/common/test/cmdlinewrappertest.cpp @@ -54,7 +54,7 @@ namespace util testLine("\nspam"); testLine("eat more spam"); testLine(" oo _O()O_ ä + €"); - testLine("\0\too\0\to\0o\t\0oo"); + testLine("Ω\tooΩ\toΩo\tΩoo"); testStandardCmdlineformat(); } From 5da016aa5a4b7f91022170e10d2a4cd5248f9851 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 16 Sep 2007 03:02:05 +0200 Subject: [PATCH 2/5] WIP integration of Asset types and AssetManager --- src/common/multithread.hpp | 54 +++++++++++++++++ src/common/singletonpolicies.hpp | 8 +-- src/common/util.cpp | 6 +- src/proc/asset.hpp | 1 + src/proc/asset/category.cpp | 17 ++++++ src/proc/asset/category.hpp | 3 +- src/proc/asset/db.hpp | 32 +++++++--- src/proc/asset/media.hpp | 3 - src/proc/asset/meta.cpp | 28 ++++++++- src/proc/asset/meta.hpp | 64 +++++++++++++++++++- src/proc/asset/proc.cpp | 28 ++++++++- src/proc/asset/proc.hpp | 61 ++++++++++++++++++- src/proc/asset/struct.cpp | 28 +++++++++ src/proc/asset/struct.hpp | 62 ++++++++++++++++++- src/proc/assetmanager.cpp | 101 ++++++++++++++++++++++++++++--- src/proc/assetmanager.hpp | 10 +++ 16 files changed, 468 insertions(+), 38 deletions(-) create mode 100644 src/common/multithread.hpp diff --git a/src/common/multithread.hpp b/src/common/multithread.hpp new file mode 100644 index 000000000..9451ada05 --- /dev/null +++ b/src/common/multithread.hpp @@ -0,0 +1,54 @@ +/* + MULTITHREAD.hpp - generic interface for multithreading primitives + + Copyright (C) CinelerraCV + 2007, 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 CINELERRA_MULTITHREAD_H +#define CINELERRA_MULTITHREAD_H + + + +namespace cinelerra + { + + /** + * Interface/Policy for managing parallelism issues. + * Basically everything is forwarded to the corresponding backend functions, + * because managing threads and locking belongs to the cinelerra backend layer. + * + * @todo actually implement this policy using the cinelerra databackend. + */ + struct Thread + { + template + class Lock + { + public: + Lock() { TODO ("aquire Thread Lock for Class"); } + Lock(X*) { TODO ("aquire Thread Lock for Instance"); } + ~Lock() { TODO ("release Thread Lock"); } + }; + }; + + +} // namespace cinelerra +#endif diff --git a/src/common/singletonpolicies.hpp b/src/common/singletonpolicies.hpp index 6cb212660..a5d499c12 100644 --- a/src/common/singletonpolicies.hpp +++ b/src/common/singletonpolicies.hpp @@ -34,6 +34,7 @@ This code is heavily inspired by #ifndef CINELERRA_SINGLETONPOLICIES_H #define CINELERRA_SINGLETONPOLICIES_H +#include "common/multithread.hpp" #include "common/error.hpp" #include @@ -136,12 +137,7 @@ namespace cinelerra struct Multithreaded { typedef volatile S* VolatileType; - class Lock - { - public: - Lock() { UNIMPLEMENTED ("aquire Thread Lock"); } - ~Lock() { UNIMPLEMENTED ("release Thread Lock"); } - }; + typedef cinelerra::Thread::Lock Lock; }; diff --git a/src/common/util.cpp b/src/common/util.cpp index 28958ade9..6adc93ab2 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -39,9 +39,9 @@ namespace util typedef boost::function ChPredicate; ChPredicate operator! (ChPredicate p) { return ! boost::bind(p,_1); } - // character classes used for sanitizing strings - ChPredicate isValid (is_alnum() || is_any_of("-_.:+$'()@")); - ChPredicate isPunct (is_space() || is_any_of(",;#*~´`?\\=/&%![]{}")); + // character classes used for sanitizing a string + ChPredicate isValid (is_alnum() || is_any_of("-_.:+$'()@")); ///< characters to be retained + ChPredicate isPunct (is_space() || is_any_of(",;#*~´`?\\=/&%![]{}")); ///< punctuation to be replaced by '_' string diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index fb7fab2e5..dc20e28ec 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -181,6 +181,7 @@ namespace asset const Ident ident; ///< Asset identification tuple virtual const ID& getID() const { return id; } + protected: const ID id; ///< Asset primary key. diff --git a/src/proc/asset/category.cpp b/src/proc/asset/category.cpp index 520b9d830..2e07c8b3a 100644 --- a/src/proc/asset/category.cpp +++ b/src/proc/asset/category.cpp @@ -25,6 +25,9 @@ #include "common/util.hpp" #include "nobugcfg.h" +#include + +using boost::algorithm::starts_with; using util::isnil; namespace asset @@ -48,6 +51,20 @@ namespace asset str += "/"+path_; return str; } + + + + /** hierarchical inclusion test. + * @return true if \c this can be considered + * a subcategory of the given reference + */ + bool + Category::isWithin (const Category& ref) const + { + return ( ref.hasKind (kind_) + && starts_with (path_, ref.path_) + ); + } } // namespace asset diff --git a/src/proc/asset/category.hpp b/src/proc/asset/category.hpp index 69137ae1b..f27f46845 100644 --- a/src/proc/asset/category.hpp +++ b/src/proc/asset/category.hpp @@ -76,7 +76,8 @@ namespace asset bool operator== (const Category& other) const { return kind_== other.kind_ && path_== other.path_; } bool operator!= (const Category& other) const { return kind_!= other.kind_ || path_!= other.path_; } - bool hasKind (Kind refKind) const { return kind_ == refKind; } + bool hasKind (Kind refKind) const { return kind_ == refKind; } + bool isWithin (const Category&) const; operator string () const; diff --git a/src/proc/asset/db.hpp b/src/proc/asset/db.hpp index ea3c41a67..8ac4207a6 100644 --- a/src/proc/asset/db.hpp +++ b/src/proc/asset/db.hpp @@ -33,7 +33,9 @@ namespace asset { - + using std::tr1::static_pointer_cast; + using std::tr1::dynamic_pointer_cast; + /* ===== hash implementations ===== */ @@ -45,14 +47,14 @@ namespace asset boost::hash_combine(hash, idi.name); boost::hash_combine(hash, idi.category); return hash; - } + } - size_t + size_t hash_value (const Asset& asset) { return asset.getID(); } - + /** * trivial hash functor. @@ -66,12 +68,12 @@ namespace asset size_t operator() (size_t val) const { return val; } }; - + typedef std::tr1::unordered_map IdHashtable; - - - - + + + + /** * Implementation of the registry holding all Asset * instances known to the Asset Manager subsystem. @@ -85,6 +87,18 @@ namespace asset ~DB () {} friend class cinelerra::singleton::Static; + + public: + template + void put (ID hash, shared_ptr& ptr) { table[hash] = static_pointer_cast (ptr); } + void put (ID hash, PAsset& ptr) { table[hash] = ptr; } + + template + shared_ptr + get (ID hash) + { + return dynamic_pointer_cast (table[hash]); + } }; diff --git a/src/proc/asset/media.hpp b/src/proc/asset/media.hpp index 4e6507a2a..cc1a1bdc7 100644 --- a/src/proc/asset/media.hpp +++ b/src/proc/asset/media.hpp @@ -103,9 +103,6 @@ namespace asset PType operator() (Asset::Ident& key, const char* file); ///< convienience overload using C-String PType operator() (const char* file, Category& cat); PType operator() (const char* file, asset::Kind); - - protected: - static void destroy (Media* m) { delete m; } }; diff --git a/src/proc/asset/meta.cpp b/src/proc/asset/meta.cpp index fb0ff7c05..be2382f1f 100644 --- a/src/proc/asset/meta.cpp +++ b/src/proc/asset/meta.cpp @@ -21,13 +21,37 @@ * *****************************************************/ +#include "proc/assetmanager.hpp" #include "proc/asset/meta.hpp" +#include "common/util.hpp" +#include "nobugcfg.h" + namespace asset { - /** */ - + namespace // Implementation details + { + /** helper: .....*/ + } + + MetaFactory Meta::create; ///< storage for the static MetaFactory instance + + + + /** Factory method for Metadata Asset instances. .... + * @todo actually define + * @return an Meta smart ptr linked to the internally registered smart ptr + * created as a side effect of calling the concrete Meta subclass ctor. + */ + MetaFactory::PType + MetaFactory::operator() (Asset::Ident& key) ////TODO + { + UNIMPLEMENTED ("Meta-Factory"); + } + + + } // namespace asset diff --git a/src/proc/asset/meta.hpp b/src/proc/asset/meta.hpp index 4cbd3f9c1..21715fe0f 100644 --- a/src/proc/asset/meta.hpp +++ b/src/proc/asset/meta.hpp @@ -21,26 +21,86 @@ */ +/** @file meta.hpp + ** Some Metatdata elements (e.g. Automation Datasets) can be treated as + ** specific Kind of Asset. + ** For the different Kinds of Assets, we use sub-intefaces inheriting + ** from the general Asset interface. To be able to get asset::Meta instances + ** directly from the AssetManager, we define a specialization of the Asset ID. + ** + ** @see asset.hpp for explanation + ** @see MetaFactory creating concrete asset::Meta instances + ** + */ + #ifndef ASSET_META_H #define ASSET_META_H #include "proc/asset.hpp" +#include "common/factory.hpp" namespace asset { + + class Meta; + class MetaFactory; + + + template<> + class ID : public ID + { + public: + ID (size_t id); + ID (const Meta&); + }; - + + /** * key abstraction: metadata and organisational asset + * @todo just a stub, have to figure out what a asset::Proc is */ - class Meta : public proc_interface::Asset + class Meta : public Asset { + public: + static MetaFactory create; + virtual const ID& getID() const ///< @return ID of kind Meta + { + return static_cast& > (Asset::getID()); + } + + protected: + Meta (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO + friend class MetaFactory; }; + // definition of ID ctors is possible now, + // after providing full definition of class Proc + + inline ID::ID(size_t id) : ID (id) {}; + inline ID::ID(const Meta& meta) : ID (meta.getID()) {}; + + + + + /** + * Factory specialized for createing Metadata Asset objects. + */ + class MetaFactory : public cinelerra::Factory + { + public: + typedef shared_ptr PType; + + PType operator() (Asset::Ident& key); ////////////TODO define actual operation + + }; + + + } // namespace asset #endif diff --git a/src/proc/asset/proc.cpp b/src/proc/asset/proc.cpp index b82ea49d7..7f66edcca 100644 --- a/src/proc/asset/proc.cpp +++ b/src/proc/asset/proc.cpp @@ -21,13 +21,37 @@ * *****************************************************/ +#include "proc/assetmanager.hpp" #include "proc/asset/proc.hpp" +#include "common/util.hpp" +#include "nobugcfg.h" + namespace asset { - /** */ - + namespace // Implementation details + { + /** helper: .....*/ + } + + ProcFactory Proc::create; ///< storage for the static ProcFactory instance + + + + /** Factory method for Processor Asset instances. .... + * @todo actually define + * @return an Proc smart ptr linked to the internally registered smart ptr + * created as a side effect of calling the concrete Proc subclass ctor. + */ + ProcFactory::PType + ProcFactory::operator() (Asset::Ident& key) ////TODO + { + UNIMPLEMENTED ("Proc-Factory"); + } + + + } // namespace asset diff --git a/src/proc/asset/proc.hpp b/src/proc/asset/proc.hpp index 003635b4f..0c201705b 100644 --- a/src/proc/asset/proc.hpp +++ b/src/proc/asset/proc.hpp @@ -21,26 +21,85 @@ */ +/** @file proc.hpp + ** Data processing Plugins and Codecs can be treated as a specific Kind of Asset. + ** For the different Kinds of Assets, we use sub-intefaces inheriting + ** from the general Asset interface. To be able to get asset::Proc instances + ** directly from the AssetManager, we define a specialization of the Asset ID. + ** + ** @see asset.hpp for explanation + ** @see ProcFactory creating concrete asset::Proc instances + ** + */ + #ifndef ASSET_PROC_H #define ASSET_PROC_H #include "proc/asset.hpp" +#include "common/factory.hpp" namespace asset { + + class Proc; + class ProcFactory; + + + template<> + class ID : public ID + { + public: + ID (size_t id); + ID (const Proc&); + }; - + + /** * key abstraction: data processing asset + * @todo just a stub, have to figure out what a asset::Proc is */ class Proc : public Asset { + public: + static ProcFactory create; + virtual const ID& getID() const ///< @return ID of kind Proc + { + return static_cast& > (Asset::getID()); + } + + protected: + Proc (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO + friend class ProcFactory; }; + // definition of ID ctors is possible now, + // after providing full definition of class Proc + + inline ID::ID(size_t id) : ID (id) {}; + inline ID::ID(const Proc& proc) : ID (proc.getID()) {}; + + + + + /** + * Factory specialized for createing Processor Asset objects. + */ + class ProcFactory : public cinelerra::Factory + { + public: + typedef shared_ptr PType; + + PType operator() (Asset::Ident& key); ////////////TODO define actual operation + + }; + + + } // namespace asset #endif diff --git a/src/proc/asset/struct.cpp b/src/proc/asset/struct.cpp index 18769f497..8af2b2e94 100644 --- a/src/proc/asset/struct.cpp +++ b/src/proc/asset/struct.cpp @@ -21,10 +21,38 @@ * *****************************************************/ +#include "proc/assetmanager.hpp" #include "proc/asset/struct.hpp" +#include "common/util.hpp" +#include "nobugcfg.h" namespace asset { + + namespace // Implementation details + { + /** helper: .....*/ + } + + + + StructFactory Struct::create; ///< storage for the static StructFactory instance + + + + /** Factory method for Structural Asset instances. .... + * @todo actually define + * @return an Struct smart ptr linked to the internally registered smart ptr + * created as a side effect of calling the concrete Struct subclass ctor. + */ + StructFactory::PType + StructFactory::operator() (Asset::Ident& key) ////TODO + { + UNIMPLEMENTED ("Struct-Factory"); + } + + + diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp index 787c172dc..dd1b635aa 100644 --- a/src/proc/asset/struct.hpp +++ b/src/proc/asset/struct.hpp @@ -21,23 +21,83 @@ */ +/** @file struct.hpp + ** Structural facilities of the EDL (e.g. Tracks) can be treated in the + ** "bookkeeping view" as a specific Kind of Asset. + ** For the different Kinds of Assets, we use sub-intefaces inheriting + ** from the general Asset interface. To be able to get asset::Struct instances + ** directly from the AssetManager, we define a specialization of the Asset ID. + ** + ** @see asset.hpp for explanation + ** @see StructFactory creating concrete asset::Struct instances + ** + */ + + #ifndef ASSET_STRUCT_H #define ASSET_STRUCT_H #include "proc/asset.hpp" +#include "common/factory.hpp" namespace asset { + + class Struct; + class StructFactory; + + + template<> + class ID : public ID + { + public: + ID (size_t id); + ID (const Struct&); + }; - + + /** * key abstraction: structural asset + * @todo just a stub, have to figure out what a asset::Proc is */ class Struct : public Asset { + public: + static StructFactory create; + virtual const ID& getID() const ///< @return ID of kind asset::Struct + { + return static_cast& > (Asset::getID()); + } + + protected: + Struct (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO + friend class StructFactory; + }; + + + // definition of ID ctors is possible now, + // after providing full definition of class Proc + + inline ID::ID(size_t id) : ID (id) {}; + inline ID::ID(const Struct& stru) : ID (stru.getID()) {}; + + + + + /** + * Factory specialized for createing Structural Asset objects. + */ + class StructFactory : public cinelerra::Factory + { + public: + typedef shared_ptr PType; + + PType operator() (Asset::Ident& key); ////////////TODO define actual operation + }; diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 3a8111fb8..0fba91b52 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -24,13 +24,65 @@ #include "proc/assetmanager.hpp" #include "proc/asset/db.hpp" -//#include +#include "common/multithread.hpp" +#include "common/util.hpp" + +#include +#include + +#include +#include + +using boost::format; +using boost::bind; +//using boost::lambda::_1; +using util::for_each; using cinelerra::Singleton; +using cinelerra::Thread; + namespace asset { + /** + * AssetManager error responses, cause by querying + * invalid Asset IDs from the internal DB. + */ + class IDErr : public cinelerra::error::Invalid + { + public: + IDErr (const char* eID, format fmt) + : cinelerra::error::Invalid(fmt.str(),eID) {} + }; + + + // ------pre-defined-common-error-cases--------------- + // + CINELERRA_ERROR_DEFINE (UNKNOWN_ASSET_ID, "non-registered Asset ID"); + CINELERRA_ERROR_DEFINE (WRONG_ASSET_KIND, "wrong Asset kind, unable to cast"); + + class UnknownID : public IDErr + { + public: + UnknownID (ID aID) : IDErr (CINELERRA_ERROR_UNKNOWN_ASSET_ID, + format("Query for Asset with ID=%d, which up to now " + "hasn't been created or encountered.") % aID) {} + }; + + class WrongKind : public IDErr + { + public: + WrongKind (Asset::Ident idi) : IDErr (CINELERRA_ERROR_WRONG_ASSET_KIND, + format("Request for Asset(%s), specifying an Asset kind, " + "that doesn't match the actual type (and can't be " + "casted either).") % string(idi)) {} + }; + + + + + /** get at the system-wide asset manager instance. * Implemented as singleton. */ @@ -52,26 +104,45 @@ namespace asset /** - * registers an asset object in the internal DB, providing its unique key + * registers an asset object in the internal DB, providing its unique key. + * This includes creating the smart ptr in charge of the asset's lifecycle */ template ID AssetManager::reg (KIND* obj, const Asset::Ident& idi) throw(cinelerra::error::Invalid) { - UNIMPLEMENTED ("AssetManager::reg"); + typedef shared_ptr PType; + AssetManager& _aMang (AssetManager::instance()); + TODO ("check validity of Ident Category"); + ID asset_id (getID (idi)); + + Thread::Lock guard SIDEEFFECT; + TODO ("handle duplicate Registrations"); + PType smart_ptr (obj, &destroy); + + _aMang.registry.put (asset_id, smart_ptr); + return asset_id; } /** - * find and return corresponging object + * find and return the object registered with the given ID. + * @throws Invalid if nothing is found or if the actual KIND + * of the stored object differs and can't be casted. */ template shared_ptr AssetManager::getAsset (const ID& id) throw(cinelerra::error::Invalid) { - UNIMPLEMENTED ("AssetManager::getAsset"); + if (shared_ptr obj = registry.get (id)) + return obj; + else + if (known (id)) // provide Ident tuple of existing Asset + throw WrongKind (registry.get(ID(id))->ident); + else + throw UnknownID (id); } @@ -81,8 +152,9 @@ namespace asset bool AssetManager::known (IDA id) { - UNIMPLEMENTED ("asset search"); - } + return ( registry.get (ID(id)) ); + } // query most general Asset ID-kind and use implicit + // conversion from shared_ptr to bool (test if empty) /** @@ -91,9 +163,16 @@ namespace asset bool AssetManager::known (IDA id, const Category& cat) { - UNIMPLEMENTED ("asset search"); + PAsset pA = registry.get (id); + return ( pA && pA->ident.category.isWithin(cat)); } + + void + AssetManager::detach_child (PAsset& pA, IDA id) + { + pA->unlink(id); + } /** * remove the given asset together with all its dependants from the internal DB @@ -103,6 +182,12 @@ namespace asset throw(cinelerra::error::Invalid, cinelerra::error::State) { + UNIMPLEMENTED ("remove Asset with all dependecies"); + + PAsset pA = getAsset (id); + vector par = pA->getParents(); + boost::function func = bind(&detach_child, _1,id ); + for_each (par, func); // ,boost::lambda::var(id))); } diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp index d7effe221..9055c13f8 100644 --- a/src/proc/assetmanager.hpp +++ b/src/proc/assetmanager.hpp @@ -40,6 +40,7 @@ #include "common/error.hpp" #include "common/singleton.hpp" + #include #include #include @@ -94,13 +95,22 @@ namespace asset static ID reg (KIND* obj, const Asset::Ident& idi) throw(cinelerra::error::Invalid); + /** deleter function used by the Asset smart pointers to delet Asset objects */ + static void destroy (Asset* m) { delete m; } + friend Asset::Asset (const Asset::Ident& idi); AssetManager (); friend class cinelerra::singleton::Static; + private: + static void detach_child (PAsset&, IDA); }; + + + CINELERRA_ERROR_DECLARE (UNKNOWN_ASSET_ID); ///< use of a non-registered Asset ID. + CINELERRA_ERROR_DECLARE (WRONG_ASSET_KIND); ///< Asset ID of wrong Asset kind, unable to cast. } // namespace asset From 3a416f9e41f5658a8467f493bc31c56eb5f713bd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 16 Sep 2007 17:17:54 +0200 Subject: [PATCH 3/5] WIP test coverage, debugging... still have to fix a segfault :-) --- src/proc/asset.cpp | 7 ++ src/proc/asset.hpp | 10 ++ src/proc/asset/media.cpp | 6 +- src/proc/asset/media.hpp | 4 +- src/proc/assetmanager.hpp | 3 +- .../components/proc/asset/createassettest.cpp | 95 ++++++++++++--- .../proc/asset/identityofassetstest.cpp | 110 ++++++++++++++++++ 7 files changed, 214 insertions(+), 21 deletions(-) create mode 100644 tests/components/proc/asset/identityofassetstest.cpp diff --git a/src/proc/asset.cpp b/src/proc/asset.cpp index 13bda9143..0e790becb 100644 --- a/src/proc/asset.cpp +++ b/src/proc/asset.cpp @@ -59,6 +59,13 @@ namespace asset static format id_tuple("(%2%:%3%.%1% v%4%)"); // ignoring threadsafety return str (id_tuple % name % category % org % version); } + + + Asset::operator string () const + { + static format id_tuple("Asset(%2%:%3%.%1% v%4%)"); // ignoring threadsafety + return str (id_tuple % ident.name % ident.category % ident.org % ident.version); + } /** List of entities this asset depends on or requires to be functional. diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index dc20e28ec..d36ab85f2 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -181,6 +181,7 @@ namespace asset const Ident ident; ///< Asset identification tuple virtual const ID& getID() const { return id; } + virtual operator string () const; protected: const ID id; ///< Asset primary key. @@ -260,6 +261,15 @@ namespace asset /** shorthand for refcounting Asset pointers */ typedef shared_ptr PAsset; + /** convienient for debugging */ + inline string str (const PAsset& a) + { + if (a) + return string (*a.get()); + else + return "Asset(NULL)"; + } + } // namespace asset diff --git a/src/proc/asset/media.cpp b/src/proc/asset/media.cpp index 180b5b89b..437b30998 100644 --- a/src/proc/asset/media.cpp +++ b/src/proc/asset/media.cpp @@ -96,7 +96,7 @@ namespace asset } ASSERT (pM); ENSURE (key.category.hasKind (VIDEO) || key.category.hasKind(AUDIO)); - ENSURE (isnil (key.name)); + ENSURE (!isnil (key.name)); ENSURE (dynamic_cast(pM) || (isnil (file) && dynamic_cast(pM))); return aMang.getAsset (pM->getID()); // note: because we query with an ID, @@ -108,7 +108,7 @@ namespace asset * providing most of the Asset key fields based on the filename given */ MediaFactory::PType - MediaFactory::operator() (const string& file, Category& cat) + MediaFactory::operator() (const string& file, const Category& cat) { Asset::Ident key(extractName(file), cat, "cin3", 1); return operator() (key, file); @@ -123,7 +123,7 @@ namespace asset MediaFactory::PType - MediaFactory::operator() (const char* file, Category& cat) + MediaFactory::operator() (const char* file, const Category& cat) { if (!file) file = ""; return operator() (string(file),cat); diff --git a/src/proc/asset/media.hpp b/src/proc/asset/media.hpp index cc1a1bdc7..350ba86f2 100644 --- a/src/proc/asset/media.hpp +++ b/src/proc/asset/media.hpp @@ -97,11 +97,11 @@ namespace asset typedef shared_ptr PType; PType operator() (Asset::Ident& key, const string& file=""); - PType operator() (const string& file, Category& cat); + PType operator() (const string& file, const Category& cat); PType operator() (const string& file, asset::Kind); PType operator() (Asset::Ident& key, const char* file); ///< convienience overload using C-String - PType operator() (const char* file, Category& cat); + PType operator() (const char* file, const Category& cat); PType operator() (const char* file, asset::Kind); }; diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp index 9055c13f8..1dc05f584 100644 --- a/src/proc/assetmanager.hpp +++ b/src/proc/assetmanager.hpp @@ -103,7 +103,8 @@ namespace asset AssetManager (); friend class cinelerra::singleton::Static; - + + private: static void detach_child (PAsset&, IDA); }; diff --git a/tests/components/proc/asset/createassettest.cpp b/tests/components/proc/asset/createassettest.cpp index 771c7a568..3aee6c34b 100644 --- a/tests/components/proc/asset/createassettest.cpp +++ b/tests/components/proc/asset/createassettest.cpp @@ -22,18 +22,17 @@ #include "common/test/run.hpp" -//#include "common/factory.hpp" #include "common/util.hpp" #include "proc/assetmanager.hpp" #include "proc/asset/media.hpp" #include "proc/asset/proc.hpp" -//#include +#include #include +using boost::format; using util::isnil; -//using boost::format; using std::string; using std::cout; @@ -43,7 +42,6 @@ namespace asset namespace test { -// typedef Category::Kind Kind; @@ -56,15 +54,23 @@ namespace asset virtual void run(Arg arg) { createMedia(); - } + factoryVariants(); + } + typedef shared_ptr PM; + + /** @test Creating and automatically registering Asset instances. + * Re-Retrieving the newly created objects from AssetManager. + * Checking AssetManager access functions, esp. getting + * different kinds of Assets by ID, querying with the + * wrong Category and querying unknown IDs. + */ void createMedia() { - typedef shared_ptr PM; Category cat(VIDEO,"bin1"); Asset::Ident key("Name-1", cat, "ichthyo", 5); PM mm1 = asset::Media::create(key,"testfile.mov"); - PM mm2 = asset::Media::create(key); + PM mm2 = asset::Media::create("testfile1.mov", cat); PM mm3 = asset::Media::create("testfile2.mov", VIDEO); // Assets have been registered and can be retrieved by ID @@ -91,12 +97,18 @@ namespace asset aMang.getAsset (ID(mm1->getID())); NOTREACHED; } - catch (cinelerra::error::Invalid) { } + catch (cinelerra::error::Invalid& exe) {ASSERT (exe.getID()==CINELERRA_ERROR_WRONG_ASSET_KIND);} + try + { // try accessing nonexistant ID + aMang.getAsset (ID (1234567890)); + NOTREACHED; + } + catch (cinelerra::error::Invalid& exe) {ASSERT (exe.getID()==CINELERRA_ERROR_UNKNOWN_ASSET_ID);} // checking the Ident-Fields ASSERT (mm1->ident.name == "Name-1"); - ASSERT (mm2->ident.name == "Name-1"); + ASSERT (mm2->ident.name == "testfile1"); ASSERT (mm3->ident.name == "testfile2"); ASSERT (cat == Category (VIDEO,"bin1")); @@ -105,19 +117,72 @@ namespace asset ASSERT (mm3->ident.category == Category (VIDEO )); ASSERT (mm1->ident.org == "ichthyo"); - ASSERT (mm2->ident.org == "ichthyo"); + ASSERT (mm2->ident.org == "cin3"); ASSERT (mm3->ident.org == "cin3"); ASSERT (mm1->ident.version == 5); - ASSERT (mm2->ident.version == 5); + ASSERT (mm2->ident.version == 1); ASSERT (mm3->ident.version == 1); ASSERT (mm1->getFilename() == "testfile.mov"); - ASSERT (isnil (mm2->getFilename())); + ASSERT (mm2->getFilename() == "testfile1.mov"); ASSERT (mm3->getFilename() == "testfile2.mov"); -/* -////////////////////////////////////////////////////////////////////////////////TODO fuck the compiler!!! -*/ + + showPtr (mm1); + showPtr (mm2); + showPtr (mm3); + showPtr (mX1); + } + + + /** @test different variants of calling the MediaFactory, + * with focus on the behaviour of the basic Asset + * creation machinery. Covers filling out Asset's + * datafields, amending missing pieces of information. + */ + void factoryVariants() + { + PM candi; + + Asset::Ident key1("Au-1", Category(AUDIO), "ichthyo", 5); + candi = asset::Media::create(key1); + ASSERT ( checkProperties (candi, key1, "")); + + candi = asset::Media::create(key1, string("testfile.wav")); + ASSERT ( checkProperties (candi, key1, "testfile.wav")); + + Asset::Ident key2("", Category(AUDIO), "ichthyo", 5); + candi = asset::Media::create(key2, string("testfile2.wav")); + ASSERT ( checkProperties (candi, key2, "testfile2.wav")); + ASSERT (key2.name == "testfile2"); // name filled in automatically + + candi = asset::Media::create(string("testfile3.wav"), Category(AUDIO)); + ASSERT ( checkProperties (candi, Asset::Ident("testfile3", Category(AUDIO), "cin3", 1) + , "testfile3.wav")); + + candi = asset::Media::create("some/path/testfile4.wav", Category(AUDIO)); + ASSERT ( checkProperties (candi, Asset::Ident("testfile4", Category(AUDIO), "cin3", 1) + , "some/path/testfile4.wav")); + + candi = asset::Media::create("", Category(AUDIO,"sub/bin")); + ASSERT ( checkProperties (candi, Asset::Ident("nil", Category(AUDIO,"sub/bin"), "cin3", 1) + , "")); + + candi = asset::Media::create("", AUDIO); + ASSERT ( checkProperties (candi, Asset::Ident("nil", Category(AUDIO), "cin3", 1) + , "")); + } + + bool checkProperties (PM object, Asset::Ident identity, string filename) + { + return identity == object->ident + && filename == object->getFilename(); + } + + void showPtr (PM m) + { + static format fmt("Asset(%s) .... ptr=%d use-count=%d"); + cout << fmt % str(m) % &m % m.use_count() << "\n"; } }; diff --git a/tests/components/proc/asset/identityofassetstest.cpp b/tests/components/proc/asset/identityofassetstest.cpp new file mode 100644 index 000000000..d849fdc15 --- /dev/null +++ b/tests/components/proc/asset/identityofassetstest.cpp @@ -0,0 +1,110 @@ +/* + IdentityOfAssets(Test) - Asset object identity and versioning + + Copyright (C) CinelerraCV + 2007, 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 "common/test/run.hpp" +#include "common/util.hpp" + +#include "proc/assetmanager.hpp" +#include "proc/asset/media.hpp" +#include "proc/asset/proc.hpp" + +#include +#include + +using boost::format; +using util::isnil; +using std::string; +using std::cout; + + +namespace asset + { + namespace test + { + + + + + /*********************************************************************** + * @test creating several Assets and checking object identity, + * detection of duplicates and version handling. + * @see proc_interface::AssetManager#reg + * @todo to be written; features are missing as of 9/07 + */ + class IdentityOfAssets_test : public Test + { + virtual void run(Arg arg) + { + createDuplicate(); + } + + typedef shared_ptr PM; + + /** @test produce an ID clash. + * documents the current behaviour of the code as of 9/07 + * @todo this test is expected to break when the detection + * of duplicate registrations is implemented. + */ + void createDuplicate() + { + PM mm1 = asset::Media::create ("testfile1.mov", VIDEO); + + Asset::Ident idi (mm1->ident); // duplicate Ident record + PM mm1X = asset::Media::create (idi); // note: we actually don't call any ctor + ASSERT (mm1 == mm1X); // instead, we got mm1 back. + + PM mm2 = asset::Media::create (idi,"testfile2.mov"); + ASSERT (mm1->getID() == mm2->getID()); // different object, same hash + + AssetManager& aMang = AssetManager::instance(); + ASSERT (aMang.getAsset (mm1->getID()) == mm2); // record of mm1 was replaced by mm2 + ASSERT (aMang.getAsset (mm2->getID()) == mm2); + + ASSERT (aMang.known (mm1->getID())); + ASSERT (aMang.known (mm2->getID())); + ASSERT (mm1->ident.name == "testfile1"); + ASSERT (mm2->ident.name == "testfile1"); + ASSERT (mm1->getFilename() == "testfile1.mov"); + ASSERT (mm2->getFilename() == "testfile2.mov"); + + showPtr (mm1); + showPtr (mm1X); + showPtr (mm2); + } + + void showPtr (PM m) + { + static format fmt("Asset(%s) .... ptr=%d use-count=%d"); + cout << fmt % str(m) % &m % m.use_count() << "\n"; + } + }; + + + /** Register this test class... */ + LAUNCHER (IdentityOfAssets_test, "unit asset"); + + + + } // namespace test + +} // namespace asset From 3927f7d5d81a93558d19cda2fb58b31497a7c1e0 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 17 Sep 2007 05:47:22 +0200 Subject: [PATCH 4/5] WIP: ordering of Assets, dump AssetManager, bugfix (partially...) --- src/common/util.hpp | 2 +- src/proc/asset.cpp | 9 ++- src/proc/asset.hpp | 30 ++++++-- src/proc/asset/category.hpp | 14 +++- src/proc/asset/db.hpp | 10 +++ src/proc/assetmanager.cpp | 13 +++- src/proc/assetmanager.hpp | 9 ++- .../proc/asset/assetdiagnostics.hpp | 73 +++++++++++++++++++ .../components/proc/asset/createassettest.cpp | 28 +++---- .../proc/asset/identityofassetstest.cpp | 22 +++--- 10 files changed, 168 insertions(+), 42 deletions(-) create mode 100644 tests/components/proc/asset/assetdiagnostics.hpp diff --git a/src/common/util.hpp b/src/common/util.hpp index 479142069..7b036e1be 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -81,7 +81,7 @@ namespace util */ template inline Oper - for_each (Container& c, Oper& doIt) + for_each (Container& c, Oper doIt) { return std::for_each (c.begin(),c.end(), doIt); } diff --git a/src/proc/asset.cpp b/src/proc/asset.cpp index 0e790becb..622311863 100644 --- a/src/proc/asset.cpp +++ b/src/proc/asset.cpp @@ -46,24 +46,25 @@ namespace asset */ Asset::Asset (const Ident& idi) : ident(idi), id(AssetManager::reg (this, idi)) - { } + { TRACE (assetmem, "ctor Asset(id=%d) : %s p=%x", size_t(id), cStr(this->ident), this ); +} Asset::~Asset () { - TRACE (assetmem, "dtor Asset(id=%d) : %s", size_t(id), cStr(this->ident) ); + TRACE (assetmem, "dtor Asset(id=%d) : %s p=%x", size_t(id), cStr(this->ident), this ); } Asset::Ident::operator string () const { - static format id_tuple("(%2%:%3%.%1% v%4%)"); // ignoring threadsafety + format id_tuple("(%2%:%3%.%1% v%4%)"); return str (id_tuple % name % category % org % version); } Asset::operator string () const { - static format id_tuple("Asset(%2%:%3%.%1% v%4%)"); // ignoring threadsafety + format id_tuple("Asset(%2%:%3%.%1% v%4%)"); return str (id_tuple % ident.name % ident.category % ident.org % ident.version); } diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index d36ab85f2..e6fd207c6 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -175,6 +175,7 @@ namespace asset && name == other.name && category == other.category; } + int compare (const Ident& other) const; operator string () const; }; @@ -261,14 +262,31 @@ namespace asset /** shorthand for refcounting Asset pointers */ typedef shared_ptr PAsset; + /** ordering of Assets based on Ident tuple */ + inline bool operator< (const PAsset& a1, const PAsset& a2) { return a1 && a2 && (-1==a1->ident.compare(a2->ident));} + inline bool operator> (const PAsset& a1, const PAsset& a2) { return a2 < a1; } + inline bool operator>= (const PAsset& a1, const PAsset& a2) { return !(a1 < a2); } + inline bool operator<= (const PAsset& a1, const PAsset& a2) { return !(a1 > a2); } + + /** ordering of Asset Ident tuples. + * @note version is irrelevant */ + inline int Asset::Ident::compare (const Asset::Ident& oi) const + { + int res; + if (1 != (res=category.compare (oi.category))) return res; + if (1 != (res=org.compare (oi.org))) return res; + return name.compare (oi.name); + } + + /** convienient for debugging */ inline string str (const PAsset& a) - { - if (a) - return string (*a.get()); - else - return "Asset(NULL)"; - } + { + if (a) + return string (*a.get()); + else + return "Asset(NULL)"; + } diff --git a/src/proc/asset/category.hpp b/src/proc/asset/category.hpp index f27f46845..5a1bf905c 100644 --- a/src/proc/asset/category.hpp +++ b/src/proc/asset/category.hpp @@ -89,12 +89,22 @@ namespace asset boost::hash_combine(hash, cat.kind_); boost::hash_combine(hash, cat.path_); return hash; - } + } + + int compare (const Category& co) const + { + int res = int(kind_) - int(co.kind_); + if (1 != res) + return res; + else + return path_.compare (co.path_); + } }; inline ostream& operator<< (ostream& os, const Category& cago) { return os << string(cago); } - + + } // namespace asset #endif diff --git a/src/proc/asset/db.hpp b/src/proc/asset/db.hpp index 8ac4207a6..76be677f0 100644 --- a/src/proc/asset/db.hpp +++ b/src/proc/asset/db.hpp @@ -99,6 +99,16 @@ namespace asset { return dynamic_pointer_cast (table[hash]); } + + /** intended for diagnostics */ + void + asList (list& output) const + { + IdHashtable::const_iterator i = table.begin(); + IdHashtable::const_iterator e = table.end(); + for ( ; i!=e ; ++i ) + output.push_back (i->second); + } }; diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 0fba91b52..89843b1d6 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -27,7 +27,7 @@ #include "common/multithread.hpp" #include "common/util.hpp" -#include +//#include #include #include @@ -191,6 +191,17 @@ namespace asset } + + list + AssetManager::listContent() const + { + list res; + registry.asList (res); + res.sort(); + return res; + } + + } // namespace asset diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp index 1dc05f584..8ccf0ac61 100644 --- a/src/proc/assetmanager.hpp +++ b/src/proc/assetmanager.hpp @@ -43,9 +43,11 @@ #include #include +#include #include using std::string; +using std::list; @@ -86,6 +88,10 @@ namespace asset void remove (IDA id) throw(cinelerra::error::Invalid, cinelerra::error::State); + /** extract a sorted list of all registered Assets */ + list listContent() const; + + protected: /** registers an asset object in the internal DB, providing its unique key. @@ -96,7 +102,8 @@ namespace asset throw(cinelerra::error::Invalid); /** deleter function used by the Asset smart pointers to delet Asset objects */ - static void destroy (Asset* m) { delete m; } + static void destroy (Asset* m) { TRACE (assetmem, "call destroy (Asset(id=%d)) p=%x", m? size_t(m->getID()):0, m ); + delete m; } friend Asset::Asset (const Asset::Ident& idi); diff --git a/tests/components/proc/asset/assetdiagnostics.hpp b/tests/components/proc/asset/assetdiagnostics.hpp new file mode 100644 index 000000000..d5425ee66 --- /dev/null +++ b/tests/components/proc/asset/assetdiagnostics.hpp @@ -0,0 +1,73 @@ +/* + ASSETDIAGNOSTICS.hpp - collection of test and debug helpers + + Copyright (C) CinelerraCV + 2007, 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. + +*/ + +/** @file assetdiagnostics.hpp + ** Small helper and diagnosic functions related to Asset and AssetManager + ** + ** @see assetmanager.hpp + ** @see CreateAsset_test + ** @see IdentityOfAssets_test + */ + + +#ifndef ASSET_ASSETDIAGNOSTICS_H +#define ASSET_ASSETDIAGNOSTICS_H + + +#include "proc/assetmanager.hpp" +#include "common/util.hpp" + +#include +#include +#include + +using util::for_each; +using boost::format; +using boost::bind; +using std::string; +using std::cout; + + +namespace asset + { + + inline void dump (const PAsset& aa) + { + if (!aa) + cout << "Asset(NULL)\n"; + else + { + format fmt("%s %|50T.| id=%d sP=%x ptr=%x use-count=%d"); + cout << fmt % str(aa) % aa->getID() % &aa % aa.get() % aa.use_count() << "\n"; + } } + + inline void dumpAssetManager () + { + list assets (AssetManager::instance().listContent()); + cout << "----all-registered-Assets----\n"; + for_each (assets, bind (&dump, _1)); + } + + + +} // namespace asset +#endif diff --git a/tests/components/proc/asset/createassettest.cpp b/tests/components/proc/asset/createassettest.cpp index 3aee6c34b..b5f449787 100644 --- a/tests/components/proc/asset/createassettest.cpp +++ b/tests/components/proc/asset/createassettest.cpp @@ -28,13 +28,10 @@ #include "proc/asset/media.hpp" #include "proc/asset/proc.hpp" -#include -#include +#include "proc/asset/assetdiagnostics.hpp" -using boost::format; using util::isnil; using std::string; -using std::cout; namespace asset @@ -55,6 +52,7 @@ namespace asset { createMedia(); factoryVariants(); + dumpAssetManager(); } typedef shared_ptr PM; @@ -81,6 +79,9 @@ namespace asset ASSERT (aMang.getAsset (mm1->getID()) != mm2); + cout << "== 1 ==\n"; + dumpAssetManager(); + PAsset aa1 = aMang.getAsset (ID(mm1->getID())); // note we get an Asset ref ASSERT (aa1 == mm1); PM mX1 = aMang.getAsset (mm1->getID()); // ..and now we get a Media ref @@ -91,6 +92,9 @@ namespace asset ASSERT (aMang.known (mm2->getID())); ASSERT (aMang.known (mm3->getID())); + cout << "== 2 ==\n"; + dumpAssetManager(); + ASSERT ( !aMang.known (mm3->getID(), Category(AUDIO))); // not found within AUDIO-Category try { // can't be found if specifying wrong Asset kind.... @@ -128,10 +132,12 @@ namespace asset ASSERT (mm2->getFilename() == "testfile1.mov"); ASSERT (mm3->getFilename() == "testfile2.mov"); - showPtr (mm1); - showPtr (mm2); - showPtr (mm3); - showPtr (mX1); + dump (mm1); + dump (mm2); + dump (mm3); + dump (mX1); + cout << "== 3 ==\n"; + dumpAssetManager(); } @@ -178,12 +184,6 @@ namespace asset return identity == object->ident && filename == object->getFilename(); } - - void showPtr (PM m) - { - static format fmt("Asset(%s) .... ptr=%d use-count=%d"); - cout << fmt % str(m) % &m % m.use_count() << "\n"; - } }; diff --git a/tests/components/proc/asset/identityofassetstest.cpp b/tests/components/proc/asset/identityofassetstest.cpp index d849fdc15..d55623538 100644 --- a/tests/components/proc/asset/identityofassetstest.cpp +++ b/tests/components/proc/asset/identityofassetstest.cpp @@ -28,13 +28,10 @@ #include "proc/asset/media.hpp" #include "proc/asset/proc.hpp" -#include -#include +#include "proc/asset/assetdiagnostics.hpp" -using boost::format; using util::isnil; using std::string; -using std::cout; namespace asset @@ -56,6 +53,7 @@ namespace asset virtual void run(Arg arg) { createDuplicate(); + cout << "ausis\n"; } typedef shared_ptr PM; @@ -72,8 +70,9 @@ namespace asset Asset::Ident idi (mm1->ident); // duplicate Ident record PM mm1X = asset::Media::create (idi); // note: we actually don't call any ctor ASSERT (mm1 == mm1X); // instead, we got mm1 back. - + cout << "usi-v " << mm1.use_count() <<"\n"; PM mm2 = asset::Media::create (idi,"testfile2.mov"); + cout << "usi-n " << mm1.use_count() <<"\n"; ASSERT (mm1->getID() == mm2->getID()); // different object, same hash AssetManager& aMang = AssetManager::instance(); @@ -87,16 +86,13 @@ namespace asset ASSERT (mm1->getFilename() == "testfile1.mov"); ASSERT (mm2->getFilename() == "testfile2.mov"); - showPtr (mm1); - showPtr (mm1X); - showPtr (mm2); + cout << "use-cnt at end " << mm1.use_count() <<"\n"; + dump (mm1); + dump (mm1X); + dump (mm2); + dumpAssetManager(); } - void showPtr (PM m) - { - static format fmt("Asset(%s) .... ptr=%d use-count=%d"); - cout << fmt % str(m) % &m % m.use_count() << "\n"; - } }; From 14d1c5a34b499ec152ae3e6535a63492623a04f5 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 18 Sep 2007 05:16:56 +0200 Subject: [PATCH 5/5] basic AssetManager works now (creating, registering, querying), including memory management. Ordering is still WIP. --- src/proc/asset.cpp | 6 +- src/proc/asset.hpp | 17 ++- src/proc/asset/db.hpp | 20 ++- src/proc/assetmanager.hpp | 3 +- tests/51asset.tests | 12 +- .../proc/asset/assetdiagnostics.hpp | 4 +- .../components/proc/asset/createassettest.cpp | 25 ++-- .../proc/asset/identityofassetstest.cpp | 18 +-- .../proc/asset/orderingofassetstest.cpp | 125 ++++++++++++++++++ 9 files changed, 194 insertions(+), 36 deletions(-) create mode 100644 tests/components/proc/asset/orderingofassetstest.cpp diff --git a/src/proc/asset.cpp b/src/proc/asset.cpp index 622311863..460464a8e 100644 --- a/src/proc/asset.cpp +++ b/src/proc/asset.cpp @@ -27,6 +27,8 @@ #include +#include +#include using boost::format; using util::cStr; @@ -46,12 +48,12 @@ namespace asset */ Asset::Asset (const Ident& idi) : ident(idi), id(AssetManager::reg (this, idi)) - { TRACE (assetmem, "ctor Asset(id=%d) : %s p=%x", size_t(id), cStr(this->ident), this ); + { TRACE (assetmem, "ctor Asset(id=%lu) : adr=%x %s", size_t(id), this, cStr(this->ident) ); } Asset::~Asset () { - TRACE (assetmem, "dtor Asset(id=%d) : %s p=%x", size_t(id), cStr(this->ident), this ); + TRACE (assetmem, "dtor Asset(id=%lu) : adr=%x", size_t(id), this ); } diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index e6fd207c6..a6e3b1ad8 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -175,20 +175,30 @@ namespace asset && name == other.name && category == other.category; } + bool operator!= (const Ident& other) const + { + return !operator==(other); + } + int compare (const Ident& other) const; operator string () const; }; + + + /* ===== Asset ID and Datafields ===== */ + public: const Ident ident; ///< Asset identification tuple + virtual const ID& getID() const { return id; } + virtual operator string () const; + protected: const ID id; ///< Asset primary key. - - protected: /** additional classification, selections or departments this asset belongs to. * Groups are optional, non-exclusive and may be overlapping. */ @@ -209,7 +219,7 @@ namespace asset * Calling this base ctor causes registration with AssetManager. */ Asset (const Ident& idi); - virtual ~Asset() = 0; + virtual ~Asset() = 0; ///< @note Asset is abstract /** release all links to other Asset objects held internally. * The lifecycle of Asset objects is managed by smart pointers @@ -230,6 +240,7 @@ namespace asset friend class AssetManager; + public: /** List of entities this asset depends on or requires to be functional. * May be empty. The head of this list can be considered the primary prerequisite diff --git a/src/proc/asset/db.hpp b/src/proc/asset/db.hpp index 76be677f0..b9faa0a42 100644 --- a/src/proc/asset/db.hpp +++ b/src/proc/asset/db.hpp @@ -88,6 +88,7 @@ namespace asset friend class cinelerra::singleton::Static; + public: template void put (ID hash, shared_ptr& ptr) { table[hash] = static_pointer_cast (ptr); } @@ -95,20 +96,33 @@ namespace asset template shared_ptr - get (ID hash) + get (ID hash) const { - return dynamic_pointer_cast (table[hash]); + return dynamic_pointer_cast (find (hash)); } + /** intended for diagnostics */ void - asList (list& output) const + asList (list& output) const { IdHashtable::const_iterator i = table.begin(); IdHashtable::const_iterator e = table.end(); for ( ; i!=e ; ++i ) output.push_back (i->second); } + + private: + const PAsset & + find (size_t hash) const + { + static const PAsset NULLP; + IdHashtable::const_iterator i = table.find (hash); + if (i == table.end()) + return NULLP; // empty ptr signaling "not found" + else + return i->second; + } }; diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp index 8ccf0ac61..c677f6ef4 100644 --- a/src/proc/assetmanager.hpp +++ b/src/proc/assetmanager.hpp @@ -102,8 +102,7 @@ namespace asset throw(cinelerra::error::Invalid); /** deleter function used by the Asset smart pointers to delet Asset objects */ - static void destroy (Asset* m) { TRACE (assetmem, "call destroy (Asset(id=%d)) p=%x", m? size_t(m->getID()):0, m ); - delete m; } + static void destroy (Asset* m) { delete m; } friend Asset::Asset (const Asset::Ident& idi); diff --git a/tests/51asset.tests b/tests/51asset.tests index 37b7dac4f..4c87542f4 100644 --- a/tests/51asset.tests +++ b/tests/51asset.tests @@ -2,7 +2,8 @@ TESTING "Component Test Suite: Asset Manager" ./test-components --group=asset -PLANNED "CreateAsset_test" CreateAsset_test <getID() % &aa % aa.get() % aa.use_count() << "\n"; + format fmt("%s %|50T.| id=%s adr=%x smart-ptr=%x use-count=%d"); + cout << fmt % str(aa) % aa->getID() % aa.get() % &aa % (aa.use_count() - 1) << "\n"; } } inline void dumpAssetManager () diff --git a/tests/components/proc/asset/createassettest.cpp b/tests/components/proc/asset/createassettest.cpp index b5f449787..00fa049f0 100644 --- a/tests/components/proc/asset/createassettest.cpp +++ b/tests/components/proc/asset/createassettest.cpp @@ -52,9 +52,14 @@ namespace asset { createMedia(); factoryVariants(); - dumpAssetManager(); + + if (!isnil (arg)) + dumpAssetManager(); + TRACE (assetmem, "leaving CreateAsset_test::run()"); } + + typedef shared_ptr PM; /** @test Creating and automatically registering Asset instances. @@ -79,9 +84,6 @@ namespace asset ASSERT (aMang.getAsset (mm1->getID()) != mm2); - cout << "== 1 ==\n"; - dumpAssetManager(); - PAsset aa1 = aMang.getAsset (ID(mm1->getID())); // note we get an Asset ref ASSERT (aa1 == mm1); PM mX1 = aMang.getAsset (mm1->getID()); // ..and now we get a Media ref @@ -92,22 +94,19 @@ namespace asset ASSERT (aMang.known (mm2->getID())); ASSERT (aMang.known (mm3->getID())); - cout << "== 2 ==\n"; - dumpAssetManager(); - ASSERT ( !aMang.known (mm3->getID(), Category(AUDIO))); // not found within AUDIO-Category try { // can't be found if specifying wrong Asset kind.... aMang.getAsset (ID(mm1->getID())); NOTREACHED; } - catch (cinelerra::error::Invalid& exe) {ASSERT (exe.getID()==CINELERRA_ERROR_WRONG_ASSET_KIND);} + catch (cinelerra::error::Invalid& xxx) {ASSERT (xxx.getID()==CINELERRA_ERROR_WRONG_ASSET_KIND);} try { // try accessing nonexistant ID aMang.getAsset (ID (1234567890)); NOTREACHED; } - catch (cinelerra::error::Invalid& exe) {ASSERT (exe.getID()==CINELERRA_ERROR_UNKNOWN_ASSET_ID);} + catch (cinelerra::error::Invalid& xxx) {ASSERT (xxx.getID()==CINELERRA_ERROR_UNKNOWN_ASSET_ID);} // checking the Ident-Fields @@ -132,12 +131,8 @@ namespace asset ASSERT (mm2->getFilename() == "testfile1.mov"); ASSERT (mm3->getFilename() == "testfile2.mov"); - dump (mm1); - dump (mm2); - dump (mm3); - dump (mX1); - cout << "== 3 ==\n"; - dumpAssetManager(); + + TRACE (assetmem, "leaving test method scope"); } diff --git a/tests/components/proc/asset/identityofassetstest.cpp b/tests/components/proc/asset/identityofassetstest.cpp index d55623538..2e62963bc 100644 --- a/tests/components/proc/asset/identityofassetstest.cpp +++ b/tests/components/proc/asset/identityofassetstest.cpp @@ -53,9 +53,14 @@ namespace asset virtual void run(Arg arg) { createDuplicate(); - cout << "ausis\n"; + + if (!isnil (arg)) + dumpAssetManager(); + TRACE (assetmem, "leaving IdentityOfAssets_test::run()"); } + + typedef shared_ptr PM; /** @test produce an ID clash. @@ -70,9 +75,9 @@ namespace asset Asset::Ident idi (mm1->ident); // duplicate Ident record PM mm1X = asset::Media::create (idi); // note: we actually don't call any ctor ASSERT (mm1 == mm1X); // instead, we got mm1 back. - cout << "usi-v " << mm1.use_count() <<"\n"; + PM mm2 = asset::Media::create (idi,"testfile2.mov"); - cout << "usi-n " << mm1.use_count() <<"\n"; + ASSERT (mm1->getID() == mm2->getID()); // different object, same hash AssetManager& aMang = AssetManager::instance(); @@ -86,11 +91,8 @@ namespace asset ASSERT (mm1->getFilename() == "testfile1.mov"); ASSERT (mm2->getFilename() == "testfile2.mov"); - cout << "use-cnt at end " << mm1.use_count() <<"\n"; - dump (mm1); - dump (mm1X); - dump (mm2); - dumpAssetManager(); + + TRACE (assetmem, "leaving test method scope"); } }; diff --git a/tests/components/proc/asset/orderingofassetstest.cpp b/tests/components/proc/asset/orderingofassetstest.cpp new file mode 100644 index 000000000..4e6137224 --- /dev/null +++ b/tests/components/proc/asset/orderingofassetstest.cpp @@ -0,0 +1,125 @@ +/* + OrderingOfAssets(Test) - equality and comparisons + + Copyright (C) CinelerraCV + 2007, 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 "common/test/run.hpp" +#include "common/util.hpp" + +#include "proc/assetmanager.hpp" +#include "proc/asset/media.hpp" +#include "proc/asset/proc.hpp" + +#include "proc/asset/assetdiagnostics.hpp" + +using util::isnil; +using std::string; + + +namespace asset + { + namespace test + { + + + + + /****************************************************** + * @test validate the equality and order relations of + * Asset::Ident and Asset objects. + * @see Asset::Ident#compare + */ + class OrderingOfAssets_test : public Test + { + virtual void run(Arg arg) + { + typedef shared_ptr PM; + + Asset::Ident key1("Au-1", Category(AUDIO), "ichthyo", 5); + PM mm1 = asset::Media::create(key1, "Name-1"); + + Asset::Ident key2("Au-1", Category(AUDIO), "ichthyo", 7); + PM mm2 = asset::Media::create(key2, "Name-2"); + + Asset::Ident key3("Au-2", Category(AUDIO), "ichthyo", 5); + PM mm3 = asset::Media::create(key3, "Name-3"); + + Asset::Ident key4("Au-2", Category(AUDIO), "stega", 5); + PM mm4 = asset::Media::create(key4, "Name-4"); + + Asset::Ident key5("Au-1", Category(VIDEO), "ichthyo", 5); + PM mm5 = asset::Media::create(key5, "Name-5"); + + + // ordering of keys + ASSERT (key1 == key2); + ASSERT (key2 != key3); + ASSERT (key3 != key4); + ASSERT (key4 != key5); + ASSERT (key1 != key5); + + ASSERT (-1 == key2.compare(key3)); + ASSERT (+1 == key3.compare(key2)); + + ASSERT (-1 == key3.compare(key4)); + ASSERT (-1 == key4.compare(key5)); + ASSERT (-1 == key1.compare(key5)); + ASSERT (-1 == key2.compare(key5)); + ASSERT (-1 == key3.compare(key5)); + ASSERT (-1 == key1.compare(key3)); + ASSERT (-1 == key1.compare(key4)); + ASSERT (-1 == key2.compare(key4)); + + + // ordering of Asset smart ptrs + ASSERT (mm1 == mm2); + ASSERT (mm2 != mm3); + ASSERT (mm3 != mm4); + ASSERT (mm4 != mm5); + ASSERT (mm1 != mm5); + + ASSERT (mm2 < mm3); + ASSERT (mm2 <= mm3); + ASSERT (mm3 > mm2); + ASSERT (mm3 >= mm2); + + ASSERT (mm3 < mm4); + ASSERT (mm4 < mm5); + ASSERT (mm1 < mm5); + ASSERT (mm2 < mm5); + ASSERT (mm3 < mm5); + ASSERT (mm1 < mm3); + ASSERT (mm1 < mm4); + ASSERT (mm2 < mm4); + + } + + }; + + + /** Register this test class... */ + LAUNCHER (OrderingOfAssets_test, "unit asset"); + + + + } // namespace test + +} // namespace asset