OpenWalnut  1.4.0
WConditionSet.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 "WConditionSet.h"
00026 
00027 WConditionSet::WConditionSet():
00028     WCondition(),
00029     m_resetable( false ),
00030     m_autoReset( false ),
00031     m_fired( false ),
00032     m_notifier( boost::bind( &WConditionSet::conditionFired, this ) )
00033 {
00034 }
00035 
00036 WConditionSet::~WConditionSet()
00037 {
00038     // get write lock
00039     boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_conditionSetLock );
00040 
00041     // clean conditions list
00042     // NOTE: we need to disconnect here.
00043     for( ConditionConnectionMap::iterator it = m_conditionSet.begin(); it != m_conditionSet.end(); ++it )
00044     {
00045         ( *it ).second.disconnect();
00046     }
00047 
00048     m_conditionSet.clear();
00049     lock.unlock();
00050 }
00051 
00052 void WConditionSet::add( boost::shared_ptr< WCondition > condition )
00053 {
00054     // get write lock
00055     boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_conditionSetLock );
00056 
00057     if( !m_conditionSet.count( condition ) )
00058     {
00059         // create a new pair, the condition and its connection object.
00060         // this is needed since remove needs the connection to disconnect the notifier again
00061         m_conditionSet.insert( ConditionConnectionPair( condition, condition->subscribeSignal( m_notifier ) ) );
00062     }
00063 
00064     lock.unlock();
00065 }
00066 
00067 void WConditionSet::remove( boost::shared_ptr< WCondition > condition )
00068 {
00069     // get write lock
00070     boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_conditionSetLock );
00071 
00072     // get the element
00073     ConditionConnectionMap::iterator it = m_conditionSet.find( condition );
00074     if( it != m_conditionSet.end() )
00075     {
00076         ( *it ).second.disconnect();
00077         m_conditionSet.erase( it );
00078     }
00079 
00080     lock.unlock();
00081 }
00082 
00083 void WConditionSet::conditionFired()
00084 {
00085     m_fired = true;
00086     notify();
00087 }
00088 
00089 void WConditionSet::wait() const
00090 {
00091     if( !m_resetable || !m_fired )
00092     {
00093         WCondition::wait();
00094     }
00095 
00096     if( m_autoReset )
00097     {
00098         reset();
00099     }
00100 }
00101 
00102 void WConditionSet::reset() const
00103 {
00104     m_fired = false;
00105 }
00106 
00107 void WConditionSet::setResetable( bool resetable, bool autoReset )
00108 {
00109     m_autoReset = autoReset;
00110     m_resetable = resetable;
00111 }
00112 
00113 bool WConditionSet::isResetable()
00114 {
00115     return m_resetable;
00116 }
00117