WIP: fleshed out a good deal of the AssetManager foundation.
compiles ok, singleton test pass (most of asset creation just commented out...)
This commit is contained in:
parent
79c88c2c87
commit
26374ce409
18 changed files with 420 additions and 199 deletions
|
|
@ -33,6 +33,13 @@ using boost::algorithm::split;
|
|||
using boost::algorithm::join;
|
||||
using boost::algorithm::is_any_of;
|
||||
using boost::algorithm::token_compress_on;
|
||||
using boost::regex;
|
||||
using boost::smatch;
|
||||
using boost::regex_search;
|
||||
|
||||
using boost::regex;
|
||||
using boost::smatch;
|
||||
using boost::regex_search;
|
||||
|
||||
|
||||
|
||||
|
|
@ -59,12 +66,12 @@ namespace util
|
|||
*/
|
||||
Cmdline::Cmdline (const string cmdline)
|
||||
{
|
||||
boost::regex tokendef("[^ \r\n\t]+");
|
||||
boost::smatch match;
|
||||
regex tokendef("[^ \r\n\t]+");
|
||||
smatch match;
|
||||
string::const_iterator it = cmdline.begin();
|
||||
string::const_iterator end = cmdline.end();
|
||||
|
||||
while (boost::regex_search(it, end, match, tokendef))
|
||||
while (regex_search(it, end, match, tokendef))
|
||||
{
|
||||
string ss(match[0]);
|
||||
this->push_back(ss);
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
Singleton - template for implementing the singleton pattern
|
||||
|
||||
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.
|
||||
|
||||
====================================================================
|
||||
This code is heavily inspired by
|
||||
The Loki Library (loki-lib/trunk/include/loki/Singleton.h)
|
||||
Copyright (c) 2001 by Andrei Alexandrescu
|
||||
This Loki code accompanies the book:
|
||||
Alexandrescu, Andrei. "Modern C++ Design:
|
||||
Generic Programming and Design Patterns Applied".
|
||||
Copyright (c) 2001. Addison-Wesley. ISBN 0201704315
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
|
||||
#include "common/singleton.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "nobugcfg.h"
|
||||
|
||||
namespace cinelerra
|
||||
{
|
||||
|
||||
/** Interface to be used by Singleton's clients.
|
||||
* Manages internally the instance creation, lifecycle
|
||||
* and access handling in a multithreaded context.
|
||||
* @return "the" single instance of class S
|
||||
*/
|
||||
template
|
||||
< class SI, // the class to make Singleton
|
||||
template <class> class Create, // how to create/destroy the instance
|
||||
template <class> class Life, // how to manage Singleton Lifecycle
|
||||
template <class> class Threading
|
||||
>
|
||||
SI&
|
||||
Singleton<SI,Create,Life,Threading>::instance()
|
||||
{
|
||||
if (!pInstance_)
|
||||
{
|
||||
ThreadLock guard;
|
||||
if (!pInstance_)
|
||||
{
|
||||
if (isDead_)
|
||||
{
|
||||
Life<SI>::onDeadReference();
|
||||
isDead_ = false;
|
||||
}
|
||||
pInstance_ = Create<SI>::create();
|
||||
Life<SI>::scheduleDelete (&destroy);
|
||||
} }
|
||||
ENSURE (pInstance_);
|
||||
ENSURE (!isDead_);
|
||||
return *pInstance_;
|
||||
}
|
||||
|
||||
|
||||
/** @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.
|
||||
*/
|
||||
template
|
||||
< class SI,
|
||||
template <class> class Create,
|
||||
template <class> class Life,
|
||||
template <class> class Threading
|
||||
>
|
||||
void
|
||||
Singleton<SI,Create,Life,Threading>::destroy()
|
||||
{
|
||||
REQUIRE (!isDead_);
|
||||
Create<SI>::destroy (pInstance_);
|
||||
pInstance_ = 0;
|
||||
isDead_ = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
namespace singleton
|
||||
{
|
||||
|
||||
} // namespace singleton
|
||||
|
||||
} // namespace cinelerra
|
||||
|
|
@ -37,40 +37,120 @@ This code is heavily inspired by
|
|||
|
||||
#include "common/singletonpolicies.hpp" ///< several Policies usable together with singleton
|
||||
|
||||
#include "common/util.hpp"
|
||||
#include "nobugcfg.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
|
||||
namespace cinelerra
|
||||
{
|
||||
|
||||
/**
|
||||
* A configurable Template for implementing Singletons
|
||||
* A configurable Template for implementing Singletons.
|
||||
* Actually this is a Functor object, which could be placed into a static field
|
||||
* of the Singleton (target) class or used directly.
|
||||
* @note internally uses static fields, so all functor instances share pInstance_
|
||||
*/
|
||||
template
|
||||
< class S, // the class to make Singleton
|
||||
< class SI, // the class to make Singleton
|
||||
template <class> class Create = singleton::Static, // how to create/destroy the instance
|
||||
template <class> class Life = singleton::Automatic, // how to manage Singleton Lifecycle
|
||||
template <class> class Threading = singleton::IgnoreThreadsafety //TODO use Multithreaded!!!
|
||||
>
|
||||
class Singleton
|
||||
{
|
||||
public:
|
||||
static S& instance();
|
||||
|
||||
private:
|
||||
typedef typename Threading<S>::VolatileType SType;
|
||||
typedef typename Threading<S>::Lock ThreadLock;
|
||||
typedef typename Threading<SI>::VolatileType SType;
|
||||
typedef typename Threading<SI>::Lock ThreadLock;
|
||||
static SType* pInstance_;
|
||||
static bool isDead_;
|
||||
|
||||
protected:
|
||||
Singleton () { }
|
||||
Singleton (const Singleton&) { }
|
||||
Singleton& operator= (const Singleton&) { return *this; }
|
||||
public:
|
||||
/** Interface to be used by Singleton's clients.
|
||||
* Manages internally the instance creation, lifecycle
|
||||
* and access handling in a multithreaded context.
|
||||
* @return "the" single instance of class S
|
||||
*/
|
||||
SI& operator() ()
|
||||
{
|
||||
if (!pInstance_)
|
||||
{
|
||||
ThreadLock guard;
|
||||
if (!pInstance_)
|
||||
{
|
||||
if (isDead_)
|
||||
{
|
||||
Life<SI>::onDeadReference();
|
||||
isDead_ = false;
|
||||
}
|
||||
pInstance_ = Create<SI>::create();
|
||||
Life<SI>::scheduleDelete (&destroy);
|
||||
} }
|
||||
ENSURE (pInstance_);
|
||||
ENSURE (!isDead_);
|
||||
return *pInstance_;
|
||||
}
|
||||
|
||||
private:
|
||||
static void destroy();
|
||||
/** @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.
|
||||
*/
|
||||
static void destroy()
|
||||
{
|
||||
REQUIRE (!isDead_);
|
||||
Create<SI>::destroy (pInstance_);
|
||||
pInstance_ = 0;
|
||||
isDead_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Storage for Singleton's static fields...
|
||||
template
|
||||
< class SI,
|
||||
template <class> class C,
|
||||
template <class> class L,
|
||||
template <class> class T
|
||||
>
|
||||
typename Singleton<SI,C,L,T>::SType*
|
||||
Singleton<SI,C,L,T>::pInstance_;
|
||||
|
||||
template
|
||||
< class SI,
|
||||
template <class> class C,
|
||||
template <class> class L,
|
||||
template <class> class T
|
||||
>
|
||||
bool Singleton<SI,C,L,T>::isDead_;
|
||||
|
||||
|
||||
|
||||
///// TODO: get rid of the static fields?
|
||||
///// is tricky because of invoking the destructors. If we rely on instance vars,
|
||||
///// the object may already have been released when the runtime system calls the
|
||||
///// destructors of static objects at shutdown.
|
||||
|
||||
/** @internal used to link together the Create policy and Life policy.
|
||||
* @return a functor object for invoking this->destroy() */
|
||||
/* singleton::DelFunc getDeleter()
|
||||
{
|
||||
return boost::bind (&Singleton<SI,Create,Life,Threading>::destroy,
|
||||
this);
|
||||
}
|
||||
*/
|
||||
|
||||
/* template<class T>
|
||||
class DelFunc
|
||||
{
|
||||
typedef void (T::*Fp)(void);
|
||||
T* t_;
|
||||
Fp fun_;
|
||||
public:
|
||||
DelFunc (T* t, Fp f) : t_(t), fun_(f) {}
|
||||
void operator() () { (t_->*fun_)(); }
|
||||
};
|
||||
*/
|
||||
} // namespace cinelerra
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ This code is heavily inspired by
|
|||
|
||||
#include "common/error.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace cinelerra
|
||||
|
|
@ -56,8 +57,8 @@ namespace cinelerra
|
|||
static uint callCount (0);
|
||||
ASSERT ( 0 == callCount++ );
|
||||
#endif
|
||||
static S _theSingle_;
|
||||
return &_theSingle_;
|
||||
static char buff[sizeof(S)];
|
||||
return new(buff) S();
|
||||
}
|
||||
static void destroy (S* pSi)
|
||||
{
|
||||
|
|
@ -76,30 +77,46 @@ namespace cinelerra
|
|||
static void destroy (S* pS) { delete pS; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void (*DelFunc)(void);
|
||||
using std::vector;
|
||||
|
||||
/**
|
||||
* Policy relying on the compiler/runtime system for Singleton Lifecycle
|
||||
*/
|
||||
template<class S>
|
||||
struct Automatic
|
||||
{
|
||||
typedef void (*DeleterFunc) (void);
|
||||
/** implements the Singleton removal by calling
|
||||
* the provided deleter function at application shutdown,
|
||||
* relying on the runtime system calling destructors of
|
||||
* static objects
|
||||
* 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
|
||||
* deleter functions for calling them at shutdown.
|
||||
*/
|
||||
static void scheduleDelete (DeleterFunc kill_the_singleton)
|
||||
static void scheduleDelete (DelFunc kill_the_singleton)
|
||||
{
|
||||
struct DeleteTrigger
|
||||
class DeleteTrigger
|
||||
{
|
||||
~DeleteTrigger() { *del_ (); }
|
||||
DeleteTrigger(DeleterFunc d) : del_(d) {}
|
||||
DeleterFunc del_;
|
||||
vector<DelFunc> dels_;
|
||||
|
||||
public:
|
||||
void schedule (DelFunc del)
|
||||
{
|
||||
dels_.push_back(del);
|
||||
}
|
||||
~DeleteTrigger()
|
||||
{
|
||||
vector<DelFunc>::iterator i = dels_.begin();
|
||||
for ( ; i != dels_.end(); ++i )
|
||||
(*i)(); // invoke deleter func
|
||||
}
|
||||
};
|
||||
static DeleteTrigger finally(kill_the_singleton);
|
||||
|
||||
|
||||
REQUIRE (kill_the_singleton);
|
||||
static DeleteTrigger finally;
|
||||
finally.schedule (kill_the_singleton);
|
||||
}
|
||||
|
||||
static void onDeadReference ()
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ namespace asset
|
|||
/** Asset is a Interface class; usually, objects of
|
||||
* concrete subclasses are created via specialized Factories
|
||||
*/
|
||||
Asset::Asset (Ident& idi)
|
||||
Asset::Asset (const Ident& idi)
|
||||
: ident(idi), id(AssetManager::reg (this, idi))
|
||||
{ }
|
||||
|
||||
Asset::~Asset () throw()
|
||||
Asset::~Asset ()
|
||||
{
|
||||
TRACE (assetmem, "dtor Asset(id=%d) : %s", size_t(id), cStr(this->ident) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,16 +76,26 @@ namespace asset
|
|||
{
|
||||
public:
|
||||
const size_t hash;
|
||||
ID (size_t id) : hash(id) {}
|
||||
ID (const KIND& asset) : hash(asset.id) {}
|
||||
ID (size_t id) : hash(id) {}
|
||||
ID (const KIND& asset) : hash(asset.getID()) {}
|
||||
operator size_t() const { return hash; }
|
||||
};
|
||||
|
||||
class Asset;
|
||||
class AssetManager;
|
||||
typedef const ID<Asset>& IDA;
|
||||
|
||||
class Media;
|
||||
|
||||
|
||||
template<>
|
||||
class ID<Media> : public ID<Asset>
|
||||
{
|
||||
public:
|
||||
ID (size_t id);
|
||||
ID (const Media&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Superinterface describing especially bookeeping properties.
|
||||
* As of 09/2007, there are four <b>Kinds</b> of Assets, each
|
||||
|
|
@ -156,7 +166,9 @@ namespace asset
|
|||
operator string () const;
|
||||
};
|
||||
|
||||
const Ident ident; ///< Asset identification tuple
|
||||
const Ident ident; ///< Asset identification tuple
|
||||
virtual const ID<Asset>& getID() const { return id; }
|
||||
private:
|
||||
const ID<Asset> id; ///< Asset primary key.
|
||||
|
||||
|
||||
|
|
@ -180,8 +192,8 @@ namespace asset
|
|||
* concrete subclasses are created via specialized Factories.
|
||||
* Calling this base ctor causes registration with AssetManager.
|
||||
*/
|
||||
Asset (Ident& idi);
|
||||
virtual ~Asset() throw() = 0;
|
||||
Asset (const Ident& idi);
|
||||
virtual ~Asset() = 0;
|
||||
|
||||
/** release all links to other Asset objects held internally.
|
||||
* The lifecycle of Asset objects is managed by smart pointers
|
||||
|
|
@ -244,8 +256,8 @@ namespace proc_interface
|
|||
{
|
||||
using asset::Asset;
|
||||
using asset::Category;
|
||||
using asset::ID;
|
||||
using asset::IDA;
|
||||
// using asset::ID;
|
||||
// using asset::IDA;
|
||||
using asset::PAsset;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ 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; }
|
||||
|
||||
|
||||
operator string () const;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace asset
|
|||
size_t
|
||||
hash_value (const Asset& asset)
|
||||
{
|
||||
return asset.id;
|
||||
return asset.getID();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,104 @@
|
|||
* *****************************************************/
|
||||
|
||||
|
||||
#include "proc/assetmanager.hpp"
|
||||
#include "proc/asset/media.hpp"
|
||||
#include "proc/asset/clip.hpp"
|
||||
#include "proc/asset/unknown.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "nobugcfg.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
using util::isnil;
|
||||
|
||||
using boost::regex;
|
||||
using boost::smatch;
|
||||
using boost::regex_search;
|
||||
|
||||
|
||||
namespace asset
|
||||
{
|
||||
|
||||
/** */
|
||||
namespace // Implementation details
|
||||
{
|
||||
/** helper: extract a name token out of a given path/filename
|
||||
* @return sanitized token based on the name (minus extension),
|
||||
* empty string if not the common filename pattern.
|
||||
*/
|
||||
string extractName (const string& path)
|
||||
{
|
||||
regex pathname_pattern("([^/\\.]+)(\\.\\w+)?$");
|
||||
smatch match;
|
||||
|
||||
if (regex_search (path, match, pathname_pattern))
|
||||
return util::sanitize (string (match[1]));
|
||||
else
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
MediaFactory Media::create;
|
||||
|
||||
|
||||
/** Factory method for Media Asset instances. Depending on the filename given,
|
||||
* either a asset::Media object or an "Unknown" placeholder will be provided. If
|
||||
* the given Category already contains an "Unkown", we just get the
|
||||
* corresponding smart-ptr. Otherwise a new asset::Unknown is created. */
|
||||
MediaFactory::PType
|
||||
MediaFactory::operator() (Asset::Ident& key, const string& file)
|
||||
{
|
||||
asset::Media* pM (0);
|
||||
AssetManager& aMang = AssetManager::instance();
|
||||
TODO ("check and fix Category if necessary");
|
||||
if (isnil (file))
|
||||
{
|
||||
if (isnil (key.name)) key.name="nil";
|
||||
ID<Asset> id = aMang.getID (key);
|
||||
if (aMang.known (id))
|
||||
return aMang.getAsset(ID<Media>(id));
|
||||
else
|
||||
pM = new Unknown(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isnil (key.name)) key.name=extractName(file);
|
||||
TODO ("file exists?");
|
||||
pM = new Media (key,file);
|
||||
}
|
||||
ENSURE (key.category.hasKind (VIDEO) || key.category.hasKind(AUDIO));
|
||||
ENSURE (isnil (key.name));
|
||||
ENSURE (dynamic_cast<Media*>(pM) || (isnil (file) && dynamic_cast<Unknown*>(pM)));
|
||||
|
||||
return PType (pM, &destroy);
|
||||
}
|
||||
|
||||
|
||||
/** Variant of the Factory method for Media Assets, automatically
|
||||
* providing most of the Asset key fields based on the filename given
|
||||
*/
|
||||
MediaFactory::PType
|
||||
MediaFactory::operator() (const string& file, Category& cat)
|
||||
{
|
||||
Asset::Ident key(extractName(file), cat, "cin3", 1);
|
||||
return MediaFactory::operator() (key, file);
|
||||
}
|
||||
|
||||
|
||||
MediaFactory::PType
|
||||
MediaFactory::operator() (const char* file, Category& cat)
|
||||
{
|
||||
if (!file) file = "";
|
||||
return operator() (file,cat);
|
||||
}
|
||||
|
||||
MediaFactory::PType
|
||||
MediaFactory::operator() (Asset::Ident& key, const char* file)
|
||||
{
|
||||
if (!file) file = "";
|
||||
return operator() (key,file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace asset
|
||||
|
|
|
|||
|
|
@ -25,21 +25,68 @@
|
|||
#define ASSET_MEDIA_H
|
||||
|
||||
#include "proc/asset.hpp"
|
||||
#include "common/factory.hpp"
|
||||
|
||||
|
||||
|
||||
namespace asset
|
||||
{
|
||||
|
||||
class Media;
|
||||
class MediaFactory;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* key abstraction: media-like assets
|
||||
*/
|
||||
class Media : public proc_interface::Asset
|
||||
class Media : public Asset
|
||||
{
|
||||
string filename_;
|
||||
|
||||
public:
|
||||
virtual const ID<Media>& getID() const { return getID(); }
|
||||
static MediaFactory create;
|
||||
const string& getFilename () { return filename_; }
|
||||
|
||||
protected:
|
||||
Media (const Asset::Ident& idi, const string& file) : Asset(idi), filename_(file) {}
|
||||
friend class MediaFactory;
|
||||
};
|
||||
|
||||
|
||||
// definition of ID<Media> ctors is possible now,
|
||||
// after providing full definition of class Media
|
||||
/*
|
||||
ID<Media>::ID(size_t id)
|
||||
: ID<Asset> (id) {};
|
||||
|
||||
ID<Media>::ID(const Media& media)
|
||||
: ID<Asset> (media.getID()) {};
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Factory specialized for createing Media Asset objects.
|
||||
*/
|
||||
class MediaFactory : public cinelerra::Factory<asset::Media>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<asset::Media> PType;
|
||||
|
||||
PType operator() (Asset::Ident& key, const string& file="");
|
||||
PType operator() (const string& file, Category& cat);
|
||||
|
||||
PType operator() (Asset::Ident& key, const char* file); ///< convienience overload using cString
|
||||
PType operator() (const char* file, Category& cat);
|
||||
|
||||
protected:
|
||||
static void destroy (Media* m) { delete m; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace asset
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ namespace asset
|
|||
*/
|
||||
class Preview : public Media
|
||||
{
|
||||
|
||||
protected:
|
||||
Preview (const Asset::Ident& idi) : Media(idi,"") {}
|
||||
friend class MediaFactory;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ namespace asset
|
|||
*/
|
||||
class Unknown : public Preview
|
||||
{
|
||||
|
||||
protected:
|
||||
Unknown (const Asset::Ident& idi) : Preview(idi) {}
|
||||
friend class MediaFactory;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ namespace asset
|
|||
AssetManager&
|
||||
AssetManager::instance ()
|
||||
{
|
||||
return Singleton<AssetManager>::instance();
|
||||
return *(new AssetManager); //////////////////////////////TODO Singleton<AssetManager>::instance();
|
||||
}
|
||||
|
||||
AssetManager::AssetManager ()
|
||||
: registry (Singleton<asset::DB>::instance())
|
||||
: registry (*(new DB)) //(Singleton<asset::DB>::instance())
|
||||
{ }
|
||||
|
||||
|
||||
|
|
@ -62,8 +62,9 @@ namespace asset
|
|||
template<class KIND>
|
||||
ID<KIND>
|
||||
AssetManager::reg (KIND& obj, const Asset::Ident& idi)
|
||||
//throw(cinelerra::error::Invalid)
|
||||
throw(cinelerra::error::Invalid)
|
||||
{
|
||||
UNIMPLEMENTED ("AssetManager::reg");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -72,8 +73,10 @@ namespace asset
|
|||
*/
|
||||
template<class KIND>
|
||||
shared_ptr<KIND>
|
||||
AssetManager::getAsset (const ID<KIND>& id) ////throw(cinelerra::Invalid)
|
||||
AssetManager::getAsset (const ID<KIND>& id)
|
||||
throw(cinelerra::error::Invalid)
|
||||
{
|
||||
UNIMPLEMENTED ("AssetManager::getAsset");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -83,6 +86,17 @@ namespace asset
|
|||
bool
|
||||
AssetManager::known (IDA id)
|
||||
{
|
||||
UNIMPLEMENTED ("asset search");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the given id is registered with the given Category
|
||||
*/
|
||||
bool
|
||||
AssetManager::known (IDA id, const Category& cat)
|
||||
{
|
||||
UNIMPLEMENTED ("asset search");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -90,7 +104,9 @@ namespace asset
|
|||
* remove the given asset <i>together with all its dependants</i> from the internal DB
|
||||
*/
|
||||
void
|
||||
AssetManager::remove (IDA id) /////throw(cinelerra::Invalid, cinelerra::State)
|
||||
AssetManager::remove (IDA id)
|
||||
throw(cinelerra::error::Invalid,
|
||||
cinelerra::error::State)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,15 +70,19 @@ namespace asset
|
|||
|
||||
/** find and return corresponging object */
|
||||
template<class KIND>
|
||||
shared_ptr<KIND> getAsset (const ID<KIND>& id) ;///throw(cinelerra::error::Invalid);
|
||||
shared_ptr<KIND> getAsset (const ID<KIND>& id) throw(cinelerra::error::Invalid);
|
||||
|
||||
|
||||
/** @return true if the given id is registered in the internal asset DB */
|
||||
bool known (IDA id) ;
|
||||
|
||||
/** @return true if the given id is registered with the given Category */
|
||||
bool known (IDA id, const Category& cat) ;
|
||||
|
||||
/**remove the given asset from the internal DB.
|
||||
* <i>together with all its dependants</i> */
|
||||
void remove (IDA id) ;///throw(cinelerra::error::Invalid, cinelerra::error::State);
|
||||
void remove (IDA id) throw(cinelerra::error::Invalid,
|
||||
cinelerra::error::State);
|
||||
|
||||
|
||||
protected:
|
||||
|
|
@ -87,9 +91,9 @@ namespace asset
|
|||
*/
|
||||
template<class KIND>
|
||||
static ID<KIND> reg (KIND& obj, const Asset::Ident& idi)
|
||||
;
|
||||
// throw(cinelerra::error::Invalid);
|
||||
friend Asset::Asset (Asset::Ident& idi);
|
||||
throw(cinelerra::error::Invalid);
|
||||
|
||||
friend Asset::Asset (const Asset::Ident& idi);
|
||||
|
||||
AssetManager ();
|
||||
|
||||
|
|
|
|||
|
|
@ -133,3 +133,21 @@ out: --> Testgroup=TestGroupID
|
|||
out: --> Test-ID =SingleTestID
|
||||
out: --> remaining=SingleTestID spam --eggs
|
||||
END
|
||||
|
||||
|
||||
PLANNED "SanitizedIdentifier_test" SanitizedIdentifier_test <<END
|
||||
END
|
||||
|
||||
|
||||
TEST "Singleton_test" Singleton_test 23 <<END
|
||||
out: testing TargetObj(23) as Singleton(statically allocated)
|
||||
out: ctor TargetObj(23) successfull
|
||||
out: calling a non-static method on the Singleton instance
|
||||
out: .....TargetObj(23): data="***********************", array[23]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,}
|
||||
out: testing TargetObj(24) as Singleton(heap allocated)
|
||||
out: ctor TargetObj(24) successfull
|
||||
out: calling a non-static method on the Singleton instance
|
||||
out: .....TargetObj(24): data="************************", array[24]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,}
|
||||
out: dtor ~TargetObj(23) successfull
|
||||
out: dtor ~TargetObj(24) successfull
|
||||
END
|
||||
|
|
|
|||
|
|
@ -29,9 +29,11 @@
|
|||
#include "nobugcfg.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using boost::lexical_cast;
|
||||
using boost::format;
|
||||
using util::isnil;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
|
|
@ -42,8 +44,6 @@ namespace cinelerra
|
|||
namespace test
|
||||
{
|
||||
|
||||
class ObjFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Target object to be instantiated as Singleton
|
||||
|
|
@ -57,6 +57,9 @@ namespace cinelerra
|
|||
static void setCountParam (uint c) { TargetObj::cnt = c; }
|
||||
protected:
|
||||
TargetObj () : TestTargetObj(cnt) {}
|
||||
|
||||
friend class singleton::Static<TargetObj>;
|
||||
friend class singleton::Heap<TargetObj>;
|
||||
};
|
||||
|
||||
int TargetObj::cnt = 0;
|
||||
|
|
@ -76,42 +79,45 @@ namespace cinelerra
|
|||
*/
|
||||
class Singleton_test : public Test
|
||||
{
|
||||
typedef TargetObj& (*InstanceAccessFunc) (void);
|
||||
typedef boost::function<TargetObj& ()> InstanceAccessFunc;
|
||||
InstanceAccessFunc instance;
|
||||
|
||||
virtual void run(Arg arg)
|
||||
{
|
||||
uint num= isnil(arg)? 1 : lexical_cast<uint>(arg[1]);
|
||||
TargetObj::setCountParam(num);
|
||||
|
||||
testStaticallyAllocatedSingleton ();
|
||||
testHeapAllocatedSingleton ();
|
||||
testStaticallyAllocatedSingleton (num++);
|
||||
testHeapAllocatedSingleton (num++);
|
||||
}
|
||||
|
||||
|
||||
/** @test parametrize the Singleton creation such as to create
|
||||
* the single TargetObj instance as a static variable.
|
||||
*/
|
||||
void testStaticallyAllocatedSingleton ()
|
||||
void testStaticallyAllocatedSingleton (uint num)
|
||||
{
|
||||
instance = &Singleton<TargetObj>::instance;
|
||||
useInstance ();
|
||||
Singleton<TargetObj> single;
|
||||
instance = single;
|
||||
useInstance (num, "statically allocated");
|
||||
}
|
||||
|
||||
/** @test parametrize the Singleton creation such as to create
|
||||
* the single TargetObj instance allocated on the Heap
|
||||
* and deleted automatically at application shutdown.
|
||||
*/
|
||||
void testHeapAllocatedSingleton ()
|
||||
void testHeapAllocatedSingleton (uint num)
|
||||
{
|
||||
instance = &Singleton<TargetObj,singleton::Heap>::instance;
|
||||
useInstance ();
|
||||
Singleton<TargetObj,singleton::Heap> single;
|
||||
instance = single;
|
||||
useInstance (num, "heap allocated");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void useInstance ()
|
||||
void useInstance (uint num, string kind)
|
||||
{
|
||||
cout << format("testing TargetObj(%d) as Singleton(%s)\n") % num % kind;
|
||||
TargetObj::setCountParam(num);
|
||||
TargetObj& t1 = instance();
|
||||
TargetObj& t2 = instance();
|
||||
|
||||
|
|
|
|||
|
|
@ -23,14 +23,16 @@
|
|||
|
||||
#include "common/test/run.hpp"
|
||||
//#include "common/factory.hpp"
|
||||
//#include "common/util.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
#include "proc/assetmanager.hpp"
|
||||
#include "proc/asset/media.hpp"
|
||||
#include "proc/asset/proc.hpp"
|
||||
|
||||
//#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using util::isnil;
|
||||
//using boost::format;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
|
|
@ -58,28 +60,36 @@ namespace asset
|
|||
|
||||
void createMedia()
|
||||
{
|
||||
typedef shared_ptr<asset::Media> PM;
|
||||
/* typedef shared_ptr<asset::Media> 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 mm3 = asset::Media::create("testfile2.mov",Category::VIDEO);
|
||||
Category vid(VIDEO);////////////////////////////////////////////////FIXME
|
||||
PM mm3 = asset::Media::create("testfile2.mov", vid);
|
||||
|
||||
// Assets have been registered and can be retrieved by ID
|
||||
ASSERT (AssetManager::getAsset (mm1.id) == mm1);
|
||||
ASSERT (AssetManager::getAsset (mm2.id) == mm2);
|
||||
ASSERT (AssetManager::getAsset (mm3.id) == mm3);
|
||||
AssetManager& aMang = AssetManager::instance();
|
||||
ASSERT (aMang.getAsset (mm1->getID()) == mm1);
|
||||
ASSERT (aMang.getAsset (mm2->getID()) == mm2);
|
||||
ASSERT (aMang.getAsset (mm3->getID()) == mm3);
|
||||
|
||||
ASSERT (AssetManager::getAsset (mm1.id) != mm2);
|
||||
ASSERT (aMang.getAsset (mm1->getID()) != mm2);
|
||||
|
||||
PAsset aa1 = AssetManager::getAsset (mm1.id);
|
||||
ASSERT (aa1 == mm1);
|
||||
PM mX1 = AssetManager::getAsset (mm1.id, Category::VIDEO);
|
||||
// PAsset aa1 = aMang.getAsset (ID<Asset>(mm1->getID())); // note we get an Asset ref
|
||||
// ASSERT (aa1 == mm1);
|
||||
PM mX1 = aMang.getAsset (mm1->getID()); // ..and now we get a Media ref
|
||||
ASSERT (mX1 == mm1);
|
||||
ASSERT (mX1 == aa1);
|
||||
// ASSERT (mX1 == aa1);
|
||||
|
||||
ASSERT (aMang.known (mm1->getID()));
|
||||
ASSERT (aMang.known (mm2->getID()));
|
||||
ASSERT (aMang.known (mm3->getID()));
|
||||
|
||||
ASSERT ( !aMang.known (mm3->getID(), Category(AUDIO))); // not found within AUDIO-Category
|
||||
try
|
||||
{ // can't be found if the Category is wrong....
|
||||
AssetManager::getAsset (mm1.id, Category::AUDIO);
|
||||
{ // can't be found if specifying wrong Asset kind....
|
||||
// aMang.getAsset (ID<asset::Proc>(mm1->getID()));
|
||||
NOTREACHED;
|
||||
}
|
||||
catch (cinelerra::error::Invalid) { }
|
||||
|
|
@ -93,7 +103,7 @@ namespace asset
|
|||
ASSERT (cat == Category (VIDEO,"bin1"));
|
||||
ASSERT (mm1->ident.category == Category (VIDEO,"bin1"));
|
||||
ASSERT (mm2->ident.category == Category (VIDEO,"bin1"));
|
||||
ASSERT (mm3->ident.category == Category (VIDEO,""));
|
||||
ASSERT (mm3->ident.category == Category (VIDEO ));
|
||||
|
||||
ASSERT (mm1->ident.org == "ichthyo");
|
||||
ASSERT (mm2->ident.org == "ichthyo");
|
||||
|
|
@ -104,9 +114,9 @@ namespace asset
|
|||
ASSERT (mm3->ident.version == 1);
|
||||
|
||||
ASSERT (mm1->getFilename() == "testfile.mov");
|
||||
ASSERT (isnil (mm2.getFilename()));
|
||||
ASSERT (isnil (mm2->getFilename()));
|
||||
ASSERT (mm3->getFilename() == "testfile2.mov");
|
||||
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,34 @@
|
|||
window_sizes 1140 783 270 860 584 120
|
||||
window_sizes 1140 783 270 860 633 71
|
||||
diagrams
|
||||
active classdiagram_ref 130309 // Asset Kinds
|
||||
860 584 100 4 0 0
|
||||
classdiagram_ref 130309 // Asset Kinds
|
||||
860 607 100 4 0 0
|
||||
classdiagram_ref 130437 // Media-Asset Relations
|
||||
688 506 100 4 0 0
|
||||
classdiagram_ref 128133 // Session structure
|
||||
688 506 100 4 60 0
|
||||
classdiagram_ref 128389 // Render Entities
|
||||
688 506 100 4 120 0
|
||||
objectdiagram_ref 128901 // EDL Example2
|
||||
688 506 100 4 132 0
|
||||
objectdiagram_ref 128773 // EDL Example1
|
||||
688 506 100 4 0 0
|
||||
active objectdiagram_ref 129029 // Engine Example1
|
||||
860 633 100 4 28 0
|
||||
end
|
||||
show_stereotypes
|
||||
selected
|
||||
package_ref 129 // cinelerra3
|
||||
selected objectdiagram_ref 129029 // Engine Example1
|
||||
open
|
||||
deploymentview_ref 128517 // gen
|
||||
deploymentview_ref 128645 // gen
|
||||
deploymentview_ref 128773 // gen
|
||||
deploymentview_ref 128901 // gen
|
||||
deploymentview_ref 129029 // gen
|
||||
|
||||
package_ref 130309 // engine
|
||||
package_ref 128005 // design
|
||||
class_ref 136453 // Asset
|
||||
operation_ref 133125 // getID
|
||||
operation_ref 132357 // reg
|
||||
class_ref 136709 // Media
|
||||
class_ref 137349 // Clip
|
||||
classview_ref 128005 // Session
|
||||
classview_ref 128133 // Engine Workings
|
||||
class_ref 138501 // SpecialWish
|
||||
|
||||
package_ref 128389 // RenderEngine
|
||||
usecaseview_ref 128005 // Renderengine Use
|
||||
class_ref 135685 // Logic
|
||||
class_ref 135813 // Config
|
||||
class_ref 135941 // State
|
||||
|
|
|
|||
Loading…
Reference in a new issue