OpenWalnut  1.4.0
WPropertyObserver.cpp
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