<commit_before>/*************************************************************************
 *
 *  $RCSfile: macro_expander.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2003-07-16 17:52:22 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2002 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <rtl/bootstrap.hxx>

#include <cppuhelper/factory.hxx>
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/compbase3.hxx>
#include <cppuhelper/component_context.hxx>

#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/util/XMacroExpander.hpp>

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
#define SERVICE_NAME_A "com.sun.star.lang.MacroExpander"
#define SERVICE_NAME_B "com.sun.star.lang.BootstrapMacroExpander"
#define IMPL_NAME "com.sun.star.lang.comp.cppuhelper.BootstrapMacroExpander"

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace cppu
{
//---- private forward -----------------------------------------------------------------------------
Bootstrap const & get_unorc() SAL_THROW( () );
}

namespace
{

// static stuff initialized when loading lib
static OUString s_impl_name = OUSTR(IMPL_NAME);
static Sequence< OUString > const & s_get_service_names()
{
    static Sequence< OUString > const * s_pnames = 0;
    if (! s_pnames)
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if (! s_pnames)
        {
            static Sequence< OUString > s_names( 2 );
            s_names[ 0 ] = OUSTR(SERVICE_NAME_A);
            s_names[ 1 ] = OUSTR(SERVICE_NAME_B);
            s_pnames = &s_names;
        }
    }
    return *s_pnames;
}

typedef ::cppu::WeakComponentImplHelper3<
    util::XMacroExpander, lang::XServiceInfo, lang::XInitialization > t_uno_impl;

#if defined( MACOSX ) && ( __GNUC__ < 3 )
// Initialize static template data here to break circular reference to libstatic

cppu::ClassData3 cppu::WeakComponentImplHelper3< com::sun::star::util::XMacroExpander, com::sun::star::lang::XServiceInfo, com::sun::star::lang::XInitialization >::s_aCD(1);
#endif

struct mutex_holder
{
    Mutex m_mutex;
};
class Bootstrap_MacroExpander : public mutex_holder, public t_uno_impl
{
    rtlBootstrapHandle m_bstrap;
    OUString m_rc_path;

protected:
    virtual void SAL_CALL disposing();

public:
    inline Bootstrap_MacroExpander( Reference< XComponentContext > const & ) SAL_THROW( () )
        : t_uno_impl( m_mutex ),
          m_bstrap( 0 )
        {}
    virtual ~Bootstrap_MacroExpander()
        SAL_THROW( () );

    // XMacroExpander impl
    virtual OUString SAL_CALL expandMacros( OUString const & exp )
        throw (lang::IllegalArgumentException);
    //  XInitialization impl
    virtual void SAL_CALL initialize(
        Sequence< Any > const & arguments )
        throw (Exception);
    // XServiceInfo impl
    virtual OUString SAL_CALL getImplementationName()
        throw (RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
        throw (RuntimeException);
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
        throw (RuntimeException);
};

//__________________________________________________________________________________________________
void Bootstrap_MacroExpander::disposing()
{
    if (m_bstrap)
    {
        rtl_bootstrap_args_close( m_bstrap );
        m_bstrap = 0;
    }
}
//__________________________________________________________________________________________________
Bootstrap_MacroExpander::~Bootstrap_MacroExpander() SAL_THROW( () )
{
    if (m_bstrap)
    {
        rtl_bootstrap_args_close( m_bstrap );
        m_bstrap = 0;
    }
}

// XServiceInfo impl
//__________________________________________________________________________________________________
OUString Bootstrap_MacroExpander::getImplementationName()
    throw (RuntimeException)
{
    return s_impl_name;
}
//__________________________________________________________________________________________________
sal_Bool Bootstrap_MacroExpander::supportsService( OUString const & serviceName )
    throw (RuntimeException)
{
    Sequence< OUString > const & service_names = s_get_service_names();
    OUString const * p = service_names.getConstArray();
    for ( sal_Int32 nPos = service_names.getLength(); nPos--; )
    {
        if (p[ nPos ].equals( serviceName ))
            return sal_True;
    }
    return sal_False;
}
//__________________________________________________________________________________________________
Sequence< OUString > Bootstrap_MacroExpander::getSupportedServiceNames()
    throw (RuntimeException)
{
    return s_get_service_names();
}
//  XInitialization impl
//__________________________________________________________________________________________________
void SAL_CALL Bootstrap_MacroExpander::initialize(
    Sequence< Any > const & arguments )
    throw (Exception)
{
    if (m_bstrap)
    {
        throw RuntimeException(
            OUSTR("already initialized!"),
            Reference< XInterface >() );
    }
    if (1 != arguments.getLength())
    {
        throw lang::IllegalArgumentException(
            OUSTR("invalid number of args given!  give single file url!"),
            Reference< XInterface >(),
            0 );
    }
    if (! (arguments[ 0 ] >>= m_rc_path))
    {
        throw lang::IllegalArgumentException(
            OUSTR("give file url!"),
            Reference< XInterface >(),
            0 );
    }
}

// XMacroExpander impl
//__________________________________________________________________________________________________
OUString Bootstrap_MacroExpander::expandMacros( OUString const & exp )
    throw (lang::IllegalArgumentException)
{
    // determine bootstrap handle
    rtlBootstrapHandle bstrap;
    if (m_rc_path.getLength())
    {
        // late init
        if (! m_bstrap)
        {
            rtlBootstrapHandle bstrap = rtl_bootstrap_args_open( m_rc_path.pData );
            ClearableMutexGuard guard( Mutex::getGlobalMutex() );
            if (m_bstrap)
            {
                guard.clear();
                rtl_bootstrap_args_close( bstrap );
            }
            else
            {
                m_bstrap = bstrap;
            }
        }
        bstrap = m_bstrap;
    }
    else
    {
        bstrap = ::cppu::get_unorc().getHandle();
    }

    // expand
    OUString ret( exp );
    rtl_bootstrap_expandMacros_from_handle( bstrap, &ret.pData );
    return ret;
}

//==================================================================================================
Reference< XInterface > SAL_CALL service_create(
    Reference< XComponentContext > const & xComponentContext )
    SAL_THROW( (RuntimeException) )
{
    return static_cast< ::cppu::OWeakObject * >( new Bootstrap_MacroExpander( xComponentContext ) );
}

}

namespace cppu
{

//##################################################################################################
Reference< lang::XSingleComponentFactory > create_boostrap_macro_expander_factory() SAL_THROW( () )
{
    return ::cppu::createSingleComponentFactory(
        service_create,
        s_impl_name,
        s_get_service_names() );
}

}
<commit_msg>INTEGRATION: CWS geordi2q14 (1.4.40); FILE MERGED 2004/01/29 15:10:12 hr 1.4.40.1: #111934#: merge CWS ooo111fix2<commit_after>/*************************************************************************
 *
 *  $RCSfile: macro_expander.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2004-02-02 23:15:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2002 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <rtl/bootstrap.hxx>

#include <cppuhelper/factory.hxx>
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/compbase3.hxx>
#include <cppuhelper/component_context.hxx>

#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/util/XMacroExpander.hpp>

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
#define SERVICE_NAME_A "com.sun.star.lang.MacroExpander"
#define SERVICE_NAME_B "com.sun.star.lang.BootstrapMacroExpander"
#define IMPL_NAME "com.sun.star.lang.comp.cppuhelper.BootstrapMacroExpander"

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace cppu
{
//---- private forward -----------------------------------------------------------------------------
Bootstrap const & get_unorc() SAL_THROW( () );
}

namespace
{

// static stuff initialized when loading lib
static OUString s_impl_name = OUSTR(IMPL_NAME);
static Sequence< OUString > const & s_get_service_names()
{
    static Sequence< OUString > const * s_pnames = 0;
    if (! s_pnames)
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if (! s_pnames)
        {
            static Sequence< OUString > s_names( 2 );
            s_names[ 0 ] = OUSTR(SERVICE_NAME_A);
            s_names[ 1 ] = OUSTR(SERVICE_NAME_B);
            s_pnames = &s_names;
        }
    }
    return *s_pnames;
}

typedef ::cppu::WeakComponentImplHelper3<
    util::XMacroExpander, lang::XServiceInfo, lang::XInitialization > t_uno_impl;

struct mutex_holder
{
    Mutex m_mutex;
};
class Bootstrap_MacroExpander : public mutex_holder, public t_uno_impl
{
    rtlBootstrapHandle m_bstrap;
    OUString m_rc_path;

protected:
    virtual void SAL_CALL disposing();

public:
    inline Bootstrap_MacroExpander( Reference< XComponentContext > const & ) SAL_THROW( () )
        : t_uno_impl( m_mutex ),
          m_bstrap( 0 )
        {}
    virtual ~Bootstrap_MacroExpander()
        SAL_THROW( () );

    // XMacroExpander impl
    virtual OUString SAL_CALL expandMacros( OUString const & exp )
        throw (lang::IllegalArgumentException);
    //  XInitialization impl
    virtual void SAL_CALL initialize(
        Sequence< Any > const & arguments )
        throw (Exception);
    // XServiceInfo impl
    virtual OUString SAL_CALL getImplementationName()
        throw (RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
        throw (RuntimeException);
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
        throw (RuntimeException);
};

//__________________________________________________________________________________________________
void Bootstrap_MacroExpander::disposing()
{
    if (m_bstrap)
    {
        rtl_bootstrap_args_close( m_bstrap );
        m_bstrap = 0;
    }
}
//__________________________________________________________________________________________________
Bootstrap_MacroExpander::~Bootstrap_MacroExpander() SAL_THROW( () )
{
    if (m_bstrap)
    {
        rtl_bootstrap_args_close( m_bstrap );
        m_bstrap = 0;
    }
}

// XServiceInfo impl
//__________________________________________________________________________________________________
OUString Bootstrap_MacroExpander::getImplementationName()
    throw (RuntimeException)
{
    return s_impl_name;
}
//__________________________________________________________________________________________________
sal_Bool Bootstrap_MacroExpander::supportsService( OUString const & serviceName )
    throw (RuntimeException)
{
    Sequence< OUString > const & service_names = s_get_service_names();
    OUString const * p = service_names.getConstArray();
    for ( sal_Int32 nPos = service_names.getLength(); nPos--; )
    {
        if (p[ nPos ].equals( serviceName ))
            return sal_True;
    }
    return sal_False;
}
//__________________________________________________________________________________________________
Sequence< OUString > Bootstrap_MacroExpander::getSupportedServiceNames()
    throw (RuntimeException)
{
    return s_get_service_names();
}
//  XInitialization impl
//__________________________________________________________________________________________________
void SAL_CALL Bootstrap_MacroExpander::initialize(
    Sequence< Any > const & arguments )
    throw (Exception)
{
    if (m_bstrap)
    {
        throw RuntimeException(
            OUSTR("already initialized!"),
            Reference< XInterface >() );
    }
    if (1 != arguments.getLength())
    {
        throw lang::IllegalArgumentException(
            OUSTR("invalid number of args given!  give single file url!"),
            Reference< XInterface >(),
            0 );
    }
    if (! (arguments[ 0 ] >>= m_rc_path))
    {
        throw lang::IllegalArgumentException(
            OUSTR("give file url!"),
            Reference< XInterface >(),
            0 );
    }
}

// XMacroExpander impl
//__________________________________________________________________________________________________
OUString Bootstrap_MacroExpander::expandMacros( OUString const & exp )
    throw (lang::IllegalArgumentException)
{
    // determine bootstrap handle
    rtlBootstrapHandle bstrap;
    if (m_rc_path.getLength())
    {
        // late init
        if (! m_bstrap)
        {
            rtlBootstrapHandle bstrap = rtl_bootstrap_args_open( m_rc_path.pData );
            ClearableMutexGuard guard( Mutex::getGlobalMutex() );
            if (m_bstrap)
            {
                guard.clear();
                rtl_bootstrap_args_close( bstrap );
            }
            else
            {
                m_bstrap = bstrap;
            }
        }
        bstrap = m_bstrap;
    }
    else
    {
        bstrap = ::cppu::get_unorc().getHandle();
    }

    // expand
    OUString ret( exp );
    rtl_bootstrap_expandMacros_from_handle( bstrap, &ret.pData );
    return ret;
}

//==================================================================================================
Reference< XInterface > SAL_CALL service_create(
    Reference< XComponentContext > const & xComponentContext )
    SAL_THROW( (RuntimeException) )
{
    return static_cast< ::cppu::OWeakObject * >( new Bootstrap_MacroExpander( xComponentContext ) );
}

}

namespace cppu
{

//##################################################################################################
Reference< lang::XSingleComponentFactory > create_boostrap_macro_expander_factory() SAL_THROW( () )
{
    return ::cppu::createSingleComponentFactory(
        service_create,
        s_impl_name,
        s_get_service_names() );
}

}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>

#include "libtorrent/policy.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp"

namespace
{
	enum
	{
		// we try to maintain 4 requested blocks in the download
		// queue
		request_queue = 16
	};

	using namespace libtorrent;

	// TODO: replace these two functions with std::find_first_of
	template<class It1, class It2>
	bool has_intersection(It1 start1, It1 end1, It2 start2, It2 end2)
	{
		for (;start1 != end1; ++start1)
			for (;start2 != end2; ++start2)
				if (*start1 == *start2) return true;
		return false;
	}

	piece_block find_first_common(const std::vector<piece_block>& queue,
		const std::vector<piece_block>& busy)
	{
		for (std::vector<piece_block>::const_reverse_iterator i
			= queue.rbegin();
			i != queue.rend();
			++i)
		{
			for (std::vector<piece_block>::const_iterator j
				= busy.begin();
				j != busy.end();
				++j)
			{
				if ((*j) == (*i)) return *i;
			}
		}
		assert(false);
	}

	void request_a_block(torrent& t, peer_connection& c)
	{
		int num_requests = request_queue - c.download_queue().size();

		// if our request queue is already full, we
		// don't have to make any new requests yet
		if (num_requests <= 0) return;

		piece_picker& p = t.picker();
		std::vector<piece_block> interesting_pieces;
		interesting_pieces.reserve(100);

		// picks the interesting pieces from this peer
		// the integer is the number of pieces that
		// should be guaranteed to be available for download
		// (if this number is too big, too many pieces are
		// picked and cpu-time is wasted)
		p.pick_pieces(c.get_bitfield(), interesting_pieces, num_requests);

		// this vector is filled with the interestin pieces
		// that some other peer is currently downloading
		// we should then compare this peer's download speed
		// with the other's, to see if we should abort another
		// peer_connection in favour of this one
		std::vector<piece_block> busy_pieces;
		busy_pieces.reserve(10);

		for (std::vector<piece_block>::iterator i = interesting_pieces.begin();
			i != interesting_pieces.end();
			++i)
		{
			if (p.is_downloading(*i))
			{
				busy_pieces.push_back(*i);
				continue;
			}

			// ok, we found a piece that's not being downloaded
			// by somebody else. request it from this peer
			c.request_block(*i);
			num_requests--;
			if (num_requests <= 0) return;
		}

		if (busy_pieces.empty()) return;

		// first look for blocks that are just queued
		// and not actually sent to us yet
		// (then we can cancel those and request them
		// from this peer instead)

		peer_connection* peer = 0;
		float down_speed = 0.f;
		// find the peer with the lowest download
		// speed that also has a piece thatt this
		// peer could send us
		for (torrent::peer_iterator i = t.begin();
			i != t.end();
			++i)
		{
			const std::vector<piece_block>& queue = (*i)->download_queue();
			if ((*i)->statistics().down_peak() > down_speed
				&& has_intersection(busy_pieces.begin(),
					busy_pieces.end(),
					queue.begin(),
					queue.end()))
			{
				peer = *i;
				down_speed = (*i)->statistics().down_peak();
			}
		}

		assert(peer != 0);

		// this peer doesn't have a faster connection than the
		// slowest peer. Don't take over any blocks
		if (c.statistics().down_peak() <= down_speed) return;

		// find a suitable block to take over from this peer
		piece_block block = find_first_common(peer->download_queue(), busy_pieces);
		peer->cancel_block(block);
		c.request_block(block);

		// the one we interrupted may need to request a new piece
		request_a_block(t, *peer);

		num_requests--;
	}
}

namespace libtorrent
{
/*
	TODO: make two proxy classes that filter out
	all unneccesary members from torrent and peer_connection
	to make it easier to use them in the policy

	useful member functions:

	void torrent::connect_to_peer(address, peer_id);
	piece_picker& torrent::picker();
	std::vector<peer_connection*>::const_iterator torrent::begin() const
	std::vector<peer_connection*>::const_iterator torrent::end() const

	void peer_connection::interested();
	void peer_connection::not_interested();
	void peer_connection::choke();
	void peer_connection::unchoke();
	void peer_connection::request_piece(int index);
	const std::vector<int>& peer_connection::download_queue();
*/

	policy::policy(torrent* t)
		: m_num_peers(0)
		, m_torrent(t)
	{}

	// this is called when a connection is made, before any
	// handshake (it's possible to ban certain ip:s).
	bool policy::accept_connection(const address& remote)
	{
		m_num_peers++;
		return true;
	}

	void policy::peer_from_tracker(const address& remote, const peer_id& id)
	{
		try
		{
			m_torrent->connect_to_peer(remote, id);
			m_num_peers++;
		}
		catch(network_error&) {}
	}

	// this is called when we are choked by a peer
	// i.e. a peer lets us know that we will not receive
	// anything for a while
	void policy::choked(peer_connection& c)
	{
		c.choke();
	}

	void policy::piece_finished(peer_connection& c, int index, bool successfully_verified)
	{
		// TODO: if verification failed, mark the peers that were involved
		// in some way
	}

	void policy::block_finished(peer_connection& c, piece_block b)
	{
		if (c.has_peer_choked()) return;
		request_a_block(*m_torrent, c);
	}

	// this is called when we are unchoked by a peer
	// i.e. a peer lets us know that we will receive
	// data from now on
	void policy::unchoked(peer_connection& c)
	{
		c.unchoke();
		if (c.is_interesting()) request_a_block(*m_torrent, c);
	}

	void policy::interested(peer_connection& c)
	{
		c.unchoke();
	}

	void policy::not_interested(peer_connection& c)
	{
	}

	void policy::connection_closed(const peer_connection& c)
	{
	}

	void policy::peer_is_interesting(peer_connection& c)
	{
		c.interested();
		if (c.has_peer_choked()) return;
		request_a_block(*m_torrent, c);
	}
}
<commit_msg>bugfix<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>

#include "libtorrent/policy.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp"

namespace
{
	enum
	{
		// we try to maintain 4 requested blocks in the download
		// queue
		request_queue = 16
	};

	using namespace libtorrent;

	// TODO: replace these two functions with std::find_first_of
	template<class It1, class It2>
	bool has_intersection(It1 start1, It1 end1, It2 start2, It2 end2)
	{
		for (;start1 != end1; ++start1)
			for (;start2 != end2; ++start2)
				if (*start1 == *start2) return true;
		return false;
	}

	piece_block find_first_common(const std::vector<piece_block>& queue,
		const std::vector<piece_block>& busy)
	{
		for (std::vector<piece_block>::const_reverse_iterator i
			= queue.rbegin();
			i != queue.rend();
			++i)
		{
			for (std::vector<piece_block>::const_iterator j
				= busy.begin();
				j != busy.end();
				++j)
			{
				if ((*j) == (*i)) return *i;
			}
		}
		assert(false);
	}

	void request_a_block(torrent& t, peer_connection& c)
	{
		int num_requests = request_queue - c.download_queue().size();

		// if our request queue is already full, we
		// don't have to make any new requests yet
		if (num_requests <= 0) return;

		piece_picker& p = t.picker();
		std::vector<piece_block> interesting_pieces;
		interesting_pieces.reserve(100);

		// picks the interesting pieces from this peer
		// the integer is the number of pieces that
		// should be guaranteed to be available for download
		// (if this number is too big, too many pieces are
		// picked and cpu-time is wasted)
		p.pick_pieces(c.get_bitfield(), interesting_pieces, num_requests);

		// this vector is filled with the interestin pieces
		// that some other peer is currently downloading
		// we should then compare this peer's download speed
		// with the other's, to see if we should abort another
		// peer_connection in favour of this one
		std::vector<piece_block> busy_pieces;
		busy_pieces.reserve(10);

		for (std::vector<piece_block>::iterator i = interesting_pieces.begin();
			i != interesting_pieces.end();
			++i)
		{
			if (p.is_downloading(*i))
			{
				busy_pieces.push_back(*i);
				continue;
			}

			// ok, we found a piece that's not being downloaded
			// by somebody else. request it from this peer
			c.request_block(*i);
			num_requests--;
			if (num_requests <= 0) return;
		}

		if (busy_pieces.empty()) return;

		// first look for blocks that are just queued
		// and not actually sent to us yet
		// (then we can cancel those and request them
		// from this peer instead)

		peer_connection* peer = 0;
		float down_speed = -1.f;
		// find the peer with the lowest download
		// speed that also has a piece thatt this
		// peer could send us
		for (torrent::peer_iterator i = t.begin();
			i != t.end();
			++i)
		{
			const std::vector<piece_block>& queue = (*i)->download_queue();
			if ((*i)->statistics().down_peak() > down_speed
				&& has_intersection(busy_pieces.begin(),
					busy_pieces.end(),
					queue.begin(),
					queue.end()))
			{
				peer = *i;
				down_speed = (*i)->statistics().down_peak();
			}
		}

		assert(peer != 0);

		// this peer doesn't have a faster connection than the
		// slowest peer. Don't take over any blocks
		if (c.statistics().down_peak() <= down_speed) return;

		// find a suitable block to take over from this peer
		piece_block block = find_first_common(peer->download_queue(), busy_pieces);
		peer->cancel_block(block);
		c.request_block(block);

		// the one we interrupted may need to request a new piece
		request_a_block(t, *peer);

		num_requests--;
	}
}

namespace libtorrent
{
/*
	TODO: make two proxy classes that filter out
	all unneccesary members from torrent and peer_connection
	to make it easier to use them in the policy

	useful member functions:

	void torrent::connect_to_peer(address, peer_id);
	piece_picker& torrent::picker();
	std::vector<peer_connection*>::const_iterator torrent::begin() const
	std::vector<peer_connection*>::const_iterator torrent::end() const

	void peer_connection::interested();
	void peer_connection::not_interested();
	void peer_connection::choke();
	void peer_connection::unchoke();
	void peer_connection::request_piece(int index);
	const std::vector<int>& peer_connection::download_queue();
*/

	policy::policy(torrent* t)
		: m_num_peers(0)
		, m_torrent(t)
	{}

	// this is called when a connection is made, before any
	// handshake (it's possible to ban certain ip:s).
	bool policy::accept_connection(const address& remote)
	{
		m_num_peers++;
		return true;
	}

	void policy::peer_from_tracker(const address& remote, const peer_id& id)
	{
		try
		{
			m_torrent->connect_to_peer(remote, id);
			m_num_peers++;
		}
		catch(network_error&) {}
	}

	// this is called when we are choked by a peer
	// i.e. a peer lets us know that we will not receive
	// anything for a while
	void policy::choked(peer_connection& c)
	{
		c.choke();
	}

	void policy::piece_finished(peer_connection& c, int index, bool successfully_verified)
	{
		// TODO: if verification failed, mark the peers that were involved
		// in some way
	}

	void policy::block_finished(peer_connection& c, piece_block b)
	{
		if (c.has_peer_choked()) return;
		request_a_block(*m_torrent, c);
	}

	// this is called when we are unchoked by a peer
	// i.e. a peer lets us know that we will receive
	// data from now on
	void policy::unchoked(peer_connection& c)
	{
		c.unchoke();
		if (c.is_interesting()) request_a_block(*m_torrent, c);
	}

	void policy::interested(peer_connection& c)
	{
		c.unchoke();
	}

	void policy::not_interested(peer_connection& c)
	{
	}

	void policy::connection_closed(const peer_connection& c)
	{
	}

	void policy::peer_is_interesting(peer_connection& c)
	{
		c.interested();
		if (c.has_peer_choked()) return;
		request_a_block(*m_torrent, c);
	}
}
<|endoftext|>


<commit_before>#include <errno.h>

#include "Recipe.hh"
#include "str.hh"

Recipe::Info::Info()
  : start_time(0), end_time(0), start_line(0), end_line(0),
    speaker_id(""), utterance_id("")
{
}

void
Recipe::clear()
{
  infos.clear();
}

void
Recipe::read(FILE *f, int num_batches, int batch_index, bool cluster_speakers)
{
  std::string line;
  std::vector<std::string> field;
  std::vector<std::string> line_buffer;
  std::map<std::string, std::string> key_value_map;
  std::vector<std::string> key_value;
  int cur_index = 1;
  int cur_line = 0;
  int target_lines;
  int i, j;
  std::map<std::string,std::string>::const_iterator it;
  std::string cur_speaker = "", new_speaker;

  if (num_batches > 1 && (batch_index < 1 || batch_index > num_batches))
    throw std::string("Invalid batch index");

  while (1) {
    bool ok = str::read_line(&line, f);

    // Do we have an error or eof?
    if (!ok) {
      if (ferror(f)) {
	fprintf(stderr, "Recipe: str::read_file(): read error: %s\n",
		strerror(errno));
	exit(1);
      }

      if (feof(f))
	break;
    }

    // Parse string in fields and skip empty or commented lines
    str::clean(&line, "\n\t ");
    if (line.length() == 0 || line[0] == '#')
      continue;
    line_buffer.push_back(line);
  }

  if (num_batches <= 1)
    target_lines = line_buffer.size();
  else
    target_lines = (int)line_buffer.size()/num_batches;
  if (target_lines < 1)
    target_lines = 1;

  for (i = 0; i < (int)line_buffer.size(); i++)
  {
    // Parse the recipe line
    str::split(&line_buffer[i], " \t", true, &field);
    for (j = 0; j < (int)field.size(); j++)
    {
      str::split(&field[j], "=", false, &key_value);
      if ((int)key_value.size() != 2)
        throw std::string("Invalid recipe line: ") + line_buffer[i];
      if ((int)key_value.size() == 2)
        key_value_map[key_value[0]] = key_value[1];
    }

    // Check if batch index needs updating
    if (num_batches > 1 && cur_index < num_batches)
    {
      if ((it = key_value_map.find("speaker")) != key_value_map.end())
        new_speaker = (*it).second;
      else
        new_speaker = "";
      if (cur_line >= target_lines && (!cluster_speakers ||
                                      cur_speaker.size() == 0 ||
                                      cur_speaker != new_speaker))
      {
        cur_index++;
        if (cur_index > batch_index)
          break;
        cur_line -= target_lines;
      }
      cur_speaker = new_speaker;
    }

    if (num_batches <= 1 || cur_index == batch_index)
    {
      // This line belongs to the current batch, save it
      infos.push_back(Info());
      Info &info = infos.back();
      if ((it = key_value_map.find("audio")) != key_value_map.end())
        info.audio_path = (*it).second;
      if ((it = key_value_map.find("transcript")) != key_value_map.end())
        info.transcript_path = (*it).second;
      if ((it = key_value_map.find("alignment")) != key_value_map.end())
        info.alignment_path = (*it).second;
      if ((it = key_value_map.find("hmmnet")) != key_value_map.end())
        info.hmmnet_path = (*it).second;
      if ((it = key_value_map.find("den-hmmnet")) != key_value_map.end())
        info.den_hmmnet_path = (*it).second;
      if ((it = key_value_map.find("lna")) != key_value_map.end())
        info.lna_path = (*it).second;
      if ((it = key_value_map.find("start-time")) != key_value_map.end())
        info.start_time = atof((*it).second.c_str());
      if ((it = key_value_map.find("end-time")) != key_value_map.end())
        info.end_time = atof((*it).second.c_str());
      if ((it = key_value_map.find("start-line")) != key_value_map.end())
        info.start_line = atoi((*it).second.c_str());
      if ((it = key_value_map.find("end-line")) != key_value_map.end())
        info.end_line = atoi((*it).second.c_str());
      if ((it = key_value_map.find("speaker")) != key_value_map.end())
        info.speaker_id = (*it).second;
      if ((it = key_value_map.find("utterance")) != key_value_map.end())
        info.utterance_id = (*it).second;
    }

    cur_line++;
  }
}

PhnReader*
Recipe::Info::init_phn_files(HmmSet *model, bool relative_sample_nums,
                              bool out_phn, FeatureGenerator *fea_gen,
                              bool raw_audio, PhnReader *phn_reader)
{
  float frame_rate;

  // Open the audio file
  fea_gen->open(audio_path, raw_audio);

  // Initialize the PhnReader
  if (phn_reader == NULL)
    phn_reader = new PhnReader;
  if (model == NULL)
    phn_reader->set_state_num_labels(true);
  phn_reader->set_relative_sample_numbers(relative_sample_nums);
  frame_rate = fea_gen->frame_rate();
  phn_reader->set_frame_rate(frame_rate);
  phn_reader->set_hmm_model(model);

  // Open the segmentation
  phn_reader->open(out_phn?alignment_path:transcript_path);

  if (start_time > 0 || end_time > 0)
  {
    phn_reader->set_frame_limits((int)(start_time * frame_rate),
                                (int)(end_time * frame_rate));
  }
  if (start_line > 0 || end_line > 0)
  {
    phn_reader->set_line_limits(start_line, end_line);
  }

  return phn_reader;
}

HmmNetBaumWelch*
Recipe::Info::init_hmmnet_files(HmmSet *model, FeatureGenerator *fea_gen,
                                bool raw_audio, HmmNetBaumWelch *hnbw)
{
  // Open the audio file
  fea_gen->open(audio_path, raw_audio);

  // Initialize the HmmNetBaumWelch
  if (hnbw == NULL)
  {
    if (model == NULL)
      throw std::string("Recipe::Info::init_hmmnet_files: HMM model is required if hnbw==NULL");
     hnbw= new HmmNetBaumWelch(*fea_gen, *model);
  }

  // Open the HMM network
  hnbw->open(hmmnet_path);

  if (start_time > 0 || end_time > 0)
  {
    float frame_rate = fea_gen->frame_rate();
    hnbw->set_frame_limits((int)(start_time * frame_rate),
                           (int)(end_time * frame_rate));
  }

  return hnbw;
}
<commit_msg>*** empty log message ***<commit_after>#include <errno.h>

#include "Recipe.hh"
#include "str.hh"

Recipe::Info::Info()
  : start_time(0), end_time(0), start_line(0), end_line(0),
    speaker_id(""), utterance_id("")
{
}

void
Recipe::clear()
{
  infos.clear();
}

void
Recipe::read(FILE *f, int num_batches, int batch_index, bool cluster_speakers)
{
  std::string line;
  std::vector<std::string> field;
  std::vector<std::string> line_buffer;
  std::map<std::string, std::string> key_value_map;
  std::vector<std::string> key_value;
  int cur_index = 1;
  int cur_line = 0;
  int target_lines;
  int i, j;
  std::map<std::string,std::string>::const_iterator it;
  std::string cur_speaker = "", new_speaker;

  if (num_batches > 1 && (batch_index < 1 || batch_index > num_batches))
    throw std::string("Invalid batch index");

  while (1) {
    bool ok = str::read_line(&line, f);

    // Do we have an error or eof?
    if (!ok) {
      if (ferror(f)) {
	fprintf(stderr, "Recipe: str::read_file(): read error: %s\n",
		strerror(errno));
	exit(1);
      }

      if (feof(f))
	break;
    }

    // Parse string in fields and skip empty or commented lines
    str::clean(&line, "\n\t ");
    if (line.length() == 0 || line[0] == '#')
      continue;
    line_buffer.push_back(line);
  }

  if (num_batches <= 1)
    target_lines = line_buffer.size();
  else
    target_lines = (int)line_buffer.size()/num_batches;
  if (target_lines < 1)
    target_lines = 1;

  for (i = 0; i < (int)line_buffer.size(); i++)
  {
    // Parse the recipe line
    str::split(&line_buffer[i], " \t", true, &field);
    for (j = 0; j < (int)field.size(); j++)
    {
      str::split(&field[j], "=", false, &key_value);
      if ((int)key_value.size() != 2)
        throw std::string("Invalid recipe line: ") + line_buffer[i];
      if ((int)key_value.size() == 2)
        key_value_map[key_value[0]] = key_value[1];
    }

    // Check if batch index needs updating
    if (num_batches > 1 && cur_index < num_batches)
    {
      if ((it = key_value_map.find("speaker")) != key_value_map.end())
        new_speaker = (*it).second;
      else
        new_speaker = "";
      if (cur_line >= target_lines && (!cluster_speakers ||
                                      cur_speaker.size() == 0 ||
                                      cur_speaker != new_speaker))
      {
        cur_index++;
        if (cur_index > batch_index)
          break;
        cur_line -= target_lines;
      }
      cur_speaker = new_speaker;
    }

    if (num_batches <= 1 || cur_index == batch_index)
    {
      // This line belongs to the current batch, save it
      infos.push_back(Info());
      Info &info = infos.back();
      if ((it = key_value_map.find("audio")) != key_value_map.end())
        info.audio_path = (*it).second;
      if ((it = key_value_map.find("transcript")) != key_value_map.end())
        info.transcript_path = (*it).second;
      if ((it = key_value_map.find("alignment")) != key_value_map.end())
        info.alignment_path = (*it).second;
      if ((it = key_value_map.find("hmmnet")) != key_value_map.end())
        info.hmmnet_path = (*it).second;
      if ((it = key_value_map.find("den-hmmnet")) != key_value_map.end())
        info.den_hmmnet_path = (*it).second;
      if ((it = key_value_map.find("lna")) != key_value_map.end())
        info.lna_path = (*it).second;
      if ((it = key_value_map.find("start-time")) != key_value_map.end())
        info.start_time = atof((*it).second.c_str());
      if ((it = key_value_map.find("end-time")) != key_value_map.end())
        info.end_time = atof((*it).second.c_str());
      if ((it = key_value_map.find("start-line")) != key_value_map.end())
        info.start_line = atoi((*it).second.c_str());
      if ((it = key_value_map.find("end-line")) != key_value_map.end())
        info.end_line = atoi((*it).second.c_str());
      if ((it = key_value_map.find("speaker")) != key_value_map.end())
        info.speaker_id = (*it).second;
      if ((it = key_value_map.find("utterance")) != key_value_map.end())
        info.utterance_id = (*it).second;
    }

    cur_line++;
  }
}

PhnReader*
Recipe::Info::init_phn_files(HmmSet *model, bool relative_sample_nums,
                              bool out_phn, FeatureGenerator *fea_gen,
                              bool raw_audio, PhnReader *phn_reader)
{
  float frame_rate;

  // Open the audio file
  fea_gen->open(audio_path, raw_audio);

  // Initialize the PhnReader
  if (phn_reader == NULL)
    phn_reader = new PhnReader;
  if (model == NULL)
    phn_reader->set_state_num_labels(true);
  phn_reader->set_relative_sample_numbers(relative_sample_nums);
  frame_rate = fea_gen->frame_rate();
  phn_reader->set_frame_rate(frame_rate);
  phn_reader->set_hmm_model(model);

  // Open the segmentation
  phn_reader->open(out_phn?alignment_path:transcript_path);

  if (start_time > 0 || end_time > 0)
  {
    phn_reader->set_frame_limits((int)(start_time * frame_rate),
                                (int)(end_time * frame_rate));
  }
  if (start_line > 0 || end_line > 0)
  {
    phn_reader->set_line_limits(start_line, end_line);
  }

  return phn_reader;
}

HmmNetBaumWelch*
Recipe::Info::init_hmmnet_files(HmmSet *model, bool den_hmmnet,
                                FeatureGenerator *fea_gen,
                                bool raw_audio, HmmNetBaumWelch *hnbw)
{
  // Open the audio file
  fea_gen->open(audio_path, raw_audio);

  // Initialize the HmmNetBaumWelch
  if (hnbw == NULL)
  {
    if (model == NULL)
      throw std::string("Recipe::Info::init_hmmnet_files: HMM model is required if hnbw==NULL");
     hnbw= new HmmNetBaumWelch(*fea_gen, *model);
  }

  // Open the HMM network
  if (den_hmmnet)
    hnbw->open(den_hmmnet_path);
  else
    hnbw->open(hmmnet_path);

  if (start_time > 0 || end_time > 0)
  {
    float frame_rate = fea_gen->frame_rate();
    hnbw->set_frame_limits((int)(start_time * frame_rate),
                           (int)(end_time * frame_rate));
  }

  return hnbw;
}
<|endoftext|>


<commit_before>
#if !defined(WIN32)

#include "GenericVRPNServer.h"
#include <iostream>
#include <cmath>

#define DEFAULT_PORT 50555

int main(int argc, char** argv)
{
	GenericVRPNServer* vrpnServer = GenericVRPNServer::getInstance(DEFAULT_PORT);

	vrpnServer->addButton("button_test", 1);
	vrpnServer->addAnalog("analog_test", 2);

	double time = 0;
	double period = 0;

	while (true)
	{
		if (period >= 2 * M_PI)
		{
			vrpnServer->changeButtonState("button_test", 0, 1 - vrpnServer->getButtonState("button_test", 0));
			period = 0;
		}

		vrpnServer->changeAnalogState("analog_test", sin(time), cos(time));

		time = time + 0.01;
		period = period + 0.01;

		vrpnServer->loop();

		// sleep for 10 miliseconds (on Unix)
		usleep(10000);
	}

	return 0;
}

#endif // !WIN32<commit_msg>Applications: Fixed vrpn-to-openvibe build on Fedora<commit_after>
#if !defined(WIN32)

#include "GenericVRPNServer.h"
#include <iostream>
#include <cmath>
#include <unistd.h>

#define DEFAULT_PORT 50555

int main(int argc, char** argv)
{
	GenericVRPNServer* vrpnServer = GenericVRPNServer::getInstance(DEFAULT_PORT);

	vrpnServer->addButton("button_test", 1);
	vrpnServer->addAnalog("analog_test", 2);

	double time = 0;
	double period = 0;

	while (true)
	{
		if (period >= 2 * M_PI)
		{
			vrpnServer->changeButtonState("button_test", 0, 1 - vrpnServer->getButtonState("button_test", 0));
			period = 0;
		}

		vrpnServer->changeAnalogState("analog_test", sin(time), cos(time));

		time = time + 0.01;
		period = period + 0.01;

		vrpnServer->loop();

		// sleep for 10 miliseconds (on Unix)
		usleep(10000);
	}

	return 0;
}

#endif // !WIN32<|endoftext|>


<commit_before>#include "Scene.hpp"

/* SDL and OpenGL */
#include <GL/glu.h>
#include <GL/glx.h>

#include <math.h>

#include <iostream>

void Scene::abort (std::string message) {
    fprintf(stderr, "%s [%s]\n", message.c_str(), SDL_GetError());
    exit(1);
}

void Scene::initialize () {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        abort("Failed to initialize SDL Video!\n");
    }

    // tell system which funciton to process when exit() call is made
    atexit(SDL_Quit);

    // set opengl attributes
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE,     8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,   8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,    8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,   8);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,   24);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    resize(_width, _height);
    configScreen(1, 1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    onInitialize();
}

int Scene::run () {
    initialize();

    while (!_stopped) {
        update(1.0f / 60.0f);
        draw();

        //usleep(1000000 / 60);
    }

    return _exitCode;
}

void Scene::quit () {
    if (onQuit()) {
        stop(0);
    }
}

void Scene::stop (int code) {
    if (!_stopped) {
        _stopped = true;
        _exitCode = code;
        onStop(code);
    }
}

void Scene::update (float delta) {
    processEvents();
    onUpdate(delta);
}

void Scene::draw () {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    for (std::vector<Camera2D>::iterator cam = _cameras.begin(); cam != _cameras.end(); ++cam) {
        // Viewport
        Quad vp = cam->vp();
        glViewport(
            _width*vp.left,
            _height - (_height*vp.top),
            _width*(vp.right-vp.left),
            _height*(vp.top-vp.bottom)
        );

        // Projection
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        Quad view = cam->view(_width, _height);
        gluOrtho2D(view.left, view.right, view.bottom, view.top);

        onDraw();
    }
    SDL_GL_SwapBuffers();
}

void Scene::processEvents () {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
            /* Quit the scene */
            case SDL_QUIT: {
                quit();
                break;
            }

            case SDL_VIDEORESIZE: {
                handleResize(event.resize.w, event.resize.h);
                break;
            }

            /* Keyboard Event */
            case SDL_KEYDOWN:
            case SDL_KEYUP: {
                int code = event.key.keysym.sym;

                // Resize the keys array
                if (_keysPressed.size() < code+1) {
                    _keysPressed.resize(code+1);
                }

                // Call the event method
                if (event.type == SDL_KEYDOWN) {
                    _keysPressed[code] = true;
                    onKeyDown(code);
                } else if (event.type == SDL_KEYUP) {
                    _keysPressed[code] = false;
                    onKeyUp(code);
                }

                break;
            }

            case SDL_MOUSEMOTION: {
                _mouseX = event.motion.x;
                _mouseY = event.motion.y;

                findCurrentCamera();

                onMouseMove(_mouseX, _mouseY);

                break;
            }

            /* Mouse Event */
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP: {
                int btn = event.button.button;

                // Resize the keys array
                if (_mousePressed.size() < btn+1) {
                    _mousePressed.resize(btn+1);
                }

                // Call the event method
                if (event.type == SDL_MOUSEBUTTONDOWN) {
                    _mousePressed[btn] = true;
                    onMouseDown(btn);
                } else if (event.type == SDL_MOUSEBUTTONUP) {
                    _mousePressed[btn] = false;
                    onMouseUp(btn);
                }

                break;
            }
        }
    }
}

bool Scene::isKeyPressed (int code) {
    if (_keysPressed.size() < code+1) {
        return false;
    }

    return _keysPressed[code];
}

void Scene::resize (int width, int height) {
    handleResize(width, height);
}

void Scene::handleResize (int width, int height) {
    // Resize the OpenGL Viewport
    SDL_SetVideoMode(width, height, 32, SDL_OPENGL|SDL_RESIZABLE);

    // Update the local fields
    _width = width;
    _height = height;

    // Event
    onResize(width, height);
}

void Scene::zoomTo (double zoom) {
    _cameras[_cam].zoom(zoom);
}

void Scene::zoom (double zoom) {
    _cameras[_cam].zoom(_cameras[_cam].zoom() + zoom);
}

void Scene::moveTo (double x, double y) {
    _cameras[_cam].pos(Point2D(x, y));
}

void Scene::move (double x, double y) {
    _cameras[_cam].pos(Point2D(
        _cameras[_cam].pos().x + x / exp(_cameras[_cam].zoom()),
        _cameras[_cam].pos().y + y / exp(_cameras[_cam].zoom())
    ));
}

void Scene::configScreen (int rows, int cols) {
    _cameras.clear();

    GLdouble w = 1.0 / cols;
    GLdouble h = 1.0 / rows;

    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            Quad vp;
            vp.left = c*w;
            vp.right = (c+1)*w;
            vp.bottom = r*h;
            vp.top = (r+1)*h;

            Camera2D cam;
            cam.vp(vp);

            _cameras.push_back(cam);
        }
    }

    findCurrentCamera();
}

void Scene::findCurrentCamera () {
    double xr = (double) _mouseX / _width;
    double yr = (double) _mouseY / _height;

    for (int i = 0; i < _cameras.size(); i++) {
        Quad vp = _cameras[i].vp();
        if (xr >= vp.left && xr < vp.right && yr >= vp.bottom && yr < vp.top) {
            _cam = i;
        }
    }
}

Point2D Scene::getMouseWorldPosition () {
    Quad vp = cam().vp();
    Quad view = cam().view(_width, _height);

    /* Normalized mouse position */
    Point2D mr (
        (double) _mouseX / _width,
        (double) _mouseY / _height);

    /* Within-camera mouse position */
    Point2D cmp (
        (mr.x - vp.left) / (vp.right - vp.left),
        (mr.y - vp.top) / (vp.bottom - vp.top));

    Point2D mwp (
        view.left + cmp.x*(view.right-view.left),
        view.bottom + cmp.y*(view.top-view.bottom));

    printf("%f, %f\r", mwp.x, mwp.y);
    fflush(stdout);
    return mwp;
}<commit_msg>Removed printf<commit_after>#include "Scene.hpp"

/* SDL and OpenGL */
#include <GL/glu.h>
#include <GL/glx.h>

#include <math.h>

#include <iostream>

void Scene::abort (std::string message) {
    fprintf(stderr, "%s [%s]\n", message.c_str(), SDL_GetError());
    exit(1);
}

void Scene::initialize () {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        abort("Failed to initialize SDL Video!\n");
    }

    // tell system which funciton to process when exit() call is made
    atexit(SDL_Quit);

    // set opengl attributes
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE,     8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,   8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,    8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,   8);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,   24);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    resize(_width, _height);
    configScreen(1, 1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    onInitialize();
}

int Scene::run () {
    initialize();

    while (!_stopped) {
        update(1.0f / 60.0f);
        draw();

        //usleep(1000000 / 60);
    }

    return _exitCode;
}

void Scene::quit () {
    if (onQuit()) {
        stop(0);
    }
}

void Scene::stop (int code) {
    if (!_stopped) {
        _stopped = true;
        _exitCode = code;
        onStop(code);
    }
}

void Scene::update (float delta) {
    processEvents();
    onUpdate(delta);
}

void Scene::draw () {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    for (std::vector<Camera2D>::iterator cam = _cameras.begin(); cam != _cameras.end(); ++cam) {
        // Viewport
        Quad vp = cam->vp();
        glViewport(
            _width*vp.left,
            _height - (_height*vp.top),
            _width*(vp.right-vp.left),
            _height*(vp.top-vp.bottom)
        );

        // Projection
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        Quad view = cam->view(_width, _height);
        gluOrtho2D(view.left, view.right, view.bottom, view.top);

        onDraw();
    }
    SDL_GL_SwapBuffers();
}

void Scene::processEvents () {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
            /* Quit the scene */
            case SDL_QUIT: {
                quit();
                break;
            }

            case SDL_VIDEORESIZE: {
                handleResize(event.resize.w, event.resize.h);
                break;
            }

            /* Keyboard Event */
            case SDL_KEYDOWN:
            case SDL_KEYUP: {
                int code = event.key.keysym.sym;

                // Resize the keys array
                if (_keysPressed.size() < code+1) {
                    _keysPressed.resize(code+1);
                }

                // Call the event method
                if (event.type == SDL_KEYDOWN) {
                    _keysPressed[code] = true;
                    onKeyDown(code);
                } else if (event.type == SDL_KEYUP) {
                    _keysPressed[code] = false;
                    onKeyUp(code);
                }

                break;
            }

            case SDL_MOUSEMOTION: {
                _mouseX = event.motion.x;
                _mouseY = event.motion.y;

                findCurrentCamera();

                onMouseMove(_mouseX, _mouseY);

                break;
            }

            /* Mouse Event */
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP: {
                int btn = event.button.button;

                // Resize the keys array
                if (_mousePressed.size() < btn+1) {
                    _mousePressed.resize(btn+1);
                }

                // Call the event method
                if (event.type == SDL_MOUSEBUTTONDOWN) {
                    _mousePressed[btn] = true;
                    onMouseDown(btn);
                } else if (event.type == SDL_MOUSEBUTTONUP) {
                    _mousePressed[btn] = false;
                    onMouseUp(btn);
                }

                break;
            }
        }
    }
}

bool Scene::isKeyPressed (int code) {
    if (_keysPressed.size() < code+1) {
        return false;
    }

    return _keysPressed[code];
}

void Scene::resize (int width, int height) {
    handleResize(width, height);
}

void Scene::handleResize (int width, int height) {
    // Resize the OpenGL Viewport
    SDL_SetVideoMode(width, height, 32, SDL_OPENGL|SDL_RESIZABLE);

    // Update the local fields
    _width = width;
    _height = height;

    // Event
    onResize(width, height);
}

void Scene::zoomTo (double zoom) {
    _cameras[_cam].zoom(zoom);
}

void Scene::zoom (double zoom) {
    _cameras[_cam].zoom(_cameras[_cam].zoom() + zoom);
}

void Scene::moveTo (double x, double y) {
    _cameras[_cam].pos(Point2D(x, y));
}

void Scene::move (double x, double y) {
    _cameras[_cam].pos(Point2D(
        _cameras[_cam].pos().x + x / exp(_cameras[_cam].zoom()),
        _cameras[_cam].pos().y + y / exp(_cameras[_cam].zoom())
    ));
}

void Scene::configScreen (int rows, int cols) {
    _cameras.clear();

    GLdouble w = 1.0 / cols;
    GLdouble h = 1.0 / rows;

    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            Quad vp;
            vp.left = c*w;
            vp.right = (c+1)*w;
            vp.bottom = r*h;
            vp.top = (r+1)*h;

            Camera2D cam;
            cam.vp(vp);

            _cameras.push_back(cam);
        }
    }

    findCurrentCamera();
}

void Scene::findCurrentCamera () {
    double xr = (double) _mouseX / _width;
    double yr = (double) _mouseY / _height;

    for (int i = 0; i < _cameras.size(); i++) {
        Quad vp = _cameras[i].vp();
        if (xr >= vp.left && xr < vp.right && yr >= vp.bottom && yr < vp.top) {
            _cam = i;
        }
    }
}

Point2D Scene::getMouseWorldPosition () {
    Quad vp = cam().vp();
    Quad view = cam().view(_width, _height);

    /* Normalized mouse position */
    Point2D mr (
        (double) _mouseX / _width,
        (double) _mouseY / _height);

    /* Within-camera mouse position */
    Point2D cmp (
        (mr.x - vp.left) / (vp.right - vp.left),
        (mr.y - vp.top) / (vp.bottom - vp.top));

    Point2D mwp (
        view.left + cmp.x*(view.right-view.left),
        view.bottom + cmp.y*(view.top-view.bottom));

    return mwp;
}<|endoftext|>


<commit_before>// Hume Library Version 0.4.3

#include "Sound.h"

namespace hm
{
	Sound::Sound() : Audio(), chunk(nullptr)
	{

	}

	Sound::~Sound()
	{
		close();
	}

	void Sound::open(std::string filename)
	{
		// Close chunk if there is one loaded.
		close();

		chunk = Mix_LoadWAV(filename.c_str());
		if(chunk == nullptr)
		{
			Logger::log("Failed to load " + filename + ".");
			Logger::log(Mix_GetError());
		}
		return;
	}

	void Sound::close()
	{
		if(chunk != nullptr)
		{
			Mix_FreeChunk(chunk);
			chunk = nullptr;
		}

		return;
	}

	void Sound::play()
	{
		Mix_PlayChannel(-1, chunk, 0);
		return;
	}

	void Sound::setVolume(int v)
	{
		// Clamp values.
		if(volume < 0)
			volume = 0;
		else if(volume > 100)
			volume = 100;
		volume = v;

		// Convert volume value to scale of 1 - 128.
		float mixer_volume = ceilf(volume * 1.28);
		hm::Logger::log("Setting chunk volume to " + std::to_string(volume) + " (" + std::to_string(int(mixer_volume)) + ")" + ".");
		Mix_VolumeChunk(chunk, int(mixer_volume));
		return;
	}
}
<commit_msg>Refuse to play chunk if none is loaded.<commit_after>// Hume Library Version 0.4.3

#include "Sound.h"

namespace hm
{
	Sound::Sound() : Audio(), chunk(nullptr)
	{

	}

	Sound::~Sound()
	{
		close();
	}

	void Sound::open(std::string filename)
	{
		// Close chunk if there is one loaded.
		close();

		chunk = Mix_LoadWAV(filename.c_str());
		if(chunk == nullptr)
		{
			Logger::log("Failed to load " + filename + ".");
			Logger::log(Mix_GetError());
		}
		return;
	}

	void Sound::close()
	{
		if(chunk != nullptr)
		{
			Mix_FreeChunk(chunk);
			chunk = nullptr;
		}

		return;
	}

	void Sound::play()
	{
		if(chunk == nullptr)
		{
			Logger::log("Chunk has not been loaded.", hm::ERROR);
			return;
		}

		Mix_PlayChannel(-1, chunk, 0);
		return;
	}

	void Sound::setVolume(int v)
	{
		// Clamp values.
		if(volume < 0)
			volume = 0;
		else if(volume > 100)
			volume = 100;
		volume = v;

		// Convert volume value to scale of 1 - 128.
		float mixer_volume = ceilf(volume * 1.28);
		hm::Logger::log("Setting chunk volume to " + std::to_string(volume) + " (" + std::to_string(int(mixer_volume)) + ")" + ".");
		Mix_VolumeChunk(chunk, int(mixer_volume));
		return;
	}
}
<|endoftext|>


<commit_before>#ifndef ref_ptr_hh_INCLUDED
#define ref_ptr_hh_INCLUDED

#include <utility>

namespace Kakoune
{

struct WorstMatch { [[gnu::always_inline]] WorstMatch(...) {} };

[[gnu::always_inline]]
inline void ref_ptr_moved(WorstMatch, void*, void*) noexcept {}

template<typename T, typename TForOverload = T>
struct RefPtr
{
    RefPtr() = default;
    explicit RefPtr(T* ptr) : m_ptr(ptr) { acquire(); }
    ~RefPtr() { release(); }
    RefPtr(const RefPtr& other) : m_ptr(other.m_ptr) { acquire(); }
    RefPtr(RefPtr&& other)
        noexcept(noexcept(std::declval<RefPtr>().moved(nullptr)))
        : m_ptr(other.m_ptr) { other.m_ptr = nullptr; moved(&other); }

    RefPtr& operator=(const RefPtr& other)
    {
        release();
        m_ptr = other.m_ptr;
        acquire();
        return *this;
    }
    RefPtr& operator=(RefPtr&& other)
    {
        release();
        m_ptr = other.m_ptr;
        other.m_ptr = nullptr;
        moved(&other);
        return *this;
    }

    RefPtr& operator=(T* ptr)
    {
        release();
        m_ptr = ptr;
        acquire();
        return *this;
    }

    [[gnu::always_inline]]
    T* operator->() const { return m_ptr; }
    [[gnu::always_inline]]
    T& operator*() const { return *m_ptr; }

    [[gnu::always_inline]]
    T* get() const { return m_ptr; }

    [[gnu::always_inline]]
    explicit operator bool() const { return m_ptr; }

    void reset(T* ptr = nullptr)
    {
        if (ptr == m_ptr)
            return;
        release();
        m_ptr = ptr;
        acquire();
    }

    friend bool operator==(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr == rhs.m_ptr; }
    friend bool operator!=(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr != rhs.m_ptr; }

private:
    T* m_ptr = nullptr;

    [[gnu::always_inline]]
    void acquire()
    {
        if (m_ptr)
            inc_ref_count(static_cast<TForOverload*>(m_ptr), this);
    }

    [[gnu::always_inline]]
    void release()
    {
        if (m_ptr)
            dec_ref_count(static_cast<TForOverload*>(m_ptr), this);
        m_ptr = nullptr;
    }

    [[gnu::always_inline]]
    void moved(void* from)
        noexcept(noexcept(ref_ptr_moved(static_cast<TForOverload*>(nullptr), nullptr, nullptr)))
    {
        if (m_ptr)
            ref_ptr_moved(static_cast<TForOverload*>(m_ptr), from, this);
    }
};

}

#endif // ref_ptr_hh_INCLUDED
<commit_msg>Avoid unneeded inc/dec rec in RefPtr::operator=<commit_after>#ifndef ref_ptr_hh_INCLUDED
#define ref_ptr_hh_INCLUDED

#include <utility>

namespace Kakoune
{

struct WorstMatch { [[gnu::always_inline]] WorstMatch(...) {} };

[[gnu::always_inline]]
inline void ref_ptr_moved(WorstMatch, void*, void*) noexcept {}

template<typename T, typename TForOverload = T>
struct RefPtr
{
    RefPtr() = default;
    explicit RefPtr(T* ptr) : m_ptr(ptr) { acquire(); }
    ~RefPtr() { release(); }
    RefPtr(const RefPtr& other) : m_ptr(other.m_ptr) { acquire(); }
    RefPtr(RefPtr&& other)
        noexcept(noexcept(std::declval<RefPtr>().moved(nullptr)))
        : m_ptr(other.m_ptr) { other.m_ptr = nullptr; moved(&other); }

    RefPtr& operator=(const RefPtr& other)
    {
        if (other.m_ptr != m_ptr)
        {
            release();
            m_ptr = other.m_ptr;
            acquire();
        }
        return *this;
    }

    RefPtr& operator=(RefPtr&& other)
    {
        release();
        m_ptr = other.m_ptr;
        other.m_ptr = nullptr;
        moved(&other);
        return *this;
    }

    RefPtr& operator=(T* ptr)
    {
        if (ptr != m_ptr)
        {
            release();
            m_ptr = ptr;
            acquire();
        }
        return *this;
    }

    [[gnu::always_inline]]
    T* operator->() const { return m_ptr; }
    [[gnu::always_inline]]
    T& operator*() const { return *m_ptr; }

    [[gnu::always_inline]]
    T* get() const { return m_ptr; }

    [[gnu::always_inline]]
    explicit operator bool() const { return m_ptr; }

    void reset(T* ptr = nullptr)
    {
        if (ptr == m_ptr)
            return;
        release();
        m_ptr = ptr;
        acquire();
    }

    friend bool operator==(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr == rhs.m_ptr; }
    friend bool operator!=(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr != rhs.m_ptr; }

private:
    T* m_ptr = nullptr;

    [[gnu::always_inline]]
    void acquire()
    {
        if (m_ptr)
            inc_ref_count(static_cast<TForOverload*>(m_ptr), this);
    }

    [[gnu::always_inline]]
    void release()
    {
        if (m_ptr)
            dec_ref_count(static_cast<TForOverload*>(m_ptr), this);
        m_ptr = nullptr;
    }

    [[gnu::always_inline]]
    void moved(void* from)
        noexcept(noexcept(ref_ptr_moved(static_cast<TForOverload*>(nullptr), nullptr, nullptr)))
    {
        if (m_ptr)
            ref_ptr_moved(static_cast<TForOverload*>(m_ptr), from, this);
    }
};

}

#endif // ref_ptr_hh_INCLUDED
<|endoftext|>


<commit_before>/*
 * Copyright 2013-2016 Grigory Demchenko (aka gridem)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "verifier.h"

#include <set>

template<typename T>
std::set<T> operator-(const std::set<T>& s1, const std::set<T>& s2)
{
    std::set<T> res;
    for (auto&& t: s1)
        if (s2.count(t) == 0)
            res.insert(t);
    return res;
}

template<typename T>
void operator|=(std::set<T>& s, const T& t)
{
    s.insert(t);
}

template<typename T>
void operator|=(std::set<T>& s, const std::set<T>& t)
{
    s.insert(t.begin(), t.end());
}

template<typename T>
void operator&=(std::set<T>& s, const std::set<T>& t)
{
    std::set<T> newSet;
    for (auto&& e: s)
        if (t.count(e) == 1)
            newSet |= e;
    s = std::move(newSet);
}

template<typename T>
std::set<T> operator|(const std::set<T>& s1, const std::set<T>& s2)
{
    std::set<T> res = s1;
    res |= s2;
    return res;
}

struct MsgId
{
    int id = nextId();

    static int nextId()
    {
        static int i = 0;
        return ++ i;
    }

    bool operator<(const MsgId& m) const
    {
        return id < m.id;
    }
};

using NodeId = int;

using CarrySet = std::set<MsgId>;
using NodesSet = std::set<NodeId>;

struct Apply
{
    MsgId id;
};

struct Vote
{
    CarrySet carrySet;
    NodeId srcNode;
    NodesSet nodesSet;
};

struct Commit
{
    CarrySet carrySet;
};

struct Replob : Service<Replob>
{
    using Service<Replob>::on;

    enum struct State
    {
        Initial, // can vote only in initial state
        Voted,
        Completed,
    };

    void on(const Apply& apply)
    {
        SLOG("Apply");
        NodesSet nodesSet;
        for (NodeId nId = 0; nId < config->nodes; ++ nId)
            nodesSet |= nId;
        on(Vote{CarrySet{apply.id}, context().currentNode, nodesSet});
    }

    void on(const Vote& vote)
    {
        if (state_ == State::Completed)
            return;
        if (!nodes_.empty() && nodes_.count(context().sourceNode) == 0)
            return;
        carries_ |= vote.carrySet;
        if (nodes_.empty())
        {
            nodes_ = vote.nodesSet;
        }
        else if (nodes_ != vote.nodesSet)
        {
            state_ = State::Initial;
            nodes_ &= vote.nodesSet;
            voted_.clear(); // must be below nodes_ because nodesSet can be reference to voted_!!!
        }
        voted_ |= vote.srcNode;
        voted_ |= context().currentNode;
        if (voted_  == nodes_)
        {
            on(Commit{carries_});
        }
        else if (state_ == State::Initial)
        {
            state_ = State::Voted;
            // TODO: use broadcastSet().<method>(nodes_set, ...)
            this->triggerAllExceptSelf<Replob>(Vote{carries_, context().currentNode, nodes_});
        }

    }

    void on(const Commit& commit)
    {
        if (state_ == State::Completed)
            return;
        state_ = State::Completed;
        carries_ = commit.carrySet;
        this->triggerAllExceptSelf<Replob>(Commit{carries_});
        complete();
    }

    void on(const Disconnect&)
    {
        NodesSet nodesSet;
        for (NodeId nId = 0; nId < config->nodes; ++ nId)
            if (nId != context().sourceNode)
                nodesSet |= nId;
        on(Vote{carries_, context().currentNode, nodesSet});
    }

    void complete()
    {
        commited = carries_;
    }

    State state_ = State::Initial;
    NodesSet nodes_;
    NodesSet voted_;
    CarrySet carries_;
    CarrySet commited;
    An<Config> config;
};

struct Client : Service<Client>
{
    using Service<Client>::on;

    void on(const Init&)
    {
        this->trigger<Replob>(Apply{});
    }

    void on(const Disconnect&)
    {
        disconnected |= context().sourceNode;
    }

    void test()
    {
        CHECK3(!accessor.service<Replob>(0).commited.empty(), "must be commited");
    }

    NodesSet disconnected;
    ServiceAccessor accessor;
};

void replob()
{
    TLOG("Testing replob commit");
    ServiceCreator c;
    c.create<Client>(0);
    c.create<Replob>(0, c.config().nodes);

    ServiceAccessor a;
    TrueScheduler s {[&a] {
        //CHECK3(!a.service<Replob>(0).commited.empty(), "must be commited");
        a.service<Client>(0).test();
    }};
    s.run();
}
<commit_msg>Cleanup<commit_after>/*
 * Copyright 2013-2016 Grigory Demchenko (aka gridem)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "verifier.h"

#include <set>

template<typename T>
std::set<T> operator-(const std::set<T>& s1, const std::set<T>& s2)
{
    std::set<T> res;
    for (auto&& t: s1)
        if (s2.count(t) == 0)
            res.insert(t);
    return res;
}

template<typename T>
void operator|=(std::set<T>& s, const T& t)
{
    s.insert(t);
}

template<typename T>
void operator|=(std::set<T>& s, const std::set<T>& t)
{
    s.insert(t.begin(), t.end());
}

template<typename T>
void operator&=(std::set<T>& s, const std::set<T>& t)
{
    std::set<T> newSet;
    for (auto&& e: s)
        if (t.count(e) == 1)
            newSet |= e;
    s = std::move(newSet);
}

template<typename T>
std::set<T> operator|(const std::set<T>& s1, const std::set<T>& s2)
{
    std::set<T> res = s1;
    res |= s2;
    return res;
}

struct MsgId
{
    int id = nextId();

    static int nextId()
    {
        static int i = 0;
        return ++ i;
    }

    bool operator<(const MsgId& m) const
    {
        return id < m.id;
    }
};

using NodeId = int;

using CarrySet = std::set<MsgId>;
using NodesSet = std::set<NodeId>;

struct Apply
{
    MsgId id;
};

struct Vote
{
    CarrySet carrySet;
    NodeId srcNode;
    NodesSet nodesSet;
};

struct Commit
{
    CarrySet carrySet;
};

struct Replob : Service<Replob>
{
    using Service<Replob>::on;

    enum struct State
    {
        Initial, // can vote only in initial state
        Voted,
        Completed,
    };

    void on(const Apply& apply)
    {
        SLOG("Apply");
        NodesSet nodesSet;
        for (NodeId nId = 0; nId < config->nodes; ++ nId)
            nodesSet |= nId;
        on(Vote{CarrySet{apply.id}, context().currentNode, nodesSet});
    }

    void on(const Vote& vote)
    {
        if (state_ == State::Completed)
            return;
        if (!nodes_.empty() && nodes_.count(context().sourceNode) == 0)
            return;
        carries_ |= vote.carrySet;
        if (nodes_.empty())
        {
            nodes_ = vote.nodesSet;
        }
        else if (nodes_ != vote.nodesSet)
        {
            state_ = State::Initial;
            nodes_ &= vote.nodesSet;
            voted_.clear(); // must be below nodes_ because nodesSet can be reference to voted_!!!
        }
        voted_ |= vote.srcNode;
        voted_ |= context().currentNode;
        if (voted_  == nodes_)
        {
            on(Commit{carries_});
        }
        else if (state_ == State::Initial)
        {
            state_ = State::Voted;
            // TODO: use broadcastSet().<method>(nodes_set, ...)
            this->triggerAllExceptSelf<Replob>(Vote{carries_, context().currentNode, nodes_});
        }

    }

    void on(const Commit& commit)
    {
        if (state_ == State::Completed)
            return;
        state_ = State::Completed;
        carries_ = commit.carrySet;
        this->triggerAllExceptSelf<Replob>(Commit{carries_});
        complete();
    }

    void on(const Disconnect&)
    {
        NodesSet nodesSet;
        for (NodeId nId = 0; nId < config->nodes; ++ nId)
            if (nId != context().sourceNode)
                nodesSet |= nId;
        on(Vote{carries_, context().currentNode, nodesSet});
    }

    void complete()
    {
        commited = carries_;
    }

    State state_ = State::Initial;
    NodesSet nodes_;
    NodesSet voted_;
    CarrySet carries_;
    CarrySet commited;
    An<Config> config;
};

struct Client : Service<Client>
{
    using Service<Client>::on;

    void on(const Init&)
    {
        this->trigger<Replob>(Apply{});
    }

    void on(const Disconnect&)
    {
        disconnected |= context().sourceNode;
    }

    void test()
    {
        CHECK3(!accessor.service<Replob>(0).commited.empty(), "must be commited");
    }

    NodesSet disconnected;
    ServiceAccessor accessor;
};

void replob()
{
    TLOG("Testing replob commit");
    ServiceCreator c;
    c.create<Client>(0);
    c.create<Replob>(0, c.config().nodes);

    ServiceAccessor a;
    TrueScheduler s {[&a] {
        a.service<Client>(0).test();
    }};
    s.run();
}
<|endoftext|>