fw4spl
fwID.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwTools/fwID.hpp"
8 
9 #include "fwTools/Failed.hpp"
10 #include "fwTools/Object.hpp"
11 
12 #include <fwCore/Demangler.hpp>
13 
14 #include <boost/lexical_cast.hpp>
15 
16 namespace fwTools
17 {
18 
19 fwID::CategorizedCounter fwID::m_CategorizedCounter;
20 fwID::Dictionary fwID::m_dictionary;
21 ::fwCore::mt::ReadWriteMutex fwID::s_dictionaryMutex;
22 ::fwCore::mt::Mutex fwID::s_mutexCounter;
23 
24 //-----------------------------------------------------------------------------
25 
26 fwID::~fwID()
27 {
28  resetID();
29 }
30 
31 //-----------------------------------------------------------------------------
32 
33 bool fwID::exist( IDType _id)
34 {
35  ::fwCore::mt::ReadLock lock(s_dictionaryMutex);
36  return fwID::isIdFound(_id);
37 }
38 
39 //-----------------------------------------------------------------------------
40 
41 bool fwID::isIdFound( IDType _id)
42 {
43  return m_dictionary.find( _id ) != m_dictionary.end();
44 }
45 
46 //-----------------------------------------------------------------------------
47 
48 bool fwID::hasID( ) const
49 {
50  ::fwCore::mt::ReadLock lock(m_idMutex);
51  return !m_id.empty();
52 }
53 
54 //-----------------------------------------------------------------------------
55 
56 void fwID::setID( IDType newID )
57 {
58  ::fwCore::mt::WriteLock lock(m_idMutex);
59  this->addIDInDictionary(newID);
60 }
61 
62 //-----------------------------------------------------------------------------
63 
64 void fwID::addIDInDictionary( IDType newID )
65 {
66  OSLM_FATAL_IF("Try to set an existing fwID = " << newID, isIdFound(newID));
67 
68  ::fwCore::mt::WriteLock lock(s_dictionaryMutex);
69  fwID::removeIDfromDictionary(m_id);
70  // note we use a static cast for a down cast because we do not use the classical polyvi morphic approach
71  //m_dictionary[ newID ] = (static_cast< Object *>(this))->getSptr();
72  m_dictionary[ newID ] = ((Object*)(this))->getSptr();
73  m_id = newID;
74 }
75 
76 //-----------------------------------------------------------------------------
77 
78 fwID::IDType fwID::getID( Policy policy) const
79 {
80  ::fwCore::mt::ReadToWriteLock lock(m_idMutex);
81  if ( m_id.empty() ) // no id set
82  {
83  if ( policy == GENERATE )
84  {
85  IDType newID = generate();
86  ::fwCore::mt::UpgradeToWriteLock writeLock(lock);
87  const_cast<fwID*>(this)->addIDInDictionary(newID);
88  }
89  else if ( policy == EMPTY )
90  { /* nothing to do*/
91  }
92  else if ( policy == MUST_EXIST )
93  {
94  throw fwTools::Failed( "fwID::getID() no id set" );
95  }
96  }
97  return m_id;
98 }
99 
100 //-----------------------------------------------------------------------------
101 
102 fwID::IDType fwID::generate() const
103 {
104  IDType newID;
105  std::string prefix = this->getClassname();
106  do
107  {
108  ::fwCore::mt::ScopedLock lock(s_mutexCounter);
109  newID = prefix + "-" + boost::lexical_cast<std::string>( m_CategorizedCounter[prefix]++ );
110  }
111  while ( exist(newID ) );
112  return newID;
113 }
114 
115 //-----------------------------------------------------------------------------
116 
117 ::fwTools::Object::sptr fwID::getObject( fwID::IDType requestID )
118 {
119  ::fwCore::mt::ReadLock lock(s_dictionaryMutex);
120  Dictionary::iterator it = m_dictionary.find(requestID);
121  if ( it != m_dictionary.end() )
122  {
123  SLM_ASSERT( "expired object in fwID::Dictionary for id=" + requestID, !it->second.expired() );
124  return it->second.lock();
125  }
126  else
127  {
128  return ::fwTools::Object::sptr();
129  }
130 }
131 
132 //-----------------------------------------------------------------------------
133 
135 {
136  ::fwCore::mt::WriteLock lock(m_idMutex);
137  ::fwCore::mt::WriteLock dicoLock(s_dictionaryMutex);
138  fwID::removeIDfromDictionary(m_id);
139  m_id.clear();
140 }
141 
142 //-----------------------------------------------------------------------------
143 
144 void fwID::removeIDfromDictionary(IDType _id )
145 {
146  if ( !_id.empty() )
147  {
148  m_dictionary.erase(_id);
149  }
150 }
151 
152 //-----------------------------------------------------------------------------
153 
154 }
::boost::upgrade_lock< ReadWriteMutex > ReadToWriteLock
Defines an upgradable lock type for read/write mutex.
::boost::upgrade_to_unique_lock< ReadWriteMutex > UpgradeToWriteLock
Defines a write lock upgraded from ReadToWriteLock.
The namespace fwTools contains several tools like UUID, factory, dispatche, stringizer, macros, helper.
Define Base class for FW4SPL objects and services.
FWTOOLS_API void resetID()
Release the id for the object.
Definition: fwID.cpp:134
virtual const std::string & getClassname() const
return full object&#39;s classname with its namespace, i.e. fwCore::BaseObject
Definition: fwID.hpp:30
::boost::shared_mutex ReadWriteMutex
Defines a single writer, multiple readers mutex.
static FWTOOLS_API bool exist(IDType _id)
Definition: fwID.cpp:33
Defines ID for fwTools::Object. It is used to associate ID with object.
Definition: fwID.hpp:26
return an empty id if no one set
Definition: fwID.hpp:36
::boost::unique_lock< ReadWriteMutex > WriteLock
Defines a lock of write type for read/write mutex.
FWTOOLS_API IDType getID(Policy policy=GENERATE) const
Returns the id of the object. If it is not set and the policy value is.
Definition: fwID.cpp:78
virtual FWTOOLS_API void setID(IDType newID)
Set a newID for the object, (newID must not exist in fwID), the oldest one is released.
Definition: fwID.cpp:56
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
FWTOOLS_API bool hasID() const
Return true if the object has an id set.
Definition: fwID.cpp:48
::boost::shared_lock< ReadWriteMutex > ReadLock
Defines a lock of read type for read/write mutex.
Implements a failed exception class.
#define OSLM_FATAL_IF(message, cond)
Definition: spyLog.hpp:289
generate a new id if necessary
Definition: fwID.hpp:37
throw an exception if object has not id.
Definition: fwID.hpp:38
static FWTOOLS_API std::shared_ptr< ::fwTools::Object > getObject(IDType requestID)
Retrieve the object attached to the given id. Return a null sptr if no correspondence exist...
Definition: fwID.cpp:117