00001 // -*- C++ -*- 00002 // 00003 // Package: Core 00004 // Class : FWModelChangeManager 00005 // 00006 // Implementation: 00007 // <Notes on implementation> 00008 // 00009 // Original Author: Chris Jones 00010 // Created: Thu Jan 17 19:13:46 EST 2008 00011 // $Id: FWModelChangeManager.cc,v 1.16 2012/09/21 09:26:26 eulisse Exp $ 00012 // 00013 00014 // system include files 00015 #include <cassert> 00016 #include <boost/shared_ptr.hpp> 00017 #include <exception> 00018 00019 // user include files 00020 #include "Fireworks/Core/interface/FWModelChangeManager.h" 00021 #include "Fireworks/Core/interface/FWEventItem.h" 00022 #include "Fireworks/Core/interface/fwLog.h" 00023 #include "FWCore/Utilities/interface/Exception.h" 00024 00025 00026 // 00027 // constants, enums and typedefs 00028 // 00029 00030 // 00031 // static data member definitions 00032 // 00033 00034 // 00035 // constructors and destructor 00036 // 00037 FWModelChangeManager::FWModelChangeManager() : 00038 m_depth(0) 00039 { 00040 } 00041 00042 // FWModelChangeManager::FWModelChangeManager(const FWModelChangeManager& rhs) 00043 // { 00044 // // do actual copying here; 00045 // } 00046 00047 FWModelChangeManager::~FWModelChangeManager() 00048 { 00049 } 00050 00051 // 00052 // assignment operators 00053 // 00054 // const FWModelChangeManager& FWModelChangeManager::operator=(const FWModelChangeManager& rhs) 00055 // { 00056 // //An exception safe implementation is 00057 // FWModelChangeManager temp(rhs); 00058 // swap(rhs); 00059 // 00060 // return *this; 00061 // } 00062 00063 // 00064 // member functions 00065 // 00066 void 00067 FWModelChangeManager::beginChanges() 00068 { 00069 ++m_depth; 00070 } 00071 00072 void 00073 FWModelChangeManager::changed(const FWModelId& iID) 00074 { 00075 FWChangeSentry sentry(*this); 00076 assert(iID.item()); 00077 assert(iID.item()->id() < m_changes.size()); 00078 m_changes[iID.item()->id()].insert(iID); 00079 } 00080 00081 void 00082 FWModelChangeManager::changed(const FWEventItem* iItem) 00083 { 00084 FWChangeSentry sentry(*this); 00085 assert(0!= iItem); 00086 m_itemChanges.insert(iItem); 00087 //remove any pending changes on models owned by this item 00088 assert(iItem->id() <m_changes.size()); 00089 m_changes[iItem->id()].clear(); 00090 } 00091 00092 static 00093 void sendChangeSignalsAreDone(FWModelChangeManager* iCM) 00094 { 00095 //since this can cause other changes, we might as well aggregate them 00096 FWChangeSentry sentry(*iCM); 00097 iCM->changeSignalsAreDone_(); 00098 } 00099 00100 void 00101 FWModelChangeManager::endChanges() 00102 { 00103 assert(m_depth !=0); 00104 //makes sure that 'changeSignalsAreDone is called if changeSignalsAreComing_ is sent 00105 bool guard(false); 00106 if(0 == --m_depth) { 00107 unsigned int index = 0; 00108 for(std::set<const FWEventItem*>::iterator itChanges = m_itemChanges.begin(); 00109 itChanges != m_itemChanges.end(); 00110 ++itChanges,++index) { 00111 if( !guard ) { 00112 // boost::shared_ptr<FWModelChangeManager> done(this, &sendChangeSignalsAreDone); 00113 guard = true; 00114 changeSignalsAreComing_(); 00115 } 00116 FWItemChangeSignal& signal = m_itemChangeSignals[(*itChanges)->id()]; 00117 //loop over the slots ourself so we can control the behavior in case of a failure 00118 FWItemChangeSignal::slot_list_type slots = signal.slots(); 00119 for(FWItemChangeSignal::slot_list_type::iterator itSlot=slots.begin(), itEnd = slots.end(); 00120 itSlot != itEnd; 00121 ++itSlot) { 00122 try { 00123 (*itSlot)(*itChanges); 00124 } catch(const cms::Exception& iE) { 00125 fwLog(fwlog::kError) <<(*itChanges)->name()<<" had the failure in process FWItemChanged signals\n"<<iE.what()<<std::endl; 00126 } catch(const std::bad_alloc& iE) { 00127 std::cerr <<"Ran out of memory while processing "<<(*itChanges)->name()<<std::endl; 00128 exit(1); 00129 } catch(const std::exception& iE) { 00130 fwLog(fwlog::kError) <<(*itChanges)->name()<<" had the failure in process FWItemChanged signals (2) \n"<<iE.what()<<std::endl; 00131 } 00132 } 00133 } 00134 m_itemChanges.clear(); 00135 00136 for (size_t ci = 0, ce = m_changes.size(), si = 0; ci != ce; ++ci, ++si) 00137 { 00138 FWModelIds &changes = m_changes[ci]; 00139 FWModelChangeSignal &signal = m_changeSignals[si]; 00140 00141 if (not changes.empty()) 00142 { 00143 if (!guard) 00144 { 00145 // boost::shared_ptr<FWModelChangeManager> done(this, &sendChangeSignalsAreDone); 00146 guard = true; 00147 changeSignalsAreComing_(); 00148 } 00149 //loop over the slots ourself so we can control the behavior in case of a failure 00150 FWModelChangeSignal::slot_list_type slots = signal.slots(); 00151 for(FWModelChangeSignal::slot_list_type::iterator itSlot = slots.begin(), itEnd = slots.end(); 00152 itSlot != itEnd; 00153 ++itSlot) 00154 { 00155 try 00156 { 00157 (*itSlot)(changes); 00158 } 00159 catch(const cms::Exception& iE) 00160 { 00161 fwLog(fwlog::kError) << changes.begin()->item()->name()<<" had the failure in process FWModelChangeSignals\n" 00162 << iE.what() << "\n"; 00163 } 00164 catch(const std::bad_alloc& iE) 00165 { 00166 // GE: if we run out of memory why do we assume that we will be able to print? 00167 fwLog(fwlog::kError) << "Ran out of memory while processing " << changes.begin()->item()->name() << "\n"; 00168 exit(1); 00169 } 00170 catch(const std::exception& iE) 00171 { 00172 fwLog(fwlog::kError) << changes.begin()->item()->name() 00173 << " had the failure in process FWModelChangeSignals (2)\n" 00174 << iE.what() << "\n"; 00175 } 00176 } 00177 changes.clear(); 00178 } 00179 } 00180 } 00181 if (guard) sendChangeSignalsAreDone(this); 00182 } 00183 00184 void 00185 FWModelChangeManager::newItemSlot(FWEventItem* iItem) 00186 { 00187 assert(0!=iItem); 00188 assert(iItem->id() == m_changes.size()); 00189 assert(iItem->id() == m_changeSignals.size()); 00190 m_changes.push_back(FWModelIds()); 00191 m_changeSignals.push_back(FWModelChangeSignal()); 00192 m_itemChangeSignals.push_back(FWItemChangeSignal()); 00193 //propagate our signal to the item 00194 m_changeSignals.back().connect(iItem->changed_); 00195 m_itemChangeSignals.back().connect(iItem->itemChanged_); 00196 } 00197 00201 void 00202 FWModelChangeManager::itemsGoingToBeClearedSlot(void) 00203 { 00204 m_changes.clear(); 00205 m_changeSignals.clear(); 00206 00207 m_itemChangeSignals.clear(); 00208 m_itemChanges.clear(); 00209 } 00210 00211 // 00212 // const member functions 00213 // 00214 00215 // 00216 // static member functions 00217 //