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 <map> 00026 #include <set> 00027 #include <string> 00028 00029 #include "WPropertyObserver.h" 00030 00031 WPropertyObserver::WPropertyObserver(): 00032 WCondition(), 00033 m_subscriptions(), 00034 m_updated( false ), 00035 m_properties(), 00036 m_propNames(), 00037 m_updateConditionConnection() 00038 { 00039 // initialize members 00040 } 00041 00042 WPropertyObserver::~WPropertyObserver() 00043 { 00044 // cleanup 00045 } 00046 00047 bool WPropertyObserver::updated() const 00048 { 00049 return m_updated; 00050 } 00051 00052 WPropertyObserver::PropertyNameMap WPropertyObserver::handled() 00053 { 00054 LastUpdated::WriteTicket l = m_lastUpdated.getWriteTicket(); 00055 00056 // reset everything 00057 m_updated = false; 00058 00059 // return a copy of the list 00060 PropertyNameMap ret( l->get() ); 00061 l->get().clear(); 00062 00063 return ret; 00064 } 00065 00066 void WPropertyObserver::observe( boost::shared_ptr< WProperties > properties, std::set< std::string > names ) 00067 { 00068 // something to do? 00069 if( m_properties == properties ) 00070 { 00071 return; 00072 } 00073 00074 // remove old subscriptions to the old properties 00075 m_updateConditionConnection.disconnect(); 00076 cancelSubscriptions(); 00077 m_updated = false; 00078 LastUpdated::WriteTicket l = m_lastUpdated.getWriteTicket(); 00079 l->get().clear(); 00080 00081 m_propNames = names; 00082 00083 // set new properties and subscribe to all signals 00084 m_properties = properties; 00085 // we need to get a call if properties get added or removed 00086 m_updateConditionConnection = m_properties->getUpdateCondition()->subscribeSignal( 00087 boost::bind( &WPropertyObserver::updateSubscriptions, this ) 00088 ); 00089 00090 // and subscribe again to the new group's properties 00091 // NOTE: it may be possible that the updateSubscriptions method was called already by the above callback. But thats not that evil. 00092 updateSubscriptions(); 00093 } 00094 00095 void WPropertyObserver::cancelSubscriptions() 00096 { 00097 // NOTE: locking is handled by WSharedAssociativeContainer 00098 00099 // unfortunately, scoped_connections can't be used for the container as it requires copy construction which is not allowed by 00100 // scoped_connections. So we need to iterate by hand and disconnect 00101 00102 Subscriptions::WriteTicket subs = m_subscriptions.getWriteTicket(); 00103 for( Subscriptions::Iterator i = subs->get().begin(); i != subs->get().end(); ++i ) 00104 { 00105 ( *i ).second.disconnect(); 00106 } 00107 subs->get().clear(); 00108 } 00109 00110 void WPropertyObserver::updateSubscriptions() 00111 { 00112 // lock m_subscriptions 00113 Subscriptions::WriteTicket subs = m_subscriptions.getWriteTicket(); 00114 00115 // iterate the properties 00116 WProperties::PropertySharedContainerType::ReadTicket props = m_properties->getReadTicket(); 00117 for( WProperties::PropertyConstIterator i = props->get().begin(); i != props->get().end(); ++i ) 00118 { 00119 // should the property be handled? (empty container ensures handling of all props) 00120 if( !m_propNames.size() || ( m_propNames.find( ( *i )->getName() ) != m_propNames.end() ) ) 00121 { 00122 // subscribe to each update signal of the properties 00123 subs->get().insert( std::make_pair( *i, 00124 ( *i )->getUpdateCondition()->subscribeSignal( boost::bind( boost::mem_fn( &WPropertyObserver::propertyUpdated ), this, *i ) ) 00125 ) ); 00126 } 00127 } 00128 } 00129 00130 void WPropertyObserver::propertyUpdated( boost::shared_ptr< WPropertyBase > property ) 00131 { 00132 // lock m_lastUpdated 00133 LastUpdated::WriteTicket l = m_lastUpdated.getWriteTicket(); 00134 m_updated = true; 00135 l->get().insert( std::make_pair( property->getName(), property ) ); 00136 notify(); 00137 } 00138 00139 boost::shared_ptr< WPropertyObserver > WPropertyObserver::create() 00140 { 00141 return boost::shared_ptr< WPropertyObserver >( new WPropertyObserver() ); 00142 } 00143