OpenWalnut
1.4.0
|
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( bool excludeFinished ) 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 bool addComma = false; // when true, a "," is appended before printing the next name. This is needed as we do not know if an element is the 00091 // last one if excludeFinished == true. 00092 for( std::set< boost::shared_ptr< WProgress > >::const_iterator i = m_children.begin(); i != m_children.end(); ++i ) 00093 { 00094 if( !( !( *i )->isPending() && excludeFinished ) ) 00095 { 00096 if( addComma ) 00097 { 00098 ss << ", "; 00099 } 00100 00101 // enforce child to update 00102 ss << ( *i )->getName(); 00103 // in next step, add a comma 00104 addComma = true; 00105 } 00106 } 00107 00108 // Done. Free lock. 00109 rlock.unlock(); 00110 return ss.str(); 00111 } 00112 00113 void WProgressCombiner::addSubProgress( boost::shared_ptr< WProgress > progress ) 00114 { 00115 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock ); 00116 // add the progress to the children list 00117 m_children.insert( progress ); 00118 lock.unlock(); 00119 } 00120 00121 void WProgressCombiner::removeSubProgress( boost::shared_ptr< WProgress > progress ) 00122 { 00123 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock ); 00124 // add the progress to the children list 00125 m_children.erase( progress ); 00126 lock.unlock(); 00127 } 00128 00129 void WProgressCombiner::finish() 00130 { 00131 // combiner just propagate the finish request down to all children 00132 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock ); 00133 00134 // as the children define this progress' state -> iterate children 00135 for( std::set< boost::shared_ptr< WProgress > >::iterator i = m_children.begin(); i != m_children.end(); ++i ) 00136 { 00137 // enforce child to update 00138 ( *i )->finish(); 00139 ( *i )->update(); 00140 } 00141 00142 // remove the children 00143 m_children.clear(); 00144 00145 // set the defaults 00146 WProgress::finish(); 00147 m_progress = 0.0; 00148 00149 lock.unlock(); 00150 } 00151 00152 WProgressCombiner& WProgressCombiner::operator++() 00153 { 00154 // in progress combiners, this can be ignored. The progress is defined by the children. 00155 return *this; 00156 } 00157 00158 float WProgressCombiner::getProgress() 00159 { 00160 return m_progress; 00161 } 00162