<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: UnoNamespaceMap.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:01:31 $
 *
 *  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 <set>

#include "UnoNamespaceMap.hxx"

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif

#ifndef _SFXITEMPOOL_HXX
#include <svtools/itempool.hxx>
#endif

#ifndef _SVX_UNOAPI_HXX_
#include "unoapi.hxx"
#endif

#ifndef _SVX_XMLCNITM_HXX
#include "xmlcnitm.hxx"
#endif

using namespace ::comphelper;
using namespace ::osl;
using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;

namespace svx
{
    /** implements a component to export namespaces of all SvXMLAttrContainerItem inside
        one or two pools with a variable count of which ids.
    */
    class NamespaceMap : public WeakImplHelper2< XNameAccess, XServiceInfo >
    {
    private:
        sal_uInt16* mpWhichIds;
        SfxItemPool* mpPool;

    public:
        NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool );
        virtual ~NamespaceMap();

        // XNameAccess
        virtual Any SAL_CALL getByName( const OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
        virtual Sequence< OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw (RuntimeException);

        // XElementAccess
        virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);

        // XServiceInfo
        virtual OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
        virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
        virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
    };

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool1, SfxItemPool* pPool2 )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool1 );
    }

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool );
    }

    Sequence< OUString > SAL_CALL NamespaceMap_getSupportedServiceNames()
        throw()
    {
        Sequence< OUString > aSupportedServiceNames( 1 );
        aSupportedServiceNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.NamespaceMap" ) );
        return aSupportedServiceNames;
    }

    OUString SAL_CALL NamespaceMap_getImplementationName()
        throw()
    {
        return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.NamespaceMap" ) );
    }

    class NamespaceIteratorImpl
    {
    private:
        SfxItemPool* mpPool;

        sal_uInt16* mpWhichId;

        sal_uInt16 mnItemCount;
        sal_uInt16 mnItem;

        const SvXMLAttrContainerItem* mpCurrentAttr;
        sal_uInt16 mnCurrentAttr;

    public:

        NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool );

        sal_Bool next( OUString& rPrefix, OUString& rURL );
    };
}

using namespace ::svx;

// -------------

NamespaceIteratorImpl::NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool )
{
    mpPool = pPool;
    mpCurrentAttr = NULL;
    mnCurrentAttr = 0;

    mpWhichId = pWhichIds;

    mnItem = 0;
    mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
}

sal_Bool NamespaceIteratorImpl::next( OUString& rPrefix, OUString& rURL )
{
    // we still need to process the current attribute
    if( mpCurrentAttr && (mnCurrentAttr != USHRT_MAX) )
    {
        rPrefix = mpCurrentAttr->GetPrefix( mnCurrentAttr );
        rURL = mpCurrentAttr->GetNamespace( mnCurrentAttr );

        mnCurrentAttr = mpCurrentAttr->GetNextNamespaceIndex( mnCurrentAttr );
        return sal_True;
    }

    // we need the next namespace item
    mpCurrentAttr = NULL;

    const SfxPoolItem* pItem;
    // look for the next available item in the current pool
    while( (mnItem < mnItemCount) && ( NULL == (pItem = mpPool->GetItem( *mpWhichId, mnItem ) ) ) )
        mnItem++;

    // are we finished with the current whichid?
    if( mnItem == mnItemCount )
    {
        mpWhichId++;

        // are we finished with the current pool?
        if( 0 != *mpWhichId )
        {
            mnItem = 0;
            mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
            return next( rPrefix, rURL );
        }

        pItem = NULL;
    }

    if( pItem )
    {
        mnItem++;

        // get that item and see if there namespaces inside
        const SvXMLAttrContainerItem *pUnknown = (const SvXMLAttrContainerItem *)pItem;
        if( (pUnknown->GetAttrCount() > 0) )
        {
            mpCurrentAttr = pUnknown;
            mnCurrentAttr = pUnknown->GetFirstNamespaceIndex();
        }
        return next( rPrefix, rURL );
    }

    return false;
}

// -------------

NamespaceMap::NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool )
: mpWhichIds( pWhichIds ), mpPool( pPool )
{
}

NamespaceMap::~NamespaceMap()
{
}

// XNameAccess
Any SAL_CALL NamespaceMap::getByName( const OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    if( !bFound )
        throw NoSuchElementException();

    return makeAny( aURL );
}

Sequence< OUString > SAL_CALL NamespaceMap::getElementNames() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    std::set< OUString, comphelper::UStringLess > aPrefixSet;

    while( aIter.next( aPrefix, aURL ) )
        aPrefixSet.insert( aPrefix );

    Sequence< OUString > aSeq( aPrefixSet.size() );
    OUString* pPrefixes = aSeq.getArray();

    std::set< OUString, comphelper::UStringLess >::iterator aPrefixIter( aPrefixSet.begin() );
    const std::set< OUString, comphelper::UStringLess >::iterator aEnd( aPrefixSet.end() );

    while( aPrefixIter != aEnd )
    {
        *pPrefixes++ = *aPrefixIter++;
    }

    return aSeq;
}

sal_Bool SAL_CALL NamespaceMap::hasByName( const OUString& aName ) throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    return bFound;
}

// XElementAccess
Type SAL_CALL NamespaceMap::getElementType() throw (RuntimeException)
{
    return ::getCppuType( (const OUString*) 0 );
}

sal_Bool SAL_CALL NamespaceMap::hasElements() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    return aIter.next( aPrefix, aURL );
}

// XServiceInfo
OUString SAL_CALL NamespaceMap::getImplementationName(  )
    throw(RuntimeException)
{
    return NamespaceMap_getImplementationName();
}

sal_Bool SAL_CALL NamespaceMap::supportsService( const OUString& ServiceName )
    throw(RuntimeException)
{
    return sal_True;
}

Sequence< OUString > SAL_CALL NamespaceMap::getSupportedServiceNames(  )
    throw(RuntimeException)
{
    return NamespaceMap_getSupportedServiceNames();
}

<commit_msg>INTEGRATION: CWS warnings01 (1.4.222); FILE MERGED 2006/02/17 15:22:23 cl 1.4.222.1: warning free code changes<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: UnoNamespaceMap.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 16:53:42 $
 *
 *  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 <set>

#include "UnoNamespaceMap.hxx"

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif

#ifndef _SFXITEMPOOL_HXX
#include <svtools/itempool.hxx>
#endif

#ifndef _SVX_UNOAPI_HXX_
#include "unoapi.hxx"
#endif

#ifndef _SVX_XMLCNITM_HXX
#include "xmlcnitm.hxx"
#endif

using namespace ::comphelper;
using namespace ::osl;
using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;

namespace svx
{
    /** implements a component to export namespaces of all SvXMLAttrContainerItem inside
        one or two pools with a variable count of which ids.
    */
    class NamespaceMap : public WeakImplHelper2< XNameAccess, XServiceInfo >
    {
    private:
        sal_uInt16* mpWhichIds;
        SfxItemPool* mpPool;

    public:
        NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool );
        virtual ~NamespaceMap();

        // XNameAccess
        virtual Any SAL_CALL getByName( const OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
        virtual Sequence< OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw (RuntimeException);

        // XElementAccess
        virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);

        // XServiceInfo
        virtual OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
        virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
        virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
    };

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool1, SfxItemPool* )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool1 );
    }

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool );
    }

    Sequence< OUString > SAL_CALL NamespaceMap_getSupportedServiceNames()
        throw()
    {
        Sequence< OUString > aSupportedServiceNames( 1 );
        aSupportedServiceNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.NamespaceMap" ) );
        return aSupportedServiceNames;
    }

    OUString SAL_CALL NamespaceMap_getImplementationName()
        throw()
    {
        return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.NamespaceMap" ) );
    }

    class NamespaceIteratorImpl
    {
    private:
        SfxItemPool* mpPool;

        sal_uInt16* mpWhichId;

        sal_uInt16 mnItemCount;
        sal_uInt16 mnItem;

        const SvXMLAttrContainerItem* mpCurrentAttr;
        sal_uInt16 mnCurrentAttr;

    public:

        NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool );

        sal_Bool next( OUString& rPrefix, OUString& rURL );
    };
}

using namespace ::svx;

// -------------

NamespaceIteratorImpl::NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool )
{
    mpPool = pPool;
    mpCurrentAttr = NULL;
    mnCurrentAttr = 0;

    mpWhichId = pWhichIds;

    mnItem = 0;
    mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
}

sal_Bool NamespaceIteratorImpl::next( OUString& rPrefix, OUString& rURL )
{
    // we still need to process the current attribute
    if( mpCurrentAttr && (mnCurrentAttr != USHRT_MAX) )
    {
        rPrefix = mpCurrentAttr->GetPrefix( mnCurrentAttr );
        rURL = mpCurrentAttr->GetNamespace( mnCurrentAttr );

        mnCurrentAttr = mpCurrentAttr->GetNextNamespaceIndex( mnCurrentAttr );
        return sal_True;
    }

    // we need the next namespace item
    mpCurrentAttr = NULL;

    const SfxPoolItem* pItem;
    // look for the next available item in the current pool
    while( (mnItem < mnItemCount) && ( NULL == (pItem = mpPool->GetItem( *mpWhichId, mnItem ) ) ) )
        mnItem++;

    // are we finished with the current whichid?
    if( mnItem == mnItemCount )
    {
        mpWhichId++;

        // are we finished with the current pool?
        if( 0 != *mpWhichId )
        {
            mnItem = 0;
            mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
            return next( rPrefix, rURL );
        }

        pItem = NULL;
    }

    if( pItem )
    {
        mnItem++;

        // get that item and see if there namespaces inside
        const SvXMLAttrContainerItem *pUnknown = (const SvXMLAttrContainerItem *)pItem;
        if( (pUnknown->GetAttrCount() > 0) )
        {
            mpCurrentAttr = pUnknown;
            mnCurrentAttr = pUnknown->GetFirstNamespaceIndex();
        }
        return next( rPrefix, rURL );
    }

    return false;
}

// -------------

NamespaceMap::NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool )
: mpWhichIds( pWhichIds ), mpPool( pPool )
{
}

NamespaceMap::~NamespaceMap()
{
}

// XNameAccess
Any SAL_CALL NamespaceMap::getByName( const OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    if( !bFound )
        throw NoSuchElementException();

    return makeAny( aURL );
}

Sequence< OUString > SAL_CALL NamespaceMap::getElementNames() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    std::set< OUString, comphelper::UStringLess > aPrefixSet;

    while( aIter.next( aPrefix, aURL ) )
        aPrefixSet.insert( aPrefix );

    Sequence< OUString > aSeq( aPrefixSet.size() );
    OUString* pPrefixes = aSeq.getArray();

    std::set< OUString, comphelper::UStringLess >::iterator aPrefixIter( aPrefixSet.begin() );
    const std::set< OUString, comphelper::UStringLess >::iterator aEnd( aPrefixSet.end() );

    while( aPrefixIter != aEnd )
    {
        *pPrefixes++ = *aPrefixIter++;
    }

    return aSeq;
}

sal_Bool SAL_CALL NamespaceMap::hasByName( const OUString& aName ) throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    return bFound;
}

// XElementAccess
Type SAL_CALL NamespaceMap::getElementType() throw (RuntimeException)
{
    return ::getCppuType( (const OUString*) 0 );
}

sal_Bool SAL_CALL NamespaceMap::hasElements() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    return aIter.next( aPrefix, aURL );
}

// XServiceInfo
OUString SAL_CALL NamespaceMap::getImplementationName(  )
    throw(RuntimeException)
{
    return NamespaceMap_getImplementationName();
}

sal_Bool SAL_CALL NamespaceMap::supportsService( const OUString& )
    throw(RuntimeException)
{
    return sal_True;
}

Sequence< OUString > SAL_CALL NamespaceMap::getSupportedServiceNames(  )
    throw(RuntimeException)
{
    return NamespaceMap_getSupportedServiceNames();
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2014 Ableton AG, Berlin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

// clang-format off

#pragma once

#if defined(__clang__)

  #if __has_warning("-Wunused-local-typedef")
    #define ABL_PRAGMA_CLANG_DIAGNOSTIC_IGNORED_UNUSED_LOCAL_TYPEDEF \
    _Pragma("clang diagnostic ignored \"-Wunused-local-typedef\"")
  #else
    #define ABL_PRAGMA_CLANG_DIAGNOSTIC_IGNORED_UNUSED_LOCAL_TYPEDEF
  #endif

  #define SUPPRESS_WARNINGS \
    _Pragma("clang diagnostic push") \
    _Pragma("clang diagnostic ignored \"-Wconversion\"") \
    _Pragma("clang diagnostic ignored \"-Wconditional-uninitialized\"") \
    _Pragma("clang diagnostic ignored \"-Wcovered-switch-default\"") \
    _Pragma("clang diagnostic ignored \"-Wdeprecated\"") \
    _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \
    _Pragma("clang diagnostic ignored \"-Wdocumentation-unknown-command\"") \
    _Pragma("clang diagnostic ignored \"-Wdocumentation\"") \
    _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
    _Pragma("clang diagnostic ignored \"-Wextra-semi\"") \
    _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
    _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
    _Pragma("clang diagnostic ignored \"-Wheader-hygiene\"") \
    _Pragma("clang diagnostic ignored \"-Wmissing-noreturn\"") \
    _Pragma("clang diagnostic ignored \"-Wmissing-prototypes\"") \
    _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
    _Pragma("clang diagnostic ignored \"-Wpadded\"") \
    _Pragma("clang diagnostic ignored \"-Wshadow\"") \
    _Pragma("clang diagnostic ignored \"-Wshift-sign-overflow\"") \
    _Pragma("clang diagnostic ignored \"-Wshorten-64-to-32\"") \
    _Pragma("clang diagnostic ignored \"-Wsign-compare\"") \
    _Pragma("clang diagnostic ignored \"-Wsign-conversion\"") \
    _Pragma("clang diagnostic ignored \"-Wswitch-enum\"") \
    _Pragma("clang diagnostic ignored \"-Wundef\"") \
    _Pragma("clang diagnostic ignored \"-Wunreachable-code\"") \
    _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \
    _Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"") \
    _Pragma("clang diagnostic ignored \"-Wweak-vtables\"") \
    ABL_PRAGMA_CLANG_DIAGNOSTIC_IGNORED_UNUSED_LOCAL_TYPEDEF

  #define RESTORE_WARNINGS \
    _Pragma("clang diagnostic pop")

#elif defined(_MSC_VER)

  /**
  * C4100: 'identifier' : unreferenced formal parameter
  * C4127: conditional expression is constant
  * C4244: 'conversion' conversion from 'type1' to 'type2', possible loss of data
  * C4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
  * C4365: 'action' : conversion from 'type_1' to 'type_2', signed/unsigned mismatch
  * C4388: signed/unsigned mismatch
  * C4555: expression has no effect; expected expression with side-effect
  * C4619: #pragma warning : there is no warning number 'number'
  * C4628: digraphs not supported with -Ze. Character sequence 'digraph' not interpreted as alternate token for 'char'
  * C4640: 'instance' : construction of local static object is not thread-safe
  * C4668: 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
  * C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)
  * C4826: Conversion from 'type1 ' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
  */
  #define SUPPRESS_WARNINGS \
    __pragma(warning(push)) \
    __pragma(warning(disable: 4100)) \
    __pragma(warning(disable: 4127)) \
    __pragma(warning(disable: 4244)) \
    __pragma(warning(disable: 4251)) \
    __pragma(warning(disable: 4365)) \
    __pragma(warning(disable: 4388)) \
    __pragma(warning(disable: 4555)) \
    __pragma(warning(disable: 4619)) \
    __pragma(warning(disable: 4628)) \
    __pragma(warning(disable: 4640)) \
    __pragma(warning(disable: 4668)) \
    __pragma(warning(disable: 4800)) \
    __pragma(warning(disable: 4826))

  #define RESTORE_WARNINGS \
    __pragma(warning(pop))

#else

  #define SUPPRESS_WARNINGS
  #define RESTORE_WARNINGS

#endif
<commit_msg>Disable shadowing warning of MSVS2015 for external headers<commit_after>/*
Copyright (c) 2014 Ableton AG, Berlin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

// clang-format off

#pragma once

#if defined(__clang__)

  #if __has_warning("-Wunused-local-typedef")
    #define ABL_PRAGMA_CLANG_DIAGNOSTIC_IGNORED_UNUSED_LOCAL_TYPEDEF \
    _Pragma("clang diagnostic ignored \"-Wunused-local-typedef\"")
  #else
    #define ABL_PRAGMA_CLANG_DIAGNOSTIC_IGNORED_UNUSED_LOCAL_TYPEDEF
  #endif

  #define SUPPRESS_WARNINGS \
    _Pragma("clang diagnostic push") \
    _Pragma("clang diagnostic ignored \"-Wconversion\"") \
    _Pragma("clang diagnostic ignored \"-Wconditional-uninitialized\"") \
    _Pragma("clang diagnostic ignored \"-Wcovered-switch-default\"") \
    _Pragma("clang diagnostic ignored \"-Wdeprecated\"") \
    _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \
    _Pragma("clang diagnostic ignored \"-Wdocumentation-unknown-command\"") \
    _Pragma("clang diagnostic ignored \"-Wdocumentation\"") \
    _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
    _Pragma("clang diagnostic ignored \"-Wextra-semi\"") \
    _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
    _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
    _Pragma("clang diagnostic ignored \"-Wheader-hygiene\"") \
    _Pragma("clang diagnostic ignored \"-Wmissing-noreturn\"") \
    _Pragma("clang diagnostic ignored \"-Wmissing-prototypes\"") \
    _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
    _Pragma("clang diagnostic ignored \"-Wpadded\"") \
    _Pragma("clang diagnostic ignored \"-Wshadow\"") \
    _Pragma("clang diagnostic ignored \"-Wshift-sign-overflow\"") \
    _Pragma("clang diagnostic ignored \"-Wshorten-64-to-32\"") \
    _Pragma("clang diagnostic ignored \"-Wsign-compare\"") \
    _Pragma("clang diagnostic ignored \"-Wsign-conversion\"") \
    _Pragma("clang diagnostic ignored \"-Wswitch-enum\"") \
    _Pragma("clang diagnostic ignored \"-Wundef\"") \
    _Pragma("clang diagnostic ignored \"-Wunreachable-code\"") \
    _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \
    _Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"") \
    _Pragma("clang diagnostic ignored \"-Wweak-vtables\"") \
    ABL_PRAGMA_CLANG_DIAGNOSTIC_IGNORED_UNUSED_LOCAL_TYPEDEF

  #define RESTORE_WARNINGS \
    _Pragma("clang diagnostic pop")

#elif defined(_MSC_VER)

  /**
  * C4100: 'identifier' : unreferenced formal parameter
  * C4127: conditional expression is constant
  * C4244: 'conversion' conversion from 'type1' to 'type2', possible loss of data
  * C4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
  * C4365: 'action' : conversion from 'type_1' to 'type_2', signed/unsigned mismatch
  * C4388: signed/unsigned mismatch
  * C4459: declaration of 'identifier' hides global declaration
  * C4555: expression has no effect; expected expression with side-effect
  * C4619: #pragma warning : there is no warning number 'number'
  * C4628: digraphs not supported with -Ze. Character sequence 'digraph' not interpreted as alternate token for 'char'
  * C4640: 'instance' : construction of local static object is not thread-safe
  * C4668: 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
  * C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)
  * C4826: Conversion from 'type1 ' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
  */
  #define SUPPRESS_WARNINGS \
    __pragma(warning(push)) \
    __pragma(warning(disable: 4100)) \
    __pragma(warning(disable: 4127)) \
    __pragma(warning(disable: 4244)) \
    __pragma(warning(disable: 4251)) \
    __pragma(warning(disable: 4365)) \
    __pragma(warning(disable: 4388)) \
    __pragma(warning(disable: 4459)) \
    __pragma(warning(disable: 4555)) \
    __pragma(warning(disable: 4619)) \
    __pragma(warning(disable: 4628)) \
    __pragma(warning(disable: 4640)) \
    __pragma(warning(disable: 4668)) \
    __pragma(warning(disable: 4800)) \
    __pragma(warning(disable: 4826))

  #define RESTORE_WARNINGS \
    __pragma(warning(pop))

#else

  #define SUPPRESS_WARNINGS
  #define RESTORE_WARNINGS

#endif
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 Michael W Powell <mwpowellhtx@gmail.com>
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include "../catch/catch_tags.h"
#include "../helpers/constants.h"

#include "transport.h"

#include <core/listener.h>
#include <core/dialer.h>
#include <algorithms/string_algo.hpp>

#include <cstdlib>
#include <sstream>
#include <algorithm>

#include <iostream>

namespace nng {

    int address_calculator::port = TEST_PORT;

    address_calculator::address_calculator(char port_delim) : _port_delim() {
        if (port_delim) {
            _port_delim.push_back(port_delim);
        }
    }

    address_calculator::~address_calculator() {
    }

    uint16_t address_calculator::get_port(int delta) {
        return port += delta;
    }

    uint16_t address_calculator::get_current_port() {
        return port;
    }

    std::string address_calculator::get_addr(const std::string& base_addr, int delta) {
        std::ostringstream os;
        os << base_addr << _port_delim << get_port(delta);
        return os.str();
    }

    std::string address_calculator::get_next_addr(const std::string& base_addr, int delta) {
        return get_addr(base_addr, std::abs(delta));
    }

    std::string address_calculator::get_prev_addr(const std::string& base_addr, int delta) {
        return get_addr(base_addr, -std::abs(delta));
    }

    // TODO: TBD: could expose this, but random generators are a dime a dozen...
    void seed_random_generator(std::time_t seed) {
        // Initialize the random generator.
        std::srand(static_cast<int>(seed));
    }

    namespace messaging {

        // TODO: TBD: this is a likely candidate for everything besides just transport.
        void init_random_buffer(buffer_vector_type& buf,  const size_type sz) {

            buf.resize(sz);

            for (size_type i = 0; i < sz; i++) {
                buf[i] = std::rand() & 0xff;
            }
        }

        void twos_compliment_buffer(buffer_vector_type& buf) {
            const auto &twos_compliment = [](buffer_vector_type::value_type& x) {
                x = ~x;
            };
            std::for_each(buf.begin(), buf.end(), twos_compliment);
        }
    }

    c_style_transport_fixture_redeux::c_style_transport_fixture_redeux()
        : transport_fixture_redeux_base(0, 0) {
        REQUIRE(::nng_rep_open(&_rep) == 0);
        REQUIRE(::nng_req_open(&_req) == 0);
    }

    c_style_transport_fixture_redeux::~c_style_transport_fixture_redeux() {
        if (_rep) REQUIRE(::nng_close(_rep) == 0);
        if (_req) REQUIRE(::nng_close(_req) == 0);
        _rep = _req = 0;
    }

    transport_fixture_redeux::transport_fixture_redeux()
        : transport_fixture_redeux_base() {

        using namespace protocol;
        _req.reset(new latest_req_socket());
        _rep.reset(new latest_rep_socket());
    }

    transport_fixture_redeux::~transport_fixture_redeux() {
        REQUIRE_NOTHROW(_req.reset());
        REQUIRE_NOTHROW(_rep.reset());
    }
}

namespace constants {

    const std::string ping = "ping";
    const std::string acknowledge = "acknowledge";

    const auto ping_buf = to_buffer(ping);
    const auto acknowledge_buf = to_buffer(acknowledge);
}

TEST_CASE("Test the transport using C++ wrappers", Catch::Tags(constants::prefix_tags
    , "rep", "req", "transport", "nng", "cxx", "sample").c_str()) {

    using namespace std;
    using namespace nng;
    using namespace nng::protocol;
    using namespace nng::messaging;
    using namespace constants;
    using namespace Catch::Matchers;
    using O = option_names;

    auto calc = address_calculator(port_delim);

    const auto addr = calc.get_next_addr(test_addr_base);

    std::unique_ptr<latest_rep_socket> repp;
    std::unique_ptr<latest_req_socket> reqp;

    REQUIRE_NOTHROW(repp = make_unique<latest_rep_socket>());
    REQUIRE_NOTHROW(reqp = make_unique<latest_req_socket>());

    init(addr);

    SECTION("Connection refused works") {

        WARN("Connection refused works: '" + addr + "'");

        dialer d;

        REQUIRE_THROWS_AS_MATCHING(reqp->dial(addr, &d), nng_exception, THROWS_NNG_EXCEPTION(ec_econnrefused));
        REQUIRE_THROWS_AS_MATCHING(repp->dial(addr, &d), nng_exception, THROWS_NNG_EXCEPTION(ec_econnrefused));
    }

    SECTION("Duplicate listeners rejected") {

        WARN("Duplicate listeners rejected: '" + addr + "'");

        // Smart pointers is overkill for these sections.
        listener l1, l2;

        REQUIRE_NOTHROW(repp->listen(addr, &l1));
        REQUIRE(l1.has_one() == true);

        // Leaving the first Listener open and available.
        REQUIRE_THROWS_AS_MATCHING(reqp->listen(addr, &l2), nng_exception, THROWS_NNG_EXCEPTION(ec_eaddrinuse));
        REQUIRE(l2.has_one() == false);
    }

    SECTION("Listener and dialer accepted") {

        WARN("Listener and dialer accepted: '" + addr + "'");

        // Smart pointers is overkill for these sections.
        listener l;
        dialer d;

        REQUIRE_NOTHROW(repp->listen(addr, &l));
        REQUIRE(l.has_one() == true);

        REQUIRE_NOTHROW(reqp->dial(addr, &d));
        REQUIRE(d.has_one() == true);
    }

    SECTION("Send and receive") {

        WARN("Send and receive: '" + addr + "'");

        listener l;
        dialer d;

        unique_ptr<message_pipe> pp;
        unique_ptr<binary_message> sendp, recvp;

        string actual_addr;

        REQUIRE_NOTHROW(repp->listen(addr, &l));
        REQUIRE(l.has_one() == true);
        REQUIRE_NOTHROW(reqp->dial(addr, &d));
        REQUIRE(d.has_one() == true);

        // Sleep so listener catches up, may be running slightly behind.
        SLEEP_FOR(20ms);

        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(*sendp << ping);
        REQUIRE_NOTHROW(reqp->send(sendp.get()));

        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));
        REQUIRE_NOTHROW(repp->try_receive(recvp.get()));
        REQUIRE_THAT(recvp->body()->get(), Equals(ping_buf));

        REQUIRE_NOTHROW(*sendp << acknowledge);
        REQUIRE_NOTHROW(repp->send(sendp.get()));
        REQUIRE_NOTHROW(recvp->set_msgp(nullptr));
        REQUIRE_NOTHROW(reqp->try_receive(recvp.get()));
        REQUIRE_THAT(recvp->body()->get(), Equals(acknowledge_buf));

        REQUIRE_NOTHROW(pp = make_unique<message_pipe>(recvp.get()));
        REQUIRE(pp->has_one() == true);

        // TODO: TBD: this bit is borderline message pipe unit testing and that's about it...
        REQUIRE_NOTHROW(actual_addr.resize(NNG_MAXADDRLEN));
        REQUIRE_NOTHROW(pp->get_option(O::url, actual_addr));
        REQUIRE(actual_addr == addr);
    }

    SECTION("Send and receive large data") {

        WARN("Send and receive large data: '" + addr + "'");

        listener l;
        dialer d;

        unique_ptr<binary_message> sendp, recvp;

        REQUIRE_NOTHROW(seed_random_generator(time(static_cast<std::time_t*>(nullptr))));

        // What's a buffer without some HEX involvement...
        const size_type sz = 0x400 * 0x80; // Much larger than any transport segment.
        buffer_vector_type data;

        REQUIRE_NOTHROW(init_random_buffer(data, sz));

        REQUIRE_NOTHROW(repp->listen(addr, &l));
        REQUIRE(l.has_one() == true);

        REQUIRE_NOTHROW(reqp->dial(addr, &d));
        REQUIRE(d.has_one() == true);

        // Wait for listener to catch up since it may be slightly behind.
        SLEEP_FOR(20ms);

        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(*sendp << data);
        REQUIRE_NOTHROW(reqp->send(sendp.get()));
        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));
        REQUIRE_NOTHROW(repp->try_receive(recvp.get()));
        // Heaven help us if this fails: expect report to be truncated due to excessive size.
        REQUIRE_THAT(recvp->body()->get(), Equals(data));

        REQUIRE_NOTHROW(twos_compliment_buffer(data));
        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(*sendp << data);
        REQUIRE_NOTHROW(repp->send(sendp.get()));
        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));
        REQUIRE_NOTHROW(reqp->try_receive(recvp.get()));
        // Ditto excessive size truncation.
        REQUIRE_THAT(recvp->body()->get(), Equals(data));
    }
}

TEST_CASE("Test the transport in C style", Catch::Tags(constants::prefix_tags
    , "rep", "req", "transport", "nng", "c", "sample").c_str()) {

    using namespace std;
    using namespace trx;
    using namespace nng;
    using namespace nng::protocol;
    using namespace nng::messaging;
    using namespace constants;
    using namespace Catch::Matchers;
    using O = option_names;

    address_calculator calc(port_delim);

    const auto addr = calc.get_next_addr(test_addr_base);

    init(addr);

    c_style_transport_fixture_redeux redeux;

    const auto& req = redeux._req;
    const auto& rep = redeux._rep;

    SECTION("Connection refused works") {

        WARN("Connection refused works: '" + addr + "'");

        ::nng_dialer d = 0;

        REQUIRE(::nng_dial(req, addr.c_str(), &d, 0) == ::NNG_ECONNREFUSED);
        REQUIRE(!d);

        REQUIRE(::nng_dial(rep, addr.c_str(), &d, 0) == ::NNG_ECONNREFUSED);
        REQUIRE(!d);
    }

    SECTION("Duplicate listen rejected") {

        WARN("Duplicate listen rejected: '" + addr + "'");

        ::nng_listener l = 0;

        REQUIRE(::nng_listen(rep, addr.c_str(), &l, 0) == 0);
        // TODO: TBD: close the listener before the next attempt? or just let it be?
        REQUIRE(l);

        l = 0;
        REQUIRE(::nng_listen(req, addr.c_str(), &l, 0) == ::NNG_EADDRINUSE);
        REQUIRE(!l);
    }

    SECTION("Listener and dialer accepted") {

        WARN("Listener and dialer accepted: '" + addr + "'");

        // DUH! Listener and a _D_I_A_L_E_R_!
        ::nng_listener l;
        ::nng_dialer d;

        REQUIRE(::nng_listen(rep, addr.c_str(), &l, 0) == 0);
        REQUIRE(l);

        REQUIRE(::nng_dial(req, addr.c_str(), &d, 0) == 0);
        REQUIRE(d);
    }

    SECTION("Send and receive") {

        WARN("Send and receive: '" + addr + "'");

        ::nng_listener l = 0;
        ::nng_dialer d = 0;
        ::nng_pipe p = 0;

        string url;
        string::size_type sz;

        /* This is a hybrid test. The primary purpose of this test is to exercise the core socket oriented
        methodology apart from the C++ wrappers. Engaging with the C API, however, I am confident of the
        messaging work. Just not so much of the transport at the moment. Just be careful of the message
        ownership semantics and it ought to be fine. */

        ::nng_msg* msgp;
        unique_ptr<binary_message> sendp, recvp;

        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));

        /* TODO: TBD: definitely IPC is hanging up on this step during the _D_I_A_L_
        on account of what looks to be an internal transport API wait on a Condition
        Variable. The only different from what I can determine is that the unit tests
        engage with an internal nni_tran_find call, which is not exposed to us for
        public consumption. Submitted issue to the repo:
        http://github.com/nanomsg/nng/issues/117 */

        REQUIRE(::nng_listen(rep, addr.c_str(), &l, 0) == 0);
        REQUIRE(l);
        REQUIRE(::nng_dial(req, addr.c_str(), &d, 0) == 0);
        REQUIRE(d);

        // Ditto allowing listener to catch up.
        SLEEP_FOR(20ms);

        REQUIRE_NOTHROW(*sendp << ping);
        REQUIRE(::nng_sendmsg(req, sendp->get_msgp(), 0) == 0);
        REQUIRE_NOTHROW(sendp->on_sent());
        msgp = nullptr;
        REQUIRE(::nng_recvmsg(rep, &msgp, 0) == 0);
        REQUIRE(msgp);
        REQUIRE_NOTHROW(recvp->set_msgp(msgp));
        REQUIRE_THAT(recvp->body()->get(), Equals(ping_buf));

        REQUIRE_NOTHROW(recvp->body()->chop(ping.size()));
        REQUIRE_NOTHROW(*recvp << acknowledge);
        REQUIRE(::nng_sendmsg(rep, recvp->get_msgp(), 0) == 0);
        REQUIRE_NOTHROW(recvp->on_sent());
        msgp = nullptr;
        REQUIRE(::nng_recvmsg(req, &msgp, 0) == 0);
        REQUIRE(msgp);
        REQUIRE_NOTHROW(sendp->set_msgp(msgp));
        REQUIRE_THAT(sendp->body()->get(), Equals(acknowledge_buf));

        REQUIRE_NOTHROW(p = ::nng_msg_get_pipe(sendp->get_msgp()));
        REQUIRE(p);

        REQUIRE_NOTHROW(url.resize(NNG_MAXADDRLEN));
        REQUIRE(::nng_pipe_getopt(p, O::url.c_str(), &url[0], &(sz = NNG_MAXADDRLEN)) == 0);
        REQUIRE(sz < NNG_MAXADDRLEN);
        REQUIRE_NOTHROW(url.resize(sz - 1));
        REQUIRE_THAT(url, Equals(string(addr)));
    }
}
<commit_msg>better positioned the init step during transport testing<commit_after>//
// Copyright (c) 2017 Michael W Powell <mwpowellhtx@gmail.com>
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include "../catch/catch_tags.h"
#include "../helpers/constants.h"

#include "transport.h"

#include <core/listener.h>
#include <core/dialer.h>
#include <algorithms/string_algo.hpp>

#include <cstdlib>
#include <sstream>
#include <algorithm>

#include <iostream>

namespace nng {

    int address_calculator::port = TEST_PORT;

    address_calculator::address_calculator(char port_delim) : _port_delim() {
        if (port_delim) {
            _port_delim.push_back(port_delim);
        }
    }

    address_calculator::~address_calculator() {
    }

    uint16_t address_calculator::get_port(int delta) {
        return port += delta;
    }

    uint16_t address_calculator::get_current_port() {
        return port;
    }

    std::string address_calculator::get_addr(const std::string& base_addr, int delta) {
        std::ostringstream os;
        os << base_addr << _port_delim << get_port(delta);
        return os.str();
    }

    std::string address_calculator::get_next_addr(const std::string& base_addr, int delta) {
        return get_addr(base_addr, std::abs(delta));
    }

    std::string address_calculator::get_prev_addr(const std::string& base_addr, int delta) {
        return get_addr(base_addr, -std::abs(delta));
    }

    // TODO: TBD: could expose this, but random generators are a dime a dozen...
    void seed_random_generator(std::time_t seed) {
        // Initialize the random generator.
        std::srand(static_cast<int>(seed));
    }

    namespace messaging {

        // TODO: TBD: this is a likely candidate for everything besides just transport.
        void init_random_buffer(buffer_vector_type& buf,  const size_type sz) {

            buf.resize(sz);

            for (size_type i = 0; i < sz; i++) {
                buf[i] = std::rand() & 0xff;
            }
        }

        void twos_compliment_buffer(buffer_vector_type& buf) {
            const auto &twos_compliment = [](buffer_vector_type::value_type& x) {
                x = ~x;
            };
            std::for_each(buf.begin(), buf.end(), twos_compliment);
        }
    }

    c_style_transport_fixture_redeux::c_style_transport_fixture_redeux()
        : transport_fixture_redeux_base(0, 0) {
        REQUIRE(::nng_rep_open(&_rep) == 0);
        REQUIRE(::nng_req_open(&_req) == 0);
    }

    c_style_transport_fixture_redeux::~c_style_transport_fixture_redeux() {
        if (_rep) REQUIRE(::nng_close(_rep) == 0);
        if (_req) REQUIRE(::nng_close(_req) == 0);
        _rep = _req = 0;
    }

    transport_fixture_redeux::transport_fixture_redeux()
        : transport_fixture_redeux_base() {

        using namespace protocol;
        _req.reset(new latest_req_socket());
        _rep.reset(new latest_rep_socket());
    }

    transport_fixture_redeux::~transport_fixture_redeux() {
        REQUIRE_NOTHROW(_req.reset());
        REQUIRE_NOTHROW(_rep.reset());
    }
}

namespace constants {

    const std::string ping = "ping";
    const std::string acknowledge = "acknowledge";

    const auto ping_buf = to_buffer(ping);
    const auto acknowledge_buf = to_buffer(acknowledge);
}

TEST_CASE("Test the transport using C++ wrappers", Catch::Tags(constants::prefix_tags
    , "rep", "req", "transport", "nng", "cxx", "sample").c_str()) {

    using namespace std;
    using namespace nng;
    using namespace nng::protocol;
    using namespace nng::messaging;
    using namespace constants;
    using namespace Catch::Matchers;
    using O = option_names;

    auto calc = address_calculator(port_delim);

    const auto addr = calc.get_next_addr(test_addr_base);

    init(addr);

    std::unique_ptr<latest_rep_socket> repp;
    std::unique_ptr<latest_req_socket> reqp;

    REQUIRE_NOTHROW(repp = make_unique<latest_rep_socket>());
    REQUIRE_NOTHROW(reqp = make_unique<latest_req_socket>());

    SECTION("Connection refused works") {

        WARN("Connection refused works: '" + addr + "'");

        dialer d;

        REQUIRE_THROWS_AS_MATCHING(reqp->dial(addr, &d), nng_exception, THROWS_NNG_EXCEPTION(ec_econnrefused));
        REQUIRE_THROWS_AS_MATCHING(repp->dial(addr, &d), nng_exception, THROWS_NNG_EXCEPTION(ec_econnrefused));
    }

    SECTION("Duplicate listeners rejected") {

        WARN("Duplicate listeners rejected: '" + addr + "'");

        // Smart pointers is overkill for these sections.
        listener l1, l2;

        REQUIRE_NOTHROW(repp->listen(addr, &l1));
        REQUIRE(l1.has_one() == true);

        // Leaving the first Listener open and available.
        REQUIRE_THROWS_AS_MATCHING(reqp->listen(addr, &l2), nng_exception, THROWS_NNG_EXCEPTION(ec_eaddrinuse));
        REQUIRE(l2.has_one() == false);
    }

    SECTION("Listener and dialer accepted") {

        WARN("Listener and dialer accepted: '" + addr + "'");

        // Smart pointers is overkill for these sections.
        listener l;
        dialer d;

        REQUIRE_NOTHROW(repp->listen(addr, &l));
        REQUIRE(l.has_one() == true);

        REQUIRE_NOTHROW(reqp->dial(addr, &d));
        REQUIRE(d.has_one() == true);
    }

    SECTION("Send and receive") {

        WARN("Send and receive: '" + addr + "'");

        listener l;
        dialer d;

        unique_ptr<message_pipe> pp;
        unique_ptr<binary_message> sendp, recvp;

        string actual_addr;

        REQUIRE_NOTHROW(repp->listen(addr, &l));
        REQUIRE(l.has_one() == true);
        REQUIRE_NOTHROW(reqp->dial(addr, &d));
        REQUIRE(d.has_one() == true);

        // Sleep so listener catches up, may be running slightly behind.
        SLEEP_FOR(20ms);

        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(*sendp << ping);
        REQUIRE_NOTHROW(reqp->send(sendp.get()));

        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));
        REQUIRE_NOTHROW(repp->try_receive(recvp.get()));
        REQUIRE_THAT(recvp->body()->get(), Equals(ping_buf));

        REQUIRE_NOTHROW(*sendp << acknowledge);
        REQUIRE_NOTHROW(repp->send(sendp.get()));
        REQUIRE_NOTHROW(recvp->set_msgp(nullptr));
        REQUIRE_NOTHROW(reqp->try_receive(recvp.get()));
        REQUIRE_THAT(recvp->body()->get(), Equals(acknowledge_buf));

        REQUIRE_NOTHROW(pp = make_unique<message_pipe>(recvp.get()));
        REQUIRE(pp->has_one() == true);

        // TODO: TBD: this bit is borderline message pipe unit testing and that's about it...
        REQUIRE_NOTHROW(actual_addr.resize(NNG_MAXADDRLEN));
        REQUIRE_NOTHROW(pp->get_option(O::url, actual_addr));
        REQUIRE(actual_addr == addr);
    }

    SECTION("Send and receive large data") {

        WARN("Send and receive large data: '" + addr + "'");

        listener l;
        dialer d;

        unique_ptr<binary_message> sendp, recvp;

        REQUIRE_NOTHROW(seed_random_generator(time(static_cast<std::time_t*>(nullptr))));

        // What's a buffer without some HEX involvement...
        const size_type sz = 0x400 * 0x80; // Much larger than any transport segment.
        buffer_vector_type data;

        REQUIRE_NOTHROW(init_random_buffer(data, sz));

        REQUIRE_NOTHROW(repp->listen(addr, &l));
        REQUIRE(l.has_one() == true);

        REQUIRE_NOTHROW(reqp->dial(addr, &d));
        REQUIRE(d.has_one() == true);

        // Wait for listener to catch up since it may be slightly behind.
        SLEEP_FOR(20ms);

        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(*sendp << data);
        REQUIRE_NOTHROW(reqp->send(sendp.get()));
        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));
        REQUIRE_NOTHROW(repp->try_receive(recvp.get()));
        // Heaven help us if this fails: expect report to be truncated due to excessive size.
        REQUIRE_THAT(recvp->body()->get(), Equals(data));

        REQUIRE_NOTHROW(twos_compliment_buffer(data));
        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(*sendp << data);
        REQUIRE_NOTHROW(repp->send(sendp.get()));
        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));
        REQUIRE_NOTHROW(reqp->try_receive(recvp.get()));
        // Ditto excessive size truncation.
        REQUIRE_THAT(recvp->body()->get(), Equals(data));
    }
}

TEST_CASE("Test the transport in C style", Catch::Tags(constants::prefix_tags
    , "rep", "req", "transport", "nng", "c", "sample").c_str()) {

    using namespace std;
    using namespace trx;
    using namespace nng;
    using namespace nng::protocol;
    using namespace nng::messaging;
    using namespace constants;
    using namespace Catch::Matchers;
    using O = option_names;

    address_calculator calc(port_delim);

    const auto addr = calc.get_next_addr(test_addr_base);

    init(addr);

    c_style_transport_fixture_redeux redeux;

    const auto& req = redeux._req;
    const auto& rep = redeux._rep;

    SECTION("Connection refused works") {

        WARN("Connection refused works: '" + addr + "'");

        ::nng_dialer d = 0;

        REQUIRE(::nng_dial(req, addr.c_str(), &d, 0) == ::NNG_ECONNREFUSED);
        REQUIRE(!d);

        REQUIRE(::nng_dial(rep, addr.c_str(), &d, 0) == ::NNG_ECONNREFUSED);
        REQUIRE(!d);
    }

    SECTION("Duplicate listen rejected") {

        WARN("Duplicate listen rejected: '" + addr + "'");

        ::nng_listener l = 0;

        REQUIRE(::nng_listen(rep, addr.c_str(), &l, 0) == 0);
        // TODO: TBD: close the listener before the next attempt? or just let it be?
        REQUIRE(l);

        l = 0;
        REQUIRE(::nng_listen(req, addr.c_str(), &l, 0) == ::NNG_EADDRINUSE);
        REQUIRE(!l);
    }

    SECTION("Listener and dialer accepted") {

        WARN("Listener and dialer accepted: '" + addr + "'");

        // DUH! Listener and a _D_I_A_L_E_R_!
        ::nng_listener l;
        ::nng_dialer d;

        REQUIRE(::nng_listen(rep, addr.c_str(), &l, 0) == 0);
        REQUIRE(l);

        REQUIRE(::nng_dial(req, addr.c_str(), &d, 0) == 0);
        REQUIRE(d);
    }

    SECTION("Send and receive") {

        WARN("Send and receive: '" + addr + "'");

        ::nng_listener l = 0;
        ::nng_dialer d = 0;
        ::nng_pipe p = 0;

        string url;
        string::size_type sz;

        /* This is a hybrid test. The primary purpose of this test is to exercise the core socket oriented
        methodology apart from the C++ wrappers. Engaging with the C API, however, I am confident of the
        messaging work. Just not so much of the transport at the moment. Just be careful of the message
        ownership semantics and it ought to be fine. */

        ::nng_msg* msgp;
        unique_ptr<binary_message> sendp, recvp;

        REQUIRE_NOTHROW(sendp = make_unique<binary_message>());
        REQUIRE_NOTHROW(recvp = make_unique<binary_message>(nullptr));

        /* TODO: TBD: definitely IPC is hanging up on this step during the _D_I_A_L_
        on account of what looks to be an internal transport API wait on a Condition
        Variable. The only different from what I can determine is that the unit tests
        engage with an internal nni_tran_find call, which is not exposed to us for
        public consumption. Submitted issue to the repo:
        http://github.com/nanomsg/nng/issues/117 */

        REQUIRE(::nng_listen(rep, addr.c_str(), &l, 0) == 0);
        REQUIRE(l);
        REQUIRE(::nng_dial(req, addr.c_str(), &d, 0) == 0);
        REQUIRE(d);

        // Ditto allowing listener to catch up.
        SLEEP_FOR(20ms);

        REQUIRE_NOTHROW(*sendp << ping);
        REQUIRE(::nng_sendmsg(req, sendp->get_msgp(), 0) == 0);
        REQUIRE_NOTHROW(sendp->on_sent());
        msgp = nullptr;
        REQUIRE(::nng_recvmsg(rep, &msgp, 0) == 0);
        REQUIRE(msgp);
        REQUIRE_NOTHROW(recvp->set_msgp(msgp));
        REQUIRE_THAT(recvp->body()->get(), Equals(ping_buf));

        REQUIRE_NOTHROW(recvp->body()->chop(ping.size()));
        REQUIRE_NOTHROW(*recvp << acknowledge);
        REQUIRE(::nng_sendmsg(rep, recvp->get_msgp(), 0) == 0);
        REQUIRE_NOTHROW(recvp->on_sent());
        msgp = nullptr;
        REQUIRE(::nng_recvmsg(req, &msgp, 0) == 0);
        REQUIRE(msgp);
        REQUIRE_NOTHROW(sendp->set_msgp(msgp));
        REQUIRE_THAT(sendp->body()->get(), Equals(acknowledge_buf));

        REQUIRE_NOTHROW(p = ::nng_msg_get_pipe(sendp->get_msgp()));
        REQUIRE(p);

        REQUIRE_NOTHROW(url.resize(NNG_MAXADDRLEN));
        REQUIRE(::nng_pipe_getopt(p, O::url.c_str(), &url[0], &(sz = NNG_MAXADDRLEN)) == 0);
        REQUIRE(sz < NNG_MAXADDRLEN);
        REQUIRE_NOTHROW(url.resize(sz - 1));
        REQUIRE_THAT(url, Equals(string(addr)));
    }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestContext.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkObjectFactory.h"
#include "vtkContext2D.h"
#include "vtkContextItem.h"
#include "vtkContextView.h"
#include "vtkContextScene.h"
#include "vtkPen.h"
#include "vtkBrush.h"
#include "vtkOpenGLContextDevice2D.h"
#include "vtkPoints2D.h"

#include "vtkShaderProgram2.h"
#include "vtkShader2.h"
#include "vtkShader2Collection.h"
#include "vtkUniformVariables.h"
#include "vtkOpenGLRenderWindow.h"

#include "vtkRegressionTestImage.h"

const char* SimpleVertexShader =
"void main(void)\n"
"{\n"
"  gl_FrontColor = gl_Color;\n"
"  gl_Position = ftransform();\n"
"}\n";

const char* SimpleFragmentShader =
"void main()\n"
"{\n"
"  vec2 location = gl_PointCoord - vec2(0.5, 0.5);\n"
"  float length = dot(location, location);\n"
"  if (length < 0.20)\n"
"    gl_FragColor = gl_Color;\n"
"  else\n"
"    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
"}\n";

const char* SimpleFragmentShader2 =
"void main()\n"
"{\n"
"  vec2 location = gl_PointCoord - vec2(0.5, 0.5);\n"
"  float length = dot(location, location);\n"
"  if(length > 0.25)\n"
"    discard;\n"
"  if (length < 0.20)\n"
"    gl_FragColor = gl_Color;\n"
"  else\n"
"    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
"}\n";

#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

//----------------------------------------------------------------------------
class GLSLTestItem : public vtkContextItem
{
public:
  GLSLTestItem() : program(0), program2(0)
  {
  }

  static GLSLTestItem *New();
  vtkTypeMacro(GLSLTestItem, vtkContextItem);
  // Paint event for the chart, called whenever the chart needs to be drawn
  virtual bool Paint(vtkContext2D *painter);

  void BuildShader(vtkOpenGLRenderWindow*);

  vtkShaderProgram2 *program, *program2;
};

//----------------------------------------------------------------------------
int TestGLSL( int argc, char * argv [] )
{
  // Set up a 2D context view, context test object and add it to the scene
  VTK_CREATE(vtkContextView, view);
  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
  view->GetRenderWindow()->SetSize(200, 200);
  VTK_CREATE(GLSLTestItem, test);
  view->GetScene()->AddItem(test);

  // Check if GLSL is supported
  if (!vtkShaderProgram2::IsSupported(dynamic_cast<vtkOpenGLRenderWindow*>(
                                      view->GetRenderWindow())))
    {
      cout << "GLSL not supported." << endl;
      return 1;
    }

  view->GetRenderWindow()->SetMultiSamples(0);

  int retVal = vtkRegressionTestImage(view->GetRenderWindow());
  if(retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    view->GetInteractor()->Initialize();
    view->GetInteractor()->Start();
    }

  return !retVal;
}

// Make our new derived class to draw a diagram
vtkStandardNewMacro(GLSLTestItem);
// This function aims to test the primitives provided by the 2D API.
bool GLSLTestItem::Paint(vtkContext2D *painter)
{
  // Build and link our shader if necessary
  vtkOpenGLContextDevice2D* device =
    vtkOpenGLContextDevice2D::SafeDownCast(painter->GetDevice());
  if (device)
    {
    this->BuildShader(device->GetRenderWindow());
    }
  else
    {
    return false;
    }

  // Draw points without our shader code
  for (int i = 0; i < 8; ++i)
    {
    float pos[] = { 50, i*25+5 };
    painter->GetPen()->SetColor(255,
                                static_cast<unsigned char>(float(i)*35.0),
                                0);
    painter->GetPen()->SetWidth(i*5+1);
    painter->DrawPointSprites(0, pos, 1);
    }

  // Draw the points using the first shader program
  this->program->Use();
  for (int i = 0; i < 8; ++i)
    {
    float pos[] = { 100, i*25+5 };
    painter->GetPen()->SetColor(255,
                                0,
                                static_cast<unsigned char>(float(i)*35.0));
    painter->GetPen()->SetWidth(i*5+1);
    painter->DrawPointSprites(0, pos, 1);
    }
  this->program->Restore();

  // Draw the points using the second shader program
  this->program2->Use();
  for (int i = 0; i < 8; ++i)
    {
    float pos[] = { 150, i*25+5 };
    painter->GetPen()->SetColor(static_cast<unsigned char>(float(i)*35.0),
                                255,
                                0);
    painter->GetPen()->SetWidth(i*5+1);
    painter->DrawPointSprites(0, pos, 1);
    }
  this->program2->Restore();

  return true;
}

void GLSLTestItem::BuildShader(vtkOpenGLRenderWindow* glContext)
{
  if (this->program)
    {
    return;
    }
  this->program = vtkShaderProgram2::New();
  this->program->SetContext(glContext);
  this->program2 = vtkShaderProgram2::New();
  this->program2->SetContext(glContext);

  // The vertext shader
  vtkShader2 *shader = vtkShader2::New();
  shader->SetType(VTK_SHADER_TYPE_VERTEX);
  shader->SetSourceCode(SimpleVertexShader);
  shader->SetContext(this->program->GetContext());
  this->program->GetShaders()->AddItem(shader);
  this->program2->GetShaders()->AddItem(shader);
  shader->Delete();

  // The fragment shader
  shader = vtkShader2::New();
  shader->SetType(VTK_SHADER_TYPE_FRAGMENT);
  shader->SetSourceCode(SimpleFragmentShader);
  shader->SetContext(this->program->GetContext());
  this->program->GetShaders()->AddItem(shader);
  shader->Delete();

  // The 2nd fragment shader
  shader = vtkShader2::New();
  shader->SetType(VTK_SHADER_TYPE_FRAGMENT);
  shader->SetSourceCode(SimpleFragmentShader2);
  shader->SetContext(this->program->GetContext());
  this->program2->GetShaders()->AddItem(shader);
  shader->Delete();

  // Build the shader programs
  this->program->Build();
  if(this->program->GetLastBuildStatus() != VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
    {
    vtkErrorMacro("Couldn't build the shader program. It could be an error in a shader, or a driver bug.");
    return;
    }

  this->program2->Build();
  if(this->program2->GetLastBuildStatus() != VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
    {
    vtkErrorMacro("Couldn't build the shader program. It could be an error in a shader, or a driver bug.");
    return;
    }
}
<commit_msg>BUG: Fixed memory leaks in the test.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestContext.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkObjectFactory.h"
#include "vtkContext2D.h"
#include "vtkContextItem.h"
#include "vtkContextView.h"
#include "vtkContextScene.h"
#include "vtkPen.h"
#include "vtkBrush.h"
#include "vtkOpenGLContextDevice2D.h"
#include "vtkPoints2D.h"

#include "vtkShaderProgram2.h"
#include "vtkShader2.h"
#include "vtkShader2Collection.h"
#include "vtkUniformVariables.h"
#include "vtkOpenGLRenderWindow.h"

#include "vtkRegressionTestImage.h"

const char* SimpleVertexShader =
"#version 110\n"
"void main(void)\n"
"{\n"
"  gl_FrontColor = gl_Color;\n"
"  gl_Position = ftransform();\n"
"}\n";

const char* SimpleFragmentShader =
"#version 110\n"
"void main()\n"
"{\n"
"  vec2 location = gl_PointCoord - vec2(0.5, 0.5);\n"
"  float length = dot(location, location);\n"
"  if (length < 0.20)\n"
"    gl_FragColor = gl_Color;\n"
"  else\n"
"    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
"}\n";

const char* SimpleFragmentShader2 =
"#version 110\n"
"void main()\n"
"{\n"
"  vec2 location = gl_PointCoord - vec2(0.5, 0.5);\n"
"  float length = dot(location, location);\n"
"  if(length > 0.25)\n"
"    discard;\n"
"  if (length < 0.20)\n"
"    gl_FragColor = gl_Color;\n"
"  else\n"
"    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
"}\n";

#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

//----------------------------------------------------------------------------
class GLSLTestItem : public vtkContextItem
{
public:
  static GLSLTestItem *New();
  vtkTypeMacro(GLSLTestItem, vtkContextItem);
  // Paint event for the test.
  virtual bool Paint(vtkContext2D *painter);
  // Required for the shader programs - ensure they release their resources.
  virtual void ReleaseGraphicsResources();

  void BuildShader(vtkOpenGLRenderWindow*);

  vtkSmartPointer<vtkShaderProgram2> program, program2;
};

//----------------------------------------------------------------------------
int TestGLSL( int argc, char * argv [] )
{
  // Set up a 2D context view, context test object and add it to the scene
  VTK_CREATE(vtkContextView, view);
  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
  view->GetRenderWindow()->SetSize(200, 200);
  VTK_CREATE(GLSLTestItem, test);
  view->GetScene()->AddItem(test);

  // Check if GLSL is supported
  if (!vtkShaderProgram2::IsSupported(dynamic_cast<vtkOpenGLRenderWindow*>(
                                      view->GetRenderWindow())))
    {
      cout << "GLSL not supported." << endl;
      return 1;
    }

  view->GetRenderWindow()->SetMultiSamples(0);

  int retVal = vtkRegressionTestImage(view->GetRenderWindow());
  if(retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    view->GetInteractor()->Initialize();
    view->GetInteractor()->Start();
    }

  return !retVal;
}

// Make our new derived class to draw a diagram
vtkStandardNewMacro(GLSLTestItem);
// This function aims to test the primitives provided by the 2D API.
bool GLSLTestItem::Paint(vtkContext2D *painter)
{
  // Build and link our shader if necessary
  vtkOpenGLContextDevice2D* device =
    vtkOpenGLContextDevice2D::SafeDownCast(painter->GetDevice());
  if (device)
    {
    this->BuildShader(device->GetRenderWindow());
    }
  else
    {
    return false;
    }

  // Draw points without our shader code
  for (int i = 0; i < 8; ++i)
    {
    float pos[] = { 50, i*25+5 };
    painter->GetPen()->SetColor(255,
                                static_cast<unsigned char>(float(i)*35.0),
                                0);
    painter->GetPen()->SetWidth(i*5+1);
    painter->DrawPointSprites(0, pos, 1);
    }

  // Draw the points using the first shader program
  this->program->Use();
  for (int i = 0; i < 8; ++i)
    {
    float pos[] = { 100, i*25+5 };
    painter->GetPen()->SetColor(255,
                                0,
                                static_cast<unsigned char>(float(i)*35.0));
    painter->GetPen()->SetWidth(i*5+1);
    painter->DrawPointSprites(0, pos, 1);
    }
  this->program->Restore();

  // Draw the points using the second shader program
  this->program2->Use();
  for (int i = 0; i < 8; ++i)
    {
    float pos[] = { 150, i*25+5 };
    painter->GetPen()->SetColor(static_cast<unsigned char>(float(i)*35.0),
                                255,
                                0);
    painter->GetPen()->SetWidth(i*5+1);
    painter->DrawPointSprites(0, pos, 1);
    }
  this->program2->Restore();

  return true;
}

void GLSLTestItem::ReleaseGraphicsResources()
{
  if (this->program)
    {
    this->program->ReleaseGraphicsResources();
    }
  if (this->program2)
    {
    this->program2->ReleaseGraphicsResources();
    }
}

void GLSLTestItem::BuildShader(vtkOpenGLRenderWindow* glContext)
{
  if (this->program)
    {
    return;
    }
  this->program = vtkSmartPointer<vtkShaderProgram2>::New();
  this->program->SetContext(glContext);
  this->program2 = vtkSmartPointer<vtkShaderProgram2>::New();
  this->program2->SetContext(glContext);

  // The vertext shader
  vtkShader2 *shader = vtkShader2::New();
  shader->SetType(VTK_SHADER_TYPE_VERTEX);
  shader->SetSourceCode(SimpleVertexShader);
  shader->SetContext(this->program->GetContext());
  this->program->GetShaders()->AddItem(shader);
  this->program2->GetShaders()->AddItem(shader);
  shader->Delete();

  // The fragment shader
  shader = vtkShader2::New();
  shader->SetType(VTK_SHADER_TYPE_FRAGMENT);
  shader->SetSourceCode(SimpleFragmentShader);
  shader->SetContext(this->program->GetContext());
  this->program->GetShaders()->AddItem(shader);
  shader->Delete();

  // The 2nd fragment shader
  shader = vtkShader2::New();
  shader->SetType(VTK_SHADER_TYPE_FRAGMENT);
  shader->SetSourceCode(SimpleFragmentShader2);
  shader->SetContext(this->program->GetContext());
  this->program2->GetShaders()->AddItem(shader);
  shader->Delete();

  // Build the shader programs
  this->program->Build();
  if(this->program->GetLastBuildStatus() != VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
    {
    vtkErrorMacro("Couldn't build the shader program. It could be an error in a shader, or a driver bug.");
    return;
    }

  this->program2->Build();
  if(this->program2->GetLastBuildStatus() != VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
    {
    vtkErrorMacro("Couldn't build the shader program. It could be an error in a shader, or a driver bug.");
    return;
    }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// The state of a thread is controlled by the two member variables
// alive_ and dead_.
// alive_ represents the state the thread has been ordered to achieve.
// It is set to true by the thread at startup, and is set to false by
// other threads, using SetNotAlive() and Stop().
// dead_ represents the state the thread has achieved.
// It is written by the thread encapsulated by this class only
// (except at init). It is read only by the Stop() method.
// The Run() method fires event_ when it's started; this ensures that the
// Start() method does not continue until after dead_ is false.
// This protects against premature Stop() calls from the creator thread, but
// not from other threads.

// Their transitions and states:
// alive_    dead_  Set by
// false     true   Constructor
// true      false  Run() method entry
// false     any    Run() method run_function failure
// any       false  Run() method exit (happens only with alive_ false)
// false     any    SetNotAlive
// false     any    Stop         Stop waits for dead_ to become true.
//
// Summarized a different way:
// Variable   Writer               Reader
// alive_     Constructor(false)   Run.loop
//            Run.start(true)
//            Run.fail(false)
//            SetNotAlive(false)
//            Stop(false)
//
// dead_      Constructor(true)    Stop.loop
//            Run.start(false)
//            Run.exit(true)

#include "webrtc/system_wrappers/source/thread_posix.h"

#include <algorithm>

#include <assert.h>
#include <errno.h>
#include <string.h>  // strncpy
#include <time.h>    // nanosleep
#include <unistd.h>
#ifdef WEBRTC_LINUX
#include <sys/types.h>
#include <sched.h>
#include <sys/syscall.h>
#include <linux/unistd.h>
#include <sys/prctl.h>
#endif

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {

int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
                            int max_prio) {
  assert(max_prio - min_prio > 2);
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;

  switch (priority) {
    case kLowPriority:
      return low_prio;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      return (low_prio + top_prio - 1) / 2;
    case kHighPriority:
      return std::max(top_prio - 2, low_prio);
    case kHighestPriority:
      return std::max(top_prio - 1, low_prio);
    case kRealtimePriority:
      return top_prio;
  }
  assert(false);
  return low_prio;
}

extern "C"
{
  static void* StartThread(void* lp_parameter) {
    static_cast<ThreadPosix*>(lp_parameter)->Run();
    return 0;
  }
}

ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj,
                                   ThreadPriority prio,
                                   const char* thread_name) {
  ThreadPosix* ptr = new ThreadPosix(func, obj, prio, thread_name);
  if (!ptr) {
    return NULL;
  }
  const int error = ptr->Construct();
  if (error) {
    delete ptr;
    return NULL;
  }
  return ptr;
}

ThreadPosix::ThreadPosix(ThreadRunFunction func, ThreadObj obj,
                         ThreadPriority prio, const char* thread_name)
    : run_function_(func),
      obj_(obj),
      crit_state_(CriticalSectionWrapper::CreateCriticalSection()),
      alive_(false),
      dead_(true),
      prio_(prio),
      event_(EventWrapper::Create()),
      name_(),
      set_thread_name_(false),
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
      pid_(-1),
#endif
      attr_(),
      thread_(0) {
  if (thread_name != NULL) {
    set_thread_name_ = true;
    strncpy(name_, thread_name, kThreadMaxNameLength);
    name_[kThreadMaxNameLength - 1] = '\0';
  }
}

uint32_t ThreadWrapper::GetThreadId() {
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_LINUX)
  return static_cast<uint32_t>(syscall(__NR_gettid));
#else
  return reinterpret_cast<uint32_t>(pthread_self());
#endif
}

int ThreadPosix::Construct() {
  int result = 0;
#if !defined(WEBRTC_ANDROID)
  // Enable immediate cancellation if requested, see Shutdown().
  result = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  if (result != 0) {
    return -1;
  }
  result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  if (result != 0) {
    return -1;
  }
#endif
  result = pthread_attr_init(&attr_);
  if (result != 0) {
    return -1;
  }
  return 0;
}

ThreadPosix::~ThreadPosix() {
  pthread_attr_destroy(&attr_);
  delete event_;
  delete crit_state_;
}

#define HAS_THREAD_ID !defined(WEBRTC_IOS) && !defined(WEBRTC_MAC)

bool ThreadPosix::Start(unsigned int& thread_id)
{
  int result = pthread_attr_setdetachstate(&attr_, PTHREAD_CREATE_DETACHED);
  // Set the stack stack size to 1M.
  result |= pthread_attr_setstacksize(&attr_, 1024 * 1024);
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  event_->Reset();
  // If pthread_create was successful, a thread was created and is running.
  // Don't return false if it was successful since if there are any other
  // failures the state will be: thread was started but not configured as
  // asked for. However, the caller of this API will assume that a false
  // return value means that the thread never started.
  result |= pthread_create(&thread_, &attr_, &StartThread, this);
  if (result != 0) {
    return false;
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = false;
  }

  // Wait up to 10 seconds for the OS to call the callback function. Prevents
  // race condition if Stop() is called too quickly after start.
  if (kEventSignaled != event_->Wait(WEBRTC_EVENT_10_SEC)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "posix thread event never triggered");
    // Timed out. Something went wrong.
    return true;
  }

#if HAS_THREAD_ID
  thread_id = static_cast<unsigned int>(thread_);
#endif
  sched_param param;

  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);

  if ((min_prio == EINVAL) || (max_prio == EINVAL)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to retreive min or max priority for threads");
    return true;
  }
  if (max_prio - min_prio <= 2) {
    // There is no room for setting priorities with any granularity.
    return true;
  }
  param.sched_priority = ConvertToSystemPriority(prio_, min_prio, max_prio);
  result = pthread_setschedparam(thread_, policy, &param);
  if (result == EINVAL) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to set thread priority");
  }
  return true;
}

// CPU_ZERO and CPU_SET are not available in NDK r7, so disable
// SetAffinity on Android for now.
#if (defined(WEBRTC_LINUX) && (!defined(WEBRTC_ANDROID)))
bool ThreadPosix::SetAffinity(const int* processor_numbers,
                              const unsigned int amount_of_processors) {
  if (!processor_numbers || (amount_of_processors == 0)) {
    return false;
  }
  cpu_set_t mask;
  CPU_ZERO(&mask);

  for (unsigned int processor = 0;
       processor < amount_of_processors;
       ++processor) {
    CPU_SET(processor_numbers[processor], &mask);
  }
#if defined(WEBRTC_ANDROID)
  // Android.
  const int result = syscall(__NR_sched_setaffinity,
                             pid_,
                             sizeof(mask),
                             &mask);
#else
  // "Normal" Linux.
  const int result = sched_setaffinity(pid_,
                                       sizeof(mask),
                                       &mask);
#endif
  if (result != 0) {
    return false;
  }
  return true;
}

#else
// NOTE: On Mac OS X, use the Thread affinity API in
// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self()
// instead of Linux gettid() syscall.
bool ThreadPosix::SetAffinity(const int* , const unsigned int) {
  return false;
}
#endif

void ThreadPosix::SetNotAlive() {
  CriticalSectionScoped cs(crit_state_);
  alive_ = false;
}

bool ThreadPosix::Stop() {
  bool dead = false;
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = false;
    dead = dead_;
  }

  // TODO(hellner) why not use an event here?
  // Wait up to 10 seconds for the thread to terminate
  for (int i = 0; i < 1000 && !dead; ++i) {
    timespec t;
    t.tv_sec = 0;
    t.tv_nsec = 10 * 1000 * 1000;
    nanosleep(&t, NULL);
    {
      CriticalSectionScoped cs(crit_state_);
      dead = dead_;
    }
  }
  if (dead) {
    return true;
  } else {
    return false;
  }
}

void ThreadPosix::Run() {
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = true;
  }
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
  pid_ = GetThreadId();
#endif
  // The event the Start() is waiting for.
  event_->Set();

  if (set_thread_name_) {
#ifdef WEBRTC_LINUX
    prctl(PR_SET_NAME, (unsigned long)name_, 0, 0, 0);
#endif
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread with name:%s started ", name_);
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name started");
  }
  bool alive = true;
  bool run = true;
  while (alive) {
    run = run_function_(obj_);
    CriticalSectionScoped cs(crit_state_);
    if (!run) {
      alive_ = false;
    }
    alive = alive_;
  }

  if (set_thread_name_) {
    // Don't set the name for the trace thread because it may cause a
    // deadlock. TODO(hellner) there should be a better solution than
    // coupling the thread and the trace class like this.
    if (strcmp(name_, "Trace")) {
      WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                   "Thread with name:%s stopped", name_);
    }
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name stopped");
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = true;
  }
}

} // namespace webrtc
<commit_msg>Mac 64-bit compatibility for WebRTC.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// The state of a thread is controlled by the two member variables
// alive_ and dead_.
// alive_ represents the state the thread has been ordered to achieve.
// It is set to true by the thread at startup, and is set to false by
// other threads, using SetNotAlive() and Stop().
// dead_ represents the state the thread has achieved.
// It is written by the thread encapsulated by this class only
// (except at init). It is read only by the Stop() method.
// The Run() method fires event_ when it's started; this ensures that the
// Start() method does not continue until after dead_ is false.
// This protects against premature Stop() calls from the creator thread, but
// not from other threads.

// Their transitions and states:
// alive_    dead_  Set by
// false     true   Constructor
// true      false  Run() method entry
// false     any    Run() method run_function failure
// any       false  Run() method exit (happens only with alive_ false)
// false     any    SetNotAlive
// false     any    Stop         Stop waits for dead_ to become true.
//
// Summarized a different way:
// Variable   Writer               Reader
// alive_     Constructor(false)   Run.loop
//            Run.start(true)
//            Run.fail(false)
//            SetNotAlive(false)
//            Stop(false)
//
// dead_      Constructor(true)    Stop.loop
//            Run.start(false)
//            Run.exit(true)

#include "webrtc/system_wrappers/source/thread_posix.h"

#include <algorithm>

#include <assert.h>
#include <errno.h>
#include <string.h>  // strncpy
#include <time.h>    // nanosleep
#include <unistd.h>
#ifdef WEBRTC_LINUX
#include <sys/types.h>
#include <sched.h>
#include <sys/syscall.h>
#include <linux/unistd.h>
#include <sys/prctl.h>
#endif

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {

int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
                            int max_prio) {
  assert(max_prio - min_prio > 2);
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;

  switch (priority) {
    case kLowPriority:
      return low_prio;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      return (low_prio + top_prio - 1) / 2;
    case kHighPriority:
      return std::max(top_prio - 2, low_prio);
    case kHighestPriority:
      return std::max(top_prio - 1, low_prio);
    case kRealtimePriority:
      return top_prio;
  }
  assert(false);
  return low_prio;
}

extern "C"
{
  static void* StartThread(void* lp_parameter) {
    static_cast<ThreadPosix*>(lp_parameter)->Run();
    return 0;
  }
}

ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj,
                                   ThreadPriority prio,
                                   const char* thread_name) {
  ThreadPosix* ptr = new ThreadPosix(func, obj, prio, thread_name);
  if (!ptr) {
    return NULL;
  }
  const int error = ptr->Construct();
  if (error) {
    delete ptr;
    return NULL;
  }
  return ptr;
}

ThreadPosix::ThreadPosix(ThreadRunFunction func, ThreadObj obj,
                         ThreadPriority prio, const char* thread_name)
    : run_function_(func),
      obj_(obj),
      crit_state_(CriticalSectionWrapper::CreateCriticalSection()),
      alive_(false),
      dead_(true),
      prio_(prio),
      event_(EventWrapper::Create()),
      name_(),
      set_thread_name_(false),
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
      pid_(-1),
#endif
      attr_(),
      thread_(0) {
  if (thread_name != NULL) {
    set_thread_name_ = true;
    strncpy(name_, thread_name, kThreadMaxNameLength);
    name_[kThreadMaxNameLength - 1] = '\0';
  }
}

uint32_t ThreadWrapper::GetThreadId() {
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_LINUX)
  return static_cast<uint32_t>(syscall(__NR_gettid));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  return pthread_mach_thread_np(pthread_self());
#else
  return reinterpret_cast<uint32_t>(pthread_self());
#endif
}

int ThreadPosix::Construct() {
  int result = 0;
#if !defined(WEBRTC_ANDROID)
  // Enable immediate cancellation if requested, see Shutdown().
  result = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  if (result != 0) {
    return -1;
  }
  result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  if (result != 0) {
    return -1;
  }
#endif
  result = pthread_attr_init(&attr_);
  if (result != 0) {
    return -1;
  }
  return 0;
}

ThreadPosix::~ThreadPosix() {
  pthread_attr_destroy(&attr_);
  delete event_;
  delete crit_state_;
}

#define HAS_THREAD_ID !defined(WEBRTC_IOS) && !defined(WEBRTC_MAC)

bool ThreadPosix::Start(unsigned int& thread_id)
{
  int result = pthread_attr_setdetachstate(&attr_, PTHREAD_CREATE_DETACHED);
  // Set the stack stack size to 1M.
  result |= pthread_attr_setstacksize(&attr_, 1024 * 1024);
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  event_->Reset();
  // If pthread_create was successful, a thread was created and is running.
  // Don't return false if it was successful since if there are any other
  // failures the state will be: thread was started but not configured as
  // asked for. However, the caller of this API will assume that a false
  // return value means that the thread never started.
  result |= pthread_create(&thread_, &attr_, &StartThread, this);
  if (result != 0) {
    return false;
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = false;
  }

  // Wait up to 10 seconds for the OS to call the callback function. Prevents
  // race condition if Stop() is called too quickly after start.
  if (kEventSignaled != event_->Wait(WEBRTC_EVENT_10_SEC)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "posix thread event never triggered");
    // Timed out. Something went wrong.
    return true;
  }

#if HAS_THREAD_ID
  thread_id = static_cast<unsigned int>(thread_);
#endif
  sched_param param;

  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);

  if ((min_prio == EINVAL) || (max_prio == EINVAL)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to retreive min or max priority for threads");
    return true;
  }
  if (max_prio - min_prio <= 2) {
    // There is no room for setting priorities with any granularity.
    return true;
  }
  param.sched_priority = ConvertToSystemPriority(prio_, min_prio, max_prio);
  result = pthread_setschedparam(thread_, policy, &param);
  if (result == EINVAL) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to set thread priority");
  }
  return true;
}

// CPU_ZERO and CPU_SET are not available in NDK r7, so disable
// SetAffinity on Android for now.
#if (defined(WEBRTC_LINUX) && (!defined(WEBRTC_ANDROID)))
bool ThreadPosix::SetAffinity(const int* processor_numbers,
                              const unsigned int amount_of_processors) {
  if (!processor_numbers || (amount_of_processors == 0)) {
    return false;
  }
  cpu_set_t mask;
  CPU_ZERO(&mask);

  for (unsigned int processor = 0;
       processor < amount_of_processors;
       ++processor) {
    CPU_SET(processor_numbers[processor], &mask);
  }
#if defined(WEBRTC_ANDROID)
  // Android.
  const int result = syscall(__NR_sched_setaffinity,
                             pid_,
                             sizeof(mask),
                             &mask);
#else
  // "Normal" Linux.
  const int result = sched_setaffinity(pid_,
                                       sizeof(mask),
                                       &mask);
#endif
  if (result != 0) {
    return false;
  }
  return true;
}

#else
// NOTE: On Mac OS X, use the Thread affinity API in
// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self()
// instead of Linux gettid() syscall.
bool ThreadPosix::SetAffinity(const int* , const unsigned int) {
  return false;
}
#endif

void ThreadPosix::SetNotAlive() {
  CriticalSectionScoped cs(crit_state_);
  alive_ = false;
}

bool ThreadPosix::Stop() {
  bool dead = false;
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = false;
    dead = dead_;
  }

  // TODO(hellner) why not use an event here?
  // Wait up to 10 seconds for the thread to terminate
  for (int i = 0; i < 1000 && !dead; ++i) {
    timespec t;
    t.tv_sec = 0;
    t.tv_nsec = 10 * 1000 * 1000;
    nanosleep(&t, NULL);
    {
      CriticalSectionScoped cs(crit_state_);
      dead = dead_;
    }
  }
  if (dead) {
    return true;
  } else {
    return false;
  }
}

void ThreadPosix::Run() {
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = true;
  }
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
  pid_ = GetThreadId();
#endif
  // The event the Start() is waiting for.
  event_->Set();

  if (set_thread_name_) {
#ifdef WEBRTC_LINUX
    prctl(PR_SET_NAME, (unsigned long)name_, 0, 0, 0);
#endif
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread with name:%s started ", name_);
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name started");
  }
  bool alive = true;
  bool run = true;
  while (alive) {
    run = run_function_(obj_);
    CriticalSectionScoped cs(crit_state_);
    if (!run) {
      alive_ = false;
    }
    alive = alive_;
  }

  if (set_thread_name_) {
    // Don't set the name for the trace thread because it may cause a
    // deadlock. TODO(hellner) there should be a better solution than
    // coupling the thread and the trace class like this.
    if (strcmp(name_, "Trace")) {
      WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                   "Thread with name:%s stopped", name_);
    }
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name stopped");
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = true;
  }
}

} // namespace webrtc
<|endoftext|>