WIP integration of Asset types and AssetManager

This commit is contained in:
Fischlurch 2007-09-16 03:02:05 +02:00
parent c746629312
commit 5da016aa5a
16 changed files with 468 additions and 38 deletions

View file

@ -0,0 +1,54 @@
/*
MULTITHREAD.hpp - generic interface for multithreading primitives
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#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 X>
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

View file

@ -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 <vector>
@ -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<S> Lock;
};

View file

@ -39,9 +39,9 @@ namespace util
typedef boost::function<bool(string::value_type)> 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

View file

@ -181,6 +181,7 @@ namespace asset
const Ident ident; ///< Asset identification tuple
virtual const ID<Asset>& getID() const { return id; }
protected:
const ID<Asset> id; ///< Asset primary key.

View file

@ -25,6 +25,9 @@
#include "common/util.hpp"
#include "nobugcfg.h"
#include <boost/algorithm/string.hpp>
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

View file

@ -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;

View file

@ -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<size_t, PAsset, IdentityHash> 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<DB>;
public:
template<class KIND>
void put (ID<KIND> hash, shared_ptr<KIND>& ptr) { table[hash] = static_pointer_cast (ptr); }
void put (ID<Asset> hash, PAsset& ptr) { table[hash] = ptr; }
template<class KIND>
shared_ptr<KIND>
get (ID<KIND> hash)
{
return dynamic_pointer_cast<KIND,Asset> (table[hash]);
}
};

View file

@ -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; }
};

View file

@ -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

View file

@ -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 <i>Kinds</i> 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<Meta> : public ID<Asset>
{
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<Meta>& getID() const ///< @return ID of kind Meta
{
return static_cast<const ID<Meta>& > (Asset::getID());
}
protected:
Meta (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO
friend class MetaFactory;
};
// definition of ID<Meta> ctors is possible now,
// after providing full definition of class Proc
inline ID<Meta>::ID(size_t id) : ID<Asset> (id) {};
inline ID<Meta>::ID(const Meta& meta) : ID<Asset> (meta.getID()) {};
/**
* Factory specialized for createing Metadata Asset objects.
*/
class MetaFactory : public cinelerra::Factory<asset::Meta>
{
public:
typedef shared_ptr<asset::Meta> PType;
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
};
} // namespace asset
#endif

View file

@ -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

View file

@ -21,26 +21,85 @@
*/
/** @file proc.hpp
** Data processing Plugins and Codecs can be treated as a specific Kind of Asset.
** For the different <i>Kinds</i> 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<Proc> : public ID<Asset>
{
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<Proc>& getID() const ///< @return ID of kind Proc
{
return static_cast<const ID<Proc>& > (Asset::getID());
}
protected:
Proc (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO
friend class ProcFactory;
};
// definition of ID<Proc> ctors is possible now,
// after providing full definition of class Proc
inline ID<Proc>::ID(size_t id) : ID<Asset> (id) {};
inline ID<Proc>::ID(const Proc& proc) : ID<Asset> (proc.getID()) {};
/**
* Factory specialized for createing Processor Asset objects.
*/
class ProcFactory : public cinelerra::Factory<asset::Proc>
{
public:
typedef shared_ptr<asset::Proc> PType;
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
};
} // namespace asset
#endif

View file

@ -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");
}

View file

@ -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 <i>Kinds</i> 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<Struct> : public ID<Asset>
{
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<Struct>& getID() const ///< @return ID of kind asset::Struct
{
return static_cast<const ID<Struct>& > (Asset::getID());
}
protected:
Struct (const Asset::Ident& idi) : Asset(idi) {} //////////////TODO
friend class StructFactory;
};
// definition of ID<Struct> ctors is possible now,
// after providing full definition of class Proc
inline ID<Struct>::ID(size_t id) : ID<Asset> (id) {};
inline ID<Struct>::ID(const Struct& stru) : ID<Asset> (stru.getID()) {};
/**
* Factory specialized for createing Structural Asset objects.
*/
class StructFactory : public cinelerra::Factory<asset::Struct>
{
public:
typedef shared_ptr<asset::Struct> PType;
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
};

View file

@ -24,13 +24,65 @@
#include "proc/assetmanager.hpp"
#include "proc/asset/db.hpp"
//#include <boost/functional/hash.hpp>
#include "common/multithread.hpp"
#include "common/util.hpp"
#include <boost/lambda/lambda.hpp>
#include <boost/function.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
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<Asset> 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<class KIND>
ID<KIND>
AssetManager::reg (KIND* obj, const Asset::Ident& idi)
throw(cinelerra::error::Invalid)
{
UNIMPLEMENTED ("AssetManager::reg");
typedef shared_ptr<KIND> PType;
AssetManager& _aMang (AssetManager::instance());
TODO ("check validity of Ident Category");
ID<KIND> asset_id (getID (idi));
Thread::Lock<DB> 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<class KIND>
shared_ptr<KIND>
AssetManager::getAsset (const ID<KIND>& id)
throw(cinelerra::error::Invalid)
{
UNIMPLEMENTED ("AssetManager::getAsset");
if (shared_ptr<KIND> obj = registry.get (id))
return obj;
else
if (known (id)) // provide Ident tuple of existing Asset
throw WrongKind (registry.get(ID<Asset>(id))->ident);
else
throw UnknownID (id);
}
@ -81,8 +152,9 @@ namespace asset
bool
AssetManager::known (IDA id)
{
UNIMPLEMENTED ("asset search");
}
return ( registry.get (ID<Asset>(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 <i>together with all its dependants</i> 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<PAsset> par = pA->getParents();
boost::function<void(PAsset&)> func = bind(&detach_child, _1,id );
for_each (par, func); // ,boost::lambda::var(id)));
}

View file

@ -40,6 +40,7 @@
#include "common/error.hpp"
#include "common/singleton.hpp"
#include <cstddef>
#include <string>
#include <boost/utility.hpp>
@ -94,13 +95,22 @@ namespace asset
static ID<KIND> 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<AssetManager>;
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