OpenWalnut
1.2.5
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <sstream> 00026 #include <string> 00027 #include <set> 00028 00029 #include <boost/utility.hpp> 00030 00031 #include "WProgressCombiner.h" 00032 00033 WProgressCombiner::WProgressCombiner( std::string name ): 00034 WProgress( name, 1 ), 00035 m_name( name ), 00036 m_progress( 0.0 ) 00037 { 00038 // initialize members 00039 m_pending = false; 00040 } 00041 00042 WProgressCombiner::~WProgressCombiner() 00043 { 00044 // cleanup 00045 } 00046 00047 void WProgressCombiner::update() 00048 { 00049 // This updates the internal state. Here, all states from child progress' get combined. 00050 00051 // get read lock 00052 boost::shared_lock< boost::shared_mutex > rlock; 00053 rlock = boost::shared_lock< boost::shared_mutex >( m_updateLock ); 00054 00055 m_pending = false; 00056 m_determined = true; 00057 m_progress = 0.0; 00058 unsigned int numPendingChildren = 0; 00059 00060 // as the children define this progress' state -> iterate children 00061 for( std::set< boost::shared_ptr< WProgress > >::iterator i = m_children.begin(); i != m_children.end(); ++i ) 00062 { 00063 // enforce child to update 00064 ( *i )->update(); 00065 00066 // update own state basing on child states. 00067 if( ( *i )->isPending() ) 00068 { 00069 // This actually builds the mean value. This might cause backstepping in progress, which is not wanted. 00070 m_pending = true; 00071 m_determined &= ( *i )->isDetermined(); 00072 m_progress += ( *i )->getProgress(); 00073 numPendingChildren++; 00074 } 00075 } 00076 if( numPendingChildren ) 00077 { 00078 m_progress /= static_cast< float >( numPendingChildren ); 00079 } 00080 00081 rlock.unlock(); 00082 } 00083 00084 std::string WProgressCombiner::getCombinedNames() const 00085 { 00086 // read lock combiner 00087 boost::shared_lock< boost::shared_mutex > rlock = boost::shared_lock< boost::shared_mutex >( m_updateLock ); 00088 00089 std::stringstream ss; 00090 ss << "["; 00091 for( std::set< boost::shared_ptr< WProgress > >::const_iterator i = m_children.begin(); i != m_children.end(); ++i ) 00092 { 00093 // enforce child to update 00094 ss << ( *i )->getName(); 00095 if( boost::next( i ) != m_children.end() ) 00096 { 00097 ss << ", "; 00098 } 00099 } 00100 ss << "]"; 00101 00102 // Done. Free lock. 00103 rlock.unlock(); 00104 return ss.str(); 00105 } 00106 00107 void WProgressCombiner::addSubProgress( boost::shared_ptr< WProgress > progress ) 00108 { 00109 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock ); 00110 // add the progress to the children list 00111 m_children.insert( progress ); 00112 lock.unlock(); 00113 } 00114 00115 void WProgressCombiner::removeSubProgress( boost::shared_ptr< WProgress > progress ) 00116 { 00117 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock ); 00118 // add the progress to the children list 00119 m_children.erase( progress ); 00120 lock.unlock(); 00121 } 00122 00123 void WProgressCombiner::finish() 00124 { 00125 // combiner just propagate the finish request down to all children 00126 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock ); 00127 00128 // as the children define this progress' state -> iterate children 00129 for( std::set< boost::shared_ptr< WProgress > >::iterator i = m_children.begin(); i != m_children.end(); ++i ) 00130 { 00131 // enforce child to update 00132 ( *i )->finish(); 00133 ( *i )->update(); 00134 } 00135 00136 // remove the children 00137 m_children.clear(); 00138 00139 // set the defaults 00140 WProgress::finish(); 00141 m_progress = 0.0; 00142 00143 lock.unlock(); 00144 } 00145 00146 WProgressCombiner& WProgressCombiner::operator++() 00147 { 00148 // in progress combiners, this can be ignored. The progress is defined by the children. 00149 return *this; 00150 } 00151 00152 float WProgressCombiner::getProgress() 00153 { 00154 return m_progress; 00155 } 00156