OpenWalnut  1.3.1
WProgressCombiner.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <sstream>
26 #include <string>
27 #include <set>
28 
29 #include <boost/utility.hpp>
30 
31 #include "WProgressCombiner.h"
32 
34  WProgress( name, 1 ),
35  m_name( name ),
36  m_progress( 0.0 )
37 {
38  // initialize members
39  m_pending = false;
40 }
41 
43 {
44  // cleanup
45 }
46 
48 {
49  // This updates the internal state. Here, all states from child progress' get combined.
50 
51  // get read lock
52  boost::shared_lock< boost::shared_mutex > rlock;
53  rlock = boost::shared_lock< boost::shared_mutex >( m_updateLock );
54 
55  m_pending = false;
56  m_determined = true;
57  m_progress = 0.0;
58  unsigned int numPendingChildren = 0;
59 
60  // as the children define this progress' state -> iterate children
61  for( std::set< boost::shared_ptr< WProgress > >::iterator i = m_children.begin(); i != m_children.end(); ++i )
62  {
63  // enforce child to update
64  ( *i )->update();
65 
66  // update own state basing on child states.
67  if( ( *i )->isPending() )
68  {
69  // This actually builds the mean value. This might cause backstepping in progress, which is not wanted.
70  m_pending = true;
71  m_determined &= ( *i )->isDetermined();
72  m_progress += ( *i )->getProgress();
73  numPendingChildren++;
74  }
75  }
76  if( numPendingChildren )
77  {
78  m_progress /= static_cast< float >( numPendingChildren );
79  }
80 
81  rlock.unlock();
82 }
83 
84 std::string WProgressCombiner::getCombinedNames( bool excludeFinished ) const
85 {
86  // read lock combiner
87  boost::shared_lock< boost::shared_mutex > rlock = boost::shared_lock< boost::shared_mutex >( m_updateLock );
88 
89  std::stringstream ss;
90  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
91  // last one if excludeFinished == true.
92  for( std::set< boost::shared_ptr< WProgress > >::const_iterator i = m_children.begin(); i != m_children.end(); ++i )
93  {
94  if( !( !( *i )->isPending() && excludeFinished ) )
95  {
96  if( addComma )
97  {
98  ss << ", ";
99  }
100 
101  // enforce child to update
102  ss << ( *i )->getName();
103  // in next step, add a comma
104  addComma = true;
105  }
106  }
107 
108  // Done. Free lock.
109  rlock.unlock();
110  return ss.str();
111 }
112 
113 void WProgressCombiner::addSubProgress( boost::shared_ptr< WProgress > progress )
114 {
115  boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock );
116  // add the progress to the children list
117  m_children.insert( progress );
118  lock.unlock();
119 }
120 
121 void WProgressCombiner::removeSubProgress( boost::shared_ptr< WProgress > progress )
122 {
123  boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock );
124  // add the progress to the children list
125  m_children.erase( progress );
126  lock.unlock();
127 }
128 
130 {
131  // combiner just propagate the finish request down to all children
132  boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_updateLock );
133 
134  // as the children define this progress' state -> iterate children
135  for( std::set< boost::shared_ptr< WProgress > >::iterator i = m_children.begin(); i != m_children.end(); ++i )
136  {
137  // enforce child to update
138  ( *i )->finish();
139  ( *i )->update();
140  }
141 
142  // remove the children
143  m_children.clear();
144 
145  // set the defaults
147  m_progress = 0.0;
148 
149  lock.unlock();
150 }
151 
153 {
154  // in progress combiners, this can be ignored. The progress is defined by the children.
155  return *this;
156 }
157 
159 {
160  return m_progress;
161 }
162