Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion Modules/Core/Common/include/itkMetaDataDictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <vector>
#include <map>
#include <string>
#include <memory>

namespace itk
{
Expand All @@ -35,6 +36,15 @@ namespace itk
* classes, is designed to provide a mechanism for storing a collection of
* arbitrary data types. The main motivation for such a collection is to
* associate arbitrary data elements with itk DataObjects.
*
* The MetaDataDictionary implements shallow copying with copy on
* write behavior. When a copy of this class is created, the new copy
* will be shared with the old copy via C++11 shared pointers. When a
* non-constant operation is done, if the dictionary is not unique to
* this object, then a deep copy is performed. This make is very cheap
* to create multiple copies of the same dictionary if they are never
* modified.
*
* \ingroup ITKCommon
*/
class ITKCommon_EXPORT MetaDataDictionary
Expand All @@ -57,8 +67,10 @@ class ITKCommon_EXPORT MetaDataDictionary
MetaDataDictionary();
// Copy Constructor
MetaDataDictionary(const MetaDataDictionary &);
MetaDataDictionary(MetaDataDictionary &&);
// operator =
MetaDataDictionary & operator=(const MetaDataDictionary &);
MetaDataDictionary & operator=(MetaDataDictionary &&);

// Destructor
virtual ~MetaDataDictionary();
Expand Down Expand Up @@ -112,8 +124,18 @@ class ITKCommon_EXPORT MetaDataDictionary
/** remove all MetaObjects from dictionary */
void Clear();

void Swap( MetaDataDictionary &other );

private:
MetaDataDictionaryMapType *m_Dictionary;
bool MakeUnique(void);

std::shared_ptr<MetaDataDictionaryMapType> m_Dictionary;
};

inline void swap(MetaDataDictionary &a, MetaDataDictionary &b )
{
a.Swap(b);
}

}
#endif // itkMetaDataDictionary_h
1 change: 1 addition & 0 deletions Modules/Core/Common/include/itkObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class ITKCommon_EXPORT Object:public LightObject
* Set the MetaDataDictionary
*/
void SetMetaDataDictionary(const MetaDataDictionary & rhs);
void SetMetaDataDictionary( MetaDataDictionary && rrhs);

/**
* A facility to help application programmers set a
Expand Down
59 changes: 53 additions & 6 deletions Modules/Core/Common/src/itkMetaDataDictionary.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,46 @@ namespace itk
{
MetaDataDictionary
::MetaDataDictionary()
: m_Dictionary( std::make_shared<MetaDataDictionaryMapType>() )
{
m_Dictionary = new MetaDataDictionaryMapType;
}

MetaDataDictionary
::~MetaDataDictionary()
{
delete m_Dictionary;
m_Dictionary = nullptr;
}

MetaDataDictionary
::MetaDataDictionary(const MetaDataDictionary & old)
// perform shallow copy, so m_Dictionary is shared
: m_Dictionary( old.m_Dictionary )
{
m_Dictionary = new MetaDataDictionaryMapType;
*m_Dictionary = *( old.m_Dictionary );
}

MetaDataDictionary
::MetaDataDictionary( MetaDataDictionary && rr)
: m_Dictionary( std::move(rr.m_Dictionary) )
{
Copy link
Copy Markdown
Contributor

@N-Dekker N-Dekker Nov 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still looks like an explicitly defaulted move-constructor (= default) would just do the right thing, OK?

}


MetaDataDictionary & MetaDataDictionary
::operator=(const MetaDataDictionary & old)
{
if(this != &old)
{
*m_Dictionary = *( old.m_Dictionary );
// perform shallow copy, so m_Dictionary is shared
m_Dictionary = old.m_Dictionary;
}
return *this;
}

MetaDataDictionary & MetaDataDictionary
::operator=(MetaDataDictionary && rr)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't an explicitly defaulted move-assignment operator (= default) just do the right thing?

{
if(this != &rr)
{
m_Dictionary = std::move( rr.m_Dictionary );
}
return *this;
}
Expand All @@ -53,19 +69,22 @@ void
MetaDataDictionary
::Print(std::ostream & os) const
{
os << "Dictionary use_count: " << m_Dictionary.use_count() << std::endl;
for ( MetaDataDictionaryMapType::const_iterator it = m_Dictionary->begin();
it != m_Dictionary->end();
++it )
{
os << ( *it ).first << " ";
( *it ).second->Print(os);
}

}

MetaDataObjectBase::Pointer &
MetaDataDictionary
::operator[](const std::string & key)
{
MakeUnique();
return ( *m_Dictionary )[key];
}

Expand Down Expand Up @@ -96,6 +115,7 @@ void
MetaDataDictionary
::Set(const std::string & key, MetaDataObjectBase * object)
{
MakeUnique();
(*m_Dictionary)[key] = object;
}

Expand Down Expand Up @@ -126,6 +146,7 @@ MetaDataDictionary::Iterator
MetaDataDictionary
::Begin()
{
MakeUnique();
return m_Dictionary->begin();
}

Expand All @@ -140,6 +161,7 @@ MetaDataDictionary::Iterator
MetaDataDictionary
::End()
{
MakeUnique();
return m_Dictionary->end();
}

Expand All @@ -154,6 +176,7 @@ MetaDataDictionary::Iterator
MetaDataDictionary
::Find(const std::string & key)
{
MakeUnique();
return m_Dictionary->find(key);
}

Expand All @@ -168,9 +191,32 @@ void
MetaDataDictionary
::Clear()
{
MakeUnique();
this->m_Dictionary->clear();
}

void
MetaDataDictionary
::Swap( MetaDataDictionary &other )
{
using std::swap;
swap(m_Dictionary, other.m_Dictionary);
}


bool
MetaDataDictionary
::MakeUnique()
{
if (m_Dictionary.use_count() > 1)
{
// copy the shared dictionary.
m_Dictionary = std::make_shared<MetaDataDictionaryMapType>(*m_Dictionary);
return true;
}
return false;
}

bool
MetaDataDictionary
::Erase( const std::string& key )
Expand All @@ -180,6 +226,7 @@ ::Erase( const std::string& key )

if( it != end )
{
MakeUnique();
m_Dictionary->erase( it );
return true;
}
Expand Down
16 changes: 15 additions & 1 deletion Modules/Core/Common/src/itkObject.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,22 @@ ::SetMetaDataDictionary(const MetaDataDictionary & rhs)
{
if ( m_MetaDataDictionary == nullptr )
{
m_MetaDataDictionary = new MetaDataDictionary;
m_MetaDataDictionary = new MetaDataDictionary(rhs);
return;
}
*m_MetaDataDictionary = rhs;
}

void
Object
::SetMetaDataDictionary( MetaDataDictionary && rrhs)
{
if ( m_MetaDataDictionary == nullptr )
{
m_MetaDataDictionary = new MetaDataDictionary(std::move(rrhs));
return;
}
*m_MetaDataDictionary = std::move(rrhs);
}

} // end namespace itk