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