Locked container

This topic is 3672 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Does anyone have a nice solution to detecting when an STL container is being modified while it's being iterated over? In the following code, I would like to assert if listpObjects gets modified as a side effect of pObject->update(). I don't want to put an if inside the loop either.
typedef std::list< Object* >	ObjectPtrList;
typedef ObjectPtrList::iterator	ObjectPtrListIter;
//==================================================================================================
//==================================================================================================
void UpdateAll( ObjectPtrList& listpObjects )
{
for( ObjectPtrListIter iter = listpObjects.end(); iter != listpObjects.end(); ++iter )
{
Object*	pObject = *iter;
pObject->update();
}
}


I wrote a very simple wrapper for std::list that acquires the list but it's not all that hot, plus I will have to write it for other containers.
//==================================================================================================
//==================================================================================================
template < typename TYPE >
class STL_LockList
{
private:
//----------------------------------------------------------------------------------------------
typedef	std::list< TYPE >	ListType;

//----------------------------------------------------------------------------------------------
bool			m_bLocked;
ListType		m_list;

public:
//----------------------------------------------------------------------------------------------
STL_LockList() : m_bLocked( false )
{

}
~STL_LockList()
{
T_Assert( m_bLocked == false );
}

//----------------------------------------------------------------------------------------------
ListType&		lock()
{
T_Assert( m_bLocked == false );
m_bLocked = true;
return m_list;
}
//----------------------------------------------------------------------------------------------
void			unlock()
{
T_Assert( m_bLocked == true );
m_bLocked = false;
}

//----------------------------------------------------------------------------------------------
void			push_front( const TYPE& item )
{
T_Assert( m_bLocked == false );
m_list.push_front( item );
}
//----------------------------------------------------------------------------------------------
void			push_back( const TYPE& item )
{
T_Assert( m_bLocked == false );
m_list.push_back( item );
}
//----------------------------------------------------------------------------------------------
void			remove( const TYPE& item )
{
T_Assert( m_bLocked == false );
m_list.remove( item );
}
};



Share on other sites
I'm assuming this is for concurrency work.

the STL is not threadsafe. you should look into using a thread-safe library for those containers that need to support concurrent access; and use the STL for those that you know will only be accessed in a single thread.

intel released a multi-thread safe library with some container primitives that are simple to use:
http://www.intel.com/cd/software/products/asmo-na/eng/294797.htm

-me

Share on other sites
Quote:
 Original post by PalidineI'm assuming this is for concurrency work.

No it's not. It's just to protect against bugs, hence the assert. These lists are for stuff like Physics::UpdateAll(), AI::UpdateAll() etc. It can be a hard bug to trace down if somehow one of these lists is modified, say an object being destroyed, while I am iterating over it.

Share on other sites
Quote:
Original post by Tesshu
Quote:
 Original post by PalidineI'm assuming this is for concurrency work.

No it's not. It's just to protect against bugs, hence the assert. These lists are for stuff like Physics::UpdateAll(), AI::UpdateAll() etc. It can be a hard bug to trace down if somehow one of these lists is modified, say an object being destroyed, while I am iterating over it.

No, there is no reliable way.

Use containers where iterators aren't invalidated, or structure your code in such a way that it cannot happen. std::list is one way, although performance penalty is likely unacceptable.

This is a considerable problem with events and callbacks, where callback may modify subscriptions while the dispatcher is iterating through the same collection.

There's are solutions, but neither is the silver bullet.

Share on other sites
Quote:
 Original post by AntheusThere's are solutions, but neither is the silver bullet.

Thank you for the link, it's a very good read. I actually had the method of using a vector and instead of removing the element, I assigned NULL to it. Thing is that you have to put an if NULL in the loop, which makes me feel dirty. I decided to make it policy not not allow updating the list at all while iterating over it.

I was just hoping that there would be version of STL that had this kind of support :(