<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: stub.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 22:44:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/
#include <sal/alloca.h>
#include <osl/diagnose.h>

#include <uno/data.h>
#include <uno/mapping.hxx>

#include <bridges/remote/stub.hxx>
#include <bridges/remote/proxy.hxx>
#include <bridges/remote/context.h>
#include <bridges/remote/bridgeimpl.hxx>

#include "remote_types.hxx"

#if OSL_DEBUG_LEVEL > 1
#include <bridges/remote/counter.hxx>
static MyCounter thisCounter( "DEBUG : Uno2RemoteStub");
#endif

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

namespace bridges_remote {

Uno2RemoteStub::Uno2RemoteStub( uno_Interface *pUnoI,
                                rtl_uString *pOid,
                                typelib_InterfaceTypeDescription *pType,
                                uno_Environment *pEnvUno,
                                uno_Environment *pEnvRemote ) :
    m_sOid( pOid ),
    m_pType(  pType ),
    m_pUnoI( pUnoI ),
    m_nRef( 1 ),
    m_pEnvUno( pEnvUno ),
    m_pEnvRemote( pEnvRemote ),
    m_mapRemote2Uno( pEnvRemote, pEnvUno ),
    m_mapUno2Remote( pEnvUno, pEnvRemote )
{
    typelib_typedescription_acquire( (typelib_TypeDescription * )m_pType );
    m_pEnvUno->acquire( m_pEnvUno );
    m_pEnvRemote->acquire( m_pEnvRemote );

    acquire = thisAcquire;
    release = thisRelease;
    pDispatcher = thisDispatch;

    m_pEnvUno->pExtEnv->registerInterface( m_pEnvUno->pExtEnv,
                                           (void **)&m_pUnoI,
                                           m_sOid.pData,
                                           m_pType );
    m_pUnoI->acquire( m_pUnoI );
#if OSL_DEBUG_LEVEL > 1
    thisCounter.acquire();
#endif
}

Uno2RemoteStub::~Uno2RemoteStub()
{
    m_pEnvUno->pExtEnv->revokeInterface( m_pEnvUno->pExtEnv , m_pUnoI );

    typelib_typedescription_release( (typelib_TypeDescription * )m_pType );
    m_pUnoI->release( m_pUnoI );
    m_pEnvUno->release( m_pEnvUno );
    m_pEnvRemote->release( m_pEnvRemote );
#if OSL_DEBUG_LEVEL > 1
    thisCounter.release();
#endif
}

void Uno2RemoteStub::thisFree( uno_ExtEnvironment *pEnvRemote, void *pThis )
{
    delete ( Uno2RemoteStub * ) pThis;
}

void Uno2RemoteStub::thisAcquire( remote_Interface *pThis )
{
    Uno2RemoteStub *p = ( Uno2RemoteStub * ) pThis;
    if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) )
    {

        p->m_pEnvRemote->pExtEnv->registerProxyInterface(
            p->m_pEnvRemote->pExtEnv,
            (void**)&pThis,
            Uno2RemoteStub::thisFree,
            p->m_sOid.pData,
            p->m_pType );

        OSL_ASSERT( (remote_Interface*) p == pThis );
    }
}

void Uno2RemoteStub::thisRelease( remote_Interface *pThis )
{
    Uno2RemoteStub *p = ( Uno2RemoteStub * ) pThis;
    if (! osl_decrementInterlockedCount( &(p->m_nRef) ))
    {
        p->m_pEnvRemote->pExtEnv->revokeInterface( p->m_pEnvRemote->pExtEnv, pThis );
    }
}

void Uno2RemoteStub::thisDispatch(
    remote_Interface * pRemoteI,
    typelib_TypeDescription * pType,
    void * pReturn,
    void * ppArgs[],
    uno_Any ** ppException )
{
    Uno2RemoteStub *p = ( Uno2RemoteStub * ) pRemoteI;

    RemoteThreadCounter counter( p->m_pEnvRemote );

    typelib_InterfaceMethodTypeDescription *pMethodType = 0;
    typelib_InterfaceAttributeTypeDescription *pAttributeType = 0;
    typelib_TypeDescription *pReturnType = 0;
    typelib_TypeDescription **ppArgType = 0;
    sal_Int32 nArgCount = 0;
    sal_Bool *pbIsIn = 0;
    sal_Bool *pbIsOut = 0;
    sal_Bool bConversionNeededForReturn = sal_False;
    sal_Bool *pbConversionNeeded = 0;

    sal_Int32 i;
    //--------------------------------
    // Collect all needed types !
    //--------------------------------
    if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pType->eTypeClass )
    {
        pAttributeType = ( typelib_InterfaceAttributeTypeDescription * ) pType;
        if( pReturn )
        {
            TYPELIB_DANGER_GET( &pReturnType , pAttributeType->pAttributeTypeRef );
            bConversionNeededForReturn = remote_relatesToInterface( pReturnType );
        }
        else
        {
            nArgCount = 1;
            ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) );
            pbIsIn  = ( sal_Bool * ) alloca( sizeof( sal_Bool ) );
            pbIsOut = ( sal_Bool * ) alloca( sizeof( sal_Bool ) );
            pbConversionNeeded = ( sal_Bool * ) alloca( sizeof( sal_Bool ) );
            pbIsIn[0]  = sal_True;
            pbIsOut[0] = sal_False;
            ppArgType[0] = 0;
            TYPELIB_DANGER_GET( &( ppArgType[0] ) , pAttributeType->pAttributeTypeRef );
            pbConversionNeeded[0] = remote_relatesToInterface( ppArgType[0] );
        }
    }
    if( typelib_TypeClass_INTERFACE_METHOD == pType->eTypeClass )
    {
        pMethodType = ( typelib_InterfaceMethodTypeDescription * ) pType;
        TYPELIB_DANGER_GET( &pReturnType , pMethodType->pReturnTypeRef );
        bConversionNeededForReturn = remote_relatesToInterface( pReturnType );
        nArgCount = pMethodType->nParams;
        ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) * nArgCount );
        pbIsIn  = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount );
        pbIsOut = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount );
        pbConversionNeeded = ( sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount );

        for( i = 0 ; i < nArgCount ; i ++ )
        {
            ppArgType[i] = 0;
            TYPELIB_DANGER_GET( & (ppArgType[i]) ,  pMethodType->pParams[i].pTypeRef );
            pbIsIn[i]  = pMethodType->pParams[i].bIn;
            pbIsOut[i] = pMethodType->pParams[i].bOut;
            pbConversionNeeded[i] = remote_relatesToInterface( ppArgType[i] );
        }
    }

    // create Mapping

    void *pUnoReturn = 0;
    void **ppUnoArgs = 0;

    if( pReturnType )
    {
        if( bConversionNeededForReturn )
        {
            pUnoReturn = alloca( pReturnType->nSize );
        }
        else
        {
            pUnoReturn = pReturn;
        }
    }

    ppUnoArgs = (void **) alloca( nArgCount * sizeof( void * ) );
    for( i = 0 ; i < nArgCount ; i ++ )
    {
        if( pbConversionNeeded[i] )
        {
            ppUnoArgs[i] = alloca( ppArgType[i]->nSize );
            if( pbIsIn[i] )
            {
                uno_copyAndConvertData(
                    ppUnoArgs[i],
                    ppArgs[i],
                    ppArgType[i],
                    p->m_mapRemote2Uno.get()
                    );
            }
        }
        else
        {
            ppUnoArgs[i] = ppArgs[i];
        }
    }

    // do the call
    uno_Any any;
    uno_Any *pAny = &any;

    p->m_pUnoI->pDispatcher( p->m_pUnoI,
                             pType,
                             pUnoReturn,
                             ppUnoArgs,
                             &pAny);

    if( ! pAny )
    {
        // ------------------
        // No Exception
        // ------------------

        // Map return value
        if( pReturnType && bConversionNeededForReturn )
        {
            uno_copyAndConvertData(
                pReturn ,
                pUnoReturn,
                pReturnType,
                p->m_mapUno2Remote.get() );
            uno_destructData( pUnoReturn , pReturnType, 0 );
        }

        // map arguments
        for( i = 0 ; i < nArgCount ; i ++ )
        {
            if( pbConversionNeeded[i] )
            {
                if( pbIsIn[i] ) {
                    if( pbIsOut[i] ) {
                        uno_destructData(
                            ppArgs[i] ,
                            ppArgType[i] ,
                            remote_release );
                        uno_copyAndConvertData( ppArgs[i] ,
                                                ppUnoArgs[i],
                                                ppArgType[i],
                                                p->m_mapUno2Remote.get()  );
                    }
                }
                else // pure out
                {
                    uno_copyAndConvertData( ppArgs[i] ,
                                            ppUnoArgs[i],
                                            ppArgType[i],
                                            p->m_mapUno2Remote.get() );
                }
                uno_destructData( ppUnoArgs[i],
                                  ppArgType[i],
                                  0 );
            }
        }
        *ppException = 0;
    }
    else
    {
        // -----------------------
        // an exception occured
        // -----------------------
        typelib_TypeDescription *pAnyType = 0;
        getCppuType( (Any*) 0 ).getDescription( &pAnyType );
        uno_copyAndConvertData( *ppException ,
                                pAny ,
                                pAnyType,
                                p->m_mapUno2Remote.get() );
        uno_destructData( pAny , pAnyType , 0 );
        typelib_typedescription_release( pAnyType );

        // destruct uno in parameters ( out parameters have not been constructed )
        for( i = 0 ; i < nArgCount ; i ++ )
        {
            if( pbConversionNeeded[i] && pbIsIn[i] )
            {
                uno_destructData( ppUnoArgs[i],
                                  ppArgType[i],
                                  0 );
            }
        }
    }

    //--------------------------
    // release all acquired types
    //--------------------------
    if( pReturnType )
    {
        TYPELIB_DANGER_RELEASE( pReturnType );
    }
    for( i = 0 ; i < nArgCount ; i ++ )
    {
        TYPELIB_DANGER_RELEASE( ppArgType[ i] );
    }
}

} // end namespace bridges_remote
<commit_msg>INTEGRATION: CWS warnings01 (1.7.88); FILE MERGED 2005/09/22 18:34:17 sb 1.7.88.2: RESYNC: (1.7-1.8); FILE MERGED 2005/09/09 12:38:09 sb 1.7.88.1: #i53898# Made code warning-free.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: stub.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 23:51:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/
#include <sal/alloca.h>
#include <osl/diagnose.h>

#include <uno/data.h>
#include <uno/mapping.hxx>

#include <bridges/remote/stub.hxx>
#include <bridges/remote/proxy.hxx>
#include <bridges/remote/context.h>
#include <bridges/remote/bridgeimpl.hxx>

#include "remote_types.hxx"

#if OSL_DEBUG_LEVEL > 1
#include <bridges/remote/counter.hxx>
static MyCounter thisCounter( "DEBUG : Uno2RemoteStub");
#endif

using namespace ::com::sun::star::uno;
using namespace bridges_remote;

extern "C" {

void SAL_CALL thisRelease( remote_Interface *pThis )
{
    Uno2RemoteStub *p = ( Uno2RemoteStub * ) pThis;
    if (! osl_decrementInterlockedCount( &(p->m_nRef) ))
    {
        p->m_pEnvRemote->pExtEnv->revokeInterface( p->m_pEnvRemote->pExtEnv, pThis );
    }
}

void SAL_CALL thisDispatch(
    remote_Interface * pRemoteI,
    typelib_TypeDescription const * pType,
    void * pReturn,
    void * ppArgs[],
    uno_Any ** ppException )
{
    Uno2RemoteStub *p = ( Uno2RemoteStub * ) pRemoteI;

    RemoteThreadCounter counter( p->m_pEnvRemote );

    typelib_InterfaceMethodTypeDescription *pMethodType = 0;
    typelib_InterfaceAttributeTypeDescription *pAttributeType = 0;
    typelib_TypeDescription *pReturnType = 0;
    typelib_TypeDescription **ppArgType = 0;
    sal_Int32 nArgCount = 0;
    sal_Bool *pbIsIn = 0;
    sal_Bool *pbIsOut = 0;
    sal_Bool bConversionNeededForReturn = sal_False;
    sal_Bool *pbConversionNeeded = 0;

    sal_Int32 i;
    //--------------------------------
    // Collect all needed types !
    //--------------------------------
    if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pType->eTypeClass )
    {
        pAttributeType = ( typelib_InterfaceAttributeTypeDescription * ) pType;
        if( pReturn )
        {
            TYPELIB_DANGER_GET( &pReturnType , pAttributeType->pAttributeTypeRef );
            bConversionNeededForReturn = remote_relatesToInterface( pReturnType );
        }
        else
        {
            nArgCount = 1;
            ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) );
            pbIsIn  = ( sal_Bool * ) alloca( sizeof( sal_Bool ) );
            pbIsOut = ( sal_Bool * ) alloca( sizeof( sal_Bool ) );
            pbConversionNeeded = ( sal_Bool * ) alloca( sizeof( sal_Bool ) );
            pbIsIn[0]  = sal_True;
            pbIsOut[0] = sal_False;
            ppArgType[0] = 0;
            TYPELIB_DANGER_GET( &( ppArgType[0] ) , pAttributeType->pAttributeTypeRef );
            pbConversionNeeded[0] = remote_relatesToInterface( ppArgType[0] );
        }
    }
    if( typelib_TypeClass_INTERFACE_METHOD == pType->eTypeClass )
    {
        pMethodType = ( typelib_InterfaceMethodTypeDescription * ) pType;
        TYPELIB_DANGER_GET( &pReturnType , pMethodType->pReturnTypeRef );
        bConversionNeededForReturn = remote_relatesToInterface( pReturnType );
        nArgCount = pMethodType->nParams;
        ppArgType = (typelib_TypeDescription **) alloca( sizeof( void * ) * nArgCount );
        pbIsIn  = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount );
        pbIsOut = (sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount );
        pbConversionNeeded = ( sal_Bool * ) alloca( sizeof( sal_Bool ) * nArgCount );

        for( i = 0 ; i < nArgCount ; i ++ )
        {
            ppArgType[i] = 0;
            TYPELIB_DANGER_GET( & (ppArgType[i]) ,  pMethodType->pParams[i].pTypeRef );
            pbIsIn[i]  = pMethodType->pParams[i].bIn;
            pbIsOut[i] = pMethodType->pParams[i].bOut;
            pbConversionNeeded[i] = remote_relatesToInterface( ppArgType[i] );
        }
    }

    // create Mapping

    void *pUnoReturn = 0;
    void **ppUnoArgs = 0;

    if( pReturnType )
    {
        if( bConversionNeededForReturn )
        {
            pUnoReturn = alloca( pReturnType->nSize );
        }
        else
        {
            pUnoReturn = pReturn;
        }
    }

    ppUnoArgs = (void **) alloca( nArgCount * sizeof( void * ) );
    for( i = 0 ; i < nArgCount ; i ++ )
    {
        if( pbConversionNeeded[i] )
        {
            ppUnoArgs[i] = alloca( ppArgType[i]->nSize );
            if( pbIsIn[i] )
            {
                uno_copyAndConvertData(
                    ppUnoArgs[i],
                    ppArgs[i],
                    ppArgType[i],
                    p->m_mapRemote2Uno.get()
                    );
            }
        }
        else
        {
            ppUnoArgs[i] = ppArgs[i];
        }
    }

    // do the call
    uno_Any any;
    uno_Any *pAny = &any;

    p->m_pUnoI->pDispatcher( p->m_pUnoI,
                             pType,
                             pUnoReturn,
                             ppUnoArgs,
                             &pAny);

    if( ! pAny )
    {
        // ------------------
        // No Exception
        // ------------------

        // Map return value
        if( pReturnType && bConversionNeededForReturn )
        {
            uno_copyAndConvertData(
                pReturn ,
                pUnoReturn,
                pReturnType,
                p->m_mapUno2Remote.get() );
            uno_destructData( pUnoReturn , pReturnType, 0 );
        }

        // map arguments
        for( i = 0 ; i < nArgCount ; i ++ )
        {
            if( pbConversionNeeded[i] )
            {
                if( pbIsIn[i] ) {
                    if( pbIsOut[i] ) {
                        uno_destructData(
                            ppArgs[i] ,
                            ppArgType[i] ,
                            remote_release );
                        uno_copyAndConvertData( ppArgs[i] ,
                                                ppUnoArgs[i],
                                                ppArgType[i],
                                                p->m_mapUno2Remote.get()  );
                    }
                }
                else // pure out
                {
                    uno_copyAndConvertData( ppArgs[i] ,
                                            ppUnoArgs[i],
                                            ppArgType[i],
                                            p->m_mapUno2Remote.get() );
                }
                uno_destructData( ppUnoArgs[i],
                                  ppArgType[i],
                                  0 );
            }
        }
        *ppException = 0;
    }
    else
    {
        // -----------------------
        // an exception occured
        // -----------------------
        typelib_TypeDescription *pAnyType = 0;
        getCppuType( (Any*) 0 ).getDescription( &pAnyType );
        uno_copyAndConvertData( *ppException ,
                                pAny ,
                                pAnyType,
                                p->m_mapUno2Remote.get() );
        uno_destructData( pAny , pAnyType , 0 );
        typelib_typedescription_release( pAnyType );

        // destruct uno in parameters ( out parameters have not been constructed )
        for( i = 0 ; i < nArgCount ; i ++ )
        {
            if( pbConversionNeeded[i] && pbIsIn[i] )
            {
                uno_destructData( ppUnoArgs[i],
                                  ppArgType[i],
                                  0 );
            }
        }
    }

    //--------------------------
    // release all acquired types
    //--------------------------
    if( pReturnType )
    {
        TYPELIB_DANGER_RELEASE( pReturnType );
    }
    for( i = 0 ; i < nArgCount ; i ++ )
    {
        TYPELIB_DANGER_RELEASE( ppArgType[ i] );
    }
}

}

namespace bridges_remote {

void acquireUno2RemoteStub( remote_Interface *pThis )
{
    Uno2RemoteStub *p = ( Uno2RemoteStub * ) pThis;
    if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) )
    {

        p->m_pEnvRemote->pExtEnv->registerProxyInterface(
            p->m_pEnvRemote->pExtEnv,
            (void**)&pThis,
            freeUno2RemoteStub,
            p->m_sOid.pData,
            p->m_pType );

        OSL_ASSERT( (remote_Interface*) p == pThis );
    }
}

void freeUno2RemoteStub(uno_ExtEnvironment *, void * stub) {
    delete static_cast< Uno2RemoteStub * >(stub);
}

Uno2RemoteStub::Uno2RemoteStub( uno_Interface *pUnoI,
                                rtl_uString *pOid,
                                typelib_InterfaceTypeDescription *pType,
                                uno_Environment *pEnvUno,
                                uno_Environment *pEnvRemote ) :
    m_sOid( pOid ),
    m_pType(  pType ),
    m_pUnoI( pUnoI ),
    m_nRef( 1 ),
    m_pEnvUno( pEnvUno ),
    m_pEnvRemote( pEnvRemote ),
    m_mapRemote2Uno( pEnvRemote, pEnvUno ),
    m_mapUno2Remote( pEnvUno, pEnvRemote )
{
    typelib_typedescription_acquire( (typelib_TypeDescription * )m_pType );
    m_pEnvUno->acquire( m_pEnvUno );
    m_pEnvRemote->acquire( m_pEnvRemote );

    acquire = acquireUno2RemoteStub;
    release = thisRelease;
    pDispatcher = thisDispatch;

    m_pEnvUno->pExtEnv->registerInterface( m_pEnvUno->pExtEnv,
                                           (void **)&m_pUnoI,
                                           m_sOid.pData,
                                           m_pType );
    m_pUnoI->acquire( m_pUnoI );
#if OSL_DEBUG_LEVEL > 1
    thisCounter.acquire();
#endif
}

Uno2RemoteStub::~Uno2RemoteStub()
{
    m_pEnvUno->pExtEnv->revokeInterface( m_pEnvUno->pExtEnv , m_pUnoI );

    typelib_typedescription_release( (typelib_TypeDescription * )m_pType );
    m_pUnoI->release( m_pUnoI );
    m_pEnvUno->release( m_pEnvUno );
    m_pEnvRemote->release( m_pEnvRemote );
#if OSL_DEBUG_LEVEL > 1
    thisCounter.release();
#endif
}

} // end namespace bridges_remote
<|endoftext|>


<commit_before>
#include "Chip8Timers.hpp"

	// constructor
Chip8Timers::Chip8Timers() {
		// initialize the timer values
		DT = 0;
		ST = 0;
		// set the thread pointer to null
		timerThread = NULL;
		// thread is NOT running initially
		runThread = false;
	}

	// destructor
Chip8Timers::~Chip8Timers() {
		// stop the timer thread
		stopTimers();
		// thread has completed, no more objects need
		//  to be destroyed.
	}

void Chip8Timers::setDelayTimer(u8 value) {
		timerLock.lock();
		DT = value;
		timerLock.unlock();
	}

u8   Chip8Timers::readDelayTimer() {
		return DT;
	}

void Chip8Timers::setSoundTimer(u8 value) {
		timerLock.lock();
		ST = value;
		timerLock.unlock();
	}

u8   Chip8Timers::readSoundTimer() {
		return ST;
	}

	// checks the status of the timer thread
bool Chip8Timers::isStarted() {
		return runThread;
	}

void Chip8Timers::startTimers() {
		runThread = true;
		if (timerThread == NULL) {
			// spawn thread to run the updateTimers() method
			std::function<bool()> func = std::bind(&Chip8Timers::updateTimers, this);
			timerThread = new std::thread(&invokeFuncAtInterval, func, 60L);
		}

	}

void Chip8Timers::stopTimers() {
		// check to see if the thread has been started
		if (runThread) {
			// set the thread to complete.
			runThread = false;
			// wait for the thread to complete
			timerThread->join();
		}
	}

	// method method that will be ran
	//  inside the timer updating thread
bool Chip8Timers::updateTimers() {
		// lock the timers to modifications
		timerLock.lock();
		// if timers are 0, set to zero
		// else > 0, decrement by 1
		DT = DT == 0 ?
			0 :
			DT - 1;
		ST = ST == 0 ?
			0 :
			ST - 1;
		timerLock.unlock();

		// return whether or not thread should keep running
		return runThread;
	}<commit_msg>Memory management: delete thread object after thread is stopped and no longer useful.<commit_after>
#include "Chip8Timers.hpp"

	// constructor
Chip8Timers::Chip8Timers() {
		// initialize the timer values
		DT = 0;
		ST = 0;
		// set the thread pointer to null
		timerThread = NULL;
		// thread is NOT running initially
		runThread = false;
	}

	// destructor
Chip8Timers::~Chip8Timers() {
		// stop the timer thread
		stopTimers();
		// thread has completed, no more objects need
		//  to be destroyed.
	}

void Chip8Timers::setDelayTimer(u8 value) {
		timerLock.lock();
		DT = value;
		timerLock.unlock();
	}

u8   Chip8Timers::readDelayTimer() {
		return DT;
	}

void Chip8Timers::setSoundTimer(u8 value) {
		timerLock.lock();
		ST = value;
		timerLock.unlock();
	}

u8   Chip8Timers::readSoundTimer() {
		return ST;
	}

	// checks the status of the timer thread
bool Chip8Timers::isStarted() {
		return runThread;
	}

void Chip8Timers::startTimers() {
		runThread = true;
		if (timerThread == NULL) {
			// spawn thread to run the updateTimers() method
			std::function<bool()> func = std::bind(&Chip8Timers::updateTimers, this);
			timerThread = new std::thread(&invokeFuncAtInterval, func, 60L);
		}

	}

void Chip8Timers::stopTimers() {
		// check to see if the thread has been started
		if (runThread) {
			// set the thread to complete.
			runThread = false;
			// wait for the thread to complete
			timerThread->join();
            delete timerThread;
		}
	}

	// method method that will be ran
	//  inside the timer updating thread
bool Chip8Timers::updateTimers() {
		// lock the timers to modifications
		timerLock.lock();
		// if timers are 0, set to zero
		// else > 0, decrement by 1
		DT = DT == 0 ?
			0 :
			DT - 1;
		ST = ST == 0 ?
			0 :
			ST - 1;
		timerLock.unlock();

		// return whether or not thread should keep running
		return runThread;
	}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 <stddef.h>
#include <stdint.h>

#include "perfetto/base/utils.h"
#include "perfetto/tracing/core/basic_types.h"
#include "src/profiling/memory/shared_ring_buffer.h"
#include "src/profiling/memory/unwinding.h"
#include "src/profiling/memory/unwound_messages.h"

namespace perfetto {
namespace profiling {
namespace {

class NopDelegate : public UnwindingWorker::Delegate {
  void PostAllocRecord(AllocRecord) override {}
  void PostFreeRecord(FreeRecord) override {}
  void PostSocketDisconnected(DataSourceInstanceID, pid_t) override {}
};

int FuzzUnwinding(const uint8_t* data, size_t size) {
  SharedRingBuffer::Buffer buf(const_cast<uint8_t*>(data), size);

  pid_t self_pid = getpid();
  DataSourceInstanceID id = 0;
  UnwindingMetadata metadata(self_pid,
                             base::OpenFile("/proc/self/maps", O_RDONLY),
                             base::OpenFile("/proc/self/mem", O_RDONLY));

  NopDelegate nop_delegate;
  UnwindingWorker::HandleBuffer(buf, &metadata, id, self_pid, &nop_delegate);
  return 0;
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  return perfetto::profiling::FuzzUnwinding(data, size);
}
<commit_msg>Fix fuzzer build error.<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 <stddef.h>
#include <stdint.h>

#include "perfetto/base/utils.h"
#include "perfetto/tracing/core/basic_types.h"
#include "src/profiling/memory/shared_ring_buffer.h"
#include "src/profiling/memory/unwinding.h"
#include "src/profiling/memory/unwound_messages.h"

namespace perfetto {
namespace profiling {
namespace {

class NopDelegate : public UnwindingWorker::Delegate {
  void PostAllocRecord(AllocRecord) override {}
  void PostFreeRecord(FreeRecord) override {}
  void PostSocketDisconnected(DataSourceInstanceID,
                              pid_t,
                              SharedRingBuffer::Stats) override {}
};

int FuzzUnwinding(const uint8_t* data, size_t size) {
  SharedRingBuffer::Buffer buf(const_cast<uint8_t*>(data), size);

  pid_t self_pid = getpid();
  DataSourceInstanceID id = 0;
  UnwindingMetadata metadata(self_pid,
                             base::OpenFile("/proc/self/maps", O_RDONLY),
                             base::OpenFile("/proc/self/mem", O_RDONLY));

  NopDelegate nop_delegate;
  UnwindingWorker::HandleBuffer(buf, &metadata, id, self_pid, &nop_delegate);
  return 0;
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  return perfetto::profiling::FuzzUnwinding(data, size);
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <sstream>
#include <fstream>

typedef std::string  tstring;
typedef unsigned int ruint;

void main(int paramCount, char* params[])
{
	//if (paramCount != 2)
	//{
	//	std::cerr << "using version.exe <rev.number>" << std::endl;
	//	return;
	//}

	//std::stringstream revStr;
	//revStr << params[1];
	//ruint rev;
	//revStr >> rev;
	//const tstring versionFileName = "C:/rdo/rdo_studio/rdo_studio/res/version.h";

	ruint rev;
	std::cin >> rev;
	const tstring versionFileName = "../app/rdo_studio_mfc/res/version.h";

	std::ifstream ifile(versionFileName.c_str());
	if (ifile.is_open())
	{
		std::stringstream revStr;
		revStr << rev;
		std::stringstream ifileStr;
		while (true)
		{
			tstring str;
			ifile >> str;
			if (str.find(revStr.str()) != tstring::npos)
			{
				return;
			}
			if (ifile.eof())
			{
				break;
			}
		}
	}

	std::ofstream ofile;
	ofile.open(versionFileName.c_str());
	ofile << "#define FILEVER        1,1,0," << rev << std::endl;
	ofile << "#define PRODUCTVER     FILEVER" << std::endl;
	ofile << "#define STRCONVERT(x)  #x" << std::endl;
	ofile << "#define STR(x)         STRCONVERT(x)" << std::endl;
	ofile.close();
}
<commit_msg> - имя выходного файла стало параметром<commit_after>#include <string>
#include <iostream>
#include <sstream>
#include <fstream>

typedef std::string  tstring;
typedef unsigned int ruint;

void main(int paramCount, char* params[])
{
	if (paramCount != 2)
	{
		std::cerr << "using version.exe <filename.h>" << std::endl;
		return;
	}

	ruint rev;
	std::cin >> rev;
	const tstring versionFileName = params[1];

	std::ifstream ifile(versionFileName.c_str());
	if (ifile.is_open())
	{
		std::stringstream revStr;
		revStr << rev;
		std::stringstream ifileStr;
		while (true)
		{
			tstring str;
			ifile >> str;
			if (str.find(revStr.str()) != tstring::npos)
			{
				return;
			}
			if (ifile.eof())
			{
				break;
			}
		}
	}

	std::ofstream ofile;
	ofile.open(versionFileName.c_str());
	ofile << "#define FILEVER        1,1,0," << rev << std::endl;
	ofile << "#define PRODUCTVER     FILEVER" << std::endl;
	ofile << "#define STRCONVERT(x)  #x" << std::endl;
	ofile << "#define STR(x)         STRCONVERT(x)" << std::endl;
	ofile.close();
}
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "serializer/log/lba/disk_structure.hpp"
#include "containers/scoped.hpp"

lba_disk_structure_t::lba_disk_structure_t(extent_manager_t *_em, file_t *_file)
    : em(_em), file(_file), superblock_extent(NULL), last_extent(NULL)
{
}

lba_disk_structure_t::lba_disk_structure_t(extent_manager_t *_em, file_t *_file, lba_shard_metablock_t *metablock)
    : em(_em), file(_file)
{
    if (metablock->last_lba_extent_offset != NULL_OFFSET) {
        last_extent = new lba_disk_extent_t(em, file, metablock->last_lba_extent_offset, metablock->last_lba_extent_entries_count);
    } else {
        last_extent = NULL;
    }

    if (metablock->lba_superblock_offset != NULL_OFFSET) {
        superblock_offset = metablock->lba_superblock_offset;
        startup_superblock_count = metablock->lba_superblock_entries_count;

        int64_t superblock_extent_offset = superblock_offset - (superblock_offset % em->extent_size);
        size_t superblock_size = ceil_aligned(
            offsetof(lba_superblock_t, entries[0]) + sizeof(lba_superblock_entry_t) * startup_superblock_count,
            DEVICE_BLOCK_SIZE);
        superblock_extent = new extent_t(em, file, superblock_extent_offset,
            superblock_offset + superblock_size - superblock_extent_offset);

        startup_superblock_buffer = reinterpret_cast<lba_superblock_t *>(malloc_aligned(superblock_size, DEVICE_BLOCK_SIZE));
        superblock_extent->read(
            superblock_offset - superblock_extent_offset,
            superblock_size,
            startup_superblock_buffer,
            this);
    } else {
        superblock_extent = NULL;
    }
}

void lba_disk_structure_t::set_load_callback(load_callback_t *cb) {
    if (superblock_extent) {
        start_callback = cb;
    } else {
        cb->on_lba_load();
    }
}

void lba_disk_structure_t::on_extent_read() {

    /* We just read the superblock extent. */

    for (int i = 0; i < startup_superblock_count; i++) {
        extents_in_superblock.push_back(
            new lba_disk_extent_t(em, file,
                startup_superblock_buffer->entries[i].offset,
                startup_superblock_buffer->entries[i].lba_entries_count));
    }

    free(startup_superblock_buffer);

    start_callback->on_lba_load();
}

void lba_disk_structure_t::add_entry(block_id_t block_id, repli_timestamp_t recency,
                                     flagged_off64_t offset, uint32_t ser_block_size,
                                     file_account_t *io_account, extent_transaction_t *txn) {
    if (last_extent && last_extent->full()) {
        /* We have filled up an extent. Transfer it to the superblock. */

        extents_in_superblock.push_back(last_extent);
        last_extent = NULL;

        /* Since there is a new extent on the superblock, we need to rewrite the superblock. */

        write_superblock(io_account, txn);
    }

    if (!last_extent) {
        last_extent = new lba_disk_extent_t(em, file, io_account);
    }

    rassert(!last_extent->full());

    last_extent->add_entry(lba_entry_t::make(block_id, recency, offset, ser_block_size), io_account);
}

std::set<lba_disk_extent_t *> lba_disk_structure_t::get_inactive_extents() const {
    std::set<lba_disk_extent_t *> result;
    for (lba_disk_extent_t *e = extents_in_superblock.head();
         e; e = extents_in_superblock.next(e)) {
        result.insert(e);
    }
    return result;
}

void lba_disk_structure_t::destroy_extents(const std::set<lba_disk_extent_t *> &extents,
                                           file_account_t *io_account,
                                           extent_transaction_t *txn) {
    for (auto e = extents.begin(); e != extents.end(); ++e) {
        extents_in_superblock.remove(*e);
        (*e)->destroy(txn);
    }
    write_superblock(io_account, txn);
}

void lba_disk_structure_t::write_superblock(file_account_t *io_account,
                                            extent_transaction_t *txn) {

    /* Make sure that the superblock extent has enough room for a new superblock. */

    size_t superblock_size = sizeof(lba_superblock_t)
        + sizeof(lba_superblock_entry_t) * extents_in_superblock.size();
    rassert(superblock_size <= em->extent_size);

    if (superblock_extent
            && superblock_extent->amount_filled + superblock_size > em->extent_size) {
        superblock_extent->destroy(txn);
        superblock_extent = NULL;
    }

    if (!superblock_extent) {
        superblock_extent = new extent_t(em, file);
    }

    /* Prepare the new superblock. */

    scoped_malloc_t<char> buffer(ceil_aligned(superblock_size, DEVICE_BLOCK_SIZE));
    bzero(buffer.get(), ceil_aligned(superblock_size, DEVICE_BLOCK_SIZE));

    lba_superblock_t *new_superblock = reinterpret_cast<lba_superblock_t *>(buffer.get());
    memcpy(new_superblock->magic, lba_super_magic, LBA_SUPER_MAGIC_SIZE);
    int i = 0;
    for (lba_disk_extent_t *e = extents_in_superblock.head();
         e; e = extents_in_superblock.next(e)) {
        new_superblock->entries[i].offset = e->data->extent_ref.offset();
        new_superblock->entries[i].lba_entries_count = e->count;
        i++;
    }

    /* Write the new superblock */

    superblock_offset = superblock_extent->extent_ref.offset()
        + superblock_extent->amount_filled;
    superblock_extent->append(buffer.get(),
            ceil_aligned(superblock_size, DEVICE_BLOCK_SIZE), io_account);
}

class lba_writer_t :
    public extent_t::sync_callback_t
{
public:
    int outstanding_cbs;
    lba_disk_structure_t::sync_callback_t *callback;

    explicit lba_writer_t(lba_disk_structure_t::sync_callback_t *cb) {
        outstanding_cbs = 0;
        callback = cb;
    }

    void on_extent_sync() {
        outstanding_cbs--;
        if (outstanding_cbs == 0) {
            if (callback) callback->on_lba_sync();
            delete this;
        }
    }
};

void lba_disk_structure_t::sync(file_account_t *io_account, sync_callback_t *cb) {
    lba_writer_t *writer = new lba_writer_t(cb);

    /* Count how many things need to be synced */
    if (last_extent) writer->outstanding_cbs++;
    if (superblock_extent) writer->outstanding_cbs++;
    writer->outstanding_cbs += extents_in_superblock.size();

    /* Sync the things that need to be synced */
    if (writer->outstanding_cbs == 0) {
        cb->on_lba_sync();
        delete writer;
    } else {
        if (last_extent) last_extent->sync(io_account, writer);
        if (superblock_extent) superblock_extent->sync(writer);
        for (lba_disk_extent_t *e = extents_in_superblock.head(); e; e = extents_in_superblock.next(e)) {
            e->sync(io_account, writer);
        }
    }
}

struct reader_t
{
    lba_disk_structure_t *ds;   // The disk structure we are reading from
    in_memory_index_t *index;   // The in-memory-index we are reading into
    lba_disk_structure_t::read_callback_t *rcb;   // Who to call back when we finish

    /* extent_reader_t takes care of reading a single extent. */
    struct extent_reader_t :
        public extent_t::read_callback_t
    {
        reader_t *parent;   // Our reader_t that we were created by
        int index;   // parent->readers[index] = this
        lba_disk_extent_t *extent;   // The extent we are supposed to read
        lba_disk_extent_t::read_info_t read_info;   // Opaque data used by extent_t::read()
        bool have_read;   // true if our extent has been loaded from disk

        /* true if the extent before us called read_step_2(). We keep track of this
        because we must be sure to call read_step_2() in the right order at all times;
        otherwise more recent LBA data would be applied after less recent LBA data
        and the LBA would be corrupted. */
        bool prev_done;

        extent_reader_t(reader_t *p, lba_disk_extent_t *e)
            : parent(p), extent(e), have_read(false)
        {
            index = parent->readers.size();
            parent->readers.push_back(this);

            if (index == 0) {
                // We are the first; we don't have to wait for a previous extent
                prev_done = true;
            } else {
                prev_done = false;
            }
        }
        void start_reading() {
            parent->active_readers++;
            extent->read_step_1(&read_info, this);
        }
        void on_extent_read() {   // Called when our extent has been read from disk
            rassert(!have_read);
            have_read = true;
            if (prev_done) done();
        }
        void on_prev_done() {   // Called by the previous extent_reader_t when it finishes
            rassert(!prev_done);
            prev_done = true;
            if (have_read) done();
        }
        void done() {
            extent->read_step_2(&read_info, parent->index);
            parent->active_readers--;
            parent->start_more_readers();
            if (index == static_cast<int>(parent->readers.size()) - 1) {
                parent->done();
            } else {
                parent->readers[index+1]->on_prev_done();
            }
            delete this;
        }
    };
    std::vector< extent_reader_t* > readers;

    int next_reader;   // The index of the next reader that we should call start_reading() on

    // The number of readers that have done start_reading() but not done(). Used to throttle the
    // reading process so that we stay under LBA_READ_BUFFER_SIZE.
    int active_readers;

    reader_t(lba_disk_structure_t *_ds, in_memory_index_t *_index, lba_disk_structure_t::read_callback_t *cb)
        : ds(_ds), index(_index), rcb(cb)
    {
        for (lba_disk_extent_t *e = ds->extents_in_superblock.head(); e; e = ds->extents_in_superblock.next(e)) {
            new extent_reader_t(this, e);
        }
        if (ds->last_extent) new extent_reader_t(this, ds->last_extent);

        /* The constructor for extent_reader_t pushed them onto our 'readers' vector. So now we
        have a vector with an extent_reader_t object for each extent we need to read, but none
        of them have been started yet. */

        if (readers.empty()) {
            done();
        } else {
            next_reader = 0;
            active_readers = 0;
            start_more_readers();
        }
    }

    void start_more_readers() {
        int limit = std::max<int>(LBA_READ_BUFFER_SIZE / ds->em->extent_size / LBA_SHARD_FACTOR, 1);
        while (next_reader != static_cast<int>(readers.size()) && active_readers < limit) {
            readers[next_reader++]->start_reading();
        }
    }

    void done() {
        rcb->on_lba_extents_read();
        delete this;
    }
};

void lba_disk_structure_t::read(in_memory_index_t *index, read_callback_t *cb) {
    new reader_t(this, index, cb);
}

void lba_disk_structure_t::prepare_metablock(lba_shard_metablock_t *mb_out) {
    if (last_extent) {
        mb_out->last_lba_extent_offset = last_extent->data->extent_ref.offset();
        mb_out->last_lba_extent_entries_count = last_extent->count;

        rassert(divides(DEVICE_BLOCK_SIZE, offsetof(lba_extent_t, entries[0]) + sizeof(lba_entry_t) * mb_out->last_lba_extent_entries_count));

    } else {
        mb_out->last_lba_extent_offset = NULL_OFFSET;
        mb_out->last_lba_extent_entries_count = 0;
    }

    if (extents_in_superblock.size()) {
        mb_out->lba_superblock_offset = superblock_offset;
        mb_out->lba_superblock_entries_count = extents_in_superblock.size();
    } else {
        mb_out->lba_superblock_offset = NULL_OFFSET;
        mb_out->lba_superblock_entries_count = 0;
    }
}

int lba_disk_structure_t::num_entries_that_can_fit_in_an_extent() const {
    return (em->extent_size - offsetof(lba_extent_t, entries[0])) / sizeof(lba_entry_t);
}

void lba_disk_structure_t::destroy(extent_transaction_t *txn) {
    if (superblock_extent) {
        superblock_extent->destroy(txn);
    }

    while (lba_disk_extent_t *e = extents_in_superblock.head()) {
        extents_in_superblock.remove(e);
        e->destroy(txn);
    }

    if (last_extent) {
        last_extent->destroy(txn);
    }

    delete this;
}

void lba_disk_structure_t::shutdown() {
    if (superblock_extent) superblock_extent->shutdown();
    while (lba_disk_extent_t *e = extents_in_superblock.head()) {
        extents_in_superblock.remove(e);
        e->shutdown();
    }
    if (last_extent) last_extent->shutdown();
    delete this;
}
<commit_msg>Replaced implicit pointer->bool conversion by explicit != NULL comparison<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "serializer/log/lba/disk_structure.hpp"
#include "containers/scoped.hpp"

lba_disk_structure_t::lba_disk_structure_t(extent_manager_t *_em, file_t *_file)
    : em(_em), file(_file), superblock_extent(NULL), last_extent(NULL)
{
}

lba_disk_structure_t::lba_disk_structure_t(extent_manager_t *_em, file_t *_file, lba_shard_metablock_t *metablock)
    : em(_em), file(_file)
{
    if (metablock->last_lba_extent_offset != NULL_OFFSET) {
        last_extent = new lba_disk_extent_t(em, file, metablock->last_lba_extent_offset, metablock->last_lba_extent_entries_count);
    } else {
        last_extent = NULL;
    }

    if (metablock->lba_superblock_offset != NULL_OFFSET) {
        superblock_offset = metablock->lba_superblock_offset;
        startup_superblock_count = metablock->lba_superblock_entries_count;

        int64_t superblock_extent_offset = superblock_offset - (superblock_offset % em->extent_size);
        size_t superblock_size = ceil_aligned(
            offsetof(lba_superblock_t, entries[0]) + sizeof(lba_superblock_entry_t) * startup_superblock_count,
            DEVICE_BLOCK_SIZE);
        superblock_extent = new extent_t(em, file, superblock_extent_offset,
            superblock_offset + superblock_size - superblock_extent_offset);

        startup_superblock_buffer = reinterpret_cast<lba_superblock_t *>(malloc_aligned(superblock_size, DEVICE_BLOCK_SIZE));
        superblock_extent->read(
            superblock_offset - superblock_extent_offset,
            superblock_size,
            startup_superblock_buffer,
            this);
    } else {
        superblock_extent = NULL;
    }
}

void lba_disk_structure_t::set_load_callback(load_callback_t *cb) {
    if (superblock_extent) {
        start_callback = cb;
    } else {
        cb->on_lba_load();
    }
}

void lba_disk_structure_t::on_extent_read() {

    /* We just read the superblock extent. */

    for (int i = 0; i < startup_superblock_count; i++) {
        extents_in_superblock.push_back(
            new lba_disk_extent_t(em, file,
                startup_superblock_buffer->entries[i].offset,
                startup_superblock_buffer->entries[i].lba_entries_count));
    }

    free(startup_superblock_buffer);

    start_callback->on_lba_load();
}

void lba_disk_structure_t::add_entry(block_id_t block_id, repli_timestamp_t recency,
                                     flagged_off64_t offset, uint32_t ser_block_size,
                                     file_account_t *io_account, extent_transaction_t *txn) {
    if (last_extent && last_extent->full()) {
        /* We have filled up an extent. Transfer it to the superblock. */

        extents_in_superblock.push_back(last_extent);
        last_extent = NULL;

        /* Since there is a new extent on the superblock, we need to rewrite the superblock. */

        write_superblock(io_account, txn);
    }

    if (!last_extent) {
        last_extent = new lba_disk_extent_t(em, file, io_account);
    }

    rassert(!last_extent->full());

    last_extent->add_entry(lba_entry_t::make(block_id, recency, offset, ser_block_size), io_account);
}

std::set<lba_disk_extent_t *> lba_disk_structure_t::get_inactive_extents() const {
    std::set<lba_disk_extent_t *> result;
    for (lba_disk_extent_t *e = extents_in_superblock.head();
         e != NULL; e = extents_in_superblock.next(e)) {
        result.insert(e);
    }
    return result;
}

void lba_disk_structure_t::destroy_extents(const std::set<lba_disk_extent_t *> &extents,
                                           file_account_t *io_account,
                                           extent_transaction_t *txn) {
    for (auto e = extents.begin(); e != extents.end(); ++e) {
        extents_in_superblock.remove(*e);
        (*e)->destroy(txn);
    }
    write_superblock(io_account, txn);
}

void lba_disk_structure_t::write_superblock(file_account_t *io_account,
                                            extent_transaction_t *txn) {

    /* Make sure that the superblock extent has enough room for a new superblock. */

    size_t superblock_size = sizeof(lba_superblock_t)
        + sizeof(lba_superblock_entry_t) * extents_in_superblock.size();
    rassert(superblock_size <= em->extent_size);

    if (superblock_extent
            && superblock_extent->amount_filled + superblock_size > em->extent_size) {
        superblock_extent->destroy(txn);
        superblock_extent = NULL;
    }

    if (!superblock_extent) {
        superblock_extent = new extent_t(em, file);
    }

    /* Prepare the new superblock. */

    scoped_malloc_t<char> buffer(ceil_aligned(superblock_size, DEVICE_BLOCK_SIZE));
    bzero(buffer.get(), ceil_aligned(superblock_size, DEVICE_BLOCK_SIZE));

    lba_superblock_t *new_superblock = reinterpret_cast<lba_superblock_t *>(buffer.get());
    memcpy(new_superblock->magic, lba_super_magic, LBA_SUPER_MAGIC_SIZE);
    int i = 0;
    for (lba_disk_extent_t *e = extents_in_superblock.head();
         e != NULL; e = extents_in_superblock.next(e)) {
        new_superblock->entries[i].offset = e->data->extent_ref.offset();
        new_superblock->entries[i].lba_entries_count = e->count;
        i++;
    }

    /* Write the new superblock */

    superblock_offset = superblock_extent->extent_ref.offset()
        + superblock_extent->amount_filled;
    superblock_extent->append(buffer.get(),
            ceil_aligned(superblock_size, DEVICE_BLOCK_SIZE), io_account);
}

class lba_writer_t :
    public extent_t::sync_callback_t
{
public:
    int outstanding_cbs;
    lba_disk_structure_t::sync_callback_t *callback;

    explicit lba_writer_t(lba_disk_structure_t::sync_callback_t *cb) {
        outstanding_cbs = 0;
        callback = cb;
    }

    void on_extent_sync() {
        outstanding_cbs--;
        if (outstanding_cbs == 0) {
            if (callback) callback->on_lba_sync();
            delete this;
        }
    }
};

void lba_disk_structure_t::sync(file_account_t *io_account, sync_callback_t *cb) {
    lba_writer_t *writer = new lba_writer_t(cb);

    /* Count how many things need to be synced */
    if (last_extent) writer->outstanding_cbs++;
    if (superblock_extent) writer->outstanding_cbs++;
    writer->outstanding_cbs += extents_in_superblock.size();

    /* Sync the things that need to be synced */
    if (writer->outstanding_cbs == 0) {
        cb->on_lba_sync();
        delete writer;
    } else {
        if (last_extent) last_extent->sync(io_account, writer);
        if (superblock_extent) superblock_extent->sync(writer);
        for (lba_disk_extent_t *e = extents_in_superblock.head();
             e != NULL; e = extents_in_superblock.next(e)) {
            e->sync(io_account, writer);
        }
    }
}

struct reader_t
{
    lba_disk_structure_t *ds;   // The disk structure we are reading from
    in_memory_index_t *index;   // The in-memory-index we are reading into
    lba_disk_structure_t::read_callback_t *rcb;   // Who to call back when we finish

    /* extent_reader_t takes care of reading a single extent. */
    struct extent_reader_t :
        public extent_t::read_callback_t
    {
        reader_t *parent;   // Our reader_t that we were created by
        int index;   // parent->readers[index] = this
        lba_disk_extent_t *extent;   // The extent we are supposed to read
        lba_disk_extent_t::read_info_t read_info;   // Opaque data used by extent_t::read()
        bool have_read;   // true if our extent has been loaded from disk

        /* true if the extent before us called read_step_2(). We keep track of this
        because we must be sure to call read_step_2() in the right order at all times;
        otherwise more recent LBA data would be applied after less recent LBA data
        and the LBA would be corrupted. */
        bool prev_done;

        extent_reader_t(reader_t *p, lba_disk_extent_t *e)
            : parent(p), extent(e), have_read(false)
        {
            index = parent->readers.size();
            parent->readers.push_back(this);

            if (index == 0) {
                // We are the first; we don't have to wait for a previous extent
                prev_done = true;
            } else {
                prev_done = false;
            }
        }
        void start_reading() {
            parent->active_readers++;
            extent->read_step_1(&read_info, this);
        }
        void on_extent_read() {   // Called when our extent has been read from disk
            rassert(!have_read);
            have_read = true;
            if (prev_done) done();
        }
        void on_prev_done() {   // Called by the previous extent_reader_t when it finishes
            rassert(!prev_done);
            prev_done = true;
            if (have_read) done();
        }
        void done() {
            extent->read_step_2(&read_info, parent->index);
            parent->active_readers--;
            parent->start_more_readers();
            if (index == static_cast<int>(parent->readers.size()) - 1) {
                parent->done();
            } else {
                parent->readers[index+1]->on_prev_done();
            }
            delete this;
        }
    };
    std::vector< extent_reader_t* > readers;

    int next_reader;   // The index of the next reader that we should call start_reading() on

    // The number of readers that have done start_reading() but not done(). Used to throttle the
    // reading process so that we stay under LBA_READ_BUFFER_SIZE.
    int active_readers;

    reader_t(lba_disk_structure_t *_ds, in_memory_index_t *_index, lba_disk_structure_t::read_callback_t *cb)
        : ds(_ds), index(_index), rcb(cb)
    {
        for (lba_disk_extent_t *e = ds->extents_in_superblock.head();
             e != NULL; e = ds->extents_in_superblock.next(e)) {
            new extent_reader_t(this, e);
        }
        if (ds->last_extent) new extent_reader_t(this, ds->last_extent);

        /* The constructor for extent_reader_t pushed them onto our 'readers' vector. So now we
        have a vector with an extent_reader_t object for each extent we need to read, but none
        of them have been started yet. */

        if (readers.empty()) {
            done();
        } else {
            next_reader = 0;
            active_readers = 0;
            start_more_readers();
        }
    }

    void start_more_readers() {
        int limit = std::max<int>(LBA_READ_BUFFER_SIZE / ds->em->extent_size / LBA_SHARD_FACTOR, 1);
        while (next_reader != static_cast<int>(readers.size()) && active_readers < limit) {
            readers[next_reader++]->start_reading();
        }
    }

    void done() {
        rcb->on_lba_extents_read();
        delete this;
    }
};

void lba_disk_structure_t::read(in_memory_index_t *index, read_callback_t *cb) {
    new reader_t(this, index, cb);
}

void lba_disk_structure_t::prepare_metablock(lba_shard_metablock_t *mb_out) {
    if (last_extent) {
        mb_out->last_lba_extent_offset = last_extent->data->extent_ref.offset();
        mb_out->last_lba_extent_entries_count = last_extent->count;

        rassert(divides(DEVICE_BLOCK_SIZE, offsetof(lba_extent_t, entries[0]) + sizeof(lba_entry_t) * mb_out->last_lba_extent_entries_count));

    } else {
        mb_out->last_lba_extent_offset = NULL_OFFSET;
        mb_out->last_lba_extent_entries_count = 0;
    }

    if (extents_in_superblock.size()) {
        mb_out->lba_superblock_offset = superblock_offset;
        mb_out->lba_superblock_entries_count = extents_in_superblock.size();
    } else {
        mb_out->lba_superblock_offset = NULL_OFFSET;
        mb_out->lba_superblock_entries_count = 0;
    }
}

int lba_disk_structure_t::num_entries_that_can_fit_in_an_extent() const {
    return (em->extent_size - offsetof(lba_extent_t, entries[0])) / sizeof(lba_entry_t);
}

void lba_disk_structure_t::destroy(extent_transaction_t *txn) {
    if (superblock_extent) {
        superblock_extent->destroy(txn);
    }

    while (lba_disk_extent_t *e = extents_in_superblock.head()) {
        extents_in_superblock.remove(e);
        e->destroy(txn);
    }

    if (last_extent) {
        last_extent->destroy(txn);
    }

    delete this;
}

void lba_disk_structure_t::shutdown() {
    if (superblock_extent) superblock_extent->shutdown();
    while (lba_disk_extent_t *e = extents_in_superblock.head()) {
        extents_in_superblock.remove(e);
        e->shutdown();
    }
    if (last_extent) last_extent->shutdown();
    delete this;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLTextPropertySetContext.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 18:47:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLTEXTPROPERTYSETCONTEXT_HXX
#define _XMLOFF_XMLTEXTPROPERTYSETCONTEXT_HXX

#ifndef _XMLOFF_XMLPROPERTYSETCONTEXT_HXX
#include "xmlprcon.hxx"
#endif

class XMLTextPropertySetContext : public SvXMLPropertySetContext
{
//  SvXMLImportContextRef xTabStop;
//  SvXMLImportContextRef xBackground;
//  SvXMLImportContextRef xDropCap;
    ::rtl::OUString& rDropCapTextStyleName;

public:
    XMLTextPropertySetContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
                const ::rtl::OUString& rLName,
                 const ::com::sun::star::uno::Reference<
                         ::com::sun::star::xml::sax::XAttributeList >& xAttrList,
                sal_uInt32 nFamily,
                 ::std::vector< XMLPropertyState > &rProps,
                 const UniReference < SvXMLImportPropertyMapper > &rMap,
                ::rtl::OUString& rDopCapTextStyleName );

    virtual ~XMLTextPropertySetContext();

    using SvXMLPropertySetContext::CreateChildContext;
    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
                                   const ::rtl::OUString& rLocalName,
                                   const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList,
                                   ::std::vector< XMLPropertyState > &rProperties,
                                   const XMLPropertyState& rProp);
};

#endif  //  _XMLOFF_XMLTEXTPROPERTYSETCONTEXT_HXX
<commit_msg>INTEGRATION: CWS vgbugs07 (1.4.156); FILE MERGED 2007/06/04 13:23:40 vg 1.4.156.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLTextPropertySetContext.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:12:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLTEXTPROPERTYSETCONTEXT_HXX
#define _XMLOFF_XMLTEXTPROPERTYSETCONTEXT_HXX

#ifndef _XMLOFF_XMLPROPERTYSETCONTEXT_HXX
#include <xmloff/xmlprcon.hxx>
#endif

class XMLTextPropertySetContext : public SvXMLPropertySetContext
{
//  SvXMLImportContextRef xTabStop;
//  SvXMLImportContextRef xBackground;
//  SvXMLImportContextRef xDropCap;
    ::rtl::OUString& rDropCapTextStyleName;

public:
    XMLTextPropertySetContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
                const ::rtl::OUString& rLName,
                 const ::com::sun::star::uno::Reference<
                         ::com::sun::star::xml::sax::XAttributeList >& xAttrList,
                sal_uInt32 nFamily,
                 ::std::vector< XMLPropertyState > &rProps,
                 const UniReference < SvXMLImportPropertyMapper > &rMap,
                ::rtl::OUString& rDopCapTextStyleName );

    virtual ~XMLTextPropertySetContext();

    using SvXMLPropertySetContext::CreateChildContext;
    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
                                   const ::rtl::OUString& rLocalName,
                                   const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList,
                                   ::std::vector< XMLPropertyState > &rProperties,
                                   const XMLPropertyState& rProp);
};

#endif  //  _XMLOFF_XMLTEXTPROPERTYSETCONTEXT_HXX
<|endoftext|>


<commit_before>#include "xchainer/python/graph.h"

#include <memory>
#include <sstream>
#include <string>
#include <utility>

#include "xchainer/context.h"
#include "xchainer/error.h"
#include "xchainer/graph.h"
#include "xchainer/graph_scope.h"

#include "xchainer/python/common.h"
#include "xchainer/python/context.h"

namespace xchainer {
namespace python {
namespace python_internal {

namespace py = pybind11;  // standard convention

class PyGraphScope {
public:
    explicit PyGraphScope(std::string graph_name, Context& context) : graph_name_{std::move(graph_name)}, context_{context} {}
    GraphId Enter() {
        if (scope_ != nullptr) {
            throw XchainerError{"Graph scope cannot be nested."};
        }
        if (exited_) {
            throw XchainerError{"Exited graph scope cannot be reused."};
        }
        scope_ = std::make_unique<GraphScope>(graph_name_, context_);
        return scope_->graph_id();
    }
    void Exit(py::args args) {
        (void)args;  // unused
        exited_ = true;
        scope_.reset();
    }

private:
    std::string graph_name_;
    Context& context_;
    std::unique_ptr<GraphScope> scope_;
    bool exited_{false};
};

void InitXchainerGraph(pybind11::module& m) {
    py::class_<AnyGraph>{m, "AnyGraph"};  // NOLINT: misc-unused-raii

    // TODO(imanishi): Add module function to retrieve default graph id.
    m.attr("anygraph") = AnyGraph{};

    py::class_<GraphId> c{m, "GraphId"};
    c.def("__repr__", [](const GraphId& graph_id) {
            std::ostringstream stream;
            stream << graph_id;
            return stream.str();
        });
    c.def_property_readonly("context", &GraphId::context);
}

void InitXchainerGraphScope(pybind11::module& m) {
    py::class_<PyGraphScope> c{m, "GraphScope"};
    c.def("__enter__", &PyGraphScope::Enter);
    c.def("__exit__", &PyGraphScope::Exit);

    m.def("graph_scope",
          [](const std::string& graph_name, py::handle context) { return PyGraphScope(graph_name, GetContext(context)); },
          py::arg("graph_name"),
          py::arg("context") = py::none());
}

}  // namespace python_internal
}  // namespace python
}  // namespace xchainer
<commit_msg>Fix for clang-format<commit_after>#include "xchainer/python/graph.h"

#include <memory>
#include <sstream>
#include <string>
#include <utility>

#include "xchainer/context.h"
#include "xchainer/error.h"
#include "xchainer/graph.h"
#include "xchainer/graph_scope.h"

#include "xchainer/python/common.h"
#include "xchainer/python/context.h"

namespace xchainer {
namespace python {
namespace python_internal {

namespace py = pybind11;  // standard convention

class PyGraphScope {
public:
    explicit PyGraphScope(std::string graph_name, Context& context) : graph_name_{std::move(graph_name)}, context_{context} {}
    GraphId Enter() {
        if (scope_ != nullptr) {
            throw XchainerError{"Graph scope cannot be nested."};
        }
        if (exited_) {
            throw XchainerError{"Exited graph scope cannot be reused."};
        }
        scope_ = std::make_unique<GraphScope>(graph_name_, context_);
        return scope_->graph_id();
    }
    void Exit(py::args args) {
        (void)args;  // unused
        exited_ = true;
        scope_.reset();
    }

private:
    std::string graph_name_;
    Context& context_;
    std::unique_ptr<GraphScope> scope_;
    bool exited_{false};
};

void InitXchainerGraph(pybind11::module& m) {
    py::class_<AnyGraph>{m, "AnyGraph"};  // NOLINT: misc-unused-raii

    // TODO(imanishi): Add module function to retrieve default graph id.
    m.attr("anygraph") = AnyGraph{};

    py::class_<GraphId> c{m, "GraphId"};
    c.def("__repr__", [](const GraphId& graph_id) {
        std::ostringstream stream;
        stream << graph_id;
        return stream.str();
    });
    c.def_property_readonly("context", &GraphId::context);
}

void InitXchainerGraphScope(pybind11::module& m) {
    py::class_<PyGraphScope> c{m, "GraphScope"};
    c.def("__enter__", &PyGraphScope::Enter);
    c.def("__exit__", &PyGraphScope::Exit);

    m.def("graph_scope",
          [](const std::string& graph_name, py::handle context) { return PyGraphScope(graph_name, GetContext(context)); },
          py::arg("graph_name"),
          py::arg("context") = py::none());
}

}  // namespace python_internal
}  // namespace python
}  // namespace xchainer
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/protocol/message_reader.h"

#include "base/message_loop.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/socket/socket.h"
#include "remoting/base/compound_buffer.h"
#include "remoting/proto/internal.pb.h"

namespace remoting {
namespace protocol {

static const int kReadBufferSize = 4096;

MessageReader::MessageReader()
    : socket_(NULL),
      message_loop_(NULL),
      read_pending_(false),
      pending_messages_(0),
      closed_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          read_callback_(this, &MessageReader::OnRead)) {
}

MessageReader::~MessageReader() {
  CHECK_EQ(pending_messages_, 0);
}

void MessageReader::Init(net::Socket* socket,
                         MessageReceivedCallback* callback) {
  message_received_callback_.reset(callback);
  DCHECK(socket);
  socket_ = socket;
  message_loop_ = MessageLoop::current();
  DoRead();
}

void MessageReader::DoRead() {
  DCHECK(!read_pending_);

  // Don't try to read again if there is another read pending or we
  // have messages that we haven't finished processing yet.
  while (!closed_ && !read_pending_ && pending_messages_ == 0) {
    read_buffer_ = new net::IOBuffer(kReadBufferSize);
    int result = socket_->Read(
        read_buffer_, kReadBufferSize, &read_callback_);
    HandleReadResult(result);
  }
}

void MessageReader::OnRead(int result) {
  DCHECK(read_pending_);
  read_pending_ = false;

  if (!closed_) {
    HandleReadResult(result);
    DoRead();
  }
}

void MessageReader::HandleReadResult(int result) {
  if (closed_)
    return;

  if (result > 0) {
    OnDataReceived(read_buffer_, result);
  } else {
    if (result == net::ERR_CONNECTION_CLOSED) {
      closed_ = true;
    } else if (result == net::ERR_IO_PENDING) {
      read_pending_ = true;
    } else {
      LOG(ERROR) << "Read() returned error " << result;
    }
  }
}

void MessageReader::OnDataReceived(net::IOBuffer* data, int data_size) {
  message_decoder_.AddData(data, data_size);

  // Get list of all new messages first, and then call the callback
  // for all of them.
  std::vector<CompoundBuffer*> new_messages;
  while (true) {
    CompoundBuffer* buffer = message_decoder_.GetNextMessage();
    if (!buffer)
      break;
    new_messages.push_back(buffer);
  }

  pending_messages_ += new_messages.size();

  for (std::vector<CompoundBuffer*>::iterator it = new_messages.begin();
       it != new_messages.end(); ++it) {
    message_received_callback_->Run(*it, NewRunnableMethod(
        this, &MessageReader::OnMessageDone, *it));
  }
}

void MessageReader::OnMessageDone(CompoundBuffer* message) {
  delete message;
  ProcessDoneEvent();
}

void MessageReader::ProcessDoneEvent() {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &MessageReader::ProcessDoneEvent));
    return;
  }

  pending_messages_--;
  DCHECK_GE(pending_messages_, 0);

  DoRead(); // Start next read if neccessary.
}

}  // namespace protocol
}  // namespace remoting
<commit_msg>Remove aggressive DCHECK in remoting::protocol::MessageReader()<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/protocol/message_reader.h"

#include "base/message_loop.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/socket/socket.h"
#include "remoting/base/compound_buffer.h"
#include "remoting/proto/internal.pb.h"

namespace remoting {
namespace protocol {

static const int kReadBufferSize = 4096;

MessageReader::MessageReader()
    : socket_(NULL),
      message_loop_(NULL),
      read_pending_(false),
      pending_messages_(0),
      closed_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          read_callback_(this, &MessageReader::OnRead)) {
}

MessageReader::~MessageReader() {
  CHECK_EQ(pending_messages_, 0);
}

void MessageReader::Init(net::Socket* socket,
                         MessageReceivedCallback* callback) {
  message_received_callback_.reset(callback);
  DCHECK(socket);
  socket_ = socket;
  message_loop_ = MessageLoop::current();
  DoRead();
}

void MessageReader::DoRead() {
  // Don't try to read again if there is another read pending or we
  // have messages that we haven't finished processing yet.
  while (!closed_ && !read_pending_ && pending_messages_ == 0) {
    read_buffer_ = new net::IOBuffer(kReadBufferSize);
    int result = socket_->Read(
        read_buffer_, kReadBufferSize, &read_callback_);
    HandleReadResult(result);
  }
}

void MessageReader::OnRead(int result) {
  DCHECK(read_pending_);
  read_pending_ = false;

  if (!closed_) {
    HandleReadResult(result);
    DoRead();
  }
}

void MessageReader::HandleReadResult(int result) {
  if (closed_)
    return;

  if (result > 0) {
    OnDataReceived(read_buffer_, result);
  } else {
    if (result == net::ERR_CONNECTION_CLOSED) {
      closed_ = true;
    } else if (result == net::ERR_IO_PENDING) {
      read_pending_ = true;
    } else {
      LOG(ERROR) << "Read() returned error " << result;
    }
  }
}

void MessageReader::OnDataReceived(net::IOBuffer* data, int data_size) {
  message_decoder_.AddData(data, data_size);

  // Get list of all new messages first, and then call the callback
  // for all of them.
  std::vector<CompoundBuffer*> new_messages;
  while (true) {
    CompoundBuffer* buffer = message_decoder_.GetNextMessage();
    if (!buffer)
      break;
    new_messages.push_back(buffer);
  }

  pending_messages_ += new_messages.size();

  for (std::vector<CompoundBuffer*>::iterator it = new_messages.begin();
       it != new_messages.end(); ++it) {
    message_received_callback_->Run(*it, NewRunnableMethod(
        this, &MessageReader::OnMessageDone, *it));
  }
}

void MessageReader::OnMessageDone(CompoundBuffer* message) {
  delete message;
  ProcessDoneEvent();
}

void MessageReader::ProcessDoneEvent() {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &MessageReader::ProcessDoneEvent));
    return;
  }

  pending_messages_--;
  DCHECK_GE(pending_messages_, 0);

  DoRead(); // Start next read if neccessary.
}

}  // namespace protocol
}  // namespace remoting
<|endoftext|>


<commit_before>#pragma once

#include <utilgpu/cpp/cfl.h>

#include <cassert>

#include <utilgpu/cpp/str.h>

namespace util
{
template <size_t size>
std::array<float, size> CFLNode::valueVector(
    const std::array<float, size>& defaultValue) const
{
    const auto stringValue = value();
    std::array<float, size> results;
    if (stringValue == "")
    {
        results = defaultValue;
    }
    else
    {
        size_t i = 0;
        for (const auto& value : splitAll(stringValue, ","))
        {
            results[i++] = std::stof(value);
        }
        assert(i == 1 || i == size);
        if (i == 1)
        {
            results.fill(results[i]);
        }
    }
    return results;
}
}
<commit_msg>Fix CFL vectors being filled incorrectly<commit_after>#pragma once

#include <utilgpu/cpp/cfl.h>

#include <cassert>

#include <utilgpu/cpp/str.h>

namespace util
{
template <size_t size>
std::array<float, size> CFLNode::valueVector(
    const std::array<float, size>& defaultValue) const
{
    const auto stringValue = value();
    std::array<float, size> results;
    if (stringValue == "")
    {
        results = defaultValue;
    }
    else
    {
        size_t i = 0;
        for (const auto& value : splitAll(stringValue, ","))
        {
            results[i++] = std::stof(value);
        }
        assert(i == 1 || i == size);
        if (i == 1)
        {
            results.fill(results[0]);
        }
    }
    return results;
}
}
<|endoftext|>


<commit_before>/* Copyright 2013 Roman Kurbatov, Yurii Litvinov
 *
 * 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 "trikWiFi.h"

#include <QtCore/QStringList>
#include <QtNetwork/QNetworkInterface>

#include <QsLog.h>

#include "wpaSupplicantCommunicator.h"
#include "QsLog.h"

using namespace trikWiFi;

TrikWiFi::TrikWiFi(const QString &interfaceFilePrefix
		, const QString &daemonFile
		, QObject *parent)
	: QObject(parent)
	, mInterfaceFile(interfaceFilePrefix)
	, mDaemonFile(daemonFile)
{
	reinit();
}

TrikWiFi::~TrikWiFi()
{
	mMonitorInterface->detach();
}

void TrikWiFi::reinit()
{
	QLOG_INFO() << "Reinitializing WiFi";

	if (!mMonitorInterface.isNull()) {
		mMonitorInterface->detach();
	}

	mControlInterface.reset(new WpaSupplicantCommunicator(mInterfaceFile + "ctrl", mDaemonFile));
	mMonitorInterface.reset(new WpaSupplicantCommunicator(mInterfaceFile + "mon", mDaemonFile));

	mMonitorInterface->attach();
	const int monitorFileDesc = mMonitorInterface->fileDescriptor();
	if (monitorFileDesc >= 0) {
		mMonitorFileSocketNotifier.reset(new QSocketNotifier(monitorFileDesc, QSocketNotifier::Read));
		QObject::connect(mMonitorFileSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(receiveMessages()));
	} else {
		QLOG_ERROR() << "Can not get monitor file descriptor";
	}

	QLOG_INFO() << "WiFi initialized";
}

void TrikWiFi::dispose()
{
	if (!mMonitorInterface.isNull()) {
		mMonitorInterface->detach();
	}

	mControlInterface.reset(nullptr);
	mMonitorInterface.reset(nullptr);
}

int TrikWiFi::connect(int id)
{
	QString reply;
	int result = mControlInterface->request("DISCONNECT", reply);
	if (result < 0 || reply != "OK\n") {
		return -1;
	}

	result = mControlInterface->request("SELECT_NETWORK " + QString::number(id), reply);
	if (result < 0 || reply != "OK\n") {
		return -1;
	}

	return 0;
}

int TrikWiFi::disconnect()
{
	QString reply;
	const int result = mControlInterface->request("DISCONNECT", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::scan()
{
	QString reply;

	const int result = mControlInterface->request("SCAN", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

Status TrikWiFi::status() const
{
	const QString command = "STATUS";
	QString reply;

	Status result;

	if (mControlInterface->request(command, reply) < 0) {
		return result;
	}

	QHash<QString, QString> parsedReply = parseReply(reply);

	result.connected = parsedReply.contains("ssid") && !parsedReply["ssid"].isEmpty();
	if (result.connected) {
		result.ipAddress = parsedReply["ip_address"];
		result.ssid = parsedReply["ssid"];
	}

	return result;
}

QList<ScanResult> TrikWiFi::scanResults()
{
	int index = 0;
	QList<ScanResult> results;

	forever {
		const QString command = "BSS " + QString::number(index++);

		QString reply;

		if (mControlInterface->request(command, reply) < 0) {
			break;
		}

		QHash<QString, QString> parsedReply = parseReply(reply);

		if (parsedReply.isEmpty()) {
			break;
		}

		ScanResult currentResult;

		// TODO: Add error processing.
		currentResult.frequency = parsedReply["freq"].toInt();
		currentResult.ssid = parsedReply["ssid"];

		results.append(currentResult);
	}

	return results;
}

int TrikWiFi::addNetwork()
{
	QString reply;
	mControlInterface->request("ADD_NETWORK", reply);
	if (reply.startsWith("FAIL")) {
		return -1;
	}

	bool ok = false;
	const int id = reply.toInt(&ok);
	if (ok) {
		mControlInterface->request("SET_NETWORK " + QString::number(id) + " disabled 1", reply);
		return id;
	} else {
		return -1;
	}
}

int TrikWiFi::removeNetwork(int id)
{
	QString reply;
	const int result = mControlInterface->request("REMOVE_NETWORK " + QString::number(id), reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::setSsid(int id, const QString &ssid)
{
	QString reply;
	const int result
			= mControlInterface->request("SET_NETWORK " + QString::number(id) + " ssid \"" + ssid + "\"", reply);

	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::setKey(int id, const QString &key)
{
	QString reply;
	const int result = mControlInterface->request("SET_NETWORK " + QString::number(id) + " psk \"" + key + "\"", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::setNoKeyNeeded(int id)
{
	QString reply;
	const int result = mControlInterface->request("SET_NETWORK " + QString::number(id) + " key_mgmt NONE", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::saveConfiguration()
{
	QString reply;
	const int result = mControlInterface->request("SAVE_CONFIG", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

QList<NetworkConfiguration> TrikWiFi::listNetworks()
{
	QString reply;
	const int result = mControlInterface->request("LIST_NETWORKS", reply);
	if (result < 0 || reply.isEmpty() || reply.startsWith("FAIL")) {
		return QList<NetworkConfiguration>();
	}

	QStringList const lines = reply.split('\n');
	QList<NetworkConfiguration> list;
	for (const QString &line : lines) {
		QStringList const values = line.split('\t');
		if (values.size() != 4) {
			continue;
		}

		NetworkConfiguration currentNetwork;
		bool ok = false;
		currentNetwork.id = values[0].toInt(&ok);
		if (!ok) {
			currentNetwork.id = -1;
		}

		currentNetwork.ssid = values[1];
		list.append(currentNetwork);
	}

	return list;
}

void TrikWiFi::processMessage(const QString &message)
{
	if (message.contains("CTRL-EVENT-SCAN-RESULTS")) {
		emit scanFinished();
	} else if (message.contains("CTRL-EVENT-CONNECTED")) {
		int result = system("udhcpc -i wlan0");
		if (result == 0) {
			emit connected();
		}
	} else if (message.contains("CTRL-EVENT-DISCONNECTED")) {
		emit disconnected();
	}
}

void TrikWiFi::receiveMessages()
{
	while (mMonitorInterface->isPending()) {
		QString message;
		mMonitorInterface->receive(message);
		processMessage(message);
	}
}

QHash<QString, QString> TrikWiFi::parseReply(const QString &reply)
{
	QHash<QString, QString> result;

	if (reply.isEmpty() || reply.startsWith("FAIL")) {
		return result;
	}

	QStringList const lines = reply.split('\n');

	for (const QString &line : lines) {
		const int valuePos = line.indexOf('=') + 1;
		if (valuePos < 1) {
			continue;
		}

		const QString key = line.left(valuePos - 1);
		const QString value = line.mid(valuePos);

		result.insert(key, value);
	}

	return result;
}
<commit_msg>Removed call to dhcp client after reconnect, it should be done automagically by now<commit_after>/* Copyright 2013 Roman Kurbatov, Yurii Litvinov
 *
 * 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 "trikWiFi.h"

#include <QtCore/QStringList>
#include <QtNetwork/QNetworkInterface>

#include <QsLog.h>

#include "wpaSupplicantCommunicator.h"
#include "QsLog.h"

using namespace trikWiFi;

TrikWiFi::TrikWiFi(const QString &interfaceFilePrefix
		, const QString &daemonFile
		, QObject *parent)
	: QObject(parent)
	, mInterfaceFile(interfaceFilePrefix)
	, mDaemonFile(daemonFile)
{
	reinit();
}

TrikWiFi::~TrikWiFi()
{
	mMonitorInterface->detach();
}

void TrikWiFi::reinit()
{
	QLOG_INFO() << "Reinitializing WiFi";

	if (!mMonitorInterface.isNull()) {
		mMonitorInterface->detach();
	}

	mControlInterface.reset(new WpaSupplicantCommunicator(mInterfaceFile + "ctrl", mDaemonFile));
	mMonitorInterface.reset(new WpaSupplicantCommunicator(mInterfaceFile + "mon", mDaemonFile));

	mMonitorInterface->attach();
	const int monitorFileDesc = mMonitorInterface->fileDescriptor();
	if (monitorFileDesc >= 0) {
		mMonitorFileSocketNotifier.reset(new QSocketNotifier(monitorFileDesc, QSocketNotifier::Read));
		QObject::connect(mMonitorFileSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(receiveMessages()));
	} else {
		QLOG_ERROR() << "Can not get monitor file descriptor";
	}

	QLOG_INFO() << "WiFi initialized";
}

void TrikWiFi::dispose()
{
	if (!mMonitorInterface.isNull()) {
		mMonitorInterface->detach();
	}

	mControlInterface.reset(nullptr);
	mMonitorInterface.reset(nullptr);
}

int TrikWiFi::connect(int id)
{
	QString reply;
	int result = mControlInterface->request("DISCONNECT", reply);
	if (result < 0 || reply != "OK\n") {
		return -1;
	}

	result = mControlInterface->request("SELECT_NETWORK " + QString::number(id), reply);
	if (result < 0 || reply != "OK\n") {
		return -1;
	}

	return 0;
}

int TrikWiFi::disconnect()
{
	QString reply;
	const int result = mControlInterface->request("DISCONNECT", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::scan()
{
	QString reply;

	const int result = mControlInterface->request("SCAN", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

Status TrikWiFi::status() const
{
	const QString command = "STATUS";
	QString reply;

	Status result;

	if (mControlInterface->request(command, reply) < 0) {
		return result;
	}

	QHash<QString, QString> parsedReply = parseReply(reply);

	result.connected = parsedReply.contains("ssid") && !parsedReply["ssid"].isEmpty();
	if (result.connected) {
		result.ipAddress = parsedReply["ip_address"];
		result.ssid = parsedReply["ssid"];
	}

	return result;
}

QList<ScanResult> TrikWiFi::scanResults()
{
	int index = 0;
	QList<ScanResult> results;

	forever {
		const QString command = "BSS " + QString::number(index++);

		QString reply;

		if (mControlInterface->request(command, reply) < 0) {
			break;
		}

		QHash<QString, QString> parsedReply = parseReply(reply);

		if (parsedReply.isEmpty()) {
			break;
		}

		ScanResult currentResult;

		// TODO: Add error processing.
		currentResult.frequency = parsedReply["freq"].toInt();
		currentResult.ssid = parsedReply["ssid"];

		results.append(currentResult);
	}

	return results;
}

int TrikWiFi::addNetwork()
{
	QString reply;
	mControlInterface->request("ADD_NETWORK", reply);
	if (reply.startsWith("FAIL")) {
		return -1;
	}

	bool ok = false;
	const int id = reply.toInt(&ok);
	if (ok) {
		mControlInterface->request("SET_NETWORK " + QString::number(id) + " disabled 1", reply);
		return id;
	} else {
		return -1;
	}
}

int TrikWiFi::removeNetwork(int id)
{
	QString reply;
	const int result = mControlInterface->request("REMOVE_NETWORK " + QString::number(id), reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::setSsid(int id, const QString &ssid)
{
	QString reply;
	const int result
			= mControlInterface->request("SET_NETWORK " + QString::number(id) + " ssid \"" + ssid + "\"", reply);

	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::setKey(int id, const QString &key)
{
	QString reply;
	const int result = mControlInterface->request("SET_NETWORK " + QString::number(id) + " psk \"" + key + "\"", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::setNoKeyNeeded(int id)
{
	QString reply;
	const int result = mControlInterface->request("SET_NETWORK " + QString::number(id) + " key_mgmt NONE", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

int TrikWiFi::saveConfiguration()
{
	QString reply;
	const int result = mControlInterface->request("SAVE_CONFIG", reply);
	if (result == 0 && reply == "OK\n") {
		return 0;
	} else {
		return -1;
	}
}

QList<NetworkConfiguration> TrikWiFi::listNetworks()
{
	QString reply;
	const int result = mControlInterface->request("LIST_NETWORKS", reply);
	if (result < 0 || reply.isEmpty() || reply.startsWith("FAIL")) {
		return QList<NetworkConfiguration>();
	}

	QStringList const lines = reply.split('\n');
	QList<NetworkConfiguration> list;
	for (const QString &line : lines) {
		QStringList const values = line.split('\t');
		if (values.size() != 4) {
			continue;
		}

		NetworkConfiguration currentNetwork;
		bool ok = false;
		currentNetwork.id = values[0].toInt(&ok);
		if (!ok) {
			currentNetwork.id = -1;
		}

		currentNetwork.ssid = values[1];
		list.append(currentNetwork);
	}

	return list;
}

void TrikWiFi::processMessage(const QString &message)
{
	if (message.contains("CTRL-EVENT-SCAN-RESULTS")) {
		emit scanFinished();
	} else if (message.contains("CTRL-EVENT-CONNECTED")) {
		emit connected();
	} else if (message.contains("CTRL-EVENT-DISCONNECTED")) {
		emit disconnected();
	}
}

void TrikWiFi::receiveMessages()
{
	while (mMonitorInterface->isPending()) {
		QString message;
		mMonitorInterface->receive(message);
		processMessage(message);
	}
}

QHash<QString, QString> TrikWiFi::parseReply(const QString &reply)
{
	QHash<QString, QString> result;

	if (reply.isEmpty() || reply.startsWith("FAIL")) {
		return result;
	}

	QStringList const lines = reply.split('\n');

	for (const QString &line : lines) {
		const int valuePos = line.indexOf('=') + 1;
		if (valuePos < 1) {
			continue;
		}

		const QString key = line.left(valuePos - 1);
		const QString value = line.mid(valuePos);

		result.insert(key, value);
	}

	return result;
}
<|endoftext|>


<commit_before>/**
 * @file unstagger.cpp
 *
 * Calculate the co-located velocity field for U and V
 *
 * @date Oct 16, 2014
 * @author Tack
 */

#include <boost/lexical_cast.hpp>

#include "util.h"
#include "matrix.h"
#include "unstagger.h"
#include "logger_factory.h"
#include "level.h"
#include "forecast_time.h"
#include "plugin_factory.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

unstagger::unstagger()
{
	itsClearTextFormula = "U(i) = (U(i-0.5) + U(i+0.5)) / 2";

	itsLogger = logger_factory::Instance()->GetLog("unstagger");
}

void unstagger::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);

	/*
	 * Set target parameter properties
	 * - name PARM_NAME, this name is found from neons. For example: T-K
	 * - univ_id UNIV_ID, newbase-id, ie code table 204
	 * - grib1 id must be in database
	 * - grib2 descriptor X'Y'Z, http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table4-2.shtml
	 *
	 */

	param theUVelocityParam("U-MS", 23, 0, 2, 2);
	param theVVelocityParam("V-MS", 24, 0, 2, 3);

	// If this param is also used as a source param for other calculations
	// (like for example dewpoint, relative humidity), unit should also be
	// specified

	theUVelocityParam.Unit(kMs);
	theVVelocityParam.Unit(kMs);

	SetParams({theUVelocityParam, theVVelocityParam});

	Start();
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void unstagger::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{

	/*
	 * Required source parameters
	 *
	 * eg. param PParam("P-Pa"); for pressure in pascals
	 *
	 */

	const param UParam("U-MS");
	const param VParam("V-MS");

	// ----

	forecast_time forecastTime = myTargetInfo->Time();
	level forecastLevel = myTargetInfo->Level();

	auto myThreadedLogger = logger_factory::Instance()->GetLog("unstagger Thread #" + boost::lexical_cast<string> (threadIndex));

	myThreadedLogger->Debug("Calculating time " + static_cast<string> (*forecastTime.ValidDateTime()) + " level " + static_cast<string> (forecastLevel));

    auto f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

    info_t UInfo, VInfo;

    try
    {
		f->DoInterpolation(false);
        UInfo = f->Fetch(itsConfiguration, forecastTime, forecastLevel, UParam, itsConfiguration->UseCudaForPacking());
		VInfo = f->Fetch(itsConfiguration, forecastTime, forecastLevel, VParam, itsConfiguration->UseCudaForPacking());

#ifdef HAVE_CUDA
        if (UInfo->Grid()->IsPackedData())
        {
            assert(UInfo->Grid()->PackedData()->ClassName() == "simple_packed");

            util::Unpack({UInfo->Grid(), VInfo->Grid()});
        }
#endif
    }
    catch (HPExceptionType& e)
    {
        if (e != kFileDataNotFound)
        {
            throw runtime_error(ClassName() + ": Unable to proceed");
        }
		myThreadedLogger->Info("Skipping step " + boost::lexical_cast<string> (forecastTime.Step()) + ", level " + static_cast<string> (forecastLevel));
    	return;
	}

	// If calculating for hybrid levels, A/B vertical coordinates must be set
	// (copied from source)

	SetAB(myTargetInfo, UInfo);

	string deviceType = "CPU";
	// calculate for U
    himan::matrix<double> filter_kernel_U(2,1,1);
    filter_kernel_U.Fill(0.5);

	himan::matrix<double> unstaggered_U = util::Filter2D(*UInfo->Data(), filter_kernel_U);

    auto unstaggered_U_ptr = make_shared<himan::matrix<double>> (unstaggered_U);
	myTargetInfo->ParamIndex(0);
	myTargetInfo->Grid()->Data(unstaggered_U_ptr);

	// calculate for V
    himan::matrix<double> filter_kernel_V(1,2,1);
    filter_kernel_V.Fill(0.5);

	himan::matrix<double> unstaggered_V = util::Filter2D(*VInfo->Data(), filter_kernel_V);

    auto unstaggered_V_ptr = make_shared<himan::matrix<double>> (unstaggered_V);
	myTargetInfo->ParamIndex(1);
	myTargetInfo->Grid()->Data(unstaggered_V_ptr);

	myThreadedLogger->Info("[" + deviceType + "] Missing values: " + boost::lexical_cast<string> (myTargetInfo->Data()->MissingCount()) + "/" + boost::lexical_cast<string> (myTargetInfo->Data()->Size()));

}
<commit_msg>Manipulate cache manually; Recalculate grid coordinates<commit_after>/**
 * @file unstagger.cpp
 *
 * Calculate the co-located velocity field for U and V
 *
 * @date Oct 16, 2014
 * @author Tack
 */

#include <boost/lexical_cast.hpp>

#include "util.h"
#include "matrix.h"
#include "unstagger.h"
#include "logger_factory.h"
#include "level.h"
#include "forecast_time.h"
#include "plugin_factory.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "cache.h"
#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

unstagger::unstagger()
{
	itsClearTextFormula = "U(i) = (U(i-0.5) + U(i+0.5)) / 2";

	itsLogger = logger_factory::Instance()->GetLog("unstagger");
}

void unstagger::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);

	/*
	 * Set target parameter properties
	 * - name PARM_NAME, this name is found from neons. For example: T-K
	 * - univ_id UNIV_ID, newbase-id, ie code table 204
	 * - grib1 id must be in database
	 * - grib2 descriptor X'Y'Z, http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table4-2.shtml
	 *
	 */

	param theUVelocityParam("U-MS", 23, 0, 2, 2);
	param theVVelocityParam("V-MS", 24, 0, 2, 3);

	// If this param is also used as a source param for other calculations
	// (like for example dewpoint, relative humidity), unit should also be
	// specified

	theUVelocityParam.Unit(kMs);
	theVVelocityParam.Unit(kMs);

	SetParams({theUVelocityParam, theVVelocityParam});

	Start();
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void unstagger::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{

	/*
	 * Required source parameters
	 *
	 * eg. param PParam("P-Pa"); for pressure in pascals
	 *
	 */

	const param UParam("U-MS");
	const param VParam("V-MS");

	// ----

	forecast_time forecastTime = myTargetInfo->Time();
	level forecastLevel = myTargetInfo->Level();

	auto myThreadedLogger = logger_factory::Instance()->GetLog("unstagger Thread #" + boost::lexical_cast<string> (threadIndex));

	myThreadedLogger->Debug("Calculating time " + static_cast<string> (*forecastTime.ValidDateTime()) + " level " + static_cast<string> (forecastLevel));

	auto f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	info_t UInfo, VInfo;

	try
	{
		f->DoInterpolation(false);
		f->UseCache(false);

		UInfo = f->Fetch(itsConfiguration, forecastTime, forecastLevel, UParam, itsConfiguration->UseCudaForPacking());
		VInfo = f->Fetch(itsConfiguration, forecastTime, forecastLevel, VParam, itsConfiguration->UseCudaForPacking());

#ifdef HAVE_CUDA
		if (UInfo->Grid()->IsPackedData())
		{
			assert(UInfo->Grid()->PackedData()->ClassName() == "simple_packed");

			util::Unpack({UInfo->Grid(), VInfo->Grid()});
		}
#endif
	}
	catch (HPExceptionType& e)
	{
		if (e != kFileDataNotFound)
		{
			throw runtime_error(ClassName() + ": Unable to proceed");
		}
		myThreadedLogger->Info("Skipping step " + boost::lexical_cast<string> (forecastTime.Step()) + ", level " + static_cast<string> (forecastLevel));
		return;
	}

	// If calculating for hybrid levels, A/B vertical coordinates must be set
	// (copied from source)

	SetAB(myTargetInfo, UInfo);

	string deviceType = "CPU";
	// calculate for U
	himan::matrix<double> filter_kernel_U(2,1,1);
	filter_kernel_U.Fill(0.5);

	himan::matrix<double> unstaggered_U = util::Filter2D(*UInfo->Data(), filter_kernel_U);

	auto unstaggered_U_ptr = make_shared<himan::matrix<double>> (unstaggered_U);
	myTargetInfo->ParamIndex(0);
	myTargetInfo->Grid()->Data(unstaggered_U_ptr);

	// calculate for V
	himan::matrix<double> filter_kernel_V(1,2,1);
	filter_kernel_V.Fill(0.5);

	himan::matrix<double> unstaggered_V = util::Filter2D(*VInfo->Data(), filter_kernel_V);

	auto unstaggered_V_ptr = make_shared<himan::matrix<double>> (unstaggered_V);
	myTargetInfo->ParamIndex(1);
	myTargetInfo->Grid()->Data(unstaggered_V_ptr);

	// Re-calculate grid coordinates

	point bl = UInfo->Grid()->BottomLeft(), tr = UInfo->Grid()->TopRight();

	UInfo->Grid()->BottomLeft(point(bl.X() - (UInfo->Grid()->Di() * 0.5), bl.Y()));
	UInfo->Grid()->TopRight(point(tr.X() - (UInfo->Grid()->Di() * 0.5), tr.Y()));

	bl = VInfo->Grid()->BottomLeft(), tr = VInfo->Grid()->TopRight();
	VInfo->Grid()->BottomLeft(point(bl.X(), bl.Y() - (VInfo->Grid()->Dj() * 0.5)));
	VInfo->Grid()->TopRight(point(tr.X(), tr.Y() - (VInfo->Grid()->Dj() * 0.5)));

	auto c = dynamic_pointer_cast <cache> (plugin_factory::Instance()->Plugin("cache"));

	c->Insert(UInfo);
	c->Insert(VInfo);

	myThreadedLogger->Info("[" + deviceType + "] Missing values: " +
		boost::lexical_cast<string> (UInfo->Data()->MissingCount() + VInfo->Data()->MissingCount()) +
		"/" + boost::lexical_cast<string> (UInfo->Data()->Size() + VInfo->Data()->Size()));

}
<|endoftext|>