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

// includes *******************************************************************

#pragma hdrstop

#ifndef _COM_SUN_STAR_FRAME_XDISPATCHRECORDERSUPPLIER_HPP_
#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
#include <com/sun/star/frame/XModuleManager.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#include <svtools/eitem.hxx>
#include <svtools/generictoolboxcontroller.hxx>
#include <vcl/msgbox.hxx>
#include <comphelper/processfactory.hxx>

#include "recfloat.hxx"
#include "dialog.hrc"
#include "sfxresid.hxx"
#include "app.hxx"
#include "bindings.hxx"
#include "dispatch.hxx"
#include "viewfrm.hxx"
#include "viewsh.hxx"
#include "imagemgr.hxx"

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

static rtl::OUString GetLabelFromCommandURL( const rtl::OUString& rCommandURL, const uno::Reference< frame::XFrame >& xFrame )
{
    rtl::OUString aLabel;
    rtl::OUString aModuleIdentifier;
    uno::Reference< container::XNameAccess > xUICommandLabels;
    uno::Reference< lang::XMultiServiceFactory > xServiceManager;
    uno::Reference< container::XNameAccess > xUICommandDescription;
    uno::Reference< ::com::sun::star::frame::XModuleManager > xModuleManager;

    static uno::WeakReference< lang::XMultiServiceFactory > xTmpServiceManager;
    static uno::WeakReference< container::XNameAccess >     xTmpNameAccess;
    static uno::WeakReference< ::com::sun::star::frame::XModuleManager > xTmpModuleMgr;

    xServiceManager = xTmpServiceManager;
    if ( !xServiceManager.is() )
    {
        xServiceManager = ::comphelper::getProcessServiceFactory();
        xTmpServiceManager = xServiceManager;
    }

    xUICommandDescription = xTmpNameAccess;
    if ( !xUICommandDescription.is() )
    {
        xUICommandDescription = uno::Reference< container::XNameAccess >(
                                    xServiceManager->createInstance(
                                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                            "com.sun.star.frame.UICommandDescription" ))),
                                    uno::UNO_QUERY );
        xTmpNameAccess = xUICommandDescription;
    }

    xModuleManager = xTmpModuleMgr;
    if ( !xModuleManager.is() )
    {
        xModuleManager = uno::Reference< ::com::sun::star::frame::XModuleManager >(
            xServiceManager->createInstance(
                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.frame.ModuleManager" ))),
            uno::UNO_QUERY_THROW );
        xTmpModuleMgr = xModuleManager;
    }

    // Retrieve label from UI command description service
    try
    {
        try
        {
            aModuleIdentifier = xModuleManager->identify( xFrame );
        }
        catch( uno::Exception& )
        {
        }

        if ( xUICommandDescription.is() )
        {
            uno::Any a = xUICommandDescription->getByName( aModuleIdentifier );
            uno::Reference< container::XNameAccess > xUICommands;
            a >>= xUICommandLabels;
        }
    }
    catch ( uno::Exception& )
    {
    }

    if ( xUICommandLabels.is() )
    {
        try
        {
            if ( rCommandURL.getLength() > 0 )
            {
                uno::Sequence< beans::PropertyValue > aPropSeq;
                uno::Any a( xUICommandLabels->getByName( rCommandURL ));
                if ( a >>= aPropSeq )
                {
                    for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
                    {
                        if ( aPropSeq[i].Name.equalsAscii( "Label" ))
                        {
                            aPropSeq[i].Value >>= aLabel;
                            break;
                        }
                    }
                }
            }
        }
        catch (uno::Exception& )
        {
        }
    }

    return aLabel;
}

SFX_IMPL_FLOATINGWINDOW( SfxRecordingFloatWrapper_Impl, SID_RECORDING_FLOATWINDOW );

SfxRecordingFloatWrapper_Impl::SfxRecordingFloatWrapper_Impl( Window* pParent ,
                                                USHORT nId ,
                                                SfxBindings* pBind ,
                                                SfxChildWinInfo* pInfo )
                    : SfxChildWindow( pParent , nId )
                    , pBindings( pBind )
{
    pWindow = new SfxRecordingFloat_Impl( pBindings, this, pParent );
    SetWantsFocus( FALSE );
    eChildAlignment = SFX_ALIGN_NOALIGNMENT;
    ( ( SfxFloatingWindow* ) pWindow )->Initialize( pInfo );
}

SfxRecordingFloatWrapper_Impl::~SfxRecordingFloatWrapper_Impl()
{
    SfxBoolItem aItem( FN_PARAM_1, TRUE );
    com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder = pBindings->GetRecorder();
    if ( xRecorder.is() )
        pBindings->GetDispatcher()->Execute( SID_STOP_RECORDING, SFX_CALLMODE_SYNCHRON, &aItem, 0L );
}

sal_Bool SfxRecordingFloatWrapper_Impl::QueryClose()
{
    // asking for recorded macro should be replaced if index access is available!
    BOOL bRet = TRUE;
    com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder = pBindings->GetRecorder();
    if ( xRecorder.is() && xRecorder->getRecordedMacro().getLength() )
    {
        QueryBox aBox( GetWindow(), WB_YES_NO | WB_DEF_NO , String( SfxResId( STR_MACRO_LOSS ) ) );
        aBox.SetText( String( SfxResId(STR_CANCEL_RECORDING) ) );
        bRet = ( aBox.Execute() == RET_YES );
    }

    return bRet;
}

SfxRecordingFloat_Impl::SfxRecordingFloat_Impl(
    SfxBindings* pBindings ,
    SfxChildWindow* pChildWin ,
    Window* pParent )
    : SfxFloatingWindow( pBindings ,
                         pChildWin ,
                         pParent ,
                         SfxResId( SID_RECORDING_FLOATWINDOW ) )
    , pWrapper( pChildWin )
    , aTbx( this, SfxResId(SID_RECORDING_FLOATWINDOW) )
{
    // Retrieve label from helper function
    uno::Reference< frame::XFrame > xFrame = GetBindings().GetActiveFrame();
    rtl::OUString aCommandStr( RTL_CONSTASCII_USTRINGPARAM( ".uno:StopRecording" ));
    aTbx.SetItemText( SID_STOP_RECORDING, GetLabelFromCommandURL( aCommandStr, xFrame ));

    // Determine size of toolbar
    Size aSize = aTbx.CalcWindowSizePixel();
    aTbx.SetPosSizePixel( Point(), aSize );
    SetOutputSizePixel( aSize );

    // create a generic toolbox controller for our internal toolbox
    svt::GenericToolboxController* pController = new svt::GenericToolboxController(
                                                    ::comphelper::getProcessServiceFactory(),
                                                    xFrame,
                                                    &aTbx,
                                                    SID_STOP_RECORDING,
                                                    aCommandStr );
    xStopRecTbxCtrl = uno::Reference< frame::XToolbarController >(
                            static_cast< cppu::OWeakObject* >( pController ),
                        uno::UNO_QUERY );
    uno::Reference< util::XUpdatable > xUpdate( xStopRecTbxCtrl, uno::UNO_QUERY );
    if ( xUpdate.is() )
        xUpdate->update();

    aTbx.SetSelectHdl( LINK( this, SfxRecordingFloat_Impl, Select ) );

    // start recording
    SfxBoolItem aItem( SID_RECORDMACRO, TRUE );
    GetBindings().GetDispatcher()->Execute( SID_RECORDMACRO, SFX_CALLMODE_SYNCHRON, &aItem, 0L );
}

SfxRecordingFloat_Impl::~SfxRecordingFloat_Impl()
{
    try
    {
        if ( xStopRecTbxCtrl.is() )
        {
            uno::Reference< lang::XComponent > xComp( xStopRecTbxCtrl, uno::UNO_QUERY );
            xComp->dispose();
        }
    }
    catch ( uno::Exception& )
    {
    }
}

BOOL SfxRecordingFloat_Impl::Close()
{
    BOOL bRet = SfxFloatingWindow::Close();
    return bRet;
}

void SfxRecordingFloat_Impl::FillInfo( SfxChildWinInfo& rInfo ) const
{
    SfxFloatingWindow::FillInfo( rInfo );
    rInfo.bVisible = sal_False;
}

void SfxRecordingFloat_Impl::StateChanged( StateChangedType nStateChange )
{
    if ( nStateChange == STATE_CHANGE_INITSHOW )
    {
        SfxViewFrame *pFrame = GetBindings().GetDispatcher_Impl()->GetFrame();
        Window* pEditWin = pFrame->GetViewShell()->GetWindow();

        Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
        aPoint = GetParent()->ScreenToOutputPixel( aPoint );
        aPoint.X() += 20;
        aPoint.Y() += 10;
        SetPosPixel( aPoint );
    }

    SfxFloatingWindow::StateChanged( nStateChange );
}

IMPL_LINK( SfxRecordingFloat_Impl, Select, ToolBox*, pToolBar )
{
    sal_Int16   nKeyModifier( (sal_Int16)aTbx.GetModifier() );
    if ( xStopRecTbxCtrl.is() )
        xStopRecTbxCtrl->execute( nKeyModifier );

    return 1;
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.8.192); FILE MERGED 2005/09/05 15:22:56 rt 1.8.192.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: recfloat.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 18:29:56 $
 *
 *  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
 *
 ************************************************************************/

// includes *******************************************************************

#pragma hdrstop

#ifndef _COM_SUN_STAR_FRAME_XDISPATCHRECORDERSUPPLIER_HPP_
#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
#include <com/sun/star/frame/XModuleManager.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#include <svtools/eitem.hxx>
#include <svtools/generictoolboxcontroller.hxx>
#include <vcl/msgbox.hxx>
#include <comphelper/processfactory.hxx>

#include "recfloat.hxx"
#include "dialog.hrc"
#include "sfxresid.hxx"
#include "app.hxx"
#include "bindings.hxx"
#include "dispatch.hxx"
#include "viewfrm.hxx"
#include "viewsh.hxx"
#include "imagemgr.hxx"

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

static rtl::OUString GetLabelFromCommandURL( const rtl::OUString& rCommandURL, const uno::Reference< frame::XFrame >& xFrame )
{
    rtl::OUString aLabel;
    rtl::OUString aModuleIdentifier;
    uno::Reference< container::XNameAccess > xUICommandLabels;
    uno::Reference< lang::XMultiServiceFactory > xServiceManager;
    uno::Reference< container::XNameAccess > xUICommandDescription;
    uno::Reference< ::com::sun::star::frame::XModuleManager > xModuleManager;

    static uno::WeakReference< lang::XMultiServiceFactory > xTmpServiceManager;
    static uno::WeakReference< container::XNameAccess >     xTmpNameAccess;
    static uno::WeakReference< ::com::sun::star::frame::XModuleManager > xTmpModuleMgr;

    xServiceManager = xTmpServiceManager;
    if ( !xServiceManager.is() )
    {
        xServiceManager = ::comphelper::getProcessServiceFactory();
        xTmpServiceManager = xServiceManager;
    }

    xUICommandDescription = xTmpNameAccess;
    if ( !xUICommandDescription.is() )
    {
        xUICommandDescription = uno::Reference< container::XNameAccess >(
                                    xServiceManager->createInstance(
                                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                            "com.sun.star.frame.UICommandDescription" ))),
                                    uno::UNO_QUERY );
        xTmpNameAccess = xUICommandDescription;
    }

    xModuleManager = xTmpModuleMgr;
    if ( !xModuleManager.is() )
    {
        xModuleManager = uno::Reference< ::com::sun::star::frame::XModuleManager >(
            xServiceManager->createInstance(
                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.frame.ModuleManager" ))),
            uno::UNO_QUERY_THROW );
        xTmpModuleMgr = xModuleManager;
    }

    // Retrieve label from UI command description service
    try
    {
        try
        {
            aModuleIdentifier = xModuleManager->identify( xFrame );
        }
        catch( uno::Exception& )
        {
        }

        if ( xUICommandDescription.is() )
        {
            uno::Any a = xUICommandDescription->getByName( aModuleIdentifier );
            uno::Reference< container::XNameAccess > xUICommands;
            a >>= xUICommandLabels;
        }
    }
    catch ( uno::Exception& )
    {
    }

    if ( xUICommandLabels.is() )
    {
        try
        {
            if ( rCommandURL.getLength() > 0 )
            {
                uno::Sequence< beans::PropertyValue > aPropSeq;
                uno::Any a( xUICommandLabels->getByName( rCommandURL ));
                if ( a >>= aPropSeq )
                {
                    for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
                    {
                        if ( aPropSeq[i].Name.equalsAscii( "Label" ))
                        {
                            aPropSeq[i].Value >>= aLabel;
                            break;
                        }
                    }
                }
            }
        }
        catch (uno::Exception& )
        {
        }
    }

    return aLabel;
}

SFX_IMPL_FLOATINGWINDOW( SfxRecordingFloatWrapper_Impl, SID_RECORDING_FLOATWINDOW );

SfxRecordingFloatWrapper_Impl::SfxRecordingFloatWrapper_Impl( Window* pParent ,
                                                USHORT nId ,
                                                SfxBindings* pBind ,
                                                SfxChildWinInfo* pInfo )
                    : SfxChildWindow( pParent , nId )
                    , pBindings( pBind )
{
    pWindow = new SfxRecordingFloat_Impl( pBindings, this, pParent );
    SetWantsFocus( FALSE );
    eChildAlignment = SFX_ALIGN_NOALIGNMENT;
    ( ( SfxFloatingWindow* ) pWindow )->Initialize( pInfo );
}

SfxRecordingFloatWrapper_Impl::~SfxRecordingFloatWrapper_Impl()
{
    SfxBoolItem aItem( FN_PARAM_1, TRUE );
    com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder = pBindings->GetRecorder();
    if ( xRecorder.is() )
        pBindings->GetDispatcher()->Execute( SID_STOP_RECORDING, SFX_CALLMODE_SYNCHRON, &aItem, 0L );
}

sal_Bool SfxRecordingFloatWrapper_Impl::QueryClose()
{
    // asking for recorded macro should be replaced if index access is available!
    BOOL bRet = TRUE;
    com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder = pBindings->GetRecorder();
    if ( xRecorder.is() && xRecorder->getRecordedMacro().getLength() )
    {
        QueryBox aBox( GetWindow(), WB_YES_NO | WB_DEF_NO , String( SfxResId( STR_MACRO_LOSS ) ) );
        aBox.SetText( String( SfxResId(STR_CANCEL_RECORDING) ) );
        bRet = ( aBox.Execute() == RET_YES );
    }

    return bRet;
}

SfxRecordingFloat_Impl::SfxRecordingFloat_Impl(
    SfxBindings* pBindings ,
    SfxChildWindow* pChildWin ,
    Window* pParent )
    : SfxFloatingWindow( pBindings ,
                         pChildWin ,
                         pParent ,
                         SfxResId( SID_RECORDING_FLOATWINDOW ) )
    , pWrapper( pChildWin )
    , aTbx( this, SfxResId(SID_RECORDING_FLOATWINDOW) )
{
    // Retrieve label from helper function
    uno::Reference< frame::XFrame > xFrame = GetBindings().GetActiveFrame();
    rtl::OUString aCommandStr( RTL_CONSTASCII_USTRINGPARAM( ".uno:StopRecording" ));
    aTbx.SetItemText( SID_STOP_RECORDING, GetLabelFromCommandURL( aCommandStr, xFrame ));

    // Determine size of toolbar
    Size aSize = aTbx.CalcWindowSizePixel();
    aTbx.SetPosSizePixel( Point(), aSize );
    SetOutputSizePixel( aSize );

    // create a generic toolbox controller for our internal toolbox
    svt::GenericToolboxController* pController = new svt::GenericToolboxController(
                                                    ::comphelper::getProcessServiceFactory(),
                                                    xFrame,
                                                    &aTbx,
                                                    SID_STOP_RECORDING,
                                                    aCommandStr );
    xStopRecTbxCtrl = uno::Reference< frame::XToolbarController >(
                            static_cast< cppu::OWeakObject* >( pController ),
                        uno::UNO_QUERY );
    uno::Reference< util::XUpdatable > xUpdate( xStopRecTbxCtrl, uno::UNO_QUERY );
    if ( xUpdate.is() )
        xUpdate->update();

    aTbx.SetSelectHdl( LINK( this, SfxRecordingFloat_Impl, Select ) );

    // start recording
    SfxBoolItem aItem( SID_RECORDMACRO, TRUE );
    GetBindings().GetDispatcher()->Execute( SID_RECORDMACRO, SFX_CALLMODE_SYNCHRON, &aItem, 0L );
}

SfxRecordingFloat_Impl::~SfxRecordingFloat_Impl()
{
    try
    {
        if ( xStopRecTbxCtrl.is() )
        {
            uno::Reference< lang::XComponent > xComp( xStopRecTbxCtrl, uno::UNO_QUERY );
            xComp->dispose();
        }
    }
    catch ( uno::Exception& )
    {
    }
}

BOOL SfxRecordingFloat_Impl::Close()
{
    BOOL bRet = SfxFloatingWindow::Close();
    return bRet;
}

void SfxRecordingFloat_Impl::FillInfo( SfxChildWinInfo& rInfo ) const
{
    SfxFloatingWindow::FillInfo( rInfo );
    rInfo.bVisible = sal_False;
}

void SfxRecordingFloat_Impl::StateChanged( StateChangedType nStateChange )
{
    if ( nStateChange == STATE_CHANGE_INITSHOW )
    {
        SfxViewFrame *pFrame = GetBindings().GetDispatcher_Impl()->GetFrame();
        Window* pEditWin = pFrame->GetViewShell()->GetWindow();

        Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
        aPoint = GetParent()->ScreenToOutputPixel( aPoint );
        aPoint.X() += 20;
        aPoint.Y() += 10;
        SetPosPixel( aPoint );
    }

    SfxFloatingWindow::StateChanged( nStateChange );
}

IMPL_LINK( SfxRecordingFloat_Impl, Select, ToolBox*, pToolBar )
{
    sal_Int16   nKeyModifier( (sal_Int16)aTbx.GetModifier() );
    if ( xStopRecTbxCtrl.is() )
        xStopRecTbxCtrl->execute( nKeyModifier );

    return 1;
}
<|endoftext|>


<commit_before>// Copyright © 2016 by Donald King <chronos@chronos-tachyon.net>
// Available under the MIT License. See LICENSE for details.

#include "event/poller.h"

#include <poll.h>
#include <sys/epoll.h>
#include <unistd.h>

#include "base/logging.h"
#include "base/util.h"

static short poll_mask(event::Set set) noexcept {
  short result = 0;
  if (set.readable()) result |= POLLIN | POLLRDHUP;
  if (set.writable()) result |= POLLOUT;
  if (set.priority()) result |= POLLPRI;
  return result;
}

static event::Set poll_unmask(short bits) noexcept {
  event::Set set;
  set.set_readable(bits & (POLLIN | POLLRDHUP));
  set.set_writable(bits & POLLOUT);
  set.set_priority(bits & POLLPRI);
  set.set_hangup(bits & POLLHUP);
  set.set_error(bits & POLLERR);
  return set;
}

static uint32_t epoll_mask(event::Set set) noexcept {
  uint32_t result = EPOLLET;
  if (set.readable()) result |= EPOLLIN | EPOLLRDHUP;
  if (set.writable()) result |= EPOLLOUT;
  if (set.priority()) result |= EPOLLPRI;
  return result;
}

static event::Set epoll_unmask(uint32_t bits) noexcept {
  event::Set set;
  set.set_readable(bits & (EPOLLIN | EPOLLRDHUP));
  set.set_writable(bits & EPOLLOUT);
  set.set_priority(bits & EPOLLPRI);
  set.set_hangup(bits & EPOLLHUP);
  set.set_error(bits & EPOLLERR);
  return set;
}

namespace event {

namespace {

class PollPoller : public Poller {
 public:
  PollPoller() = default;

  PollerType type() const noexcept override { return PollerType::poll_poller; }

  base::Result add(base::FD fd, base::token_t t, Set set) override {
    auto lock = base::acquire_lock(mu_);
    auto fdpair = fd->acquire_fd();
    map_[fdpair.first] = Item(std::move(fd), t, set);
    return base::Result();
  }

  base::Result modify(base::FD fd, base::token_t t, Set set) override {
    auto lock = base::acquire_lock(mu_);
    auto fdpair = fd->acquire_fd();
    map_[fdpair.first] = Item(std::move(fd), t, set);
    return base::Result();
  }

  base::Result remove(base::FD fd) override {
    auto lock = base::acquire_lock(mu_);
    auto fdpair = fd->acquire_fd();
    map_.erase(fdpair.first);
    return base::Result();
  }

  base::Result wait(EventVec* out, int timeout_ms) const override {
    auto lock = base::acquire_lock(mu_);
    const std::size_t n = map_.size();

    std::vector<Activation> acts;
    acts.reserve(n);
    for (const auto& pair : map_) {
      const auto& item = pair.second;
      int fdnum;
      base::RLock rlock;
      std::tie(fdnum, rlock) = item.filedesc->acquire_fd();
      acts.emplace_back(std::move(rlock), fdnum, item.token, item.set);
    }

    std::vector<struct pollfd> pfds;
    pfds.resize(n);
    for (std::size_t i = 0; i < n; ++i) {
      auto& act = acts[i];
      auto& pfd = pfds[i];
      ::bzero(&pfd, sizeof(pfd));
      pfd.fd = act.fdnum;
      pfd.events = poll_mask(act.set);
      pfd.revents = 0;
    }

    int rc = ::poll(pfds.data(), pfds.size(), timeout_ms);
    if (rc < 0) {
      int err_no = errno;
      if (err_no == EINTR) return base::Result();
      return base::Result::from_errno(err_no, "poll(2)");
    }
    if (rc > 0) {
      for (std::size_t i = 0; i < n; ++i) {
        auto& act = acts[i];
        auto& pfd = pfds[i];
        if (pfd.revents != 0) {
          Set set = poll_unmask(pfd.revents);
          out->emplace_back(act.token, set);
        }
      }
    }
    return base::Result();
  }

 private:
  struct Item {
    base::FD filedesc;
    base::token_t token;
    Set set;

    Item() noexcept = default;
    Item(base::FD fd, base::token_t t, Set s) noexcept
        : filedesc(std::move(fd)),
          token(t),
          set(s) {}
  };

  struct Activation {
    base::RLock lock;
    int fdnum;
    base::token_t token;
    Set set;

    Activation(base::RLock lk, int n, base::token_t t, Set s) noexcept
        : lock(std::move(lk)),
          fdnum(n),
          token(t),
          set(s) {}
  };

  mutable std::mutex mu_;
  std::map<int, Item> map_;
};

class EPollPoller : public Poller {
 public:
  explicit EPollPoller(int epoll_fd) noexcept : epoll_fd_(epoll_fd) {}
  ~EPollPoller() noexcept override { ::close(epoll_fd_); }

  PollerType type() const noexcept override { return PollerType::epoll_poller; }

  base::Result add(base::FD fd, base::token_t t, Set set) override {
    epoll_event ev;
    ::bzero(&ev, sizeof(ev));
    ev.events = epoll_mask(set);
    ev.data.u64 = uint64_t(t);
    auto pair = DCHECK_NOTNULL(fd)->acquire_fd();
    int rc = ::epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, pair.first, &ev);
    if (rc != 0) {
      int err_no = errno;
      return base::Result::from_errno(err_no, "epoll_ctl(2)");
    }
    return base::Result();
  }

  base::Result modify(base::FD fd, base::token_t t, Set set) override {
    epoll_event ev;
    ::bzero(&ev, sizeof(ev));
    ev.events = epoll_mask(set);
    ev.data.u64 = uint64_t(t);
    auto pair = DCHECK_NOTNULL(fd)->acquire_fd();
    int rc = ::epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, pair.first, &ev);
    if (rc != 0) {
      int err_no = errno;
      return base::Result::from_errno(err_no, "epoll_ctl(2)");
    }
    return base::Result();
  }

  base::Result remove(base::FD fd) override {
    epoll_event dummy;
    auto pair = DCHECK_NOTNULL(fd)->acquire_fd();
    int rc = ::epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, pair.first, &dummy);
    if (rc != 0) {
      int err_no = errno;
      return base::Result::from_errno(err_no, "epoll_ctl(2)");
    }
    return base::Result();
  }

  base::Result wait(EventVec* out, int timeout_ms) const override {
    base::Result result;
    std::array<epoll_event, 8> ev = {};
    std::size_t num = ev.size();
    while (num >= ev.size()) {
      ev.fill(epoll_event());
      int n = ::epoll_wait(epoll_fd_, ev.data(), ev.size(), timeout_ms);
      if (n < 0) {
        int err_no = errno;
        if (err_no == EINTR) break;
        result = base::Result::from_errno(err_no, "epoll_wait(2)");
        break;
      }
      num = n;
      if (num > ev.size()) n = ev.size();
      for (std::size_t i = 0; i < num; ++i) {
        Set set = epoll_unmask(ev[i].events);
        auto t = base::token_t(ev[i].data.u64);
        out->emplace_back(t, set);
      }
      timeout_ms = 0;
    }
    return result;
  }

 private:
  const int epoll_fd_;
};

base::Result new_poll_poller(PollerPtr* out, const PollerOptions& opts) {
  *out = std::make_shared<PollPoller>();
  return base::Result();
}

base::Result new_epoll_poller(PollerPtr* out, const PollerOptions& opts) {
  int fd = ::epoll_create1(EPOLL_CLOEXEC);
  if (fd == -1) {
    int err_no = errno;
    return base::Result::from_errno(err_no, "epoll_create1(2)");
  }
  *out = std::make_shared<EPollPoller>(fd);
  return base::Result();
}

}  // anonymous namespace

base::Result new_poller(PollerPtr* out, const PollerOptions& opts) {
  DCHECK_NOTNULL(out)->reset();
  auto type = opts.type();
  switch (type) {
    case PollerType::poll_poller:
      return new_poll_poller(out, opts);

    case PollerType::unspecified:
    case PollerType::epoll_poller:
      return new_epoll_poller(out, opts);

    default:
      return base::Result::not_implemented();
  }
}

}  // namespace event
<commit_msg>Implement select(2) polling.<commit_after>// Copyright © 2016 by Donald King <chronos@chronos-tachyon.net>
// Available under the MIT License. See LICENSE for details.

#include "event/poller.h"

#include <poll.h>
#include <sys/epoll.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include "base/logging.h"
#include "base/util.h"

static short poll_mask(event::Set set) noexcept {
  short result = 0;
  if (set.readable()) result |= POLLIN | POLLRDHUP;
  if (set.writable()) result |= POLLOUT;
  if (set.priority()) result |= POLLPRI;
  return result;
}

static event::Set poll_unmask(short bits) noexcept {
  event::Set set;
  set.set_readable(bits & (POLLIN | POLLRDHUP));
  set.set_writable(bits & POLLOUT);
  set.set_priority(bits & POLLPRI);
  set.set_hangup(bits & POLLHUP);
  set.set_error(bits & POLLERR);
  return set;
}

static uint32_t epoll_mask(event::Set set) noexcept {
  uint32_t result = EPOLLET;
  if (set.readable()) result |= EPOLLIN | EPOLLRDHUP;
  if (set.writable()) result |= EPOLLOUT;
  if (set.priority()) result |= EPOLLPRI;
  return result;
}

static event::Set epoll_unmask(uint32_t bits) noexcept {
  event::Set set;
  set.set_readable(bits & (EPOLLIN | EPOLLRDHUP));
  set.set_writable(bits & EPOLLOUT);
  set.set_priority(bits & EPOLLPRI);
  set.set_hangup(bits & EPOLLHUP);
  set.set_error(bits & EPOLLERR);
  return set;
}

namespace event {

namespace {

struct Item {
  base::FD filedesc;
  base::token_t token;
  Set set;

  Item() noexcept = default;
  Item(base::FD fd, base::token_t t, Set s) noexcept : filedesc(std::move(fd)),
                                                       token(t),
                                                       set(s) {}
};

struct Activation {
  base::RLock lock;
  int fdnum;
  base::token_t token;
  Set set;

  Activation(base::RLock lk, int n, base::token_t t, Set s) noexcept
      : lock(std::move(lk)),
        fdnum(n),
        token(t),
        set(s) {}
};

class LegacyPoller : public Poller {
 protected:
  explicit LegacyPoller(bool maintain_nfds) : nfds_(0), maint_(maintain_nfds) {}

 public:
  base::Result add(base::FD fd, base::token_t t, Set set) override {
    auto lock = base::acquire_lock(mu_);
    auto fdpair = fd->acquire_fd();
    auto it = map_.find(fdpair.first);
    if (it != map_.end()) {
      return base::Result::from_errno(EEXIST, "net::Poller::add");
    }
    map_[fdpair.first] = Item(std::move(fd), t, set);
    if (maint_ && fdpair.first >= nfds_) nfds_ = fdpair.first + 1;
    return base::Result();
  }

  base::Result modify(base::FD fd, base::token_t t, Set set) override {
    auto lock = base::acquire_lock(mu_);
    auto fdpair = fd->acquire_fd();
    auto it = map_.find(fdpair.first);
    if (it == map_.end()) {
      return base::Result::from_errno(ENOENT, "net::Poller::modify");
    }
    auto& item = it->second;
    item.token = t;
    item.set = set;
    return base::Result();
  }

  base::Result remove(base::FD fd) override {
    auto lock = base::acquire_lock(mu_);
    auto fdpair = fd->acquire_fd();
    auto it = map_.find(fdpair.first);
    if (it == map_.end()) {
      return base::Result::from_errno(ENOENT, "net::Poller::remove");
    }
    map_.erase(it);
    if (maint_ && nfds_ == fdpair.first + 1) {
      int new_nfds = 0;
      for (const auto& pair : map_) {
        if (pair.first >= new_nfds) new_nfds = pair.first + 1;
      }
      nfds_ = new_nfds;
    }
    return base::Result();
  }

 protected:
  mutable std::mutex mu_;
  std::map<int, Item> map_;
  int nfds_;
  bool maint_;
};

class SelectPoller : public LegacyPoller {
 public:
  SelectPoller() : LegacyPoller(true) {}

  PollerType type() const noexcept override {
    return PollerType::select_poller;
  }

  base::Result wait(EventVec* out, int timeout_ms) const override {
    auto lock = base::acquire_lock(mu_);
    const std::size_t n = map_.size();

    fd_set rset, wset, eset;
    FD_ZERO(&rset);
    FD_ZERO(&wset);
    FD_ZERO(&eset);

    std::vector<Activation> acts;
    acts.reserve(n);
    for (const auto& pair : map_) {
      const auto& item = pair.second;
      int fdnum;
      base::RLock rlock;
      std::tie(fdnum, rlock) = item.filedesc->acquire_fd();
      acts.emplace_back(std::move(rlock), fdnum, item.token, item.set);
      if (fdnum < 0 || fdnum >= FD_SETSIZE) {
        return base::Result::invalid_argument("fd ", fdnum,
                                              " is out of range 0..",
                                              FD_SETSIZE - 1, " for select(2)");
      }
      if (item.set.readable()) FD_SET(fdnum, &rset);
      if (item.set.writable()) FD_SET(fdnum, &wset);
      FD_SET(fdnum, &eset);
    }

    struct timeval tv;
    struct timeval* tvptr = nullptr;
    if (timeout_ms >= 0) {
      ::bzero(&tv, sizeof(tv));
      tv.tv_sec = timeout_ms / 1000;
      tv.tv_usec = (timeout_ms % 1000) * 1000;
      tvptr = &tv;
    }

    int rc = ::select(nfds_, &rset, &wset, &eset, tvptr);
    if (rc < 0) {
      int err_no = errno;
      if (err_no == EINTR) return base::Result();
      return base::Result::from_errno(err_no, "select(2)");
    }
    if (rc > 0) {
      for (auto& act : acts) {
        Set set;
        set.set_readable(FD_ISSET(act.fdnum, &rset));
        set.set_writable(FD_ISSET(act.fdnum, &wset));
        set.set_error(FD_ISSET(act.fdnum, &eset));
        if (set) out->emplace_back(act.token, set);
      }
    }
    return base::Result();
  }
};

class PollPoller : public LegacyPoller {
 public:
  PollPoller() : LegacyPoller(false) {}

  PollerType type() const noexcept override { return PollerType::poll_poller; }

  base::Result wait(EventVec* out, int timeout_ms) const override {
    auto lock = base::acquire_lock(mu_);
    const std::size_t n = map_.size();

    std::vector<Activation> acts;
    acts.reserve(n);
    for (const auto& pair : map_) {
      const auto& item = pair.second;
      int fdnum;
      base::RLock rlock;
      std::tie(fdnum, rlock) = item.filedesc->acquire_fd();
      acts.emplace_back(std::move(rlock), fdnum, item.token, item.set);
    }

    std::vector<struct pollfd> pfds;
    pfds.resize(n);
    for (std::size_t i = 0; i < n; ++i) {
      auto& act = acts[i];
      auto& pfd = pfds[i];
      ::bzero(&pfd, sizeof(pfd));
      pfd.fd = act.fdnum;
      pfd.events = poll_mask(act.set);
      pfd.revents = 0;
    }

    int rc = ::poll(pfds.data(), pfds.size(), timeout_ms);
    if (rc < 0) {
      int err_no = errno;
      if (err_no == EINTR) return base::Result();
      return base::Result::from_errno(err_no, "poll(2)");
    }
    if (rc > 0) {
      for (std::size_t i = 0; i < n; ++i) {
        auto& act = acts[i];
        auto& pfd = pfds[i];
        if (pfd.revents != 0) {
          Set set = poll_unmask(pfd.revents);
          out->emplace_back(act.token, set);
        }
      }
    }
    return base::Result();
  }
};

class EPollPoller : public Poller {
 public:
  explicit EPollPoller(int epoll_fd) noexcept : epoll_fd_(epoll_fd) {}
  ~EPollPoller() noexcept override { ::close(epoll_fd_); }

  PollerType type() const noexcept override { return PollerType::epoll_poller; }

  base::Result add(base::FD fd, base::token_t t, Set set) override {
    epoll_event ev;
    ::bzero(&ev, sizeof(ev));
    ev.events = epoll_mask(set);
    ev.data.u64 = uint64_t(t);
    auto pair = DCHECK_NOTNULL(fd)->acquire_fd();
    int rc = ::epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, pair.first, &ev);
    if (rc != 0) {
      int err_no = errno;
      return base::Result::from_errno(err_no, "epoll_ctl(2)");
    }
    return base::Result();
  }

  base::Result modify(base::FD fd, base::token_t t, Set set) override {
    epoll_event ev;
    ::bzero(&ev, sizeof(ev));
    ev.events = epoll_mask(set);
    ev.data.u64 = uint64_t(t);
    auto pair = DCHECK_NOTNULL(fd)->acquire_fd();
    int rc = ::epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, pair.first, &ev);
    if (rc != 0) {
      int err_no = errno;
      return base::Result::from_errno(err_no, "epoll_ctl(2)");
    }
    return base::Result();
  }

  base::Result remove(base::FD fd) override {
    epoll_event dummy;
    auto pair = DCHECK_NOTNULL(fd)->acquire_fd();
    int rc = ::epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, pair.first, &dummy);
    if (rc != 0) {
      int err_no = errno;
      return base::Result::from_errno(err_no, "epoll_ctl(2)");
    }
    return base::Result();
  }

  base::Result wait(EventVec* out, int timeout_ms) const override {
    base::Result result;
    std::array<epoll_event, 8> ev = {};
    std::size_t num = ev.size();
    while (num >= ev.size()) {
      ev.fill(epoll_event());
      int n = ::epoll_wait(epoll_fd_, ev.data(), ev.size(), timeout_ms);
      if (n < 0) {
        int err_no = errno;
        if (err_no == EINTR) break;
        result = base::Result::from_errno(err_no, "epoll_wait(2)");
        break;
      }
      num = n;
      if (num > ev.size()) n = ev.size();
      for (std::size_t i = 0; i < num; ++i) {
        Set set = epoll_unmask(ev[i].events);
        auto t = base::token_t(ev[i].data.u64);
        out->emplace_back(t, set);
      }
      timeout_ms = 0;
    }
    return result;
  }

 private:
  const int epoll_fd_;
};

base::Result new_select_poller(PollerPtr* out, const PollerOptions& opts) {
  *out = std::make_shared<SelectPoller>();
  return base::Result();
}

base::Result new_poll_poller(PollerPtr* out, const PollerOptions& opts) {
  *out = std::make_shared<PollPoller>();
  return base::Result();
}

base::Result new_epoll_poller(PollerPtr* out, const PollerOptions& opts) {
  int fd = ::epoll_create1(EPOLL_CLOEXEC);
  if (fd == -1) {
    int err_no = errno;
    return base::Result::from_errno(err_no, "epoll_create1(2)");
  }
  *out = std::make_shared<EPollPoller>(fd);
  return base::Result();
}

}  // anonymous namespace

base::Result new_poller(PollerPtr* out, const PollerOptions& opts) {
  DCHECK_NOTNULL(out)->reset();
  auto type = opts.type();
  switch (type) {
    case PollerType::select_poller:
      return new_select_poller(out, opts);

    case PollerType::poll_poller:
      return new_poll_poller(out, opts);

    case PollerType::unspecified:
    case PollerType::epoll_poller:
      return new_epoll_poller(out, opts);

    default:
      return base::Result::not_implemented();
  }
}

}  // namespace event
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Benchmark.h"
#include "SkMutex.h"
#include "SkSharedMutex.h"
#include "SkSpinlock.h"
#include "SkString.h"

template <typename Mutex>
class MutexBench : public Benchmark {
public:
    MutexBench(SkString benchPrefix) : fBenchName(benchPrefix += "UncontendedBenchmark") { }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }

protected:
    const char* onGetName() override {
        return fBenchName.c_str();
    }

    void onDraw(const int loops, SkCanvas*) override {
        Mutex mu;
        for (int i = 0; i < loops; i++) {
            mu.acquire();
            mu.release();
        }
    }

private:
    typedef Benchmark INHERITED;
    SkString fBenchName;
};

///////////////////////////////////////////////////////////////////////////////

DEF_BENCH( return new MutexBench<SkSharedMutex>(SkString("SkSharedMutex")); )
DEF_BENCH( return new MutexBench<SkMutex>(SkString("SkMutex")); )
DEF_BENCH( return new MutexBench<SkSpinlock>(SkString("SkSpinlock")); )
<commit_msg>Add shared mutex benchmark.<commit_after>/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Benchmark.h"
#include "SkMutex.h"
#include "SkSharedMutex.h"
#include "SkSpinlock.h"
#include "SkString.h"

template <typename Mutex>
class MutexBench : public Benchmark {
public:
    MutexBench(SkString benchPrefix) : fBenchName(benchPrefix += "UncontendedBenchmark") { }
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }

protected:
    const char* onGetName() override {
        return fBenchName.c_str();
    }

    void onDraw(const int loops, SkCanvas*) override {
        Mutex mu;
        for (int i = 0; i < loops; i++) {
            mu.acquire();
            mu.release();
        }
    }

private:
    typedef Benchmark INHERITED;
    SkString fBenchName;
};

class SharedBench : public Benchmark {
public:
    bool isSuitableFor(Backend backend) override {
        return backend == kNonRendering_Backend;
    }

protected:
    const char* onGetName() override {
        return "SkSharedMutexSharedUncontendedBenchmark";
    }

    void onDraw(const int loops, SkCanvas*) override {
        SkSharedMutex mu;
        for (int i = 0; i < loops; i++) {
            mu.acquireShared();
            mu.releaseShared();
        }
    }

private:
    typedef Benchmark INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

DEF_BENCH( return new MutexBench<SkSharedMutex>(SkString("SkSharedMutex")); )
DEF_BENCH( return new MutexBench<SkMutex>(SkString("SkMutex")); )
DEF_BENCH( return new MutexBench<SkSpinlock>(SkString("SkSpinlock")); )
DEF_BENCH( return new SharedBench; )

<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include <sstream>

using namespace std;

asm(".LC3:\n"
    "  .long 1065353216");
asm(".LC4:\n"
    "  .long 3212836864");

float evaluateClang(float a, float b) {
  asm("subss xmm0, xmm1\n"
      "movss xmm1, dword ptr [rip + .LC3]\n"
      "addss xmm1, xmm0\n"
      "mulss xmm1, xmm0\n"
      "addss xmm0, dword ptr [rip + .LC4]\n"
      "mulss xmm0, xmm1");
}

float evaluateGCC(float a, float b) {
  asm("subss xmm0, xmm1\n"
      "movss xmm2, dword ptr [rip + .LC3]\n"
      "movaps xmm1, xmm0\n"
      "addss xmm1, xmm2\n"
      "mulss xmm1, xmm0\n"
      "subss xmm0, xmm2\n"
      "mulss xmm0, xmm1");
}

int main() {
  auto start = std::chrono::steady_clock::now();
  for (int j = 0; j < 1000; j++) {
    for (int i = 0; i < 65536; i++) {
      evaluateClang(4.0f, 9.0f);
    }
  }
  auto now = std::chrono::steady_clock::now();
  std::chrono::duration<double, std::nano> ns = now - start;
  cout << ns.count() << " ns" << '\n';

  start = std::chrono::steady_clock::now();
  for (int j = 0; j < 1000; j++) {
    for (int i = 0; i < 65536; i++) {
      evaluateGCC(4.0f, 9.0f);
    }
  }
  now = std::chrono::steady_clock::now();
  ns = now - start;
  cout << ns.count() << " ns" << '\n';
}
<commit_msg>Should perform more iterations on the comparison<commit_after>#include <chrono>
#include <iostream>
#include <sstream>

using namespace std;

asm(".LC3:\n"
    "  .long 1065353216");
asm(".LC4:\n"
    "  .long 3212836864");

float evaluateClang(float a, float b) {
  asm("subss xmm0, xmm1\n"
      "movss xmm1, dword ptr [rip + .LC3]\n"
      "addss xmm1, xmm0\n"
      "mulss xmm1, xmm0\n"
      "addss xmm0, dword ptr [rip + .LC4]\n"
      "mulss xmm0, xmm1");
}

float evaluateGCC(float a, float b) {
  asm("subss xmm0, xmm1\n"
      "movss xmm2, dword ptr [rip + .LC3]\n"
      "movaps xmm1, xmm0\n"
      "addss xmm1, xmm2\n"
      "mulss xmm1, xmm0\n"
      "subss xmm0, xmm2\n"
      "mulss xmm0, xmm1");
}

int main() {
  auto start = std::chrono::steady_clock::now();
  for (int j = 0; j < 1000 * 1000 * 1000; j++) {
    evaluateClang(4.0f, 9.0f);
  }
  auto now = std::chrono::steady_clock::now();
  std::chrono::duration<double, std::nano> ns = now - start;
  cout << ns.count() << " ns" << '\n';

  start = std::chrono::steady_clock::now();
  for (int j = 0; j < 1000 * 1000 * 1000; j++) {
    evaluateGCC(4.0f, 9.0f);
  }
  now = std::chrono::steady_clock::now();
  ns = now - start;
  cout << ns.count() << " ns" << '\n';
}
<|endoftext|>


<commit_before>// ListScrollView.cpp : 实现文件
//

#include "stdafx.h"
#include "ListScrollView.h"

// ListScrollView

IMPLEMENT_DYNCREATE(ListScrollView, CScrollView)

ListScrollView::ListScrollView() : _lineHeight(15) {

}

ListScrollView::~ListScrollView() {
}

void ListScrollView::insert(const tstring& text, void* data /*= nullptr*/, unsigned before /*= 0xFFFFFFFF*/) {
	Item* i = new Item();
	i->text = text;
	i->data = data;

	auto pos = before != 0xFFFFFFFF ? _itemList.begin() + before : _itemList.end();
	_itemList.insert(pos, i);
}

void ListScrollView::resetScrollSize() {
	CRect clientRect;
	GetClientRect(clientRect);
	_totalSize.cx = 0;
	// 加1是为了最后一行一定可见
	_totalSize.cy = (_itemList.size() + 1) * _lineHeight;
#define LOGCC_WINUI_CUSTOMIZE_PAGE_SIZE_LINE_SIZE
#ifdef LOGCC_WINUI_CUSTOMIZE_PAGE_SIZE_LINE_SIZE
	CSize pageSize(clientRect.Width(), clientRect.Height() / _lineHeight * _lineHeight);
	CSize lineSize(clientRect.Width(), _lineHeight);
	SetScrollSizes(MM_TEXT, _totalSize, pageSize, lineSize);
#else
	SetScrollSizes(MM_TEXT, _totalSize);
#endif
#define LOGCC_WINUI_SCROLL_TO_END_ON_UPDATE
#ifdef LOGCC_WINUI_SCROLL_TO_END_ON_UPDATE
	int y = _totalSize.cy - clientRect.Height();
	ScrollToPosition(CPoint(0, max(y, 0)));
#endif
}

void ListScrollView::scrollTo(int yScrollPos) {
	CRect clientRect;
	GetClientRect(clientRect);

	// NOTICE:	很奇怪的现象，CScrollView在OnInitUpdate之外函数SetScrollSizes，
	//			如果设置的高度小于ClientRect，虽然没有显示滚动条仍然可以滚动，这里特殊处理一下，禁止滚动
	if (clientRect.Height() >= _totalSize.cy) return;

	ScrollToPosition(CPoint(0, yScrollPos));
}

void ListScrollView::scrollDelta(int delta) {
	int yScrollPos = GetScrollPosition().y;
	yScrollPos += delta;
	scrollTo(max(yScrollPos, 0));
}

void ListScrollView::scrollLines(int count) {
	scrollDelta(_lineHeight * count);
}

void ListScrollView::scrollPages(int count) {
	CRect clientRect;
	GetClientRect(clientRect);

	scrollLines(clientRect.Height() / _lineHeight * count);
}

bool ListScrollView::isItemVisible(unsigned index) const {
	CRect rect;
	GetClientRect(rect);
	return static_cast<int>(index * _lineHeight) >= GetScrollPosition().y
		&& static_cast<int>((index + 1) * _lineHeight) <= GetScrollPosition().y + rect.Height();
}

void ListScrollView::clear() {
	for_each(_itemList.begin(), _itemList.end(), [] (Item* p) { delete p; });
	_itemList.clear();
}

void ListScrollView::setSelectedIndex(unsigned i) {
	_selectedIndex = i;
	Invalidate();
	onSelectedChanged();
}

void ListScrollView::OnInitialUpdate() {
	CScrollView::OnInitialUpdate();

	resetScrollSize();
}

void ListScrollView::PostNcDestroy()
{
	clear();
	CScrollView::PostNcDestroy();
}

// ListScrollView 绘图

void ListScrollView::drawItem(HDC hdc, const RECT& rect, const Item* item) {
	int oldBkMode = ::SetBkMode(hdc, TRANSPARENT);
	int oldTextColor = ::GetTextColor(hdc);

	// 背景
	HBRUSH bkgdBrush = NULL;
	if (find(_itemList.begin(), _itemList.end(), item) - _itemList.begin() == (int)_selectedIndex) {
		bkgdBrush = ::CreateSolidBrush(::GetSysColor(COLOR_HIGHLIGHT));
		::SetTextColor(hdc, ::GetSysColor(COLOR_HIGHLIGHTTEXT));
	} else if (item->text.find(_T("ERROR")) != tstring::npos) {
		bkgdBrush = ::CreateSolidBrush(0x000000FF);
	} else if (item->text.find(_T("WARN")) != tstring::npos) {
		bkgdBrush = ::CreateSolidBrush(0x0000FFFF);
	} else {
		bkgdBrush = ::CreateSolidBrush(0x00FFFFFF);
	}
	HGDIOBJ oldBrush = ::SelectObject(hdc, bkgdBrush);
	::FillRect(hdc, &rect, bkgdBrush);

	::SelectObject(hdc, oldBrush);
	::DeleteObject(bkgdBrush);

	RECT textRect = rect;
	textRect.top += 1;
	textRect.bottom -= 1;
	::DrawText(hdc, item->text.c_str(), item->text.size(), &textRect,
		DT_NOCLIP | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX | DT_EXPANDTABS);

	::SetBkMode(hdc, oldBkMode);
	::SetTextColor(hdc, oldTextColor);
}

void ListScrollView::OnDraw(CDC* pDC) {
	CRect clientRect;
	GetClientRect(clientRect);

	HDC memDC = ::CreateCompatibleDC(pDC->GetSafeHdc());

	HBITMAP memBmp = ::CreateCompatibleBitmap(pDC->GetSafeHdc(), clientRect.Width(), clientRect.Height());
	HGDIOBJ oldBmp = ::SelectObject(memDC, memBmp);

	HBRUSH bkgdBrush = reinterpret_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
	::FillRect(memDC, clientRect, bkgdBrush);

	HFONT font = ::CreateFont(_lineHeight - 2, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
		DEFAULT_QUALITY, FIXED_PITCH, _T("新宋体"));
	HGDIOBJ oldFont = ::SelectObject(memDC, font);

	CPoint scrollPosition = GetScrollPosition();

	if (!_itemList.empty()) {
		// 顶部可以显示半行
		int yLogLineStart = scrollPosition.y % _lineHeight == 0 ? 0 : (scrollPosition.y % _lineHeight) * -1;
		unsigned beginLine = scrollPosition.y / _lineHeight;
		// +1是为了底部能显示半行
		unsigned endLine = (scrollPosition.y + clientRect.Height()) / _lineHeight + 1;
		endLine = min(endLine, _itemList.size());

		for (unsigned i = 0; i < endLine - beginLine; i++) {
			Item* item = _itemList[beginLine + i];
			CRect rect = clientRect;
			rect.top = yLogLineStart + i * _lineHeight;
			rect.bottom = rect.top + _lineHeight;
			drawItem(memDC, rect, item);
		}
	}

	::BitBlt(pDC->GetSafeHdc(), scrollPosition.x, scrollPosition.y, clientRect.Width(), clientRect.Height(),
		memDC, 0, 0, SRCCOPY);

	::SelectObject(memDC, oldFont);
	::DeleteObject(font);
	::SelectObject(memDC, oldBmp);
	::DeleteObject(memBmp);
	::DeleteDC(memDC);
}

// ListScrollView 消息处理程序

BEGIN_MESSAGE_MAP(ListScrollView, CScrollView)
	ON_WM_ERASEBKGND()
	ON_WM_VSCROLL()
	ON_WM_MOUSEWHEEL()
	ON_WM_KEYDOWN()
	ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

BOOL ListScrollView::OnEraseBkgnd(CDC* /*pDC*/) {
#ifdef LOGCC_WINUI_USE_DEFAULT_ERASE_BACKGROUND
	return CScrollView::OnEraseBkgnd(pDC);
#else
	return TRUE;
#endif
}

void ListScrollView::OnVScroll(UINT nSBCode, UINT /*nPos*/, CScrollBar* /*pScrollBar*/) {
	// 以下代码源自：http://blog.csdn.net/xiaji2007/article/details/5744111
	// 并予以修改
	// 解决CScrollView行数过多时滚动条回滚问题
	SCROLLINFO si = { 0 };
	si.cbSize = sizeof(SCROLLINFO);
	si.fMask = SIF_ALL;
	GetScrollInfo(SB_VERT, &si);
	int lastPos = si.nPos;
	switch (nSBCode) {
	case SB_TOP:		si.nPos = si.nMin;		break;
	case SB_BOTTOM:		si.nPos = si.nMax;		break;
	case SB_LINEUP:		si.nPos -= _lineHeight;	break;
	case SB_LINEDOWN:	si.nPos += _lineHeight;	break;
	case SB_PAGEUP:		si.nPos -= si.nPage;	break;
	case SB_PAGEDOWN:	si.nPos += si.nPage;	break;
	case SB_THUMBTRACK:	si.nPos = si.nTrackPos;	break;
	default:									break;
	}
	si.fMask = SIF_POS;
	SetScrollInfo(SB_VERT, &si);
	if (lastPos!=si.nPos) {
		::ScrollWindow(m_hWnd, 0, lastPos - si.nPos, NULL, NULL);
	}
}

BOOL ListScrollView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) {
	if (zDelta < 0) {
		// 向下3行
		scrollLines(3);
	} else {
		// 向上3行
		scrollLines(-3);
	}
	return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
}

void ListScrollView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
	// 以下是切换选中的情况
	if (nChar == VK_UP) {
		// 选中上一行
		if (_selectedIndex > 0 && _selectedIndex != 0xFFFFFFFF) {
			setSelectedIndex(_selectedIndex - 1);

			if (!isItemVisible(_selectedIndex)) {
				scrollLines(-1);
			}
		}
	} else if (nChar == VK_DOWN) {
		// 选中下一行
		if (_selectedIndex != 0xFFFFFFFF && _selectedIndex < _itemList.size() - 1) {
			setSelectedIndex(_selectedIndex + 1);;

			if (!isItemVisible(_selectedIndex)) {
				scrollLines(1);
			}
		}
	} else {
		// 以下是滚动的情况
		if (::GetKeyState(VK_CONTROL) & 0x80000000) {
			if (nChar == VK_HOME) {
				// 跳到第一页
				scrollTo(0);
			} else if (nChar == VK_END) {
				// 跳到最后一页，多出没事
				scrollTo(_itemList.size() * _lineHeight);
			} else if (nChar == VK_UP) {
				// 向上1行
				scrollLines(-1);
			} else if (nChar == VK_DOWN) {
				// 向下1行
				scrollLines(1);
			}
		}
		if (nChar == VK_PRIOR) {
			// 向上1页
			scrollPages(-1);
		} else if (nChar == VK_NEXT) {
			// 向下1页
			scrollPages(1);
		}
	}
	CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void ListScrollView::OnLButtonUp(UINT nFlags, CPoint point) {
	int yScrollPos = GetScrollPosition().y;
	unsigned index = (yScrollPos + point.y) / _lineHeight;

	if (index < _itemList.size()) {
		setSelectedIndex(index);
	}

	CScrollView::OnLButtonUp(nFlags, point);
}
<commit_msg>解决不足一页的文件打开后未重绘的问题<commit_after>// ListScrollView.cpp : 实现文件
//

#include "stdafx.h"
#include "ListScrollView.h"

// ListScrollView

IMPLEMENT_DYNCREATE(ListScrollView, CScrollView)

ListScrollView::ListScrollView() : _lineHeight(15) {

}

ListScrollView::~ListScrollView() {
}

void ListScrollView::insert(const tstring& text, void* data /*= nullptr*/, unsigned before /*= 0xFFFFFFFF*/) {
	Item* i = new Item();
	i->text = text;
	i->data = data;

	auto pos = before != 0xFFFFFFFF ? _itemList.begin() + before : _itemList.end();
	_itemList.insert(pos, i);
}

void ListScrollView::resetScrollSize() {
	CRect clientRect;
	GetClientRect(clientRect);
	_totalSize.cx = 0;
	// 加1是为了最后一行一定可见
	_totalSize.cy = (_itemList.size() + 1) * _lineHeight;
#define LOGCC_WINUI_CUSTOMIZE_PAGE_SIZE_LINE_SIZE
#ifdef LOGCC_WINUI_CUSTOMIZE_PAGE_SIZE_LINE_SIZE
	CSize pageSize(clientRect.Width(), clientRect.Height() / _lineHeight * _lineHeight);
	CSize lineSize(clientRect.Width(), _lineHeight);
	SetScrollSizes(MM_TEXT, _totalSize, pageSize, lineSize);
#else
	SetScrollSizes(MM_TEXT, _totalSize);
#endif
#define LOGCC_WINUI_SCROLL_TO_END_ON_UPDATE
#ifdef LOGCC_WINUI_SCROLL_TO_END_ON_UPDATE
	int y = _totalSize.cy - clientRect.Height();
	ScrollToPosition(CPoint(0, max(y, 0)));
#endif
	Invalidate();
}

void ListScrollView::scrollTo(int yScrollPos) {
	CRect clientRect;
	GetClientRect(clientRect);

	// NOTICE:	很奇怪的现象，CScrollView在OnInitUpdate之外函数SetScrollSizes，
	//			如果设置的高度小于ClientRect，虽然没有显示滚动条仍然可以滚动，这里特殊处理一下，禁止滚动
	if (clientRect.Height() >= _totalSize.cy) return;

	ScrollToPosition(CPoint(0, yScrollPos));
}

void ListScrollView::scrollDelta(int delta) {
	int yScrollPos = GetScrollPosition().y;
	yScrollPos += delta;
	scrollTo(max(yScrollPos, 0));
}

void ListScrollView::scrollLines(int count) {
	scrollDelta(_lineHeight * count);
}

void ListScrollView::scrollPages(int count) {
	CRect clientRect;
	GetClientRect(clientRect);

	scrollLines(clientRect.Height() / _lineHeight * count);
}

bool ListScrollView::isItemVisible(unsigned index) const {
	CRect rect;
	GetClientRect(rect);
	return static_cast<int>(index * _lineHeight) >= GetScrollPosition().y
		&& static_cast<int>((index + 1) * _lineHeight) <= GetScrollPosition().y + rect.Height();
}

void ListScrollView::clear() {
	for_each(_itemList.begin(), _itemList.end(), [] (Item* p) { delete p; });
	_itemList.clear();
}

void ListScrollView::setSelectedIndex(unsigned i) {
	_selectedIndex = i;
	Invalidate();
	onSelectedChanged();
}

void ListScrollView::OnInitialUpdate() {
	CScrollView::OnInitialUpdate();

	resetScrollSize();
}

void ListScrollView::PostNcDestroy()
{
	clear();
	CScrollView::PostNcDestroy();
}

// ListScrollView 绘图

void ListScrollView::drawItem(HDC hdc, const RECT& rect, const Item* item) {
	int oldBkMode = ::SetBkMode(hdc, TRANSPARENT);
	int oldTextColor = ::GetTextColor(hdc);

	// 背景
	HBRUSH bkgdBrush = NULL;
	if (find(_itemList.begin(), _itemList.end(), item) - _itemList.begin() == (int)_selectedIndex) {
		bkgdBrush = ::CreateSolidBrush(::GetSysColor(COLOR_HIGHLIGHT));
		::SetTextColor(hdc, ::GetSysColor(COLOR_HIGHLIGHTTEXT));
	} else if (item->text.find(_T("ERROR")) != tstring::npos) {
		bkgdBrush = ::CreateSolidBrush(0x000000FF);
	} else if (item->text.find(_T("WARN")) != tstring::npos) {
		bkgdBrush = ::CreateSolidBrush(0x0000FFFF);
	} else {
		bkgdBrush = ::CreateSolidBrush(0x00FFFFFF);
	}
	HGDIOBJ oldBrush = ::SelectObject(hdc, bkgdBrush);
	::FillRect(hdc, &rect, bkgdBrush);

	::SelectObject(hdc, oldBrush);
	::DeleteObject(bkgdBrush);

	RECT textRect = rect;
	textRect.top += 1;
	textRect.bottom -= 1;
	::DrawText(hdc, item->text.c_str(), item->text.size(), &textRect,
		DT_NOCLIP | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX | DT_EXPANDTABS);

	::SetBkMode(hdc, oldBkMode);
	::SetTextColor(hdc, oldTextColor);
}

void ListScrollView::OnDraw(CDC* pDC) {
	CRect clientRect;
	GetClientRect(clientRect);

	HDC memDC = ::CreateCompatibleDC(pDC->GetSafeHdc());

	HBITMAP memBmp = ::CreateCompatibleBitmap(pDC->GetSafeHdc(), clientRect.Width(), clientRect.Height());
	HGDIOBJ oldBmp = ::SelectObject(memDC, memBmp);

	HBRUSH bkgdBrush = reinterpret_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
	::FillRect(memDC, clientRect, bkgdBrush);

	HFONT font = ::CreateFont(_lineHeight - 2, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
		DEFAULT_QUALITY, FIXED_PITCH, _T("新宋体"));
	HGDIOBJ oldFont = ::SelectObject(memDC, font);

	CPoint scrollPosition = GetScrollPosition();

	if (!_itemList.empty()) {
		// 顶部可以显示半行
		int yLogLineStart = scrollPosition.y % _lineHeight == 0 ? 0 : (scrollPosition.y % _lineHeight) * -1;
		unsigned beginLine = scrollPosition.y / _lineHeight;
		// +1是为了底部能显示半行
		unsigned endLine = (scrollPosition.y + clientRect.Height()) / _lineHeight + 1;
		endLine = min(endLine, _itemList.size());

		for (unsigned i = 0; i < endLine - beginLine; i++) {
			Item* item = _itemList[beginLine + i];
			CRect rect = clientRect;
			rect.top = yLogLineStart + i * _lineHeight;
			rect.bottom = rect.top + _lineHeight;
			drawItem(memDC, rect, item);
		}
	}

	::BitBlt(pDC->GetSafeHdc(), scrollPosition.x, scrollPosition.y, clientRect.Width(), clientRect.Height(),
		memDC, 0, 0, SRCCOPY);

	::SelectObject(memDC, oldFont);
	::DeleteObject(font);
	::SelectObject(memDC, oldBmp);
	::DeleteObject(memBmp);
	::DeleteDC(memDC);
}

// ListScrollView 消息处理程序

BEGIN_MESSAGE_MAP(ListScrollView, CScrollView)
	ON_WM_ERASEBKGND()
	ON_WM_VSCROLL()
	ON_WM_MOUSEWHEEL()
	ON_WM_KEYDOWN()
	ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

BOOL ListScrollView::OnEraseBkgnd(CDC* /*pDC*/) {
#ifdef LOGCC_WINUI_USE_DEFAULT_ERASE_BACKGROUND
	return CScrollView::OnEraseBkgnd(pDC);
#else
	return TRUE;
#endif
}

void ListScrollView::OnVScroll(UINT nSBCode, UINT /*nPos*/, CScrollBar* /*pScrollBar*/) {
	// 以下代码源自：http://blog.csdn.net/xiaji2007/article/details/5744111
	// 并予以修改
	// 解决CScrollView行数过多时滚动条回滚问题
	SCROLLINFO si = { 0 };
	si.cbSize = sizeof(SCROLLINFO);
	si.fMask = SIF_ALL;
	GetScrollInfo(SB_VERT, &si);
	int lastPos = si.nPos;
	switch (nSBCode) {
	case SB_TOP:		si.nPos = si.nMin;		break;
	case SB_BOTTOM:		si.nPos = si.nMax;		break;
	case SB_LINEUP:		si.nPos -= _lineHeight;	break;
	case SB_LINEDOWN:	si.nPos += _lineHeight;	break;
	case SB_PAGEUP:		si.nPos -= si.nPage;	break;
	case SB_PAGEDOWN:	si.nPos += si.nPage;	break;
	case SB_THUMBTRACK:	si.nPos = si.nTrackPos;	break;
	default:									break;
	}
	si.fMask = SIF_POS;
	SetScrollInfo(SB_VERT, &si);
	if (lastPos!=si.nPos) {
		::ScrollWindow(m_hWnd, 0, lastPos - si.nPos, NULL, NULL);
	}
}

BOOL ListScrollView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) {
	if (zDelta < 0) {
		// 向下3行
		scrollLines(3);
	} else {
		// 向上3行
		scrollLines(-3);
	}
	return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
}

void ListScrollView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
	// 以下是切换选中的情况
	if (nChar == VK_UP) {
		// 选中上一行
		if (_selectedIndex > 0 && _selectedIndex != 0xFFFFFFFF) {
			setSelectedIndex(_selectedIndex - 1);

			if (!isItemVisible(_selectedIndex)) {
				scrollLines(-1);
			}
		}
	} else if (nChar == VK_DOWN) {
		// 选中下一行
		if (_selectedIndex != 0xFFFFFFFF && _selectedIndex < _itemList.size() - 1) {
			setSelectedIndex(_selectedIndex + 1);;

			if (!isItemVisible(_selectedIndex)) {
				scrollLines(1);
			}
		}
	} else {
		// 以下是滚动的情况
		if (::GetKeyState(VK_CONTROL) & 0x80000000) {
			if (nChar == VK_HOME) {
				// 跳到第一页
				scrollTo(0);
			} else if (nChar == VK_END) {
				// 跳到最后一页，多出没事
				scrollTo(_itemList.size() * _lineHeight);
			} else if (nChar == VK_UP) {
				// 向上1行
				scrollLines(-1);
			} else if (nChar == VK_DOWN) {
				// 向下1行
				scrollLines(1);
			}
		}
		if (nChar == VK_PRIOR) {
			// 向上1页
			scrollPages(-1);
		} else if (nChar == VK_NEXT) {
			// 向下1页
			scrollPages(1);
		}
	}
	CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void ListScrollView::OnLButtonUp(UINT nFlags, CPoint point) {
	int yScrollPos = GetScrollPosition().y;
	unsigned index = (yScrollPos + point.y) / _lineHeight;

	if (index < _itemList.size()) {
		setSelectedIndex(index);
	}

	CScrollView::OnLButtonUp(nFlags, point);
}
<|endoftext|>


<commit_before>#include "audiorecorder.h"
#include <QDebug>
#include <QAudioDeviceInfo>
#include <QDir>
#include <QFileInfo>

AudioRecorder::AudioRecorder(QQuickItem *parent):
    QQuickItem(parent)
  ,m_source("")
  ,m_codecIndex(0)
{
    m_supportedCodecs.clear();
    // By default, QQuickItem does not draw anything. If you subclass
    // QQuickItem to create a visual item, you will need to uncomment the
    // following line and re-implement updatePaintNode()

    // setFlag(ItemHasContents, true);

    qDebug() << "[AudioRecorder]created!!";
    this->initializeQAudioRecorder();
}

AudioRecorder::~AudioRecorder()
{
    if(m_audioRecorder)
    {
        delete m_audioRecorder;
        m_audioRecorder = NULL;
    }
}

void AudioRecorder::record(bool overWrite)
{
#ifdef defined Q_OS_MAC
    m_source.remove("file://");
#endif
    QFileInfo source(m_source);
    QAudioEncoderSettings asettings = m_audioRecorder->audioSettings();
    if(asettings.codec() == "audio/pcm" || asettings.codec() == "audio/PCM")
    {
        //setFile seems to have bug on Windows
        source.setFile(m_source + ".wav");
#if (defined Q_OS_LINUX) || (defined Q_OS_WIN)
        //added file extension
        m_source += ".wav";
#endif
    } else {
        //other formats are not tested on Mac and Windows
        QString extension = "." + (asettings.codec()).remove("audio/");
        source.setFile(m_source + extension);
#if (defined Q_OS_LINUX) || (defined Q_OS_WIN)
        m_source += extension;
#endif
    }
    qDebug() << "source.absoluteFilePath=" << source.absoluteFilePath();
    qDebug() << "m_source=" << m_source;
    qDebug() << "does file exists? -> " << source.exists();
    if(source.exists() && overWrite==false){
        emit fileExists();
        return;
    }
    m_audioRecorder->setOutputLocation(m_source);
    //setOutputLocation doesn't work on Qt5.2.0 for windows
    qDebug() << "outputLocation=" << m_audioRecorder->outputLocation();
    m_audioRecorder->record();
}

void AudioRecorder::stop()
{
    m_audioRecorder->stop();
}

int AudioRecorder::codec(){
    return m_codecIndex;
}

void AudioRecorder::setCodec(int value){
    if(m_codecIndex!=value){
        m_codecIndex = value;
        QAudioEncoderSettings audioSettings;
        qDebug() << "setCodec to " << m_supportedCodecs[m_codecIndex];
        audioSettings.setCodec(m_supportedCodecs[m_codecIndex]);
        audioSettings.setQuality(QMultimedia::HighQuality);
        m_audioRecorder->setEncodingSettings(audioSettings);
        emit codecChanged();
    }
}

void AudioRecorder::initializeQAudioRecorder()
{
    QStringList codecs;

    QAudioDeviceInfo outDeviceInfo(QAudioDeviceInfo::defaultOutputDevice());
    codecs = outDeviceInfo.supportedCodecs();
    for (int i = 0; i < codecs.size(); ++i) {
        qDebug() << "out device supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
    }
    QAudioDeviceInfo inDeviceInfo(QAudioDeviceInfo::defaultInputDevice());

    codecs = inDeviceInfo.supportedCodecs();
    for (int i = 0; i < codecs.size(); ++i) {
         qDebug() << "in device supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
    }

    qDebug() << "new QAudioRecorder";
    m_audioRecorder = new QAudioRecorder(this);

    codecs = m_audioRecorder->supportedAudioCodecs();
    for (int i = 0; i < codecs.size(); ++i){
        m_supportedCodecs.append(codecs.at(i).toLocal8Bit().constData());
        qDebug() << "supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
    }

    QAudioEncoderSettings audioSettings;
//    audioSettings.setCodec("audio/pcm");
    qDebug() << "setCodec to " << codecs.at(0).toLocal8Bit().constData();
    audioSettings.setCodec(codecs.at(0).toLocal8Bit().constData());
    audioSettings.setQuality(QMultimedia::HighQuality);

    m_audioRecorder->setEncodingSettings(audioSettings);

    qDebug() << "current path is " << QDir::currentPath();

    QStringList inputs = m_audioRecorder->audioInputs();
    QString selectedInput = m_audioRecorder->defaultAudioInput();

//    foreach (QString input, inputs) {
//        QString description = m_audioRecorder->audioInputDescription(input);
//        // show descriptions to user and allow selection
//        selectedInput = input;
//    }

    m_audioRecorder->setAudioInput(selectedInput);

//    qDebug() << "isMetaDataWritable is" << m_audioRecorder->isMetaDataWritable();
//    m_audioRecorder->setMetaData(QMediaMetaData::Title, QVariant(QLatin1String("Test Title")));
//    m_audioRecorder->setMetaData(QMediaMetaData::AlbumTitle, QVariant(QLatin1String("Album Title")));
//    m_audioRecorder->setMetaData(QMediaMetaData::AlbumArtist, QVariant(QLatin1String("Album Artist")));
//    codecs = m_audioRecorder->supportedAudioCodecs();
//    for (int i = 0; i < codecs.size(); ++i)
//         qDebug() << "supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
//    codecs = m_audioRecorder->supportedAudioSampleRates();
//    for (int i = 0; i < codecs.size(); ++i)
//         qDebug() << "supported sample rates" << i << codecs.at(i).toLocal8Bit().constData() << endl;
}

<commit_msg>bug fixed. faild to record on Mac.<commit_after>#include "audiorecorder.h"
#include <QDebug>
#include <QAudioDeviceInfo>
#include <QDir>
#include <QFileInfo>

AudioRecorder::AudioRecorder(QQuickItem *parent):
    QQuickItem(parent)
  ,m_source("")
  ,m_codecIndex(0)
{
    m_supportedCodecs.clear();
    // By default, QQuickItem does not draw anything. If you subclass
    // QQuickItem to create a visual item, you will need to uncomment the
    // following line and re-implement updatePaintNode()

    // setFlag(ItemHasContents, true);

    qDebug() << "[AudioRecorder]created!!";
    this->initializeQAudioRecorder();
}

AudioRecorder::~AudioRecorder()
{
    if(m_audioRecorder)
    {
        delete m_audioRecorder;
        m_audioRecorder = NULL;
    }
}

void AudioRecorder::record(bool overWrite)
{
#if defined Q_OS_MAC
    m_source.remove("file://");
#endif
    QFileInfo source(m_source);
    QAudioEncoderSettings asettings = m_audioRecorder->audioSettings();
    if(asettings.codec() == "audio/pcm" || asettings.codec() == "audio/PCM")
    {
        //setFile seems to have bug on Windows
        source.setFile(m_source + ".wav");
#if (defined Q_OS_LINUX) || (defined Q_OS_WIN)
        //added file extension
        m_source += ".wav";
#endif
    } else {
        //other formats are not tested on Mac and Windows
        QString extension = "." + (asettings.codec()).remove("audio/");
        source.setFile(m_source + extension);
#if (defined Q_OS_LINUX) || (defined Q_OS_WIN)
        m_source += extension;
#endif
    }
    qDebug() << "source.absoluteFilePath=" << source.absoluteFilePath();
    qDebug() << "m_source=" << m_source;
    qDebug() << "does file exists? -> " << source.exists();
    if(source.exists() && overWrite==false){
        emit fileExists();
        return;
    }
    m_audioRecorder->setOutputLocation(m_source);
    //setOutputLocation doesn't work on Qt5.2.0 for windows
    qDebug() << "outputLocation=" << m_audioRecorder->outputLocation();
    m_audioRecorder->record();
}

void AudioRecorder::stop()
{
    m_audioRecorder->stop();
}

int AudioRecorder::codec(){
    return m_codecIndex;
}

void AudioRecorder::setCodec(int value){
    if(m_codecIndex!=value){
        m_codecIndex = value;
        QAudioEncoderSettings audioSettings;
        qDebug() << "setCodec to " << m_supportedCodecs[m_codecIndex];
        audioSettings.setCodec(m_supportedCodecs[m_codecIndex]);
        audioSettings.setQuality(QMultimedia::HighQuality);
        m_audioRecorder->setEncodingSettings(audioSettings);
        emit codecChanged();
    }
}

void AudioRecorder::initializeQAudioRecorder()
{
    QStringList codecs;

    QAudioDeviceInfo outDeviceInfo(QAudioDeviceInfo::defaultOutputDevice());
    codecs = outDeviceInfo.supportedCodecs();
    for (int i = 0; i < codecs.size(); ++i) {
        qDebug() << "out device supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
    }
    QAudioDeviceInfo inDeviceInfo(QAudioDeviceInfo::defaultInputDevice());

    codecs = inDeviceInfo.supportedCodecs();
    for (int i = 0; i < codecs.size(); ++i) {
         qDebug() << "in device supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
    }

    qDebug() << "new QAudioRecorder";
    m_audioRecorder = new QAudioRecorder(this);

    codecs = m_audioRecorder->supportedAudioCodecs();
    for (int i = 0; i < codecs.size(); ++i){
        m_supportedCodecs.append(codecs.at(i).toLocal8Bit().constData());
        qDebug() << "supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
    }

    QAudioEncoderSettings audioSettings;
//    audioSettings.setCodec("audio/pcm");
    qDebug() << "setCodec to " << codecs.at(0).toLocal8Bit().constData();
    audioSettings.setCodec(codecs.at(0).toLocal8Bit().constData());
    audioSettings.setQuality(QMultimedia::HighQuality);

    m_audioRecorder->setEncodingSettings(audioSettings);

    qDebug() << "current path is " << QDir::currentPath();

    QStringList inputs = m_audioRecorder->audioInputs();
    QString selectedInput = m_audioRecorder->defaultAudioInput();

//    foreach (QString input, inputs) {
//        QString description = m_audioRecorder->audioInputDescription(input);
//        // show descriptions to user and allow selection
//        selectedInput = input;
//    }

    m_audioRecorder->setAudioInput(selectedInput);

//    qDebug() << "isMetaDataWritable is" << m_audioRecorder->isMetaDataWritable();
//    m_audioRecorder->setMetaData(QMediaMetaData::Title, QVariant(QLatin1String("Test Title")));
//    m_audioRecorder->setMetaData(QMediaMetaData::AlbumTitle, QVariant(QLatin1String("Album Title")));
//    m_audioRecorder->setMetaData(QMediaMetaData::AlbumArtist, QVariant(QLatin1String("Album Artist")));
//    codecs = m_audioRecorder->supportedAudioCodecs();
//    for (int i = 0; i < codecs.size(); ++i)
//         qDebug() << "supported codecs" << i << codecs.at(i).toLocal8Bit().constData() << endl;
//    codecs = m_audioRecorder->supportedAudioSampleRates();
//    for (int i = 0; i < codecs.size(); ++i)
//         qDebug() << "supported sample rates" << i << codecs.at(i).toLocal8Bit().constData() << endl;
}

<|endoftext|>


<commit_before>#include "ActorConfigurationParser.h"
#include "json.h"

#include "../Action.h"
#include "../Actor.h"
#include "../JITRotation.h"
#include "../Simulation.h"

#include "../models/Monk.h"

#include <memory>
#include <cstring>
#include <map>

#include <inttypes.h>

namespace applications {

int SingleJSON(int argc, const char* argv[]) {
	if (argc < 3) {
		printf("Usage: simulator single-json subject rotation length [seed]\n");
		return 1;
	}

	ActorConfigurationParser subjectParser;
	if (!subjectParser.parseFile(argv[0])) {
		printf("Unable to read configuration.\n");
		return 1;
	}

	JITRotation subjectRotation;
	if (!subjectRotation.initializeWithFile(argv[1])) {
		printf("Unable to read rotation.\n");
		return 1;
	}

	auto& subjectConfiguration = subjectParser.configuration();
	subjectConfiguration.identifier = "player";
	subjectConfiguration.rotation = &subjectRotation;
	subjectConfiguration.keepsHistory = true;

	if (subjectConfiguration.petConfiguration) {
		auto petConfiguration = *subjectConfiguration.petConfiguration;
		petConfiguration.identifier = "player-pet";
		petConfiguration.keepsHistory = subjectConfiguration.keepsHistory;
	}

	models::Monk targetModel;
	Actor::Configuration targetConfiguration;
	targetConfiguration.identifier = "target";
	targetConfiguration.model = &targetModel;
	targetConfiguration.keepsHistory = true;

	int simulationSeconds = atoi(argv[2]);

	Simulation::Configuration configuration;
	configuration.length = std::chrono::seconds(simulationSeconds);
	configuration.subjectConfiguration = &subjectConfiguration;
	configuration.targetConfiguration = &targetConfiguration;

	uint64_t seed = 0;

	if (argc < 4) {
		std::random_device rd;
		std::uniform_int_distribution<uint64_t> dist;
		seed = dist(rd);
	} else {
		seed = strtoull(argv[3], nullptr, 0);
	}

	Simulation simulation(&configuration, seed);
	simulation.run();

	Actor::SimulationStats mergedStats;
	std::map<std::string, Actor::EffectSimulationStats> mergedEffectStats;

	for (auto& subject : simulation.subjects()) {
		mergedStats += subject->simulationStats();
		for (auto& kv : subject->effectSimulationStats()) {
			mergedEffectStats[kv.first] += kv.second;
		}
	}

	printf("{");

	JSONPrint("seed"); printf(":"); JSONPrint(std::to_string(seed)); printf(",");
	JSONPrint("time"); printf(":"); JSONPrint(configuration.length); printf(",");
	JSONPrint("damage"); printf(":"); JSONPrint(mergedStats.damageDealt); printf(",");

	printf("\"subjects\":{");

	bool firstSubject = true;
	for (auto& subject : simulation.subjects()) {
		if (!firstSubject) { printf(","); }
		firstSubject = false;

		JSONPrint(subject->identifier());
		printf(":");

		auto& simStats = subject->simulationStats();

		JSONPrintDict(
			"model", subject->model()->identifier(),
			"owner", subject->owner() ? subject->owner()->identifier().c_str() : nullptr,
			"stats", subject->configuration()->stats,
			"damage", simStats.damageDealt,
			"effects", subject->effectSimulationStats(),
			"tp-samples", simStats.tpSamples,
			"mp-samples", simStats.mpSamples,
			"actions", simStats.actions,
			"auras", simStats.auraSamples
		);
	}

	printf("}");

	printf("}");

	printf("\n");

	return 0;
}

}<commit_msg>allow floating point length<commit_after>#include "ActorConfigurationParser.h"
#include "json.h"

#include "../Action.h"
#include "../Actor.h"
#include "../JITRotation.h"
#include "../Simulation.h"

#include "../models/Monk.h"

#include <chrono>
#include <memory>
#include <cstring>
#include <map>

#include <inttypes.h>

namespace applications {

int SingleJSON(int argc, const char* argv[]) {
	if (argc < 3) {
		printf("Usage: simulator single-json subject rotation length [seed]\n");
		return 1;
	}

	ActorConfigurationParser subjectParser;
	if (!subjectParser.parseFile(argv[0])) {
		printf("Unable to read configuration.\n");
		return 1;
	}

	JITRotation subjectRotation;
	if (!subjectRotation.initializeWithFile(argv[1])) {
		printf("Unable to read rotation.\n");
		return 1;
	}

	auto& subjectConfiguration = subjectParser.configuration();
	subjectConfiguration.identifier = "player";
	subjectConfiguration.rotation = &subjectRotation;
	subjectConfiguration.keepsHistory = true;

	if (subjectConfiguration.petConfiguration) {
		auto petConfiguration = *subjectConfiguration.petConfiguration;
		petConfiguration.identifier = "player-pet";
		petConfiguration.keepsHistory = subjectConfiguration.keepsHistory;
	}

	models::Monk targetModel;
	Actor::Configuration targetConfiguration;
	targetConfiguration.identifier = "target";
	targetConfiguration.model = &targetModel;
	targetConfiguration.keepsHistory = true;

	std::chrono::duration<double> simulationSeconds(strtod(argv[2], nullptr));

	Simulation::Configuration configuration;
	configuration.length = std::chrono::duration_cast<std::chrono::microseconds>(simulationSeconds);
	configuration.subjectConfiguration = &subjectConfiguration;
	configuration.targetConfiguration = &targetConfiguration;

	uint64_t seed = 0;

	if (argc < 4) {
		std::random_device rd;
		std::uniform_int_distribution<uint64_t> dist;
		seed = dist(rd);
	} else {
		seed = strtoull(argv[3], nullptr, 0);
	}

	Simulation simulation(&configuration, seed);
	simulation.run();

	Actor::SimulationStats mergedStats;
	std::map<std::string, Actor::EffectSimulationStats> mergedEffectStats;

	for (auto& subject : simulation.subjects()) {
		mergedStats += subject->simulationStats();
		for (auto& kv : subject->effectSimulationStats()) {
			mergedEffectStats[kv.first] += kv.second;
		}
	}

	printf("{");

	JSONPrint("seed"); printf(":"); JSONPrint(std::to_string(seed)); printf(",");
	JSONPrint("time"); printf(":"); JSONPrint(configuration.length); printf(",");
	JSONPrint("damage"); printf(":"); JSONPrint(mergedStats.damageDealt); printf(",");

	printf("\"subjects\":{");

	bool firstSubject = true;
	for (auto& subject : simulation.subjects()) {
		if (!firstSubject) { printf(","); }
		firstSubject = false;

		JSONPrint(subject->identifier());
		printf(":");

		auto& simStats = subject->simulationStats();

		JSONPrintDict(
			"model", subject->model()->identifier(),
			"owner", subject->owner() ? subject->owner()->identifier().c_str() : nullptr,
			"stats", subject->configuration()->stats,
			"damage", simStats.damageDealt,
			"effects", subject->effectSimulationStats(),
			"tp-samples", simStats.tpSamples,
			"mp-samples", simStats.mpSamples,
			"actions", simStats.actions,
			"auras", simStats.auraSamples
		);
	}

	printf("}");

	printf("}");

	printf("\n");

	return 0;
}

}<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <string>
#include <utility>
#include <vector>
#include <cpp-sort/sorters.h>
#include "distributions.h"

#ifdef _WIN32
    #include <intrin.h>
    #define rdtsc __rdtsc
#else
    #ifdef __i586__
        static __inline__ unsigned long long rdtsc() {
            unsigned long long int x;
            __asm__ volatile(".byte 0x0f, 0x31" : "=A" (x));
            return x;
        }
    #elif defined(__x86_64__)
        static __inline__ unsigned long long rdtsc(){
            unsigned hi, lo;
            __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
            return ((unsigned long long) lo) | (((unsigned long long) hi) << 32);
        }
    #else
        #error no rdtsc implementation
    #endif
#endif

template<template<typename...> class Collection, typename T>
using distr_f = void (*)(std::back_insert_iterator<Collection<T>>, std::size_t);

template<template<typename...> class Collection, typename T>
using sort_f = void (*)(Collection<T>&);

// Type of data to sort during the benchmark
using value_t = int;

int main()
{
    using namespace std::chrono_literals;

    std::pair<std::string, distr_f<std::vector, value_t>> distributions[] = {
        { "shuffled",               shuffled()              },
        { "shuffled_16_values",     shuffled_16_values()    },
        { "all_equal",              all_equal()             },
        { "ascending",              ascending()             },
        { "descending",             descending()            },
        { "pipe_organ",             pipe_organ()            },
        { "push_front",             push_front()            },
        { "push_middle",            push_middle()           },
        { "ascending_sawtooth",     ascending_sawtooth()    },
        { "descending_sawtooth",    descending_sawtooth()   },
        { "alternating",            alternating()           },
        { "alternating_16_values",  alternating_16_values() }
    };

    std::pair<std::string, sort_f<std::vector, value_t>> sorts[] = {
        { "heap_sort",      cppsort::heap_sort      },
        { "pdq_sort",       cppsort::pdq_sort       },
        { "quick_sort",     cppsort::quick_sort     },
        { "spread_sort",    cppsort::spread_sort    },
        { "std_sort",       cppsort::std_sort       },
        { "verge_sort",     cppsort::verge_sort     }
    };

    std::size_t sizes[] = { 1'000'000 };

    for (auto& distribution: distributions) {
        for (auto& sort: sorts) {
            for (auto size: sizes) {
                std::vector<std::uint64_t> cycles;

                auto total_start = std::chrono::high_resolution_clock::now();
                auto total_end = std::chrono::high_resolution_clock::now();
                while (std::chrono::duration_cast<std::chrono::seconds>(total_end - total_start) < 5s) {
                    std::vector<value_t> collection;
                    distribution.second(std::back_inserter(collection), size);
                    std::uint64_t start = rdtsc();
                    sort.second(collection);
                    std::uint64_t end = rdtsc();
                    assert(std::is_sorted(std::begin(collection), std::end(collection)));
                    cycles.push_back(double(end - start) / size + 0.5);
                    total_end = std::chrono::high_resolution_clock::now();
                }

                std::sort(std::begin(cycles), std::end(cycles));

                std::cerr << size << ' ' << distribution.first << ' ' << sort.first
                          << ' ' << cycles[cycles.size() / 2] << '\n';
                std::cout << size << ' ' << distribution.first << ' ' << sort.first
                          << ' ' << cycles[cycles.size() / 2] << '\n';
            }
        }
    }
}
<commit_msg>Make sure to always use a steady clock in benchmarks<commit_after>#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <cpp-sort/sorters.h>
#include "distributions.h"

#ifdef _WIN32
    #include <intrin.h>
    #define rdtsc __rdtsc
#else
    #ifdef __i586__
        static __inline__ unsigned long long rdtsc() {
            unsigned long long int x;
            __asm__ volatile(".byte 0x0f, 0x31" : "=A" (x));
            return x;
        }
    #elif defined(__x86_64__)
        static __inline__ unsigned long long rdtsc(){
            unsigned hi, lo;
            __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
            return ((unsigned long long) lo) | (((unsigned long long) hi) << 32);
        }
    #else
        #error no rdtsc implementation
    #endif
#endif

template<template<typename...> class Collection, typename T>
using distr_f = void (*)(std::back_insert_iterator<Collection<T>>, std::size_t);

template<template<typename...> class Collection, typename T>
using sort_f = void (*)(Collection<T>&);

// Type of data to sort during the benchmark
using value_t = int;

int main()
{
    using namespace std::chrono_literals;

    // Always use a steady clock
    using clock_type = std::conditional_t<
        std::chrono::high_resolution_clock::is_steady,
        std::chrono::high_resolution_clock,
        std::chrono::steady_clock
    >;

    std::pair<std::string, distr_f<std::vector, value_t>> distributions[] = {
        { "shuffled",               shuffled()              },
        { "shuffled_16_values",     shuffled_16_values()    },
        { "all_equal",              all_equal()             },
        { "ascending",              ascending()             },
        { "descending",             descending()            },
        { "pipe_organ",             pipe_organ()            },
        { "push_front",             push_front()            },
        { "push_middle",            push_middle()           },
        { "ascending_sawtooth",     ascending_sawtooth()    },
        { "descending_sawtooth",    descending_sawtooth()   },
        { "alternating",            alternating()           },
        { "alternating_16_values",  alternating_16_values() }
    };

    std::pair<std::string, sort_f<std::vector, value_t>> sorts[] = {
        { "heap_sort",      cppsort::heap_sort      },
        { "pdq_sort",       cppsort::pdq_sort       },
        { "quick_sort",     cppsort::quick_sort     },
        { "spread_sort",    cppsort::spread_sort    },
        { "std_sort",       cppsort::std_sort       },
        { "verge_sort",     cppsort::verge_sort     }
    };

    std::size_t sizes[] = { 1'000'000 };

    for (auto& distribution: distributions) {
        for (auto& sort: sorts) {
            for (auto size: sizes) {
                std::vector<std::uint64_t> cycles;

                auto total_start = clock_type::now();
                auto total_end = clock_type::now();
                while (std::chrono::duration_cast<std::chrono::seconds>(total_end - total_start) < 5s) {
                    std::vector<value_t> collection;
                    distribution.second(std::back_inserter(collection), size);
                    std::uint64_t start = rdtsc();
                    sort.second(collection);
                    std::uint64_t end = rdtsc();
                    assert(std::is_sorted(std::begin(collection), std::end(collection)));
                    cycles.push_back(double(end - start) / size + 0.5);
                    total_end = clock_type::now();
                }

                std::sort(std::begin(cycles), std::end(cycles));

                std::cerr << size << ' ' << distribution.first << ' ' << sort.first
                          << ' ' << cycles[cycles.size() / 2] << '\n';
                std::cout << size << ' ' << distribution.first << ' ' << sort.first
                          << ' ' << cycles[cycles.size() / 2] << '\n';
            }
        }
    }
}
<|endoftext|>