2010-12-03 05:13:52 +01:00
|
|
|
/*
|
2010-12-10 01:27:17 +01:00
|
|
|
ModelPortRegistry - creating and organising and accessing model ports
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-12-03 05:13:52 +01:00
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2010, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-12-03 05:13:52 +01:00
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
2010-12-17 23:28:49 +01:00
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
2010-12-03 05:13:52 +01:00
|
|
|
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.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-12-03 05:13:52 +01:00
|
|
|
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.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-12-03 05:13:52 +01:00
|
|
|
* *****************************************************/
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 23:40:12 +01:00
|
|
|
/** @file model-port-registry.cpp
|
2010-12-03 05:13:52 +01:00
|
|
|
** Implementation details of model port descriptors and references.
|
2010-12-11 23:40:12 +01:00
|
|
|
** Essentially the handling of the ModelPortRegistry datastructure is
|
2010-12-03 05:13:52 +01:00
|
|
|
** kept an opaque implementation detail and confined entirely within
|
2010-12-11 23:40:12 +01:00
|
|
|
** this translation unit. Both the client interface (ModelPort) and
|
|
|
|
|
** the management interface (ModelPortRegistry) are backed by this
|
|
|
|
|
** common translation unit.
|
2010-12-03 05:13:52 +01:00
|
|
|
**
|
|
|
|
|
** @see OutputDesignation
|
|
|
|
|
** @see OutputMapping
|
|
|
|
|
** @see Timeline
|
|
|
|
|
**
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/error.hpp"
|
2010-12-11 01:52:02 +01:00
|
|
|
#include "include/logging.h"
|
|
|
|
|
#include "lib/sync-classlock.hpp"
|
|
|
|
|
#include "proc/mobject/builderfacade.hpp"
|
2010-12-03 05:13:52 +01:00
|
|
|
#include "proc/mobject/model-port.hpp"
|
2010-12-10 01:27:17 +01:00
|
|
|
#include "proc/mobject/builder/model-port-registry.hpp"
|
2010-12-03 05:13:52 +01:00
|
|
|
|
|
|
|
|
namespace mobject {
|
2010-12-10 18:12:56 +01:00
|
|
|
namespace builder {
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
namespace error = lumiera::error;
|
2010-12-10 18:12:56 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef ModelPortRegistry::ModelPortDescriptor const& MPDescriptor;
|
2010-12-11 01:52:02 +01:00
|
|
|
typedef lib::ClassLock<ModelPortRegistry> LockRegistry;
|
2010-12-10 18:12:56 +01:00
|
|
|
|
|
|
|
|
|
2010-12-11 23:40:12 +01:00
|
|
|
/** storage for the link to the global
|
|
|
|
|
Registry instance currently in charge */
|
2010-12-11 01:52:02 +01:00
|
|
|
lib::OptionalRef<ModelPortRegistry> ModelPortRegistry::theGlobalRegistry;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** globally deactivate access to model ports */
|
|
|
|
|
void
|
|
|
|
|
ModelPortRegistry::shutdown ()
|
|
|
|
|
{
|
|
|
|
|
INFO (builder, "disabling ModelPort registry....");
|
|
|
|
|
LockRegistry global_lock;
|
|
|
|
|
theGlobalRegistry.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** switch the implicit link to \em the global ModelPort registry
|
2010-12-11 23:40:12 +01:00
|
|
|
* to point to the given implementation instance. Typically used
|
|
|
|
|
* within the Builder subsystem lifecycle methods, or for
|
|
|
|
|
* temporarily exchanging the registry for unit tests
|
2010-12-11 01:52:02 +01:00
|
|
|
* @return the registry instance previously in use or \c NULL
|
|
|
|
|
*/
|
|
|
|
|
ModelPortRegistry*
|
2010-12-10 18:12:56 +01:00
|
|
|
ModelPortRegistry::setActiveInstance (ModelPortRegistry& newRegistry)
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
ModelPortRegistry *previous = theGlobalRegistry.isValid()?
|
2010-12-11 23:40:12 +01:00
|
|
|
&( theGlobalRegistry()) : 0;
|
|
|
|
|
INFO_IF (!previous, builder, "activating new ModelPort registry.");
|
|
|
|
|
WARN_IF ( previous, builder, "switching ModelPort registry instance.");
|
2010-12-11 01:52:02 +01:00
|
|
|
theGlobalRegistry.link_to (newRegistry);
|
|
|
|
|
return previous;
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** access the globally valid registry instance.
|
|
|
|
|
* @throw error::State if this global registry is
|
|
|
|
|
* already closed or not yet initialised. */
|
2010-12-10 18:12:56 +01:00
|
|
|
ModelPortRegistry&
|
|
|
|
|
ModelPortRegistry::globalInstance()
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
if (theGlobalRegistry.isValid())
|
|
|
|
|
return theGlobalRegistry();
|
|
|
|
|
|
|
|
|
|
throw error::State ("global model port registry is not accessible"
|
|
|
|
|
, LUMIERA_ERROR_BUILDER_LIFECYCLE);
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
2010-12-11 23:40:12 +01:00
|
|
|
|
2010-12-10 18:12:56 +01:00
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** does the <i>transaction currently being built</i>
|
|
|
|
|
* already contain a model port registration for the given ID?
|
|
|
|
|
* @note this does \em not query registration state of the
|
|
|
|
|
* global registry; use #isRegistered for that...*/
|
2010-12-10 18:12:56 +01:00
|
|
|
bool
|
2010-12-11 01:52:02 +01:00
|
|
|
ModelPortRegistry::contains (ID<Pipe> key) const
|
2010-12-10 18:12:56 +01:00
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
return bool(key)
|
|
|
|
|
&& util::contains (transaction_, key);
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @return true if the given pipe-ID actually denotes an
|
2010-12-11 23:40:12 +01:00
|
|
|
* existing, connected and usable model port.
|
|
|
|
|
* @note reflects the state of the publicly visible
|
2010-12-10 18:12:56 +01:00
|
|
|
* model port registry, \em not any model ports
|
2010-12-11 01:52:02 +01:00
|
|
|
* being registered within a pending transaction
|
|
|
|
|
* (ongoing build process). */
|
2010-12-10 18:12:56 +01:00
|
|
|
bool
|
|
|
|
|
ModelPortRegistry::isRegistered (ID<Pipe> key) const
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
return bool(key)
|
|
|
|
|
&& util::contains (currentReg_, key);
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** basic access operation: access the descriptor
|
|
|
|
|
* of a currently valid model port.
|
|
|
|
|
* @note no locking (but #accessDescriptor does lock!)
|
|
|
|
|
* @throw error::Logic if accessing a non registered port
|
|
|
|
|
* @throw error::State if accessing an invalid / disconnected port
|
|
|
|
|
*/
|
2010-12-10 18:12:56 +01:00
|
|
|
MPDescriptor
|
2010-12-11 01:52:02 +01:00
|
|
|
ModelPortRegistry::get (ID<Pipe> key) const
|
2010-12-10 18:12:56 +01:00
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
if (!key)
|
|
|
|
|
throw error::State ("This model port is disconnected or NIL"
|
|
|
|
|
, LUMIERA_ERROR_UNCONNECTED_MODEL_PORT);
|
|
|
|
|
if (!isRegistered (key))
|
|
|
|
|
throw error::Logic ("Model port was never registered, or got unregistered meanwhile."
|
|
|
|
|
,LUMIERA_ERROR_INVALID_MODEL_PORT);
|
|
|
|
|
|
|
|
|
|
MPTable::const_iterator pos = currentReg_.find (key);
|
|
|
|
|
ASSERT (pos != currentReg_.end());
|
|
|
|
|
ASSERT (pos->second.isValid());
|
|
|
|
|
return pos->second;
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** access \em the globally valid model port for the given pipe.
|
|
|
|
|
* This (static) function locks and accesses the global model port registry
|
|
|
|
|
* to fetch the descriptor record. Typically invoked by client code
|
|
|
|
|
* through the ModelPort frontend
|
|
|
|
|
* @throw error::State when registry is down or the model port is disconnected
|
|
|
|
|
* @throw error::Logic when the given key wasn't registered for a model port */
|
2010-12-10 18:12:56 +01:00
|
|
|
MPDescriptor
|
|
|
|
|
ModelPortRegistry::accessDescriptor (ID<Pipe> key)
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
return theGlobalRegistry().get(key);
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/* === Mutations === */
|
|
|
|
|
|
|
|
|
|
/** create and register a new model port entry,
|
|
|
|
|
* within the pending transaction */
|
2010-12-10 18:12:56 +01:00
|
|
|
MPDescriptor
|
2010-12-11 01:52:02 +01:00
|
|
|
ModelPortRegistry::definePort (ID<Pipe> pipe, ID<Struct> element_exposing_this_port)
|
2010-12-10 18:12:56 +01:00
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
if (contains (pipe))
|
|
|
|
|
throw error::Logic ("attempt to register a model port with a pipe-ID, "
|
|
|
|
|
"which has already been used to register a "
|
|
|
|
|
"model port within this transaction (build process)."
|
|
|
|
|
, LUMIERA_ERROR_DUPLICATE_MODEL_PORT);
|
|
|
|
|
return (transaction_[pipe] = ModelPortDescriptor(pipe, element_exposing_this_port));
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** remove a model port entry from the pending transaction */
|
2010-12-10 18:12:56 +01:00
|
|
|
void
|
|
|
|
|
ModelPortRegistry::remove (PID key)
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
transaction_.erase (key);
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** schedule removal of all registry contents.
|
|
|
|
|
* When the currently pending transaction is committed,
|
|
|
|
|
* all registered model ports will be removed */
|
2010-12-10 18:12:56 +01:00
|
|
|
void
|
|
|
|
|
ModelPortRegistry::clear()
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
transaction_.clear();
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** transactional switch for new/modified model ports.
|
|
|
|
|
* Promote the registered model ports from the currently
|
|
|
|
|
* pending transaction to become the globally valid model ports
|
|
|
|
|
* @note automatically starts a new transaction, initialised
|
|
|
|
|
* with the now published mappings.
|
|
|
|
|
*/
|
2010-12-10 18:12:56 +01:00
|
|
|
void
|
|
|
|
|
ModelPortRegistry::commit()
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
MPTable newTransaction(transaction_);
|
|
|
|
|
TRACE (builder, "committing new ModelPort list....");
|
|
|
|
|
swap (currentReg_, transaction_);
|
|
|
|
|
swap (transaction_, newTransaction);
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** discard current transaction.
|
|
|
|
|
* The global port registration thus
|
|
|
|
|
* remains unaltered. */
|
2010-12-10 18:12:56 +01:00
|
|
|
void
|
|
|
|
|
ModelPortRegistry::rollback()
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
LockRegistry global_lock;
|
|
|
|
|
TRACE (builder, "discarding changes to ModelPort list (rollback)....");
|
2010-12-11 23:40:12 +01:00
|
|
|
MPTable newTransaction(currentReg_);
|
2010-12-11 01:52:02 +01:00
|
|
|
swap (transaction_, newTransaction);
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
2010-12-11 23:40:12 +01:00
|
|
|
|
2010-12-10 18:12:56 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
LUMIERA_ERROR_DEFINE (DUPLICATE_MODEL_PORT, "Attempt to define a new model port with an pipe-ID already denoting an existing port");
|
2010-12-11 23:40:12 +01:00
|
|
|
|
|
|
|
|
}// namespace builder
|
2010-12-03 05:13:52 +01:00
|
|
|
|
|
|
|
|
|
2010-12-10 18:12:56 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
LUMIERA_ERROR_DEFINE (INVALID_MODEL_PORT, "Referral to unknown model port");
|
|
|
|
|
LUMIERA_ERROR_DEFINE (UNCONNECTED_MODEL_PORT, "Attempt to operate on an existing but unconnected model port");
|
2010-12-11 23:40:12 +01:00
|
|
|
|
2010-12-10 18:12:56 +01:00
|
|
|
|
|
|
|
|
ModelPort::ModelPort (ID<asset::Pipe> refID)
|
|
|
|
|
: id_(refID)
|
2010-12-03 05:13:52 +01:00
|
|
|
{
|
2010-12-10 18:12:56 +01:00
|
|
|
builder::ModelPortRegistry::accessDescriptor (refID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** check if the global model port registration
|
|
|
|
|
* contains a mapping for the given pipe-ID*/
|
2010-12-10 18:12:56 +01:00
|
|
|
bool
|
|
|
|
|
ModelPort::exists (ID<asset::Pipe> key)
|
|
|
|
|
{
|
|
|
|
|
return builder::ModelPortRegistry::globalInstance().isRegistered (key);
|
|
|
|
|
}
|
2010-12-03 05:13:52 +01:00
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** access the Pipe (ID) of the global model port registered
|
|
|
|
|
* with the ID underlying this model port.
|
|
|
|
|
* @throw error::Logic if no model port is registered for this Pipe-ID
|
|
|
|
|
*/
|
2010-12-10 18:12:56 +01:00
|
|
|
ID<asset::Pipe>
|
|
|
|
|
ModelPort::pipe() const
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
ENSURE (this->id_ == builder::ModelPortRegistry::accessDescriptor(this->id_).id());
|
2010-12-10 18:12:56 +01:00
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
return builder::ModelPortRegistry::accessDescriptor(this->id_).id();
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** access the timeline (or similar structural element) holding
|
|
|
|
|
* a global pipe which corresponds to this model port
|
|
|
|
|
* @throw error::Logic if no model port is registered for this Pipe-ID
|
|
|
|
|
*/
|
2010-12-10 18:12:56 +01:00
|
|
|
ID<asset::Struct>
|
|
|
|
|
ModelPort::holder() const
|
|
|
|
|
{
|
2010-12-11 01:52:02 +01:00
|
|
|
return builder::ModelPortRegistry::accessDescriptor(this->id_).holder();
|
2010-12-10 18:12:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-11 01:52:02 +01:00
|
|
|
/** convenience shortcut to access the stream type
|
|
|
|
|
* associated with the pipe-ID corresponding to this model port.
|
|
|
|
|
* @note no check if this model port actually is valid
|
|
|
|
|
* @throw error::Invalid in case of unknown/unregistered Pipe-ID
|
|
|
|
|
*/
|
2010-12-10 18:12:56 +01:00
|
|
|
StreamType::ID
|
|
|
|
|
ModelPort::streamType() const
|
|
|
|
|
{
|
|
|
|
|
return this->id_.streamType();
|
|
|
|
|
}
|
2010-12-11 23:40:12 +01:00
|
|
|
|
2010-12-10 18:12:56 +01:00
|
|
|
|
2010-12-03 05:13:52 +01:00
|
|
|
|
2010-12-10 18:12:56 +01:00
|
|
|
} // namespace mobject
|