<commit_before>/*****************************************************************************
 * input_manager.cpp : Manage an input and interact with its GUI elements
 ****************************************************************************
 * Copyright (C) 2006-2007 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "qt4.hpp"
#include "input_manager.hpp"
#include "dialogs_provider.hpp"

static int ChangeVideo( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param );
static int ChangeAudio( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param );

/**********************************************************************
 * InputManager implementation
 **********************************************************************/

InputManager::InputManager( QObject *parent, intf_thread_t *_p_intf) :
                           QObject( parent ), p_intf( _p_intf )
{
    i_old_playing_status = END_S;
    old_name="";
    p_input = NULL;
    ON_TIMEOUT( update() );
}

InputManager::~InputManager()
{
    delInput();
}

void InputManager::setInput( input_thread_t *_p_input )
{
    delInput();
    p_input = _p_input;
    emit positionUpdated( 0.0,0,0 );
    b_had_audio = b_had_video = b_has_audio = b_has_video = false;
    if( p_input )
    {
        vlc_object_yield( p_input );
        vlc_value_t val;
        var_Change( p_input, "video-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
        b_has_video = val.i_int > 0;
        var_Change( p_input, "audio-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
        b_has_audio = val.i_int > 0;
        var_AddCallback( p_input, "audio-es", ChangeAudio, this );
        var_AddCallback( p_input, "video-es", ChangeVideo, this );
    }
}

void InputManager::delInput()
{
    if( p_input )
    {
        var_DelCallback( p_input, "audio-es", ChangeAudio, this );
        var_DelCallback( p_input, "video-es", ChangeVideo, this );
        vlc_object_release( p_input );
        p_input = NULL;
    }
}

void InputManager::update()
{
    /// \todo Emit the signals only if it changed
    if( !p_input ) return;

    if( p_input->b_dead || p_input->b_die )
    {
        emit positionUpdated( 0.0, 0, 0 );
        msg_Dbg( p_intf, "*********** NAV 0");
        emit navigationChanged( 0 );
        i_old_playing_status = 0;
        emit statusChanged( 0 ); // 0 = STOPPED, 1 = PLAY, 2 = PAUSE
        delInput();
        return;
    }

    if( !b_had_audio && b_has_audio )
        emit audioStarted();
    if( !b_had_video && b_has_video )
        emit videoStarted();

    /* Update position */
    mtime_t i_length, i_time;
    float f_pos;
    i_length = var_GetTime( p_input, "length" ) / 1000000;
    i_time = var_GetTime( p_input, "time") / 1000000;
    f_pos = var_GetFloat( p_input, "position" );
    emit positionUpdated( f_pos, i_time, i_length );

    /* Update disc status */
    vlc_value_t val; val.i_int = 0;
    var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
    if( val.i_int > 0 )
    {
        val.i_int = 0;
        var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
        if( val.i_int > 0 )
        {
            msg_Dbg( p_intf, "******* CHAPTER");
            emit navigationChanged( 1 ); // 1 = chapter, 2 = title, 0 = NO
        }
        else
        {
            msg_Dbg( p_intf, "******* TITLE");
            emit navigationChanged( 2 );
        }
    }
    else
    {
        emit navigationChanged( 0 );
    }

    /* Update text */
    QString text;
    char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
    char *psz_nowplaying =
        input_item_GetNowPlaying( input_GetItem( p_input ) );
    char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
    if( EMPTY_STR( psz_name ) )
    {
        free( psz_name );
        psz_name = input_item_GetName( input_GetItem( p_input ) );
    }
    if( !EMPTY_STR( psz_nowplaying ) )
    {
        text.sprintf( "%s - %s", psz_nowplaying, psz_name );
    }
    else if( !EMPTY_STR( psz_artist ) )
    {
        text.sprintf( "%s - %s", psz_artist, psz_name );
    }
    else
    {
        text.sprintf( "%s", psz_name );
    }
    free( psz_name );
    free( psz_nowplaying );
    free( psz_artist );
    if( old_name != text )
    {
        emit nameChanged( text );
        old_name=text;
    }
    /* Update playing status */
    var_Get( p_input, "state", &val );
    val.i_int = val.i_int == PAUSE_S ? PAUSE_S : PLAYING_S;
    if( i_old_playing_status != val.i_int )
    {
        i_old_playing_status = val.i_int;
        emit statusChanged(  val.i_int == PAUSE_S ? PAUSE_S : PLAYING_S );
    }
}

void InputManager::sliderUpdate( float new_pos )
{
    if( hasInput() )
        var_SetFloat( p_input, "position", new_pos );
}

void InputManager::togglePlayPause()
{
    vlc_value_t state;
    var_Get( p_input, "state", &state );
    if( state.i_int != PAUSE_S )
    {
        /* A stream is being played, pause it */
        state.i_int = PAUSE_S;
    }
    else
    {
        /* Stream is paused, resume it */
        state.i_int = PLAYING_S;
    }
    var_Set( p_input, "state", state );
    emit statusChanged( state.i_int );
}

void InputManager::sectionPrev()
{
    if( hasInput() )
    {
        int i_type = var_Type( p_input, "next-chapter" );
        vlc_value_t val; val.b_bool = VLC_TRUE;
        var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
                            "prev-chapter":"prev-title", val );
    }
}

void InputManager::sectionNext()
{
    if( hasInput() )
    {
        int i_type = var_Type( p_input, "next-chapter" );
        vlc_value_t val; val.b_bool = VLC_TRUE;
        var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
                            "next-chapter":"next-title", val );
    }
}

void InputManager::sectionMenu()
{
    if( hasInput() )
        var_SetInteger( p_input, "title 0", 2);
}

void InputManager::slower()
{
    if( hasInput() )
        var_SetVoid( p_input, "rate-slower" );
}

void InputManager::faster()
{
    if( hasInput() )
        var_SetVoid( p_input, "rate-faster" );
}

void InputManager::normalRate()
{
    if( hasInput() )
        var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
}

/**********************************************************************
 * MainInputManager implementation. Wrap an input manager and
 * take care of updating the main playlist input
 **********************************************************************/
MainInputManager * MainInputManager::instance = NULL;

MainInputManager::MainInputManager( intf_thread_t *_p_intf ) : QObject(NULL),
                                                p_intf( _p_intf )
{
    p_input = NULL;
    im = new InputManager( this, p_intf );
    ON_TIMEOUT( updateInput() );
    /* Warn our embedded IM about input changes */
    CONNECT( this, inputChanged( input_thread_t * ),
             im,   setInput( input_thread_t * ) );
}

MainInputManager::~MainInputManager()
{
    if( p_input ) vlc_object_release( p_input );
}

void MainInputManager::updateInput()
{
    if( VLC_OBJECT_INTF == p_intf->i_object_type )
    {
        vlc_mutex_lock( &p_intf->change_lock );
        if( p_input && p_input->b_dead )
        {
            vlc_object_release( p_input );
            getIM()->delInput();
            p_input = NULL;
            emit inputChanged( NULL );
        }

        if( !p_input )
        {
            QPL_LOCK;
            p_input = THEPL->p_input;
            if( p_input )
            {
                vlc_object_yield( p_input );
                emit inputChanged( p_input );
            }
            QPL_UNLOCK;
        }
        vlc_mutex_unlock( &p_intf->change_lock );
    }
    else {
        /* we are working as a dialogs provider */
        playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_intf,
                                       VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
        if( p_playlist )
        {
            p_input = p_playlist->p_input;
            emit inputChanged( p_input );
        }
    }
}

void MainInputManager::stop()
{
   playlist_Stop( THEPL );
}

void MainInputManager::next()
{
   playlist_Next( THEPL );
}

void MainInputManager::prev()
{
   playlist_Prev( THEPL );
}

void MainInputManager::togglePlayPause()
{
    if( p_input == NULL )
    {
        playlist_Play( THEPL );
        return;
    }
    getIM()->togglePlayPause();
}

static int ChangeAudio( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param )
{
    InputManager *im = (InputManager*)param;
    im->b_has_audio = true;
    return 0;
}

static int ChangeVideo( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param )
{
    InputManager *im = (InputManager*)param;
    im->b_has_video = true;
    return 0;
}
<commit_msg>Qt4 - removing some debug.<commit_after>/*****************************************************************************
 * input_manager.cpp : Manage an input and interact with its GUI elements
 ****************************************************************************
 * Copyright (C) 2006-2007 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "qt4.hpp"
#include "input_manager.hpp"
#include "dialogs_provider.hpp"

static int ChangeVideo( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param );
static int ChangeAudio( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param );

/**********************************************************************
 * InputManager implementation
 **********************************************************************/

InputManager::InputManager( QObject *parent, intf_thread_t *_p_intf) :
                           QObject( parent ), p_intf( _p_intf )
{
    i_old_playing_status = END_S;
    old_name="";
    p_input = NULL;
    ON_TIMEOUT( update() );
}

InputManager::~InputManager()
{
    delInput();
}

void InputManager::setInput( input_thread_t *_p_input )
{
    delInput();
    p_input = _p_input;
    emit positionUpdated( 0.0,0,0 );
    b_had_audio = b_had_video = b_has_audio = b_has_video = false;
    if( p_input )
    {
        vlc_object_yield( p_input );
        vlc_value_t val;
        var_Change( p_input, "video-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
        b_has_video = val.i_int > 0;
        var_Change( p_input, "audio-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
        b_has_audio = val.i_int > 0;
        var_AddCallback( p_input, "audio-es", ChangeAudio, this );
        var_AddCallback( p_input, "video-es", ChangeVideo, this );
    }
}

void InputManager::delInput()
{
    if( p_input )
    {
        var_DelCallback( p_input, "audio-es", ChangeAudio, this );
        var_DelCallback( p_input, "video-es", ChangeVideo, this );
        vlc_object_release( p_input );
        p_input = NULL;
    }
}

void InputManager::update()
{
    /// \todo Emit the signals only if it changed
    if( !p_input ) return;

    if( p_input->b_dead || p_input->b_die )
    {
        emit positionUpdated( 0.0, 0, 0 );
        emit navigationChanged( 0 );
        i_old_playing_status = 0;
        emit statusChanged( 0 ); // 0 = STOPPED, 1 = PLAY, 2 = PAUSE
        delInput();
        return;
    }

    if( !b_had_audio && b_has_audio )
        emit audioStarted();
    if( !b_had_video && b_has_video )
        emit videoStarted();

    /* Update position */
    mtime_t i_length, i_time;
    float f_pos;
    i_length = var_GetTime( p_input, "length" ) / 1000000;
    i_time = var_GetTime( p_input, "time") / 1000000;
    f_pos = var_GetFloat( p_input, "position" );
    emit positionUpdated( f_pos, i_time, i_length );

    /* Update disc status */
    vlc_value_t val; val.i_int = 0;
    var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
    if( val.i_int > 0 )
    {
        val.i_int = 0;
        var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
        if( val.i_int > 0 )
        {
            emit navigationChanged( 1 ); // 1 = chapter, 2 = title, 0 = NO
        }
        else
        {
            emit navigationChanged( 2 );
        }
    }
    else
    {
        emit navigationChanged( 0 );
    }

    /* Update text */
    QString text;
    char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
    char *psz_nowplaying =
        input_item_GetNowPlaying( input_GetItem( p_input ) );
    char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
    if( EMPTY_STR( psz_name ) )
    {
        free( psz_name );
        psz_name = input_item_GetName( input_GetItem( p_input ) );
    }
    if( !EMPTY_STR( psz_nowplaying ) )
    {
        text.sprintf( "%s - %s", psz_nowplaying, psz_name );
    }
    else if( !EMPTY_STR( psz_artist ) )
    {
        text.sprintf( "%s - %s", psz_artist, psz_name );
    }
    else
    {
        text.sprintf( "%s", psz_name );
    }
    free( psz_name );
    free( psz_nowplaying );
    free( psz_artist );
    if( old_name != text )
    {
        emit nameChanged( text );
        old_name=text;
    }
    /* Update playing status */
    var_Get( p_input, "state", &val );
    val.i_int = val.i_int == PAUSE_S ? PAUSE_S : PLAYING_S;
    if( i_old_playing_status != val.i_int )
    {
        i_old_playing_status = val.i_int;
        emit statusChanged(  val.i_int == PAUSE_S ? PAUSE_S : PLAYING_S );
    }
}

void InputManager::sliderUpdate( float new_pos )
{
    if( hasInput() )
        var_SetFloat( p_input, "position", new_pos );
}

void InputManager::togglePlayPause()
{
    vlc_value_t state;
    var_Get( p_input, "state", &state );
    if( state.i_int != PAUSE_S )
    {
        /* A stream is being played, pause it */
        state.i_int = PAUSE_S;
    }
    else
    {
        /* Stream is paused, resume it */
        state.i_int = PLAYING_S;
    }
    var_Set( p_input, "state", state );
    emit statusChanged( state.i_int );
}

void InputManager::sectionPrev()
{
    if( hasInput() )
    {
        int i_type = var_Type( p_input, "next-chapter" );
        vlc_value_t val; val.b_bool = VLC_TRUE;
        var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
                            "prev-chapter":"prev-title", val );
    }
}

void InputManager::sectionNext()
{
    if( hasInput() )
    {
        int i_type = var_Type( p_input, "next-chapter" );
        vlc_value_t val; val.b_bool = VLC_TRUE;
        var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
                            "next-chapter":"next-title", val );
    }
}

void InputManager::sectionMenu()
{
    if( hasInput() )
        var_SetInteger( p_input, "title 0", 2 );
}

void InputManager::slower()
{
    if( hasInput() )
        var_SetVoid( p_input, "rate-slower" );
}

void InputManager::faster()
{
    if( hasInput() )
        var_SetVoid( p_input, "rate-faster" );
}

void InputManager::normalRate()
{
    if( hasInput() )
        var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
}

/**********************************************************************
 * MainInputManager implementation. Wrap an input manager and
 * take care of updating the main playlist input
 **********************************************************************/
MainInputManager * MainInputManager::instance = NULL;

MainInputManager::MainInputManager( intf_thread_t *_p_intf ) : QObject(NULL),
                                                p_intf( _p_intf )
{
    p_input = NULL;
    im = new InputManager( this, p_intf );
    ON_TIMEOUT( updateInput() );
    /* Warn our embedded IM about input changes */
    CONNECT( this, inputChanged( input_thread_t * ),
             im,   setInput( input_thread_t * ) );
}

MainInputManager::~MainInputManager()
{
    if( p_input ) vlc_object_release( p_input );
}

void MainInputManager::updateInput()
{
    if( VLC_OBJECT_INTF == p_intf->i_object_type )
    {
        vlc_mutex_lock( &p_intf->change_lock );
        if( p_input && p_input->b_dead )
        {
            vlc_object_release( p_input );
            getIM()->delInput();
            p_input = NULL;
            emit inputChanged( NULL );
        }

        if( !p_input )
        {
            QPL_LOCK;
            p_input = THEPL->p_input;
            if( p_input )
            {
                vlc_object_yield( p_input );
                emit inputChanged( p_input );
            }
            QPL_UNLOCK;
        }
        vlc_mutex_unlock( &p_intf->change_lock );
    }
    else {
        /* we are working as a dialogs provider */
        playlist_t *p_playlist = (playlist_t *) vlc_object_find( p_intf,
                                       VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
        if( p_playlist )
        {
            p_input = p_playlist->p_input;
            emit inputChanged( p_input );
        }
    }
}

void MainInputManager::stop()
{
   playlist_Stop( THEPL );
}

void MainInputManager::next()
{
   playlist_Next( THEPL );
}

void MainInputManager::prev()
{
   playlist_Prev( THEPL );
}

void MainInputManager::togglePlayPause()
{
    if( p_input == NULL )
    {
        playlist_Play( THEPL );
        return;
    }
    getIM()->togglePlayPause();
}

static int ChangeAudio( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param )
{
    InputManager *im = (InputManager*)param;
    im->b_has_audio = true;
    return 0;
}

static int ChangeVideo( vlc_object_t *p_this, const char *var, vlc_value_t o,
                        vlc_value_t n, void *param )
{
    InputManager *im = (InputManager*)param;
    im->b_has_video = true;
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>fixed typo (cuz deduction guides not working like I expected)<commit_after><|endoftext|>


<commit_before>#include <algorithm>
#include <vector>

#include "pinba/globals.h"
#include "pinba/histogram.h"

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

int main(int argc, char const *argv[])
{
	histogram_conf_t const hv_conf = {
		.bucket_count = 100,
		.bucket_d     = 1 * d_millisecond,
	};

	histogram_t hv;
	// hv.increment(hv_conf, 2 * d_millisecond, 1);
	// hv.increment(hv_conf, 3 * d_millisecond, 4);
	// hv.increment(hv_conf, 4 * d_millisecond, 10);
	// hv.increment(hv_conf, 5 * d_millisecond, 50);
	hv.increment(hv_conf, 6 * d_millisecond, 25000);
	hv.increment(hv_conf, 7 * d_millisecond, 1000);
	hv.increment(hv_conf, 8 * d_millisecond, 30);
	hv.increment(hv_conf, 1000 * d_millisecond, 1);

	auto const print_percentile = [&](double percentile)
	{
		flat_histogram_t flat_hv;
		histogram___convert_ht_to_flat(hv, &flat_hv);

		ff::fmt(stdout, "percentile {0} = hash: {1}, flat: {2}\n\n",
			percentile, get_percentile(hv, hv_conf, percentile), get_percentile(flat_hv, hv_conf, percentile));
	};

	// print_percentile(0);
	print_percentile(50);
	print_percentile(75);
	print_percentile(95);
	print_percentile(99);
	print_percentile(99.9);
	print_percentile(99.99);
	print_percentile(99.999);
	print_percentile(100);

	return 0;
}
<commit_msg>updated experiment: contiguous storage for in-history histogram values<commit_after>#include <algorithm>
#include <vector>
#include <deque>

#include <meow/str_ref.hpp>

#include "pinba/globals.h"
#include "pinba/histogram.h"

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

// struct histogram_value_t
// {
// 	uint32_t bucket_id;
// 	uint32_t value;
// };
// static_assert(sizeof(histogram_value_t) == sizeof(uint64_t), "histogram_value_t must have no padding");

// inline constexpr bool operator<(histogram_value_t const& l, histogram_value_t const& r)
// {
// 	return l.bucket_id < r.bucket_id;
// }

using hvalues_ref_t = meow::string_ref<histogram_value_t>;

struct histogram_husk_t
{
	hvalues_ref_t  values;
	uint32_t       value_count;
	uint32_t       negative_inf;
	uint32_t       positive_inf;
};
static_assert(sizeof(histogram_husk_t) == (sizeof(hvalues_ref_t)+4*sizeof(uint32_t)), "histogram_husk_t must have no padding");

struct hv_storage_t
{
	std::vector<histogram_husk_t>   hvs;
	std::vector<histogram_value_t>  values_store;
};

void hv_storage___from_histograms_range(hv_storage_t *hv_storage, meow::string_ref<histogram_t const> hv_range)
{
	if (hv_range.empty())
		return;

	hv_storage->hvs.reserve(hv_range.size());

	size_t hv_values_count = 0;
	for (auto const& hv : hv_range)
	{
		histogram_husk_t flat_hv = {
			.values       = {},
			.value_count  = hv.value_count(),
			.negative_inf = hv.negative_inf(),
			.positive_inf = hv.positive_inf(),
		};

		hv_storage->hvs.emplace_back(flat_hv);

		hv_values_count += hv.map_cref().size();
	}

	// make sure values_store is never reallocated
	hv_storage->values_store.reserve(hv_values_count);

	// copy all histogram values into single contiguous array
	size_t hv_off = 0;
	for (auto const& hv : hv_range)
	{
		auto const inserted_begin = hv_storage->values_store.end();

		for (auto const& ht_pair : hv.map_cref())
			hv_storage->values_store.push_back({ .bucket_id = ht_pair.first, .value = ht_pair.second });

		// now fixup histogram husk to use newly inserted elts and sort
		histogram_husk_t *flat_hv = &hv_storage->hvs[hv_off++];
		flat_hv->values = hvalues_ref_t { &*inserted_begin, hv.map_cref().size() };
		std::sort(flat_hv->values.begin(), flat_hv->values.end());
	}

	// now fix pointers and sort
	// histogram_value_t *hvalue_ptr = &*hv_storage->values_store.begin();
	// for (auto& flat_hv : hv_storage->hvs)
	// {
	// 	flat_hv.values = hvalues_ref_t { hvalue_ptr, flat_hv.value_count };
	// 	hvalue_ptr += flat_hv.value_count;

	// 	std::sort(flat_hv.values.begin(), flat_hv.values.end());
	// }
}

hv_storage_t hv_storage___from_histograms_range(meow::string_ref<histogram_t const> hv_range)
{
	hv_storage_t result;
	hv_storage___from_histograms_range(&result, hv_range);
	return result;
}

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

int main(int argc, char const *argv[])
{
	histogram_conf_t const hv_conf = {
		.bucket_count = 100,
		.bucket_d     = 1 * d_millisecond,
	};

	std::vector<histogram_t> hvs;
	for (size_t i = 0; i < 100; i++)
	{
		histogram_t hv;
		hv.increment(hv_conf, 2 * d_millisecond, 1);
		hv.increment(hv_conf, 3 * d_millisecond, 3);
		hv.increment(hv_conf, 4 * d_millisecond, 4);

		hvs.emplace_back(std::move(hv));
	}

	auto const hv_storage = hv_storage___from_histograms_range({ &*hvs.begin(), hvs.size() });

	// histogram_t hv;
	// // hv.increment(hv_conf, 2 * d_millisecond, 1);
	// // hv.increment(hv_conf, 3 * d_millisecond, 4);
	// // hv.increment(hv_conf, 4 * d_millisecond, 10);
	// // hv.increment(hv_conf, 5 * d_millisecond, 50);
	// hv.increment(hv_conf, 6 * d_millisecond, 25000);
	// hv.increment(hv_conf, 7 * d_millisecond, 1000);
	// hv.increment(hv_conf, 8 * d_millisecond, 30);
	// hv.increment(hv_conf, 1000 * d_millisecond, 1);

	// auto const print_percentile = [&](double percentile)
	// {
	// 	flat_histogram_t flat_hv;
	// 	histogram___convert_ht_to_flat(hv, &flat_hv);

	// 	ff::fmt(stdout, "percentile {0} = hash: {1}, flat: {2}\n\n",
	// 		percentile, get_percentile(hv, hv_conf, percentile), get_percentile(flat_hv, hv_conf, percentile));
	// };

	// // print_percentile(0);
	// print_percentile(50);
	// print_percentile(75);
	// print_percentile(95);
	// print_percentile(99);
	// print_percentile(99.9);
	// print_percentile(99.99);
	// print_percentile(99.999);
	// print_percentile(100);

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <fftw3.h>
#include <time.h>

//---Define parameters---
#define factor1 0.9
#define factor2 0.7

using namespace std;

double **HIO_2D_withphase(double **HIOinput, int n1, int n2, int support1, int support2, int iteration, double *shift)
{
    // The input intensity should not be fft-shifted.
    // The input matrix should be odd.

    int i=0,j=0,iter=0;

	// checker is to check if the intensity==0, for example, the beamstop
    // 0 stands for false; 1 stands for true
    bool **checker=(bool **)malloc(sizeof(bool*) *n1);
    for (i=0;i<n1;i++)
        checker[i]=(bool *)malloc(sizeof(bool) *n2);

    double epsilon = pow(10,-10);
    for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++){
        	if (HIOinput[i][j]<epsilon){
            	checker[i][j] = false;
                HIOinput[i][j] = 1;
            }
            else
            	checker[i][j] = true;
        }
    }

	// create FFT and iFFT plans ("out" is in real space and "in" is in k-space.)
    fftw_complex *in,*out;
    fftw_plan forward_p,inverse_p;
    in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * n1*n2);
    out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * n1*n2);
    forward_p = fftw_plan_dft_2d(n1, n2, out, in,FFTW_FORWARD, FFTW_MEASURE);
    inverse_p = fftw_plan_dft_2d(n1, n2, in, out,FFTW_BACKWARD, FFTW_MEASURE);

	// shift offers input phases
	for (i=0;i<n1;i++){
		for (j=0;j<n2;j++){
			out[j+n1*i][0] = shift[j+n1*i];
			out[j+n1*i][1] = 0;
		}
	}
	fftw_execute(forward_p);

	// Normalze "in" and assign the intensity from HIOinput to "in" and use the input phase.
    double norm=0;
    for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++){
			if (checker[i][j] == true){
				norm = sqrt(pow(in[j+n1*i][0],2)+pow(in[j+n1*i][1],2));
        		in[j+n1*i][0] = HIOinput[i][j]*in[j+n1*i][0]/norm;
            	in[j+n1*i][1] = HIOinput[i][j]*in[j+n1*i][1]/norm;
			}
			else{
				in[j+n1*i][0] = in[j+n1*i][0];
                in[j+n1*i][1] = in[j+n1*i][1];
			}
        }
    }
    // Now "in" becomes our first trial solution.

    // Construct a matrix in order to store previous values of "out".
    double **previous=(double **)malloc(sizeof(double*) *n1);
    for (i=0;i<n1;i++)
    	previous[i]=(double *)malloc(sizeof(double) *n2);

	int N = n1*n2;
    fftw_execute(inverse_p);

	for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++){
        	out[j+n1*i][0] = out[j+n1*i][0]/N;
            previous [i][j] = out[j+n1*i][0];
        }
    }

	// Iteration starts here.
    for (iter=0;iter<iteration/2;iter++){
    	fftw_execute(inverse_p);

        // Since fftw only gives us unnormalized solution, we have to normalize "out" ourselves.
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	out [j+n1*i][0] = out[j+n1*i][0]/N;
                out [j+n1*i][1] = 0;
            }
        }

		// Modify the real space data. (HIO)
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	// the center square
                if ( support1<=i && i<=support2 && support1<=j && j<=support2 ){
                	if (out[j+n1*i][0]<0)
                    	out[j+n1*i][0] = previous[i][j]-factor1*out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = out[j+n1*i][0];
                }
				// the upper left triangle
                else if (i<j){
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = previous[i][j]-factor1*out[j+n1*i][0];
                }
                // the lower right triangle
                else{
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = previous[i][j]-factor2*out[j+n1*i][0];
                }
            }
        }

        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++)
            	previous [i][j] = out[j+n1*i][0];
        }

        // transfrom back to k-space and deal with the beamstop area.
        fftw_execute(forward_p);

		for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	norm = sqrt( pow(in[j+n1*i][0],2) + pow(in[j+n1*i][1],2) );
                if (norm<epsilon){
                	cout<<"Warning! There might be a zero-division error."<<endl;
					exit(0);
                }
                else{
                    // For the beamstop area, keep the value
                    if (checker[i][j] == false){
                    	in[j+n1*i][0] = in[j+n1*i][0];
                        in[j+n1*i][1] = in[j+n1*i][1];
                    }
                    // For other area, combine the intensity from HIOinput and phase from "in".
                    else{
                    	in[j+n1*i][0] = HIOinput[i][j]*(in[j+n1*i][0])/norm;
                        in[j+n1*i][1] = HIOinput[i][j]*(in[j+n1*i][1])/norm;
                    }
                }
            }
        }
    }

    for (iter=iteration/2;iter<iteration;iter++){
    	fftw_execute(inverse_p);

        // Since fftw only gives us unnormalized solution, we have to normalize "out" ourselves.
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	out [j+n1*i][0] = out[j+n1*i][0]/N;
                out [j+n1*i][1] = 0;
            }
        }

		// Modify the real space data. (HIO)
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	// the center square
                if ( support1<=i && i<=support2 && support1<=j && j<=support2 ){
                	if (out[j+n1*i][0]<0)
                    	out[j+n1*i][0] = out[j+n1*i][0]*(iteration - iter)/(iteration/2);
                    else
                        out[j+n1*i][0] = out[j+n1*i][0];
                }
				// the upper left triangle
                else if (i<j){
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = out[j+n1*i][0]*(iteration - iter)/(iteration/2);
                }
                // the lower right triangle
                else{
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = out[j+n1*i][0]*(iteration - iter)/(iteration/2);
                }
            }
        }

        /*for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++)
            	previous [i][j] = out[j+n1*i][0];
        }*/

        // transfrom back to k-space and deal with the beamstop area.
        fftw_execute(forward_p);

		for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	norm = sqrt( pow(in[j+n1*i][0],2) + pow(in[j+n1*i][1],2) );
                if (norm<epsilon){
                	cout<<"Warning! There might be a zero-division error."<<endl;
					exit(0);
                }
                else{
                    // For the beamstop area, keep the value
                    if (checker[i][j] == false){
                    	in[j+n1*i][0] = in[j+n1*i][0];
                        in[j+n1*i][1] = in[j+n1*i][1];
                    }
                    // For other area, combine the intensity from HIOinput and phase from "in".
                    else{
                    	in[j+n1*i][0] = HIOinput[i][j]*(in[j+n1*i][0])/norm;
                        in[j+n1*i][1] = HIOinput[i][j]*(in[j+n1*i][1])/norm;
                    }
                }
            }
        }
    }

	// Iteration ends here.
    // Create an array to store output data and release memory
    fftw_execute(inverse_p);

	double **HIOoutput=(double **)malloc(sizeof(double*) *n1);
	for (i=0;i<n1;i++)
		HIOoutput[i]=(double *)malloc(sizeof(double) *n2);

	for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++)
        	HIOoutput[i][j]=out[j+n1*i][0]/N;
    }

    fftw_destroy_plan(forward_p);
    fftw_destroy_plan(inverse_p);

	free(previous);
	free(checker);

    return HIOoutput;
}
<commit_msg>free in and out<commit_after>#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <fftw3.h>
#include <time.h>

//---Define parameters---
#define factor1 0.9
#define factor2 0.7

using namespace std;

double **HIO_2D_withphase(double **HIOinput, int n1, int n2, int support1, int support2, int iteration, double *shift)
{
    // The input intensity should not be fft-shifted.
    // The input matrix should be odd.

    int i=0,j=0,iter=0;

	// checker is to check if the intensity==0, for example, the beamstop
    // 0 stands for false; 1 stands for true
    bool **checker=(bool **)malloc(sizeof(bool*) *n1);
    for (i=0;i<n1;i++)
        checker[i]=(bool *)malloc(sizeof(bool) *n2);

    double epsilon = pow(10,-10);
    for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++){
        	if (HIOinput[i][j]<epsilon){
            	checker[i][j] = false;
                HIOinput[i][j] = 1;
            }
            else
            	checker[i][j] = true;
        }
    }

	// create FFT and iFFT plans ("out" is in real space and "in" is in k-space.)
    fftw_complex *in,*out;
    fftw_plan forward_p,inverse_p;
    in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * n1*n2);
    out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * n1*n2);
    forward_p = fftw_plan_dft_2d(n1, n2, out, in,FFTW_FORWARD, FFTW_MEASURE);
    inverse_p = fftw_plan_dft_2d(n1, n2, in, out,FFTW_BACKWARD, FFTW_MEASURE);

	// shift offers input phases
	for (i=0;i<n1;i++){
		for (j=0;j<n2;j++){
			out[j+n1*i][0] = shift[j+n1*i];
			out[j+n1*i][1] = 0;
		}
	}
	fftw_execute(forward_p);

	// Normalze "in" and assign the intensity from HIOinput to "in" and use the input phase.
    double norm=0;
    for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++){
			if (checker[i][j] == true){
				norm = sqrt(pow(in[j+n1*i][0],2)+pow(in[j+n1*i][1],2));
        		in[j+n1*i][0] = HIOinput[i][j]*in[j+n1*i][0]/norm;
            	in[j+n1*i][1] = HIOinput[i][j]*in[j+n1*i][1]/norm;
			}
			else{
				in[j+n1*i][0] = in[j+n1*i][0];
                in[j+n1*i][1] = in[j+n1*i][1];
			}
        }
    }
    // Now "in" becomes our first trial solution.

    // Construct a matrix in order to store previous values of "out".
    double **previous=(double **)malloc(sizeof(double*) *n1);
    for (i=0;i<n1;i++)
    	previous[i]=(double *)malloc(sizeof(double) *n2);

	int N = n1*n2;
    fftw_execute(inverse_p);

	for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++){
        	out[j+n1*i][0] = out[j+n1*i][0]/N;
            previous [i][j] = out[j+n1*i][0];
        }
    }

	// Iteration starts here.
    for (iter=0;iter<iteration/2;iter++){
    	fftw_execute(inverse_p);

        // Since fftw only gives us unnormalized solution, we have to normalize "out" ourselves.
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	out [j+n1*i][0] = out[j+n1*i][0]/N;
                out [j+n1*i][1] = 0;
            }
        }

		// Modify the real space data. (HIO)
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	// the center square
                if ( support1<=i && i<=support2 && support1<=j && j<=support2 ){
                	if (out[j+n1*i][0]<0)
                    	out[j+n1*i][0] = previous[i][j]-factor1*out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = out[j+n1*i][0];
                }
				// the upper left triangle
                else if (i<j){
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = previous[i][j]-factor1*out[j+n1*i][0];
                }
                // the lower right triangle
                else{
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = previous[i][j]-factor2*out[j+n1*i][0];
                }
            }
        }

        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++)
            	previous [i][j] = out[j+n1*i][0];
        }

        // transfrom back to k-space and deal with the beamstop area.
        fftw_execute(forward_p);

		for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	norm = sqrt( pow(in[j+n1*i][0],2) + pow(in[j+n1*i][1],2) );
                if (norm<epsilon){
                	cout<<"Warning! There might be a zero-division error."<<endl;
					exit(0);
                }
                else{
                    // For the beamstop area, keep the value
                    if (checker[i][j] == false){
                    	in[j+n1*i][0] = in[j+n1*i][0];
                        in[j+n1*i][1] = in[j+n1*i][1];
                    }
                    // For other area, combine the intensity from HIOinput and phase from "in".
                    else{
                    	in[j+n1*i][0] = HIOinput[i][j]*(in[j+n1*i][0])/norm;
                        in[j+n1*i][1] = HIOinput[i][j]*(in[j+n1*i][1])/norm;
                    }
                }
            }
        }
    }

    for (iter=iteration/2;iter<iteration;iter++){
    	fftw_execute(inverse_p);

        // Since fftw only gives us unnormalized solution, we have to normalize "out" ourselves.
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	out [j+n1*i][0] = out[j+n1*i][0]/N;
                out [j+n1*i][1] = 0;
            }
        }

		// Modify the real space data. (HIO)
        for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	// the center square
                if ( support1<=i && i<=support2 && support1<=j && j<=support2 ){
                	if (out[j+n1*i][0]<0)
                    	out[j+n1*i][0] = out[j+n1*i][0]*(iteration - iter)/(iteration/2);
                    else
                        out[j+n1*i][0] = out[j+n1*i][0];
                }
				// the upper left triangle
                else if (i<j){
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = out[j+n1*i][0]*(iteration - iter)/(iteration/2);
                }
                // the lower right triangle
                else{
                	if (out[j+n1*i][0]==0)
                    	out[j+n1*i][0] = out[j+n1*i][0];
                    else
                        out[j+n1*i][0] = out[j+n1*i][0]*(iteration - iter)/(iteration/2);
                }
            }
        }

        /*for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++)
            	previous [i][j] = out[j+n1*i][0];
        }*/

        // transfrom back to k-space and deal with the beamstop area.
        fftw_execute(forward_p);

		for (i=0;i<n1;i++){
        	for (j=0;j<n2;j++){
            	norm = sqrt( pow(in[j+n1*i][0],2) + pow(in[j+n1*i][1],2) );
                if (norm<epsilon){
                	cout<<"Warning! There might be a zero-division error."<<endl;
					exit(0);
                }
                else{
                    // For the beamstop area, keep the value
                    if (checker[i][j] == false){
                    	in[j+n1*i][0] = in[j+n1*i][0];
                        in[j+n1*i][1] = in[j+n1*i][1];
                    }
                    // For other area, combine the intensity from HIOinput and phase from "in".
                    else{
                    	in[j+n1*i][0] = HIOinput[i][j]*(in[j+n1*i][0])/norm;
                        in[j+n1*i][1] = HIOinput[i][j]*(in[j+n1*i][1])/norm;
                    }
                }
            }
        }
    }

	// Iteration ends here.
    // Create an array to store output data and release memory
    fftw_execute(inverse_p);

	double **HIOoutput=(double **)malloc(sizeof(double*) *n1);
	for (i=0;i<n1;i++)
		HIOoutput[i]=(double *)malloc(sizeof(double) *n2);

	for (i=0;i<n1;i++){
    	for (j=0;j<n2;j++)
        	HIOoutput[i][j]=out[j+n1*i][0]/N;
    }

    fftw_destroy_plan(forward_p);
    fftw_destroy_plan(inverse_p);

	free(previous);
	free(checker);
    free(in);
    free(out);
    return HIOoutput;
}
<|endoftext|>


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

#include "config.h"
#include "core/inspector/PromiseTracker.h"

#include "bindings/core/v8/ScopedPersistent.h"
#include "bindings/core/v8/ScriptCallStackFactory.h"
#include "bindings/core/v8/ScriptState.h"
#include "bindings/core/v8/ScriptValue.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/WeakPtr.h"

using blink::TypeBuilder::Array;
using blink::TypeBuilder::Console::CallFrame;
using blink::TypeBuilder::Debugger::PromiseDetails;

namespace blink {

class PromiseTracker::PromiseData FINAL : public RefCountedWillBeGarbageCollectedFinalized<PromiseData> {
public:
    static PassRefPtrWillBeRawPtr<PromiseData> create(ScriptState* scriptState, int promiseHash, int promiseId, v8::Handle<v8::Object> promise)
    {
        return adoptRefWillBeNoop(new PromiseData(scriptState, promiseHash, promiseId, promise));
    }

    int promiseHash() const { return m_promiseHash; }
    ScopedPersistent<v8::Object>& promise() { return m_promise; }

#if ENABLE(OILPAN)
    void dispose()
    {
        m_promise.clear();
        m_parentPromise.clear();
    }
#else
    WeakPtr<PromiseData> createWeakPtr()
    {
        return m_weakPtrFactory.createWeakPtr();
    }
#endif

    void trace(Visitor* visitor)
    {
        visitor->trace(m_callStack);
    }

private:
    friend class PromiseTracker;

    PromiseData(ScriptState* scriptState, int promiseHash, int promiseId, v8::Handle<v8::Object> promise)
        : m_scriptState(scriptState)
        , m_promiseHash(promiseHash)
        , m_promiseId(promiseId)
        , m_promise(scriptState->isolate(), promise)
        , m_parentPromiseId(0)
        , m_status(0)
#if !ENABLE(OILPAN)
        , m_weakPtrFactory(this)
#endif
    {
    }

    RefPtrWillBeMember<ScriptState> m_scriptState;
    int m_promiseHash;
    int m_promiseId;
    ScopedPersistent<v8::Object> m_promise;
    int m_parentPromiseId;
    int m_status;
    RefPtrWillBeMember<ScriptCallStack> m_callStack;
    ScopedPersistent<v8::Object> m_parentPromise;
#if !ENABLE(OILPAN)
    WeakPtrFactory<PromiseData> m_weakPtrFactory;
#endif
};

static int indexOf(PromiseTracker::PromiseDataVector* vector, const ScopedPersistent<v8::Object>& promise)
{
    for (size_t index = 0; index < vector->size(); ++index) {
        if (vector->at(index)->promise() == promise)
            return index;
    }
    return -1;
}

namespace {

class PromiseDataWrapper FINAL : public NoBaseWillBeGarbageCollected<PromiseDataWrapper> {
public:
    static PassOwnPtrWillBeRawPtr<PromiseDataWrapper> create(PromiseTracker::PromiseData* data, PromiseTracker* tracker)
    {
#if ENABLE(OILPAN)
        return new PromiseDataWrapper(data, tracker);
#else
        return adoptPtr(new PromiseDataWrapper(data->createWeakPtr(), tracker));
#endif
    }

#if ENABLE(OILPAN)
    static void didRemovePromise(const v8::WeakCallbackData<v8::Object, Persistent<PromiseDataWrapper> >& data)
#else
    static void didRemovePromise(const v8::WeakCallbackData<v8::Object, PromiseDataWrapper>& data)
#endif
    {
#if ENABLE(OILPAN)
        OwnPtr<Persistent<PromiseDataWrapper> > persistentWrapper = adoptPtr(data.GetParameter());
        RawPtr<PromiseDataWrapper> wrapper = *persistentWrapper;
#else
        OwnPtr<PromiseDataWrapper> wrapper = adoptPtr(data.GetParameter());
#endif
        WeakPtrWillBeRawPtr<PromiseTracker::PromiseData> promiseData = wrapper->m_data;
        if (!promiseData || !wrapper->m_tracker)
            return;

#if ENABLE(OILPAN)
        // Oilpan: let go of ScopedPersistent<>s right here (and not wait until the
        // PromiseDataWrapper is GCed later.) The v8 weak callback handling expects
        // to see the callback data upon return.
        promiseData->dispose();
#endif
        PromiseTracker::PromiseDataMap& map = wrapper->m_tracker->promiseDataMap();
        int promiseHash = promiseData->promiseHash();

        PromiseTracker::PromiseDataMap::iterator it = map.find(promiseHash);
        // The PromiseTracker may have been disabled (and, possibly, re-enabled later),
        // leaving the promiseHash as unmapped.
        if (it == map.end())
            return;

        PromiseTracker::PromiseDataVector* vector = &it->value;
        int index = indexOf(vector, promiseData->promise());
        ASSERT(index >= 0);
        vector->remove(index);
        if (vector->isEmpty())
            map.remove(promiseHash);
    }

    void trace(Visitor* visitor)
    {
#if ENABLE(OILPAN)
        visitor->trace(m_data);
        visitor->trace(m_tracker);
#endif
    }

private:
    PromiseDataWrapper(WeakPtrWillBeRawPtr<PromiseTracker::PromiseData> data, PromiseTracker* tracker)
        : m_data(data)
        , m_tracker(tracker)
    {
    }

    WeakPtrWillBeWeakMember<PromiseTracker::PromiseData> m_data;
    RawPtrWillBeWeakMember<PromiseTracker> m_tracker;
};

}

PromiseTracker::PromiseTracker()
    : m_circularSequentialId(0)
    , m_isEnabled(false)
{
}

DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(PromiseTracker);

void PromiseTracker::trace(Visitor* visitor)
{
#if ENABLE(OILPAN)
    visitor->trace(m_promiseDataMap);
#endif
}

void PromiseTracker::setEnabled(bool enabled)
{
    m_isEnabled = enabled;
    if (!enabled)
        clear();
}

void PromiseTracker::clear()
{
    m_promiseDataMap.clear();
}

int PromiseTracker::circularSequentialId()
{
    ++m_circularSequentialId;
    if (m_circularSequentialId <= 0)
        m_circularSequentialId = 1;
    return m_circularSequentialId;
}

PassRefPtrWillBeRawPtr<PromiseTracker::PromiseData> PromiseTracker::createPromiseDataIfNeeded(ScriptState* scriptState, v8::Handle<v8::Object> promise)
{
    int promiseHash = promise->GetIdentityHash();
    RawPtr<PromiseDataVector> vector = nullptr;
    PromiseDataMap::iterator it = m_promiseDataMap.find(promiseHash);
    if (it != m_promiseDataMap.end())
        vector = &it->value;
    else
        vector = &m_promiseDataMap.add(promiseHash, PromiseDataVector()).storedValue->value;

    int index = indexOf(vector, ScopedPersistent<v8::Object>(scriptState->isolate(), promise));
    if (index != -1)
        return vector->at(index);

    // FIXME: Consider using the ScriptState's DOMWrapperWorld instead
    // to handle the lifetime of PromiseDataWrapper, avoiding all this
    // manual labor to achieve the same, with and without Oilpan.
    RefPtrWillBeRawPtr<PromiseData> data = PromiseData::create(scriptState, promiseHash, circularSequentialId(), promise);
    OwnPtrWillBeRawPtr<PromiseDataWrapper> dataWrapper = PromiseDataWrapper::create(data.get(), this);
#if ENABLE(OILPAN)
    OwnPtr<Persistent<PromiseDataWrapper> > wrapper = adoptPtr(new Persistent<PromiseDataWrapper>(dataWrapper));
#else
    OwnPtr<PromiseDataWrapper> wrapper = dataWrapper.release();
#endif
    data->m_promise.setWeak(wrapper.leakPtr(), &PromiseDataWrapper::didRemovePromise);
    vector->append(data);

    return data.release();
}

void PromiseTracker::didReceiveV8PromiseEvent(ScriptState* scriptState, v8::Handle<v8::Object> promise, v8::Handle<v8::Value> parentPromise, int status)
{
    ASSERT(isEnabled());

    RefPtrWillBeRawPtr<PromiseData> data = createPromiseDataIfNeeded(scriptState, promise);
    if (!parentPromise.IsEmpty() && parentPromise->IsObject()) {
        v8::Handle<v8::Object> handle = parentPromise->ToObject();
        RefPtrWillBeRawPtr<PromiseData> parentData = createPromiseDataIfNeeded(scriptState, handle);
        data->m_parentPromiseId = parentData->m_promiseId;
        data->m_parentPromise.set(scriptState->isolate(), handle);
    } else {
        data->m_status = status;
        if (!status && !data->m_callStack) {
            RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(1, true);
            if (stack && stack->size())
                data->m_callStack = stack;
        }
    }
}

PassRefPtr<Array<PromiseDetails> > PromiseTracker::promises()
{
    ASSERT(isEnabled());

    RefPtr<Array<PromiseDetails> > result = Array<PromiseDetails>::create();
    for (PromiseDataMap::iterator it = m_promiseDataMap.begin(); it != m_promiseDataMap.end(); ++it) {
        PromiseDataVector* vector = &it->value;
        for (size_t index = 0; index < vector->size(); ++index) {
            RefPtrWillBeRawPtr<PromiseData> data = vector->at(index);
            PromiseDetails::Status::Enum status;
            if (!data->m_status)
                status = PromiseDetails::Status::Pending;
            else if (data->m_status == 1)
                status = PromiseDetails::Status::Resolved;
            else
                status = PromiseDetails::Status::Rejected;
            RefPtr<PromiseDetails> promiseDetails = PromiseDetails::create()
                .setId(data->m_promiseId)
                .setStatus(status);
            if (data->m_parentPromiseId)
                promiseDetails->setParentId(data->m_parentPromiseId);
            if (data->m_callStack)
                promiseDetails->setCallFrame(data->m_callStack->at(0).buildInspectorObject());
            result->addItem(promiseDetails);
        }
    }

    return result.release();
}

ScriptValue PromiseTracker::promiseById(int promiseId) const
{
    ASSERT(isEnabled());

    for (PromiseDataMap::const_iterator it = m_promiseDataMap.begin(); it != m_promiseDataMap.end(); ++it) {
        const PromiseDataVector* vector = &it->value;
        for (size_t index = 0; index < vector->size(); ++index) {
            RefPtrWillBeRawPtr<PromiseData> data = vector->at(index);
            if (data->m_promiseId == promiseId) {
                ScriptState* scriptState = data->m_scriptState.get();
                return ScriptValue(scriptState, data->m_promise.newLocal(scriptState->isolate()));
            }
        }
    }

    return ScriptValue();
}

} // namespace blink
<commit_msg>Oilpan: fix build after r182688.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/inspector/PromiseTracker.h"

#include "bindings/core/v8/ScopedPersistent.h"
#include "bindings/core/v8/ScriptCallStackFactory.h"
#include "bindings/core/v8/ScriptState.h"
#include "bindings/core/v8/ScriptValue.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/WeakPtr.h"

using blink::TypeBuilder::Array;
using blink::TypeBuilder::Console::CallFrame;
using blink::TypeBuilder::Debugger::PromiseDetails;

namespace blink {

class PromiseTracker::PromiseData FINAL : public RefCountedWillBeGarbageCollectedFinalized<PromiseData> {
public:
    static PassRefPtrWillBeRawPtr<PromiseData> create(ScriptState* scriptState, int promiseHash, int promiseId, v8::Handle<v8::Object> promise)
    {
        return adoptRefWillBeNoop(new PromiseData(scriptState, promiseHash, promiseId, promise));
    }

    int promiseHash() const { return m_promiseHash; }
    ScopedPersistent<v8::Object>& promise() { return m_promise; }

#if ENABLE(OILPAN)
    void dispose()
    {
        m_promise.clear();
        m_parentPromise.clear();
    }
#else
    WeakPtr<PromiseData> createWeakPtr()
    {
        return m_weakPtrFactory.createWeakPtr();
    }
#endif

    void trace(Visitor* visitor)
    {
        visitor->trace(m_callStack);
    }

private:
    friend class PromiseTracker;

    PromiseData(ScriptState* scriptState, int promiseHash, int promiseId, v8::Handle<v8::Object> promise)
        : m_scriptState(scriptState)
        , m_promiseHash(promiseHash)
        , m_promiseId(promiseId)
        , m_promise(scriptState->isolate(), promise)
        , m_parentPromiseId(0)
        , m_status(0)
#if !ENABLE(OILPAN)
        , m_weakPtrFactory(this)
#endif
    {
    }

    RefPtr<ScriptState> m_scriptState;
    int m_promiseHash;
    int m_promiseId;
    ScopedPersistent<v8::Object> m_promise;
    int m_parentPromiseId;
    int m_status;
    RefPtrWillBeMember<ScriptCallStack> m_callStack;
    ScopedPersistent<v8::Object> m_parentPromise;
#if !ENABLE(OILPAN)
    WeakPtrFactory<PromiseData> m_weakPtrFactory;
#endif
};

static int indexOf(PromiseTracker::PromiseDataVector* vector, const ScopedPersistent<v8::Object>& promise)
{
    for (size_t index = 0; index < vector->size(); ++index) {
        if (vector->at(index)->promise() == promise)
            return index;
    }
    return -1;
}

namespace {

class PromiseDataWrapper FINAL : public NoBaseWillBeGarbageCollected<PromiseDataWrapper> {
public:
    static PassOwnPtrWillBeRawPtr<PromiseDataWrapper> create(PromiseTracker::PromiseData* data, PromiseTracker* tracker)
    {
#if ENABLE(OILPAN)
        return new PromiseDataWrapper(data, tracker);
#else
        return adoptPtr(new PromiseDataWrapper(data->createWeakPtr(), tracker));
#endif
    }

#if ENABLE(OILPAN)
    static void didRemovePromise(const v8::WeakCallbackData<v8::Object, Persistent<PromiseDataWrapper> >& data)
#else
    static void didRemovePromise(const v8::WeakCallbackData<v8::Object, PromiseDataWrapper>& data)
#endif
    {
#if ENABLE(OILPAN)
        OwnPtr<Persistent<PromiseDataWrapper> > persistentWrapper = adoptPtr(data.GetParameter());
        RawPtr<PromiseDataWrapper> wrapper = *persistentWrapper;
#else
        OwnPtr<PromiseDataWrapper> wrapper = adoptPtr(data.GetParameter());
#endif
        WeakPtrWillBeRawPtr<PromiseTracker::PromiseData> promiseData = wrapper->m_data;
        if (!promiseData || !wrapper->m_tracker)
            return;

#if ENABLE(OILPAN)
        // Oilpan: let go of ScopedPersistent<>s right here (and not wait until the
        // PromiseDataWrapper is GCed later.) The v8 weak callback handling expects
        // to see the callback data upon return.
        promiseData->dispose();
#endif
        PromiseTracker::PromiseDataMap& map = wrapper->m_tracker->promiseDataMap();
        int promiseHash = promiseData->promiseHash();

        PromiseTracker::PromiseDataMap::iterator it = map.find(promiseHash);
        // The PromiseTracker may have been disabled (and, possibly, re-enabled later),
        // leaving the promiseHash as unmapped.
        if (it == map.end())
            return;

        PromiseTracker::PromiseDataVector* vector = &it->value;
        int index = indexOf(vector, promiseData->promise());
        ASSERT(index >= 0);
        vector->remove(index);
        if (vector->isEmpty())
            map.remove(promiseHash);
    }

    void trace(Visitor* visitor)
    {
#if ENABLE(OILPAN)
        visitor->trace(m_data);
        visitor->trace(m_tracker);
#endif
    }

private:
    PromiseDataWrapper(WeakPtrWillBeRawPtr<PromiseTracker::PromiseData> data, PromiseTracker* tracker)
        : m_data(data)
        , m_tracker(tracker)
    {
    }

    WeakPtrWillBeWeakMember<PromiseTracker::PromiseData> m_data;
    RawPtrWillBeWeakMember<PromiseTracker> m_tracker;
};

}

PromiseTracker::PromiseTracker()
    : m_circularSequentialId(0)
    , m_isEnabled(false)
{
}

DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(PromiseTracker);

void PromiseTracker::trace(Visitor* visitor)
{
#if ENABLE(OILPAN)
    visitor->trace(m_promiseDataMap);
#endif
}

void PromiseTracker::setEnabled(bool enabled)
{
    m_isEnabled = enabled;
    if (!enabled)
        clear();
}

void PromiseTracker::clear()
{
    m_promiseDataMap.clear();
}

int PromiseTracker::circularSequentialId()
{
    ++m_circularSequentialId;
    if (m_circularSequentialId <= 0)
        m_circularSequentialId = 1;
    return m_circularSequentialId;
}

PassRefPtrWillBeRawPtr<PromiseTracker::PromiseData> PromiseTracker::createPromiseDataIfNeeded(ScriptState* scriptState, v8::Handle<v8::Object> promise)
{
    int promiseHash = promise->GetIdentityHash();
    RawPtr<PromiseDataVector> vector = nullptr;
    PromiseDataMap::iterator it = m_promiseDataMap.find(promiseHash);
    if (it != m_promiseDataMap.end())
        vector = &it->value;
    else
        vector = &m_promiseDataMap.add(promiseHash, PromiseDataVector()).storedValue->value;

    int index = indexOf(vector, ScopedPersistent<v8::Object>(scriptState->isolate(), promise));
    if (index != -1)
        return vector->at(index);

    // FIXME: Consider using the ScriptState's DOMWrapperWorld instead
    // to handle the lifetime of PromiseDataWrapper, avoiding all this
    // manual labor to achieve the same, with and without Oilpan.
    RefPtrWillBeRawPtr<PromiseData> data = PromiseData::create(scriptState, promiseHash, circularSequentialId(), promise);
    OwnPtrWillBeRawPtr<PromiseDataWrapper> dataWrapper = PromiseDataWrapper::create(data.get(), this);
#if ENABLE(OILPAN)
    OwnPtr<Persistent<PromiseDataWrapper> > wrapper = adoptPtr(new Persistent<PromiseDataWrapper>(dataWrapper));
#else
    OwnPtr<PromiseDataWrapper> wrapper = dataWrapper.release();
#endif
    data->m_promise.setWeak(wrapper.leakPtr(), &PromiseDataWrapper::didRemovePromise);
    vector->append(data);

    return data.release();
}

void PromiseTracker::didReceiveV8PromiseEvent(ScriptState* scriptState, v8::Handle<v8::Object> promise, v8::Handle<v8::Value> parentPromise, int status)
{
    ASSERT(isEnabled());

    RefPtrWillBeRawPtr<PromiseData> data = createPromiseDataIfNeeded(scriptState, promise);
    if (!parentPromise.IsEmpty() && parentPromise->IsObject()) {
        v8::Handle<v8::Object> handle = parentPromise->ToObject();
        RefPtrWillBeRawPtr<PromiseData> parentData = createPromiseDataIfNeeded(scriptState, handle);
        data->m_parentPromiseId = parentData->m_promiseId;
        data->m_parentPromise.set(scriptState->isolate(), handle);
    } else {
        data->m_status = status;
        if (!status && !data->m_callStack) {
            RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(1, true);
            if (stack && stack->size())
                data->m_callStack = stack;
        }
    }
}

PassRefPtr<Array<PromiseDetails> > PromiseTracker::promises()
{
    ASSERT(isEnabled());

    RefPtr<Array<PromiseDetails> > result = Array<PromiseDetails>::create();
    for (PromiseDataMap::iterator it = m_promiseDataMap.begin(); it != m_promiseDataMap.end(); ++it) {
        PromiseDataVector* vector = &it->value;
        for (size_t index = 0; index < vector->size(); ++index) {
            RefPtrWillBeRawPtr<PromiseData> data = vector->at(index);
            PromiseDetails::Status::Enum status;
            if (!data->m_status)
                status = PromiseDetails::Status::Pending;
            else if (data->m_status == 1)
                status = PromiseDetails::Status::Resolved;
            else
                status = PromiseDetails::Status::Rejected;
            RefPtr<PromiseDetails> promiseDetails = PromiseDetails::create()
                .setId(data->m_promiseId)
                .setStatus(status);
            if (data->m_parentPromiseId)
                promiseDetails->setParentId(data->m_parentPromiseId);
            if (data->m_callStack)
                promiseDetails->setCallFrame(data->m_callStack->at(0).buildInspectorObject());
            result->addItem(promiseDetails);
        }
    }

    return result.release();
}

ScriptValue PromiseTracker::promiseById(int promiseId) const
{
    ASSERT(isEnabled());

    for (PromiseDataMap::const_iterator it = m_promiseDataMap.begin(); it != m_promiseDataMap.end(); ++it) {
        const PromiseDataVector* vector = &it->value;
        for (size_t index = 0; index < vector->size(); ++index) {
            RefPtrWillBeRawPtr<PromiseData> data = vector->at(index);
            if (data->m_promiseId == promiseId) {
                ScriptState* scriptState = data->m_scriptState.get();
                return ScriptValue(scriptState, data->m_promise.newLocal(scriptState->isolate()));
            }
        }
    }

    return ScriptValue();
}

} // namespace blink
<|endoftext|>


<commit_before>#include <immintrin.h>
#include <cstdint>
#include <cassert>

char* remove_spaces__avx512vbmi(const char* src, char* dst, size_t n) {
    assert(n % 64 == 0);

    const __m512i NL     = _mm512_set1_epi8('\n');
    const __m512i CR     = _mm512_set1_epi8('\r');
    const __m512i spaces = _mm512_set1_epi8(' ');

    uint64_t index_masks[6] = {
        0xaaaaaaaaaaaaaaaa,
        0xcccccccccccccccc,
        0xf0f0f0f0f0f0f0f0,
        0xff00ff00ff00ff00,
        0xffff0000ffff0000,
        0xffffffff00000000,
    };
    const __m512i bit_masks[6] = {
        _mm512_set1_epi8(1),
        _mm512_set1_epi8(2),
        _mm512_set1_epi8(4),
        _mm512_set1_epi8(8),
        _mm512_set1_epi8(16),
        _mm512_set1_epi8(32),
    };

    size_t len;
    for (size_t i=0; i < n; i += 64) {
        const __m512i input  = _mm512_loadu_si512((const __m512i*)(src + i));
        __m512i output;

        uint64_t mask = _mm512_cmpeq_epi8_mask(input, spaces)
                      | _mm512_cmpeq_epi8_mask(input, NL)
                      | _mm512_cmpeq_epi8_mask(input, CR);

        if (mask) {
            mask = ~mask;
            __m512i indices = _mm512_set1_epi8(0);
            for (size_t index = 0; index < 6; index++) {
                uint64_t m = _pext_u64(index_masks[index], mask);
                indices = _mm512_mask_add_epi8(indices, m, indices, bit_masks[index]);
            }

            output = _mm512_permutexvar_epi8(indices, input);
        } else {
            output = input;
            len = 64;
        }

        _mm512_storeu_si512((__m512i*)(dst), output);
        dst += len;
    }

    return dst;
}
<commit_msg>Rename variable<commit_after>#include <immintrin.h>
#include <cstdint>
#include <cassert>

char* remove_spaces__avx512vbmi(const char* src, char* dst, size_t n) {
    assert(n % 64 == 0);

    const __m512i NL     = _mm512_set1_epi8('\n');
    const __m512i CR     = _mm512_set1_epi8('\r');
    const __m512i spaces = _mm512_set1_epi8(' ');

    uint64_t index_masks[6] = {
        0xaaaaaaaaaaaaaaaa,
        0xcccccccccccccccc,
        0xf0f0f0f0f0f0f0f0,
        0xff00ff00ff00ff00,
        0xffff0000ffff0000,
        0xffffffff00000000,
    };
    const __m512i index_bits[6] = {
        _mm512_set1_epi8(1),
        _mm512_set1_epi8(2),
        _mm512_set1_epi8(4),
        _mm512_set1_epi8(8),
        _mm512_set1_epi8(16),
        _mm512_set1_epi8(32),
    };

    size_t len;
    for (size_t i=0; i < n; i += 64) {
        const __m512i input  = _mm512_loadu_si512((const __m512i*)(src + i));
        __m512i output;

        uint64_t mask = _mm512_cmpeq_epi8_mask(input, spaces)
                      | _mm512_cmpeq_epi8_mask(input, NL)
                      | _mm512_cmpeq_epi8_mask(input, CR);

        if (mask) {
            mask = ~mask;
            __m512i indices = _mm512_set1_epi8(0);
            for (size_t index = 0; index < 6; index++) {
                uint64_t m = _pext_u64(index_masks[index], mask);
                indices = _mm512_mask_add_epi8(indices, m, indices, index_bits[index]);
            }

            output = _mm512_permutexvar_epi8(indices, input);
        } else {
            output = input;
            len = 64;
        }

        _mm512_storeu_si512((__m512i*)(dst), output);
        dst += len;
    }

    return dst;
}
<|endoftext|>


<commit_before>// binomial_coefficients.cpp: example program to show binomial coefficients
//
// Binomial coefficients are useful to generate the inverse of a Hilbert matrix
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal number project, which is released under an MIT Open Source license.
#include <iostream>
#include <universal/integer/integer>
// enable posit arithmetic exceptions
#define POSIT_THROW_ARITHMETIC_EXCEPTION 1
#include <universal/posit/posit>
#include <universal/functions/binomial.hpp>

std::string spacing(unsigned n) {
	std::stringstream ss;
	for (unsigned i = 0; i < n; ++i) {
		ss << ' ';
	}
	return ss.str();
}

// Generate Pascal's triangle
// the bottom layer of the triangle has N+1 values, and given a columns width we can calculate the
// center of the pyramid.
template<typename Scalar>
void PascalsTriangle(Scalar N) {
	std::cout << "Pascal's Triangle for binomial coefficients of the " << N << "th order\n";
	std::cout << "Computed with type: " << typeid(N).name() << '\n';
	int widths[] = { 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7 };
	int order = int(N);
	int columnWidth = unsigned(order) < (sizeof(widths) / sizeof(int)) ? widths[order] : 10;
	int width = (order + 1) * (columnWidth + 2);
	int middle = width / 2;
	int leftMargin = middle;
	Scalar n, k;
	std::cout << spacing(leftMargin) << "             1\n";
	leftMargin -= columnWidth/2;
	//// GOTCHA!!!!! we have redefined the increment/decrement operators for posits to be working on ULP. Here we want pure integer behavior, so we need to be explicity if we want to support posits as Scalar
	for (n = 1; n <= N; n += 1) {
		std::cout << "n = " << std::setw(3) << n << spacing(leftMargin);
		for (k = 0; k <= n; k += 1) {
			std::cout << std::setw(columnWidth) << std::right << sw::function::binomial(n, k) << ' ';
		}
		leftMargin -= columnWidth/2;
		std::cout << '\n';
	}
}

// Enumerate the binomial coefficients of order n
template<typename Scalar>
void Binomials(Scalar n) {
	Scalar k;
	//// NOTE!!!!! the posit library has redefined the increment/decrement operators for posits to work at the ULP (Unit in Last Position).
	//// Here we want pure integer behavior, so we need to be explicity in our adding of the integer value of 1
	//// if we want to use posits as an integer scalar.
	for (k = 0; k <= n; k = k + 1) {
		std::cout << "Binomial(" << std::setw(3) << n << "," << std::setw(3) << k << ") = " << std::setw(10) << sw::function::BinomialCoefficient(n, k) << std::endl;
	}
}

// conditional compilation
#define MANUAL_TESTING 0
#define STRESS_TESTING 0

int main()
try {
	using namespace std;
	using namespace sw::function;

#if MANUAL_TESTING
	using int128_t = sw::unum::integer<128>;
	using posit = sw::unum::posit<32, 2>;

	PascalsTriangle(long(20));
	PascalsTriangle(int128_t(20));
	PascalsTriangle(posit(20));

	Binomials(posit(21));

#else // MANUAL_TESTING
	using int128_t = sw::unum::integer<128>;
	using posit = sw::unum::posit<32, 2>;

	PascalsTriangle(int128_t(15));
	PascalsTriangle(posit(15));

#if STRESS_TESTING
	PascalsTriangle(long(20));
	PascalsTriangle(int128_t(20));
	PascalsTriangle(posit(20));

	Binomials(posit(21));

#endif // STRESS_TESTING
#endif // MANUAL_TESTING

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_arithmetic_exception& err) {
	std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const quire_exception& err) {
	std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_internal_exception& err) {
	std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (std::runtime_error& err) {
	std::cerr << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<commit_msg>compilation fix for g++<commit_after>// binomial_coefficients.cpp: example program to show binomial coefficients
//
// Binomial coefficients are useful to generate the inverse of a Hilbert matrix
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal number project, which is released under an MIT Open Source license.
#include <iostream>
#include <universal/integer/integer>
// enable posit arithmetic exceptions
#define POSIT_THROW_ARITHMETIC_EXCEPTION 1
#include <universal/posit/posit>
#include <universal/functions/binomial.hpp>

std::string spacing(unsigned n) {
	std::stringstream ss;
	for (unsigned i = 0; i < n; ++i) {
		ss << ' ';
	}
	return ss.str();
}

// Generate Pascal's triangle
// the bottom layer of the triangle has N+1 values, and given a columns width we can calculate the
// center of the pyramid.
template<typename Scalar>
void PascalsTriangle(Scalar N) {
	std::cout << "Pascal's Triangle for binomial coefficients of the " << N << "th order\n";
	std::cout << "Computed with type: " << typeid(N).name() << '\n';
	int widths[] = { 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7 };
	int order = int(N);
	int columnWidth = unsigned(order) < (sizeof(widths) / sizeof(int)) ? widths[order] : 10;
	int width = (order + 1) * (columnWidth + 2);
	int middle = width / 2;
	int leftMargin = middle;
	Scalar n, k;
	std::cout << spacing(leftMargin) << "             1\n";
	leftMargin -= columnWidth/2;
	//// GOTCHA!!!!! we have redefined the increment/decrement operators for posits to be working on ULP. Here we want pure integer behavior, so we need to be explicity if we want to support posits as Scalar
	for (n = 1; n <= N; n += 1) {
		std::cout << "n = " << std::setw(3) << n << spacing(leftMargin);
		for (k = 0; k <= n; k += 1) {
			std::cout << std::setw(columnWidth) << std::right << sw::function::binomial(n, k) << ' ';
		}
		leftMargin -= columnWidth/2;
		std::cout << '\n';
	}
}

// Enumerate the binomial coefficients of order n
template<typename Scalar>
void Binomials(Scalar n) {
	Scalar k;
	//// NOTE!!!!! the posit library has redefined the increment/decrement operators for posits to work at the ULP (Unit in Last Position).
	//// Here we want pure integer behavior, so we need to be explicit in our adding of the integer value of 1
	//// if we want to use posits as an integer scalar.
	for (k = 0; k <= n; k = k + 1) {
		std::cout << "Binomial(" << std::setw(3) << n << "," << std::setw(3) << k << ") = " << std::setw(10) << sw::function::binomial(n, k) << std::endl;
	}
}

// conditional compilation
#define MANUAL_TESTING 0
#define STRESS_TESTING 0

int main()
try {
	using namespace std;
	using namespace sw::function;

#if MANUAL_TESTING
	using int128_t = sw::unum::integer<128>;
	using posit = sw::unum::posit<32, 2>;

	PascalsTriangle(long(20));
	PascalsTriangle(int128_t(20));
	PascalsTriangle(posit(20));

	Binomials(posit(21));

#else // MANUAL_TESTING
	using int128_t = sw::unum::integer<128>;
	using posit = sw::unum::posit<32, 2>;

	PascalsTriangle(int128_t(15));
	PascalsTriangle(posit(15));

	Binomials(10);

#if STRESS_TESTING
	PascalsTriangle(long(20));
	PascalsTriangle(int128_t(20));
	PascalsTriangle(posit(20));

	Binomials(posit(21));

#endif // STRESS_TESTING
#endif // MANUAL_TESTING

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_arithmetic_exception& err) {
	std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const quire_exception& err) {
	std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_internal_exception& err) {
	std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (std::runtime_error& err) {
	std::cerr << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2015 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

/*
 * Test how logger handles running out of file descriptors (EMFILE)
 */

#include "logger_test_common.h"

#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <unistd.h>
#include <platform/cbassert.h>
#include <platform/dirutils.h>
#include <sys/resource.h>

#include <string>

void wait_for_log_to_contain(FILE* log, const char* log_message) {
    // read() gives no guarantees of how the data will be chunked, so accumulate
    // one lines' worth (up to \n) in a string.
    std::string line;
    while (true) {
        char buffer[1024];
        ssize_t bytes_read = fread(buffer, 1, sizeof(buffer), log);
        if (bytes_read > 0) {
            line.append(buffer, bytes_read);
        } else if (bytes_read == 0) {
            if (fseek(log, 0, SEEK_CUR) != 0) {
                perror("fseek failed:");
                abort();
            }
            usleep(10);
        } else {
            perror("fread failed:");
            abort();
        }

        std::string::size_type pos;
        while ((pos = line.find('\n')) != std::string::npos) {
            if (line.find(log_message) != std::string::npos) {
                // Pass - found the warning in our log about rotation.
                return;
            }
            // Discard the line we've already cheched.
            line.erase(0, pos + 1);
        }
    }
}

int main() {

    // Timeout if takes longer than 30s.
    alarm(30);

    // Clean out any old files.
    std::vector<std::string> files;
    files = cb::io::findFilesWithPrefix("log_test_emfile");
    if (!files.empty()) {
        remove_files(files);
    }

    // Bring down out open file limit to a more conservative level (to
    // save using up a huge number of user / system FDs).
    struct rlimit rlim;
    if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
        fprintf(stderr, "Failed to get getrlimit number of files\n");
        exit(1);
    }

    rlim.rlim_cur = 100;
    if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
        fprintf(stderr, "Failed to setrlimit number of files\n");
        exit(2);
    }

    // Open the logger
    EXTENSION_ERROR_CODE ret = memcached_extensions_initialize(
            "unit_test=true;cyclesize=50;"
            "buffersize=150;sleeptime=1;filename=log_test_emfile",
            get_server_api);
    cb_assert(ret == EXTENSION_SUCCESS);

    // Wait for first log file to be created, and open it
    FILE* log_file;
    while ((log_file = fopen("log_test_emfile.000000.txt", "rb")) == nullptr) {
        usleep(10);
    }

    // Consume all available FD so we cannot open any more files
    // (i.e. rotation will fail).
    std::vector<FILE*> FDs;
    FILE* file;
    while ((file = std::fopen(".", "r")) != NULL) {
        FDs.emplace_back(file);
    }

    // add log entries, enough to trigger a rotation attempt.
    logger->log(EXTENSION_LOG_DETAIL, NULL,
                "test_emfile: Log line which should be in log_test_emfile.0.log");
    logger->log(EXTENSION_LOG_DETAIL, NULL,
                "test_emfile: Log line which should be in log_test_emfile.0.log");

    // read() gives no guarantees of how the data will be chunked, so accumulate
    // one lines' worth (up to \n) in a string.
    wait_for_log_to_contain(log_file, "Failed to open next logfile");

    // Close extra FDs so we can now print.
    for (auto f : FDs) {
        std::fclose(f);
    }

    // Wait for second log file to be created, and open it
    fclose(log_file);
    while ((log_file = fopen("log_test_emfile.000001.txt", "r")) == nullptr) {
        usleep(10);
    }

    // add log entries, enough to trigger a rotation attempt.
    logger->log(EXTENSION_LOG_DETAIL, NULL,
               "test_emfile: Log line which should be in log_test_emfile.1.log");

    wait_for_log_to_contain(log_file, "Restarting file logging");

    fclose(log_file);
    logger->shutdown(false);
}
<commit_msg>MB-24582: Make logger-emfile-test dump core if it times out<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2015 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

/*
 * Test how logger handles running out of file descriptors (EMFILE)
 */

#include "logger_test_common.h"

#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <unistd.h>
#include <platform/cbassert.h>
#include <platform/dirutils.h>
#include <sys/resource.h>

#include <string>
#include <thread>

void wait_for_log_to_contain(FILE* log, const char* log_message) {
    // read() gives no guarantees of how the data will be chunked, so accumulate
    // one lines' worth (up to \n) in a string.
    std::string line;
    while (true) {
        char buffer[1024];
        ssize_t bytes_read = fread(buffer, 1, sizeof(buffer), log);
        if (bytes_read > 0) {
            line.append(buffer, bytes_read);
        } else if (bytes_read == 0) {
            if (fseek(log, 0, SEEK_CUR) != 0) {
                perror("fseek failed:");
                abort();
            }
            usleep(10);
        } else {
            perror("fread failed:");
            abort();
        }

        std::string::size_type pos;
        while ((pos = line.find('\n')) != std::string::npos) {
            if (line.find(log_message) != std::string::npos) {
                // Pass - found the warning in our log about rotation.
                return;
            }
            // Discard the line we've already cheched.
            line.erase(0, pos + 1);
        }
    }
}

int main() {

    // Timeout (and dump core) if takes longer than 30s.
    std::thread watchdog{[]() {
        std::this_thread::sleep_for(std::chrono::seconds(30));
        std::abort();
    }};
    watchdog.detach();

    // Clean out any old files.
    std::vector<std::string> files;
    files = cb::io::findFilesWithPrefix("log_test_emfile");
    if (!files.empty()) {
        remove_files(files);
    }

    // Bring down out open file limit to a more conservative level (to
    // save using up a huge number of user / system FDs).
    struct rlimit rlim;
    if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
        fprintf(stderr, "Failed to get getrlimit number of files\n");
        exit(1);
    }

    rlim.rlim_cur = 100;
    if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
        fprintf(stderr, "Failed to setrlimit number of files\n");
        exit(2);
    }

    // Open the logger
    EXTENSION_ERROR_CODE ret = memcached_extensions_initialize(
            "unit_test=true;cyclesize=50;"
            "buffersize=150;sleeptime=1;filename=log_test_emfile",
            get_server_api);
    cb_assert(ret == EXTENSION_SUCCESS);

    // Wait for first log file to be created, and open it
    FILE* log_file;
    while ((log_file = fopen("log_test_emfile.000000.txt", "rb")) == nullptr) {
        usleep(10);
    }

    // Consume all available FD so we cannot open any more files
    // (i.e. rotation will fail).
    std::vector<FILE*> FDs;
    FILE* file;
    while ((file = std::fopen(".", "r")) != NULL) {
        FDs.emplace_back(file);
    }

    // add log entries, enough to trigger a rotation attempt.
    logger->log(EXTENSION_LOG_DETAIL, NULL,
                "test_emfile: Log line which should be in log_test_emfile.0.log");
    logger->log(EXTENSION_LOG_DETAIL, NULL,
                "test_emfile: Log line which should be in log_test_emfile.0.log");

    // read() gives no guarantees of how the data will be chunked, so accumulate
    // one lines' worth (up to \n) in a string.
    wait_for_log_to_contain(log_file, "Failed to open next logfile");

    // Close extra FDs so we can now print.
    for (auto f : FDs) {
        std::fclose(f);
    }

    // Wait for second log file to be created, and open it
    fclose(log_file);
    while ((log_file = fopen("log_test_emfile.000001.txt", "r")) == nullptr) {
        usleep(10);
    }

    // add log entries, enough to trigger a rotation attempt.
    logger->log(EXTENSION_LOG_DETAIL, NULL,
               "test_emfile: Log line which should be in log_test_emfile.1.log");

    wait_for_log_to_contain(log_file, "Restarting file logging");

    fclose(log_file);
    logger->shutdown(false);
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <Common/Colorful.hh>
#include <GC/MarkSweep.hh>

namespace Tadpole::GC {

MarkSweep::MarkSweep() noexcept {
}

MarkSweep::~MarkSweep() {
  while (!objects_.empty()) {
    auto* o = objects_.back();
    objects_.pop_back();

    reclaim_object(o);
  }
}

void MarkSweep::collect() {
  if (!is_enabled_)
    return;

  mark_from_roots();
  sweep();

  gc_threshold_ = std::max(std::min(gc_threshold_, kGCThresholdMin), objects_.size() * kGCFactor);
  gc_threshold_ = Common::as_align(gc_threshold_, kGCAlign);
}

void MarkSweep::append_object(Object::BaseObject* o) {
  if (objects_.size() >= gc_threshold_)
    collect();
  objects_.push_back(o);
}

void MarkSweep::mark_object(Object::BaseObject* o) {
  if (o == nullptr || o->is_marked())
    return;

#if defined(_TADPOLE_DEBUG_GC)
  std::cout
    << Common::Colorful::fg::lightcyan
    << "[" << o << "] mark object: `" << o->stringify() << "`"
    << Common::Colorful::reset
    << std::endl;
#endif

  o->set_marked(true);
  worklist_.push_back(o);
}

str_t MarkSweep::get_name() const {
  return "MarkSweep";
}

sz_t MarkSweep::get_count() const {
  return objects_.size();
}

sz_t MarkSweep::get_threshold() const {
  return gc_threshold_;
}

void MarkSweep::set_threshold(sz_t threshold) {
  gc_threshold_ = Common::as_align(threshold, kGCAlign);
}

bool MarkSweep::is_enabled() const {
  return is_enabled_;
}

void MarkSweep::enable() {
  is_enabled_ = true;
}

void MarkSweep::disable() {
  is_enabled_ = false;
}

void MarkSweep::mark() {
  while (!worklist_.empty()) {
    Object::BaseObject* o = worklist_.back();
    worklist_.pop_back();

    o->iter_children([this](Object::BaseObject* child) { mark_object(child); });
  }
}

void MarkSweep::mark_from_roots() {
  for (auto& r : roots_) {
    r.second->iter_objects([this](Object::BaseObject* o) {
          mark_object(o);
          mark();
        });
  }

  for (auto& s : interned_strings_) {
    mark_object(s.second);
    mark();
  }
}

void MarkSweep::sweep() {
  for (auto it = interned_strings_.begin(); it != interned_strings_.end();) {
    if (!it->second->is_marked())
      interned_strings_.erase(it++);
    else
      ++it;
  }

  for (auto it = objects_.begin(); it != objects_.end();) {
    if (!(*it)->is_marked()) {
      reclaim_object(*it);
      objects_.erase(it++);
    }
    else {
      (*it)->set_marked(true);
      ++it;
    }
  }
}

void MarkSweep::reclaim_object(Object::BaseObject* o) {
#if defined(_TADPOLE_DEBUG_GC)
  std::cout
    << Common::Colorful::fg::gray
    << "[" << o << "] reclaim object type: `" << o->type_asstr() << "`"
    << Common::Colorful::reset
    << std::endl;
#endif

  delete o;
}

}
<commit_msg>:construction: chore(gc): add gc debug output information with global setting<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <Common/Colorful.hh>
#include <Setting/Setting.hh>
#include <GC/MarkSweep.hh>

namespace Tadpole::GC {

MarkSweep::MarkSweep() noexcept {
}

MarkSweep::~MarkSweep() {
  while (!objects_.empty()) {
    auto* o = objects_.back();
    objects_.pop_back();

    reclaim_object(o);
  }
}

void MarkSweep::collect() {
  if (!is_enabled_)
    return;

  mark_from_roots();
  sweep();

  gc_threshold_ = std::max(std::min(gc_threshold_, kGCThresholdMin), objects_.size() * kGCFactor);
  gc_threshold_ = Common::as_align(gc_threshold_, kGCAlign);
}

void MarkSweep::append_object(Object::BaseObject* o) {
  if (objects_.size() >= gc_threshold_)
    collect();
  objects_.push_back(o);
}

void MarkSweep::mark_object(Object::BaseObject* o) {
  if (o == nullptr || o->is_marked())
    return;

  if (Setting::Setting::get_instance().enabled_debug_gc()) {
    std::cout
      << Common::Colorful::fg::lightcyan
      << "[" << o << "] mark object: `" << o->stringify() << "`"
      << Common::Colorful::reset
      << std::endl;
  }

  o->set_marked(true);
  worklist_.push_back(o);
}

str_t MarkSweep::get_name() const {
  return "MarkSweep";
}

sz_t MarkSweep::get_count() const {
  return objects_.size();
}

sz_t MarkSweep::get_threshold() const {
  return gc_threshold_;
}

void MarkSweep::set_threshold(sz_t threshold) {
  gc_threshold_ = Common::as_align(threshold, kGCAlign);
}

bool MarkSweep::is_enabled() const {
  return is_enabled_;
}

void MarkSweep::enable() {
  is_enabled_ = true;
}

void MarkSweep::disable() {
  is_enabled_ = false;
}

void MarkSweep::mark() {
  while (!worklist_.empty()) {
    Object::BaseObject* o = worklist_.back();
    worklist_.pop_back();

    o->iter_children([this](Object::BaseObject* child) { mark_object(child); });
  }
}

void MarkSweep::mark_from_roots() {
  for (auto& r : roots_) {
    r.second->iter_objects([this](Object::BaseObject* o) {
          mark_object(o);
          mark();
        });
  }

  for (auto& s : interned_strings_) {
    mark_object(s.second);
    mark();
  }
}

void MarkSweep::sweep() {
  for (auto it = interned_strings_.begin(); it != interned_strings_.end();) {
    if (!it->second->is_marked())
      interned_strings_.erase(it++);
    else
      ++it;
  }

  for (auto it = objects_.begin(); it != objects_.end();) {
    if (!(*it)->is_marked()) {
      reclaim_object(*it);
      objects_.erase(it++);
    }
    else {
      (*it)->set_marked(true);
      ++it;
    }
  }
}

void MarkSweep::reclaim_object(Object::BaseObject* o) {
  if (Setting::Setting::get_instance().enabled_debug_gc()) {
    std::cout
      << Common::Colorful::fg::gray
      << "[" << o << "] reclaim object type: `" << o->type_asstr() << "`"
      << Common::Colorful::reset
      << std::endl;
  }

  delete o;
}

}
<|endoftext|>


<commit_before>// https://oj.leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/

int read4(char *buf);

class Solution {
public:

    char myBuf[4];
    int myBufStart = 0;
    int myBufLen = 0;

    /**
     * @param buf Destination buffer
     * @param n   Maximum number of characters to read
     * @return    The number of characters read
     */
    int read(char *buf, int n) {
        int readBytes = 0;
        int bufStart = 0;
        bool eof = false;
        while (!eof && readBytes < n) {
            if (myBufLen == 0) {
                myBufLen = read4(myBuf);
                myBufStart = 0;
                if (myBufLen < 4) eof = true;
            }
            int copiedBytes = min(myBufLen, n - readBytes);
            memcpy(buf + bufStart, myBuf + myBufStart, copiedBytes);
            myBufStart += copiedBytes;
            myBufLen -= copiedBytes;
            bufStart += copiedBytes;
            readBytes += copiedBytes;
        }
        return readBytes;
    }
};
<commit_msg>Update ReadNCharactersGivenRead4_2.cc<commit_after>// https://oj.leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/

int read4(char *buf);

class Solution {
public:

    char myBuf[4];
    int myBufStart = 0;
    int myBufLen = 0;
    bool eof = false;

    /**
     * @param buf Destination buffer
     * @param n   Maximum number of characters to read
     * @return    The number of characters read
     */
    int read(char *buf, int n) {
        int readBytes = 0;
        int bufStart = 0;
        while (!eof && readBytes < n) {
            if (myBufLen == 0) {
                myBufLen = read4(myBuf);
                myBufStart = 0;
                if (myBufLen < 4) eof = true;
            }
            int copiedBytes = min(myBufLen, n - readBytes);
            memcpy(buf + bufStart, myBuf + myBufStart, copiedBytes);
            myBufStart += copiedBytes;
            myBufLen -= copiedBytes;
            bufStart += copiedBytes;
            readBytes += copiedBytes;
        }
        return readBytes;
    }
};
<|endoftext|>