Commit 18f27e1d authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[CHANGE] - changed many beginRead/Write line to use read/write tickets now

parent 7ef66541
......@@ -40,8 +40,7 @@
#include "WProperties.h"
WProperties::WProperties( std::string name, std::string description ):
WPropertyBase( name, description ),
m_propAccess( m_properties.getAccessObject() )
WPropertyBase( name, description )
{
m_updateCondition->add( m_properties.getChangeCondition() );
}
......@@ -52,18 +51,22 @@ WProperties::~WProperties()
WProperties::WProperties( const WProperties& from ):
WPropertyBase( from ),
m_properties(),
m_propAccess( m_properties.getAccessObject() )
m_properties()
{
// copy the properties inside
from.m_propAccess->beginRead();
// lock, unlocked if l looses focus
PropertySharedContainerType::ReadTicket l = from.m_properties.getReadTicket();
// we need to make a deep copy here.
for ( PropertyIterator iter = from.m_propAccess->get().begin(); iter != from.m_propAccess->get().end(); ++iter )
for ( PropertyConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter )
{
// clone them to keep dynamic type
addProperty( ( *iter )->clone() );
}
from.m_propAccess->endRead();
// unlock explicitly
l.reset();
// add the change condition of the prop list
m_updateCondition->add( m_properties.getChangeCondition() );
......@@ -104,15 +107,18 @@ bool WProperties::propNamePredicate( boost::shared_ptr< WPropertyBase > prop1, b
void WProperties::addProperty( boost::shared_ptr< WPropertyBase > prop )
{
m_propAccess->beginWrite();
// lock, unlocked if l looses focus
PropertySharedContainerType::WriteTicket l = m_properties.getWriteTicket();
// NOTE: WPropertyBase already prohibits invalid property names -> no check needed here
// check uniqueness:
if ( std::count_if( m_propAccess->get().begin(), m_propAccess->get().end(),
if ( std::count_if( l->get().begin(), l->get().end(),
boost::bind( boost::mem_fn( &WProperties::propNamePredicate ), this, prop, _1 ) ) )
{
m_propAccess->endWrite();
// unlock explicitly
l.reset();
// oh oh, this property name is not unique in this group
if ( !getName().empty() )
{
......@@ -131,24 +137,25 @@ void WProperties::addProperty( boost::shared_ptr< WPropertyBase > prop )
}
// INFORMATION properties are allowed inside PARAMETER groups -> do not set the properties purpose.
m_propAccess->get().push_back( prop );
m_propAccess->endWrite();
l->get().push_back( prop );
}
void WProperties::removeProperty( boost::shared_ptr< WPropertyBase > prop )
{
m_propAccess->beginWrite();
m_propAccess->get().erase( std::remove( m_propAccess->get().begin(), m_propAccess->get().end(), prop ), m_propAccess->get().end() );
m_propAccess->endWrite();
// lock, unlocked if l looses focus
PropertySharedContainerType::WriteTicket l = m_properties.getWriteTicket();
l->get().erase( std::remove( l->get().begin(), l->get().end(), prop ), l->get().end() );
}
boost::shared_ptr< WPropertyBase > WProperties::findProperty( WProperties* props, std::string name )
{
boost::shared_ptr< WPropertyBase > result = boost::shared_ptr< WPropertyBase >();
props->m_propAccess->beginRead();
// lock, unlocked if l looses focus
PropertySharedContainerType::ReadTicket l = props->m_properties.getReadTicket();
// iterate over the items
for ( PropertyContainerType::const_iterator it = props->m_propAccess->get().begin(); it != props->m_propAccess->get().end(); ++it )
for ( PropertyContainerType::const_iterator it = l->get().begin(); it != l->get().end(); ++it )
{
if ( ( *it )->getName() == name )
{
......@@ -157,9 +164,7 @@ boost::shared_ptr< WPropertyBase > WProperties::findProperty( WProperties* props
}
}
// done.
props->m_propAccess->endRead();
// done. Unlocked after l looses focus.
return result;
}
......@@ -216,8 +221,14 @@ boost::shared_ptr< WPropertyBase > WProperties::getProperty( std::string name )
return p;
}
WProperties::PropertySharedContainerType::ReadTicket WProperties::getProperties() const
{
return m_properties.getReadTicket();
}
WProperties::PropertySharedContainerType::WSharedAccess WProperties::getAccessObject()
{
// TODO(ebaum): deprecated. Clean up if not needed anymore.
return m_properties.getAccessObject();
}
......@@ -231,9 +242,9 @@ WPropGroup WProperties::addPropertyGroup( std::string name, std::string descript
void WProperties::clear()
{
m_propAccess->beginWrite();
m_propAccess->get().clear();
m_propAccess->endWrite();
// lock, unlocked if l looses focus
PropertySharedContainerType::WriteTicket l = m_properties.getWriteTicket();
l->get().clear();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
......
......@@ -63,11 +63,6 @@ public:
*/
typedef WSharedSequenceContainer< boost::shared_ptr< WPropertyBase >, PropertyContainerType > PropertySharedContainerType;
/**
* The access type
*/
typedef PropertySharedContainerType::WSharedAccess PropertyAccessType;
/**
* The const iterator type of the container.
*/
......@@ -78,6 +73,11 @@ public:
*/
typedef PropertyContainerType::iterator PropertyIterator;
/**
* The access type
*/
typedef PropertySharedContainerType::WSharedAccess PropertyAccessType;
/**
* Constructor. Creates an empty list of properties.
*
......@@ -149,21 +149,29 @@ public:
boost::shared_ptr< WPropertyBase > getProperty( std::string name );
/**
* Searches the property with a given name. It does not throw any exception. It simply returns NULL if it can't be found.
* Returns a read ticket for read-access to the list of properties.
*
* \param name the name of the property to search
*
* \return the property or NULL if not found.
* \return the read ticket.
*/
boost::shared_ptr< WPropertyBase > findProperty( std::string name );
PropertySharedContainerType::ReadTicket getProperties() const;
/**
* Returns the access object usable to iterate/modify the property list in a thread safe manner.
*
* \deprecated the method should not be used anymore.
* \return the access control object.
*/
PropertySharedContainerType::WSharedAccess getAccessObject();
/**
* Searches the property with a given name. It does not throw any exception. It simply returns NULL if it can't be found.
*
* \param name the name of the property to search
*
* \return the property or NULL if not found.
*/
boost::shared_ptr< WPropertyBase > findProperty( std::string name );
/**
* Removes all properties from the list.
*/
......@@ -926,11 +934,6 @@ private:
*/
PropertySharedContainerType m_properties;
/**
* Access to the above property list.
*/
PropertySharedContainerType::WSharedAccess m_propAccess;
/**
* Compares the names of two properties and returns true if they are equal.
*
......
......@@ -150,6 +150,7 @@ public:
* This method distributes access objects. These objects are able to read/write lock the object and grant access to it, in
* a thread-safe manner.
*
* \deprecated do not use this anymore. Use \ref getReadTicket and \ref getWriteTicket instead
* \return the access object which allows thread safe access to the object.
*/
WSharedAccess getAccessObject();
......@@ -169,7 +170,7 @@ public:
*
* \return the read ticket
*/
ReadTicket getReadTicket();
ReadTicket getReadTicket() const;
/**
* Returns a ticket to get write access to the contained data. After the ticket is freed, the write lock vanishes.
......@@ -178,7 +179,7 @@ public:
*
* \return the ticket
*/
WriteTicket getWriteTicket( bool suppressNotify = false );
WriteTicket getWriteTicket( bool suppressNotify = false ) const;
/**
* This condition fires whenever the encapsulated object changed. This is fired automatically by endWrite().
......@@ -190,14 +191,16 @@ public:
protected:
/**
* The object wrapped by this class.
* The object wrapped by this class. This member is mutable as the \ref getReadTicket and \ref getWriteTicket functions are const but need a
* non-const reference to m_object.
*/
T m_object;
mutable T m_object;
/**
* The lock to ensure thread safe access.
* The lock to ensure thread safe access. This member is mutable as the \ref getReadTicket and \ref getWriteTicket functions are const but need a
* non-const reference to m_lock.
*/
boost::shared_ptr< boost::shared_mutex > m_lock;
mutable boost::shared_ptr< boost::shared_mutex > m_lock;
/**
* This condition set fires whenever the contained object changes. This corresponds to the Observable pattern.
......@@ -224,6 +227,7 @@ WSharedObject< T >::~WSharedObject()
template < typename T >
typename WSharedObject< T >::WSharedAccess WSharedObject< T >::getAccessObject()
{
// TODO(ebaum): deprecated. Clean up if not needed anymore.
return typename WSharedObject< T >::WSharedAccess( new typename WSharedObject< T>::WSharedObjectAccess( m_object, m_lock, m_changeCondition ) );
}
......@@ -295,7 +299,7 @@ boost::shared_ptr< WCondition > WSharedObject< T >::getChangeCondition()
}
template < typename T >
typename WSharedObject< T >::ReadTicket WSharedObject< T >::getReadTicket()
typename WSharedObject< T >::ReadTicket WSharedObject< T >::getReadTicket() const
{
return boost::shared_ptr< WSharedObjectTicketRead< T > >(
new WSharedObjectTicketRead< T >( m_object, m_lock, boost::shared_ptr< WCondition >() )
......@@ -303,7 +307,7 @@ typename WSharedObject< T >::ReadTicket WSharedObject< T >::getReadTicket()
}
template < typename T >
typename WSharedObject< T >::WriteTicket WSharedObject< T >::getWriteTicket( bool suppressNotify )
typename WSharedObject< T >::WriteTicket WSharedObject< T >::getWriteTicket( bool suppressNotify ) const
{
if ( suppressNotify )
{
......
......@@ -49,11 +49,9 @@
WModuleContainer::WModuleContainer( std::string name, std::string description ):
WModule(),
m_moduleAccess( m_modules.getAccessObject() ),
m_name( name ),
m_description( description ),
m_crashIfModuleCrashes( true ),
m_moduleSubscriptionsAccess( m_moduleSubscriptions.getAccessObject() )
m_crashIfModuleCrashes( true )
{
WLogger::getLogger()->addLogMessage( "Constructing module container." , "ModuleContainer (" + getName() + ")", LL_INFO );
// initialize members
......@@ -103,9 +101,9 @@ void WModuleContainer::add( boost::shared_ptr< WModule > module, bool run )
}
// get write lock
m_moduleAccess->beginWrite();
m_moduleAccess->get().insert( module );
m_moduleAccess->endWrite();
ModuleSharedContainerType::WriteTicket wlock = m_modules.getWriteTicket();
wlock->get().insert( module );
wlock.reset();
module->setAssociatedContainer( boost::shared_static_cast< WModuleContainer >( shared_from_this() ) );
WLogger::getLogger()->addLogMessage( "Associated module \"" + module->getName() + "\" with container." , "ModuleContainer (" + getName() + ")",
......@@ -114,19 +112,19 @@ void WModuleContainer::add( boost::shared_ptr< WModule > module, bool run )
// now module->isUsable() is true
// Connect the error handler and all default handlers:
m_moduleSubscriptionsAccess->beginWrite();
ModuleSubscriptionsSharedType::WriteTicket subscriptionsLock = m_moduleSubscriptions.getWriteTicket();
// connect the containers signal handler explicitly
t_ModuleErrorSignalHandlerType func = boost::bind( &WModuleContainer::moduleError, this, _1, _2 );
boost::signals2::connection signalCon = module->subscribeSignal( WM_ERROR, func );
m_moduleSubscriptionsAccess->get().insert( ModuleSubscription( module, signalCon ) );
subscriptionsLock->get().insert( ModuleSubscription( module, signalCon ) );
// connect default ready/error notifiers
boost::shared_lock<boost::shared_mutex> slock = boost::shared_lock<boost::shared_mutex>( m_errorNotifiersLock );
for ( std::list< t_ModuleErrorSignalHandlerType >::iterator iter = m_errorNotifiers.begin(); iter != m_errorNotifiers.end(); ++iter)
{
signalCon = module->subscribeSignal( WM_ERROR, ( *iter ) );
m_moduleSubscriptionsAccess->get().insert( ModuleSubscription( module, signalCon ) );
subscriptionsLock->get().insert( ModuleSubscription( module, signalCon ) );
}
slock = boost::shared_lock<boost::shared_mutex>( m_associatedNotifiersLock );
for ( std::list< t_ModuleGenericSignalHandlerType >::iterator iter = m_associatedNotifiers.begin(); iter != m_associatedNotifiers.end(); ++iter)
......@@ -138,10 +136,12 @@ void WModuleContainer::add( boost::shared_ptr< WModule > module, bool run )
for ( std::list< t_ModuleGenericSignalHandlerType >::iterator iter = m_readyNotifiers.begin(); iter != m_readyNotifiers.end(); ++iter)
{
signalCon = module->subscribeSignal( WM_READY, ( *iter ) );
m_moduleSubscriptionsAccess->get().insert( ModuleSubscription( module, signalCon ) );
subscriptionsLock->get().insert( ModuleSubscription( module, signalCon ) );
}
slock.unlock();
m_moduleSubscriptionsAccess->endWrite();
// free the subscriptions lock
subscriptionsLock.reset();
// add the modules progress to local progress combiner
m_progress->addSubProgress( module->getRootProgressCombiner() );
......@@ -172,23 +172,23 @@ void WModuleContainer::remove( boost::shared_ptr< WModule > module )
m_progress->removeSubProgress( module->getRootProgressCombiner() );
// remove signal subscriptions to this containers default notifiers
m_moduleSubscriptionsAccess->beginWrite();
ModuleSubscriptionsSharedType::WriteTicket subscriptionsLock = m_moduleSubscriptions.getWriteTicket();
// find all subscriptions for this module
std::pair< ModuleSubscriptionsIterator, ModuleSubscriptionsIterator > subscriptions = m_moduleSubscriptionsAccess->get().equal_range( module );
std::pair< ModuleSubscriptionsIterator, ModuleSubscriptionsIterator > subscriptions = subscriptionsLock->get().equal_range( module );
for( ModuleSubscriptionsIterator it = subscriptions.first; it != subscriptions.second; ++it )
{
// disconnect subscription.
( *it ).second.disconnect();
}
// erase them
m_moduleSubscriptionsAccess->get().erase( subscriptions.first, subscriptions.second );
m_moduleSubscriptionsAccess->endWrite();
subscriptionsLock->get().erase( subscriptions.first, subscriptions.second );
subscriptionsLock.reset();
// get write lock
m_moduleAccess->beginWrite();
m_moduleAccess->get().erase( module );
m_moduleAccess->endWrite();
ModuleSharedContainerType::WriteTicket wlock = m_modules.getWriteTicket();
wlock->get().erase( module );
wlock.reset();
module->setAssociatedContainer( boost::shared_ptr< WModuleContainer >() );
......@@ -214,10 +214,11 @@ WModuleContainer::DataModuleListType WModuleContainer::getDataModules()
{
DataModuleListType l;
m_moduleAccess->beginRead();
// lock, unlocked if l looses focus
ModuleSharedContainerType::ReadTicket lock = m_modules.getReadTicket();
// iterate module list
for( ModuleConstIterator iter = m_moduleAccess->get().begin(); iter != m_moduleAccess->get().end(); ++iter )
for( ModuleConstIterator iter = lock->get().begin(); iter != lock->get().end(); ++iter )
{
// is this module a data module?
if ( ( *iter )->getType() == MODULE_DATA )
......@@ -231,9 +232,6 @@ WModuleContainer::DataModuleListType WModuleContainer::getDataModules()
}
}
}
m_moduleAccess->endRead();
// now sort the list using the sorter
return l;
}
......@@ -253,21 +251,22 @@ void WModuleContainer::stop()
WLogger::getLogger()->addLogMessage( "Stopping modules." , "ModuleContainer (" + getName() + ")", LL_INFO );
// read lock
m_moduleAccess->beginRead();
for( ModuleConstIterator listIter = m_moduleAccess->get().begin(); listIter != m_moduleAccess->get().end(); ++listIter )
// lock, unlocked if l looses focus
ModuleSharedContainerType::ReadTicket lock = m_modules.getReadTicket();
for( ModuleConstIterator listIter = lock->get().begin(); listIter != lock->get().end(); ++listIter )
{
WLogger::getLogger()->addLogMessage( "Waiting for module \"" + ( *listIter )->getName() + "\" to finish." ,
"ModuleContainer (" + getName() + ")", LL_INFO );
( *listIter )->wait( true );
( *listIter )->setAssociatedContainer( boost::shared_ptr< WModuleContainer >() ); // remove last refs to this container inside the module
}
m_moduleAccess->endRead();
lock.reset();
// get write lock
m_moduleAccess->beginWrite();
m_moduleAccess->get().clear();
m_moduleAccess->endWrite();
// lock, unlocked if l looses focus
ModuleSharedContainerType::WriteTicket wlock = m_modules.getWriteTicket();
wlock->get().clear();
}
const std::string WModuleContainer::getName() const
......@@ -434,8 +433,8 @@ void WModuleContainer::setCrashIfModuleCrashes( bool crashIfCrashed )
m_crashIfModuleCrashes = crashIfCrashed;
}
WModuleContainer::ModuleSharedContainerType::WSharedAccess WModuleContainer::getAccessObject()
WModuleContainer::ModuleSharedContainerType::ReadTicket WModuleContainer::getModules() const
{
return m_moduleAccess;
return m_modules.getReadTicket();
}
......@@ -218,6 +218,13 @@ public:
*/
void finishedPendingThread( boost::shared_ptr< WThreadedRunner > thread );
/**
* Sets a flag denoting whether the container (which also is a module) should be marked as "crashed" if a nested module crashes.
*
* \param crashIfCrashed true if it also should crash.
*/
void setCrashIfModuleCrashes( bool crashIfCrashed = true );
/**
* Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it
* should never be initialized or modified in some other way. A simple new instance is required.
......@@ -239,18 +246,12 @@ public:
DataModuleListType getDataModules();
/**
* Sets a flag denoting whether the container (which also is a module) should be marked as "crashed" if a nested module crashes.
*
* \param crashIfCrashed true if it also should crash.
*/
void setCrashIfModuleCrashes( bool crashIfCrashed = true );
/**
* Returns the access object usable to iterate the module list in a thread safe manner. DO not modify the list.
* Method returns a read ticket allowing read-access to the list of modules.
* \note If done, ensure the ticket gets destroyed.
*
* \return the access control object.
* \return the read ticket.
*/
ModuleSharedContainerType::WSharedAccess getAccessObject();
ModuleSharedContainerType::ReadTicket getModules() const;
protected:
......@@ -265,11 +266,6 @@ protected:
*/
ModuleSharedContainerType m_modules;
/**
* Access to the above module set.
*/
ModuleSharedContainerType::WSharedAccess m_moduleAccess;
/**
* Name of the module.
*/
......@@ -365,11 +361,6 @@ private:
*/
typedef WSharedObject< ModuleSubscriptionsType > ModuleSubscriptionsSharedType;
/**
* The access type
*/
typedef ModuleSubscriptionsSharedType::WSharedAccess ModuleSubscriptionsAccessType;
/**
* The const iterator type of the container.
*/
......@@ -384,11 +375,6 @@ private:
* The module's signal subscriptions.
*/
ModuleSubscriptionsSharedType m_moduleSubscriptions;
/**
* Access to the above module subscriptions map.
*/
ModuleSubscriptionsAccessType m_moduleSubscriptionsAccess;
};
#endif // WMODULECONTAINER_H
......
......@@ -328,6 +328,7 @@ std::vector< boost::shared_ptr< WApplyPrototypeCombiner > > WModuleFactory::getC
const WModuleFactory::PrototypeSharedContainerType::WSharedAccess WModuleFactory::getAvailablePrototypes() const
{
// TODO(ebaum): deprecated. Clean up if not needed anymore.
return m_prototypeAccess;
}
......@@ -166,6 +166,7 @@ public:
/**
* Get access to all the prototypes.
*
* \deprecated do not use this anymore. Use \ref getPrototypes instead.
* \return the access object to thread safe iterate.
*/
const PrototypeSharedContainerType::WSharedAccess getAvailablePrototypes() const;
......
......@@ -302,26 +302,16 @@ void WModuleProjectFileCombiner::done()
apply();
}
/**
* Recursively prints the properties and nested properties.
*
* \param output the output stream to print to
* \param props the properties to recursively print
* \param indent the indentation level
* \param prefix the prefix (name prefix of property)
* \param module the module ID to use
*/
void printProperties( std::ostream& output, boost::shared_ptr< WProperties > props, std::string indent, std::string prefix, // NOLINT
unsigned int module )
void WModuleProjectFileCombiner::printProperties( std::ostream& output, boost::shared_ptr< WProperties > props, std::string indent, //NOLINT
std::string prefix, unsigned int module )
{
// get access object
WProperties::PropertyAccessType a = props->getAccessObject();
a->beginWrite(); // use write lock here to avoid manipulation of properties list during file write
// lock, unlocked if l looses focus
WProperties::PropertySharedContainerType::ReadTicket l = props->getProperties();
output << indent << "// Property Group: " << props->getName() << std::endl;
// iterate of them and print them to output
for ( WProperties::PropertyConstIterator iter = a->get().begin(); iter != a->get().end(); ++iter )
for ( WProperties::PropertyConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter )
{
// information properties do not get written
if ( ( *iter )->getPurpose () == PV_PURPOSE_INFORMATION )
......@@ -348,20 +338,15 @@ void printProperties( std::ostream& output, boost::shared_ptr< WProperties > pro
}
output << indent << "// Property Group END: " << props->getName() << std::endl;
a->endWrite();
}
void WModuleProjectFileCombiner::save( std::ostream& output ) // NOLINT
{
// grab access object of root container
WModuleContainer::ModuleAccessType container = WKernel::getRunningKernel()->getRootContainer()->getAccessObject();
WModuleContainer::ModuleSharedContainerType::ReadTicket container = WKernel::getRunningKernel()->getRootContainer()->getModules();
std::map< boost::shared_ptr< WModule >, unsigned int > moduleToIDMap;
// get a write access to avoid others to modify the container while project file is written.
container->beginWrite();
output << "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
"// Modules and Properties" << std::endl <<
"//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
......@@ -407,7 +392,7 @@ void WModuleProjectFileCombiner::save( std::ostream& output ) // NOLINT
for ( WModule::OutputConnectorList::const_iterator citer = outs.begin(); citer != outs.end(); ++citer )
{
// iterate over all connections:
// TODO(ebaum): iterating over a protected member variable? Thats ugly. This should be adopted to WSharedAccess
// TODO(ebaum): iterating over a protected member variable? Thats ugly. This should be adopted to WSharedObject
boost::unique_lock<boost::shared_mutex> lock( ( *citer )->m_connectionListLock );
for ( std::set<boost::shared_ptr<WModuleConnector> >::const_iterator iciter = ( *citer )->m_connected.begin();
iciter != ( *citer )->m_connected.end(); ++iciter )
......@@ -420,8 +405,5 @@ void WModuleProjectFileCombiner::save( std::ostream& output ) // NOLINT
lock.unlock();
}
}
// thats it
container->endWrite();
}
......@@ -139,6 +139,18 @@ protected:
*/
std::list< PropertyValue > m_properties;
/**
* Recursively prints the properties and nested properties.
*
* \param output the output stream to print to
* \param props the properties to recursively print
* \param indent the indentation level
* \param prefix the prefix (name prefix of property)
* \param module the module ID to use
*/
void printProperties( std::ostream& output, boost::shared_ptr< WProperties > props, std::string indent, //NOLINT ( non-const ref )
std::string prefix, unsigned int module );
private:
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment