<commit_before>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/*
 * Copyright (C) FFLAS-FFPACK
 * Written by Hongguang ZHU <zhuhongguang2014@gmail.com>
 * This file is Free Software and part of FFLAS-FFPACK.
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *.
 */
#define  __FFLASFFPACK_SEQUENTIAL

#define ENABLE_ALL_CHECKINGS 1

//#include "fflas-ffpack/fflas-ffpack-config.h"
#include <givaro/modular-integer.h>

#include <iomanip>
#include <iostream>

#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "fflas-ffpack/utils/args-parser.h"
#include "fflas-ffpack/utils/test-utils.h"
#include <givaro/modular.h>
#include <givaro/modular-balanced.h>

using namespace std;
using namespace FFPACK;
using Givaro::Modular;
using Givaro::ModularBalanced;

template<typename T>
void write_matrix(Givaro::Integer p, size_t m, size_t n, T* C, size_t ldc){

	size_t www=(p.bitsize()*log(2.))/log(10.);
	for (size_t i=0;i<m;++i){
		cout<<"[ ";
		cout.width(www+1);
		cout<<std::right<<C[i*ldc];
		for (size_t j=1;j<n;++j){
			cout<<" ";
			cout.width(www);
			cout<<std::right<<C[i*ldc+j];
		}
		cout<<"]"<<endl;
	}
	cout<<endl;

}

template<typename Field, class RandIter>
bool check_solve(const Field &F, size_t m, RandIter& Rand){

	typedef typename Field::Element Element;
	Element * A, *A2,  *B, *B2, *x;

	size_t lda,incb,incx;
	lda=m;
	incb=1;
	incx=1;
	A  = FFLAS::fflas_new(F,m,m);
	A2 = FFLAS::fflas_new(F,m,m);
	B  = FFLAS::fflas_new(F,m,1);
	B2 = FFLAS::fflas_new(F,m,1);
	x  = FFLAS::fflas_new(F,m,1);

	RandomMatrix (F, m, m, A, lda, Rand);
	RandomMatrix (F, m, m, A2, lda, Rand);

	while( m!=FFPACK::Rank( F, m, m, A, lda) ){
		RandomMatrix (F, m, m, A, lda, Rand);
	}
	RandomMatrix (F, m, 1, B, incb, Rand);
	RandomMatrix (F, m, 1, B2, incb, Rand);

	FFLAS::fassign (F, m, 1, B, incb, B2, incb);
	FFLAS::fassign (F, m, m, A, lda, A2, lda);
	FFLAS::WriteMatrix(std::cout<<"b:="<<std::endl,F,m,1,B,incb)<<std::endl;

	FFLAS::Timer t; t.clear();
	double time=0.0;
	t.clear();
	t.start();
	FFPACK::Solve(F, m, A2, lda, x, incx, B2, incb);
	t.stop();
	time+=t.usertime();

	FFLAS::fgemv(F, FFLAS::FflasNoTrans, m, m, F.one, A, lda, x, incx, F.zero, B2, incb);

	bool ok = true;
	if (FFLAS::fequal (F, m, 1, B2, incb, B, incb)){

		cout << "PASSED ("<<time<<")"<<endl;

	} else{
		FFLAS::WriteMatrix(std::cout<<"A*x:="<<std::endl,F,m,1,B2,incb)<<std::endl;
		FFLAS::WriteMatrix(std::cout<<"b:="<<std::endl,F,m,1,B,incb)<<std::endl;
		cout << "FAILED ("<<time<<")"<<endl;
		ok=false;

	}

	FFLAS::fflas_delete(A);
	FFLAS::fflas_delete(A2);
	FFLAS::fflas_delete(B);
	FFLAS::fflas_delete(B2);
	FFLAS::fflas_delete(x);
	return ok;
}
template <class Field>
bool run_with_field (Givaro::Integer q, size_t b, size_t m, size_t iters, uint64_t seed){
	bool ok = true ;
	int nbit=(int)iters;

	while (ok &&  nbit){
		//typedef typename Field::Element Element ;
		// choose Field
		Field* F= chooseField<Field>(q,b);
		typename Field::RandIter G(*F,0,seed);
		if (F==nullptr)
			return true;

		cout<<"Checking with ";F->write(cout)<<endl;

		ok = ok && check_solve(*F,m,G);

		nbit--;
		delete F;
	}

	return ok;
}

int main(int argc, char** argv)
{
	cerr<<setprecision(10);
	Givaro::Integer q=-1;
	size_t b=0;
	size_t m=6;

	size_t iters=100;
	bool loop=false;
	uint64_t seed = time(NULL);
	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",         TYPE_INTEGER , &q },
		{ 'b', "-b B", "Set the bitsize of the field characteristic.",  TYPE_INT , &b },
		{ 'm', "-m M", "Set the dimension of unknown square matrix.",      TYPE_INT , &m },

		{ 'i', "-i R", "Set number of repetitions.",            TYPE_INT , &iters },
		{ 'l', "-loop Y/N", "run the test in an infinite loop.", TYPE_BOOL , &loop },
		{ 's', "-s seed", "Set seed for the random generator", TYPE_INT, &seed },
                END_OF_ARGUMENTS
        };

	FFLAS::parseArguments(argc,argv,as);

	bool ok = true;

	do{
		ok = ok && run_with_field<Modular<double> >(q,b,m,iters,seed);

		ok = ok && run_with_field<ModularBalanced<double> >(q,b,m,iters,seed);

		ok = ok && run_with_field<Modular<float> >(q,b,m,iters,seed);

		ok = ok && run_with_field<ModularBalanced<float> >(q,b,m,iters,seed);
		ok = ok && run_with_field<Modular<int32_t> >(q,b,m,iters,seed);
		ok = ok && run_with_field<ModularBalanced<int32_t> >(q,b,m,iters,seed);
		ok = ok && run_with_field<Modular<int64_t> >(q,b,m,iters,seed);
		ok = ok && run_with_field<ModularBalanced<int64_t> >(q,b,m,iters,seed);

	} while (loop && ok);

	return !ok ;
}
<commit_msg>fix generation of the system's matrix<commit_after>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/*
 * Copyright (C) FFLAS-FFPACK
 * Written by Hongguang ZHU <zhuhongguang2014@gmail.com>
 * This file is Free Software and part of FFLAS-FFPACK.
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *.
 */
#define  __FFLASFFPACK_SEQUENTIAL

//#define ENABLE_ALL_CHECKINGS 1

//#include "fflas-ffpack/fflas-ffpack-config.h"
#include <givaro/modular-integer.h>

#include <iomanip>
#include <iostream>

#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "fflas-ffpack/utils/args-parser.h"
#include "fflas-ffpack/utils/test-utils.h"
#include <givaro/modular.h>
#include <givaro/modular-balanced.h>

using namespace std;
using namespace FFPACK;
using Givaro::Modular;
using Givaro::ModularBalanced;

template<typename T>
void write_matrix(Givaro::Integer p, size_t m, size_t n, T* C, size_t ldc){

	size_t www=(p.bitsize()*log(2.))/log(10.);
	for (size_t i=0;i<m;++i){
		cout<<"[ ";
		cout.width(www+1);
		cout<<std::right<<C[i*ldc];
		for (size_t j=1;j<n;++j){
			cout<<" ";
			cout.width(www);
			cout<<std::right<<C[i*ldc+j];
		}
		cout<<"]"<<endl;
	}
	cout<<endl;

}

template<typename Field, class RandIter>
bool check_solve(const Field &F, size_t m, RandIter& Rand){

	typedef typename Field::Element Element;
	Element * A, *A2,  *B, *B2, *x;

	size_t lda,incb,incx;
	lda=m;
	incb=1;
	incx=1;
	A  = FFLAS::fflas_new(F,m,m);
	A2 = FFLAS::fflas_new(F,m,m);
	B  = FFLAS::fflas_new(F,m,1);
	B2 = FFLAS::fflas_new(F,m,1);
	x  = FFLAS::fflas_new(F,m,1);

	FFPACK::RandomMatrixWithRank (F, m, m, m,  A, lda, Rand);

	RandomMatrix (F, m, 1, B, incb, Rand);

	FFLAS::fassign (F, m, B, incb, B2, incb);
	FFLAS::fassign (F, m, m, A, lda, A2, lda);
	FFLAS::WriteMatrix(std::cout<<"b:="<<std::endl,F,m,1,B,incb)<<std::endl;

	FFLAS::Timer t; t.clear();
	double time=0.0;
	t.clear();
	t.start();
	FFPACK::Solve(F, m, A2, lda, x, incx, B2, incb);
	t.stop();
	time+=t.usertime();

	FFLAS::fgemv(F, FFLAS::FflasNoTrans, m, m, F.one, A, lda, x, incx, F.zero, B2, incb);

	bool ok = true;
	if (FFLAS::fequal (F, m, 1, B2, incb, B, incb)){

		cout << "PASSED ("<<time<<")"<<endl;

	} else{
		FFLAS::WriteMatrix(std::cout<<"A*x:="<<std::endl,F,m,1,B2,incb)<<std::endl;
		FFLAS::WriteMatrix(std::cout<<"b:="<<std::endl,F,m,1,B,incb)<<std::endl;
		cout << "FAILED ("<<time<<")"<<endl;
		ok=false;

	}

	FFLAS::fflas_delete(A);
	FFLAS::fflas_delete(A2);
	FFLAS::fflas_delete(B);
	FFLAS::fflas_delete(B2);
	FFLAS::fflas_delete(x);
	return ok;
}
template <class Field>
bool run_with_field (Givaro::Integer q, size_t b, size_t m, size_t iters, uint64_t seed){
	bool ok = true ;
	int nbit=(int)iters;

	while (ok &&  nbit){
		//typedef typename Field::Element Element ;
		// choose Field
		Field* F= chooseField<Field>(q,b);
		typename Field::RandIter G(*F,0,seed);
		if (F==nullptr)
			return true;

		cout<<"Checking with ";F->write(cout)<<endl;

		ok = ok && check_solve(*F,m,G);

		nbit--;
		delete F;
	}

	return ok;
}

int main(int argc, char** argv)
{
	cerr<<setprecision(10);
	Givaro::Integer q=-1;
	size_t b=0;
	size_t m=6;

	size_t iters=100;
	bool loop=false;
	uint64_t seed = time(NULL);
	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",         TYPE_INTEGER , &q },
		{ 'b', "-b B", "Set the bitsize of the field characteristic.",  TYPE_INT , &b },
		{ 'm', "-m M", "Set the dimension of unknown square matrix.",      TYPE_INT , &m },

		{ 'i', "-i R", "Set number of repetitions.",            TYPE_INT , &iters },
		{ 'l', "-loop Y/N", "run the test in an infinite loop.", TYPE_BOOL , &loop },
		{ 's', "-s seed", "Set seed for the random generator", TYPE_INT, &seed },
                END_OF_ARGUMENTS
        };

	FFLAS::parseArguments(argc,argv,as);

	bool ok = true;

	do{
		ok = ok && run_with_field<Modular<double> >(q,b,m,iters,seed);

		ok = ok && run_with_field<ModularBalanced<double> >(q,b,m,iters,seed);

		ok = ok && run_with_field<Modular<float> >(q,b,m,iters,seed);

		ok = ok && run_with_field<ModularBalanced<float> >(q,b,m,iters,seed);
		ok = ok && run_with_field<Modular<int32_t> >(q,b,m,iters,seed);
		ok = ok && run_with_field<ModularBalanced<int32_t> >(q,b,m,iters,seed);
		ok = ok && run_with_field<Modular<int64_t> >(q,b,m,iters,seed);
		ok = ok && run_with_field<ModularBalanced<int64_t> >(q,b,m,iters,seed);

	} while (loop && ok);

	return !ok ;
}
<|endoftext|>


<commit_before>#ifndef LEVEL
#define LEVEL

#include <SFML/Graphics.hpp>
#include <string>
#include <vector>
//#include <cAudio/cAudio.h>

const float DEFAULT_PLAYER_X = 0.0;
const float DEFAULT_PLAYER_Y = 0.0;

const sf::Vector2<float> UP     = sf::Vector2<float>(0, 1.0);
const sf::Vector2<float> DOWN   = sf::Vector2<float>(0, -1.0);
const sf::Vector2<float> RIGHT  = sf::Vector2<float>(1.0, 0);
const sf::Vector2<float> LEFT   = sf::Vector2<float>(-1.0, 0);
const sf::Vector2<float> STILL  = sf::Vector2<float>(0, 0);

const std::string DEFAULT_MAP = "images/map-default";
const std::string DEFAULT_AUDIO_MAP = "data/test_audio.json";

const int WOOD = 0x603200;
const int GRAVEL = 0x4b4b4b;
const int GRASS = 0x00ff00;
const int PUDDLE = 0x0000ff;

struct AudioSource {

    sf::Vector2<float> pos;

 //   cAudio::IAudioSource* audio;

};

class Level {

    public:

        Level();

        sf::Vector2<float> get_player_pos() const;
        sf::Vector2<float> get_player_velocity() const;

        void update();

    private:

        std::vector<AudioSource> audio_sources;

        sf::Vector2<float> player_pos;
        sf::Vector2<float> player_velocity;

        float player_speed;

        sf::Image sound_map;

        /*
         * Reads keyboard input and updates the
         * player velocities.
         */
        void handle_input();

        /*
         * Sets the player velocity such that it doesn't
         * walk through a wall. For example, walking straight
         * into a wall would just set the velocity to (0, 0).
         */
        void handle_collisions();

        /*
         * Adds the player velocity scaled by the speed
         */
        void update_player_position();

        void load_audio_sources();
};

#endif /* ifndef LEVEL */
<commit_msg>made the texture values into colors instead<commit_after>#ifndef LEVEL
#define LEVEL

#include <SFML/Graphics.hpp>
#include <string>
#include <vector>
//#include <cAudio/cAudio.h>

const float DEFAULT_PLAYER_X = 0.0;
const float DEFAULT_PLAYER_Y = 0.0;

const sf::Vector2<float> UP     = sf::Vector2<float>(0, 1.0);
const sf::Vector2<float> DOWN   = sf::Vector2<float>(0, -1.0);
const sf::Vector2<float> RIGHT  = sf::Vector2<float>(1.0, 0);
const sf::Vector2<float> LEFT   = sf::Vector2<float>(-1.0, 0);
const sf::Vector2<float> STILL  = sf::Vector2<float>(0, 0);

const std::string DEFAULT_MAP = "images/map-default";
const std::string DEFAULT_AUDIO_MAP = "data/test_audio.json";

const sf::Color WOOD = sf::Color(0x60,0x32,0x00, 255);
const sf::Color GRAVEL = sf::Color(0x4b, 0x4b, 0x4b, 255);
const sf::Color GRASS = sf::Color(0x00, 0xff, 0x00, 255);
const sf::Color PUDDLE = sf::Color(0x00, 0x00, 0xff, 255);

struct AudioSource {

    sf::Vector2<float> pos;

 //   cAudio::IAudioSource* audio;

};

class Level {

    public:

        Level();

        sf::Vector2<float> get_player_pos() const;
        sf::Vector2<float> get_player_velocity() const;

        void update();

    private:

        std::vector<AudioSource> audio_sources;

        sf::Vector2<float> player_pos;
        sf::Vector2<float> player_velocity;

        float player_speed;

        sf::Image sound_map;

        /*
         * Reads keyboard input and updates the
         * player velocities.
         */
        void handle_input();

        /*
         * Sets the player velocity such that it doesn't
         * walk through a wall. For example, walking straight
         * into a wall would just set the velocity to (0, 0).
         */
        void handle_collisions();

        /*
         * Adds the player velocity scaled by the speed
         */
        void update_player_position();

        void load_audio_sources();
};

#endif /* ifndef LEVEL */
<|endoftext|>


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

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you 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.

*******************************************************************************/

//==============================================================================
// Compiler engine class
//==============================================================================

#include "compilerengine.h"
#include "compilermath.h"
#include "corecliutils.h"

//==============================================================================

#include <QApplication>
#include <QFile>
#include <QIODevice>
#include <QTemporaryFile>
#include <QTextStream>

//==============================================================================

#include "llvmdisablewarnings.h"
    #include "llvm/IR/LLVMContext.h"
    #include "llvm/IR/Module.h"
    #include "llvm/Support/TargetSelect.h"
    #include "llvm/Support/Host.h"

    #include "clang/Basic/DiagnosticOptions.h"
    #include "clang/CodeGen/CodeGenAction.h"
    #include "clang/Driver/Compilation.h"
    #include "clang/Driver/Driver.h"
    #include "clang/Driver/Tool.h"
    #include "clang/Frontend/CompilerInstance.h"
    #include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvmenablewarnings.h"

//==============================================================================

#include <string>

//==============================================================================

namespace OpenCOR {
namespace Compiler {

//==============================================================================

CompilerEngine::CompilerEngine() :
    mExecutionEngine(std::unique_ptr<llvm::ExecutionEngine>()),
    mError(QString())
{
}

//==============================================================================

CompilerEngine::~CompilerEngine()
{
    // Reset ourselves

    reset();
}

//==============================================================================

void CompilerEngine::reset(const bool &pResetError)
{
    // Reset some internal objects

    delete mExecutionEngine.release();

    mExecutionEngine = std::unique_ptr<llvm::ExecutionEngine>();

    if (pResetError)
        mError = QString();
}

//==============================================================================

bool CompilerEngine::hasError() const
{
    // Return whether an error occurred

    return mError.size();
}

//==============================================================================

QString CompilerEngine::error() const
{
    // Return the compiler engine's error

    return mError;
}

//==============================================================================

bool CompilerEngine::compileCode(const QString &pCode)
{
    // Reset our compiler engine

    reset();

    // Determine our target triple
    // Note: normally, we would call llvm::sys::getProcessTriple(), but this
    //       returns the information about the system on which LLVM was built.
    //       In most cases it is fine, but on OS X it may be a problem. Indeed,
    //       with OS X 10.9, Apple decided to extend the C standard by adding
    //       some functions (e.g. __exp10()). So, if the given code needs one of
    //       those functions, then OpenCOR will crash if run on an 'old' version
    //       of OS X. So, to avoid this issue, we set the target triple
    //       ourselves, based on the system on which OpenCOR is being used...

    std::string targetTriple;

#if defined(Q_OS_WIN)
    targetTriple = (sizeof(void *) == 4)?"i686-pc-windows-msvc-elf":"x86_64-pc-windows-msvc-elf";
    // Note: MCJIT currently works only through the ELF object format, hence we
    //       are appending "-elf"...
    //---GRY--- WE WERE ORIGINALLY TRYING TO USE i686-pc-win32-elf AND
    //          x86_64-pc-win32-elf FOR WIN32 AND WIN64, RESPECTIVELY, BUT
    //          THOUGH IT WORKS FINE ON WIN64, IT DOESN'T ON WIN32. INDEED, ON
    //          THAT PLATFORM, WE GET THE SAME PROBLEM AS THE ONE REPORTED IN
    //          ISSUE #583. NOW, THINGS MIGHT BE DIFFERENT ONCE LLVM 3.6.1 IS
    //          OUT, SO WE MIGHT WANT TO REVISIT THE SITUATION THEN. UNTIL THEN,
    //          WE USE i686-pc-windows-msvc-elf AND x86_64-pc-windows-msvc-elf
    //          SINCE WE KNOW THEM TO WORK FINE (THANKS TO THE LLVM PATCH USED
    //          TO FIX ISSUE #583)...
#elif defined(Q_OS_LINUX)
    targetTriple = (sizeof(void *) == 4)?"i686-pc-linux-gnu":"x86_64-pc-linux-gnu";
#elif defined(Q_OS_MAC)
    targetTriple = "x86_64-apple-darwin"+std::to_string(QSysInfo::MacintoshVersion+2);
#else
    #error Unsupported platform
#endif

    // Get a driver to compile our code

#ifdef QT_DEBUG
    llvm::raw_ostream &outputStream = llvm::outs();
#else
    llvm::raw_ostream &outputStream = llvm::nulls();
#endif
    llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagnosticOptions = new clang::DiagnosticOptions();

    clang::DiagnosticsEngine diagnosticsEngine(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(new clang::DiagnosticIDs()),
                                               &*diagnosticOptions,
                                               new clang::TextDiagnosticPrinter(outputStream, &*diagnosticOptions));

    clang::driver::Driver driver("clang", targetTriple, diagnosticsEngine);

    driver.setCheckInputsExist(false);

    // Get a compilation object to which we pass some arguments

    llvm::StringRef dummyFileName("dummyFile.c");

    llvm::SmallVector<const char *, 16> compilationArguments;

    compilationArguments.push_back("clang");
    compilationArguments.push_back("-fsyntax-only");
    compilationArguments.push_back("-O3");
    compilationArguments.push_back("-ffast-math");
    compilationArguments.push_back("-Werror");
    compilationArguments.push_back(dummyFileName.data());

    std::unique_ptr<clang::driver::Compilation> compilation(driver.BuildCompilation(compilationArguments));

    if (!compilation) {
        mError = tr("the compilation object could not be created");

        return false;
    }

    // The compilation object should have only one command, so if it doesn't
    // then something went wrong

    const clang::driver::JobList &jobList = compilation->getJobs();

    if (    (jobList.size() != 1)
        || !llvm::isa<clang::driver::Command>(*jobList.begin())) {
        mError = tr("the compilation object must contain only one command");

        return false;
    }

    // Retrieve the command job

    const clang::driver::Command &command = llvm::cast<clang::driver::Command>(*jobList.begin());
    QString commandName = command.getCreator().getName();

    if (commandName.compare("clang")) {
        mError = tr("a clang command was expected, but a %1 command was found instead").arg(commandName);

        return false;
    }

    // Create a compiler invocation using our command's arguments

    const clang::driver::ArgStringList &commandArguments = command.getArguments();
    std::unique_ptr<clang::CompilerInvocation> compilerInvocation(new clang::CompilerInvocation());

    clang::CompilerInvocation::CreateFromArgs(*compilerInvocation,
                                              commandArguments.data(),
                                              commandArguments.data()+commandArguments.size(),
                                              diagnosticsEngine);

    // Map our dummy file to a memory buffer

    QByteArray codeByteArray = pCode.toUtf8();

    compilerInvocation->getPreprocessorOpts().addRemappedFile(dummyFileName, llvm::MemoryBuffer::getMemBuffer(codeByteArray.constData()).release());

    // Create a compiler instance to handle the actual work

    clang::CompilerInstance compilerInstance;

    compilerInstance.setInvocation(compilerInvocation.release());

    // Create the compiler instance's diagnostics engine

    compilerInstance.createDiagnostics();

    if (!compilerInstance.hasDiagnostics()) {
        mError = tr("the diagnostics engine could not be created");

        return false;
    }

    // Create and execute the frontend to generate an LLVM bitcode module
    // Note: the LLVM team has been meaning to modify
    //       CompilerInstance::ExecuteAction() so that we could specify the
    //       output stream we want to use (rather than always use llvm::errs()),
    //       but they have yet to actually do it, so we modified it ourselves...

    std::unique_ptr<clang::CodeGenAction> codeGenerationAction(new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext()));

    if (!compilerInstance.ExecuteAction(*codeGenerationAction, outputStream)) {
        mError = tr("the code could not be compiled");

        reset(false);

        return false;
    }

    // Retrieve the LLVM bitcode module

    std::unique_ptr<llvm::Module> module = codeGenerationAction->takeModule();

    // Initialise the native target (and its ASM printer), so not only can we
    // then create an execution engine, but more importantly its data layout
    // will match that of our target platform

    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();

    // Create and keep track of an execution engine

    mExecutionEngine = std::unique_ptr<llvm::ExecutionEngine>(llvm::EngineBuilder(std::move(module)).setEngineKind(llvm::EngineKind::JIT).create());

    if (!mExecutionEngine) {
        mError = tr("the execution engine could not be created");

        delete module.release();

        return false;
    }

    return true;
}

//==============================================================================

void * CompilerEngine::getFunction(const QString &pFunctionName)
{
    // Return the address of the requested function

    if (mExecutionEngine)
        return (void *) mExecutionEngine->getFunctionAddress(qPrintable(pFunctionName));
    else
        return 0;
}

//==============================================================================

}   // namespace Compiler
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Some minor cleaning up [ci skip].<commit_after>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you 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.

*******************************************************************************/

//==============================================================================
// Compiler engine class
//==============================================================================

#include "compilerengine.h"
#include "compilermath.h"
#include "corecliutils.h"

//==============================================================================

#include <QApplication>
#include <QFile>
#include <QIODevice>
#include <QTemporaryFile>
#include <QTextStream>

//==============================================================================

#include "llvmdisablewarnings.h"
    #include "llvm/IR/LLVMContext.h"
    #include "llvm/IR/Module.h"
    #include "llvm/Support/TargetSelect.h"
    #include "llvm/Support/Host.h"

    #include "clang/Basic/DiagnosticOptions.h"
    #include "clang/CodeGen/CodeGenAction.h"
    #include "clang/Driver/Compilation.h"
    #include "clang/Driver/Driver.h"
    #include "clang/Driver/Tool.h"
    #include "clang/Frontend/CompilerInstance.h"
    #include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvmenablewarnings.h"

//==============================================================================

#include <string>

//==============================================================================

namespace OpenCOR {
namespace Compiler {

//==============================================================================

CompilerEngine::CompilerEngine() :
    mExecutionEngine(std::unique_ptr<llvm::ExecutionEngine>()),
    mError(QString())
{
}

//==============================================================================

CompilerEngine::~CompilerEngine()
{
    // Reset ourselves

    reset();
}

//==============================================================================

void CompilerEngine::reset(const bool &pResetError)
{
    // Reset some internal objects

    delete mExecutionEngine.release();

    mExecutionEngine = std::unique_ptr<llvm::ExecutionEngine>();

    if (pResetError)
        mError = QString();
}

//==============================================================================

bool CompilerEngine::hasError() const
{
    // Return whether an error occurred

    return mError.size();
}

//==============================================================================

QString CompilerEngine::error() const
{
    // Return the compiler engine's error

    return mError;
}

//==============================================================================

bool CompilerEngine::compileCode(const QString &pCode)
{
    // Reset our compiler engine

    reset();

    // Determine our target triple
    // Note: normally, we would call llvm::sys::getProcessTriple(), but this
    //       returns the information about the system on which LLVM was built.
    //       In most cases it is fine, but on OS X it may be a problem. Indeed,
    //       with OS X 10.9, Apple decided to extend the C standard by adding
    //       some functions (e.g. __exp10()). So, if the given code needs one of
    //       those functions, then OpenCOR will crash if run on an 'old' version
    //       of OS X. So, to avoid this issue, we set the target triple
    //       ourselves, based on the system on which OpenCOR is being used...

    std::string targetTriple;

#if defined(Q_OS_WIN)
    targetTriple = (sizeof(void *) == 4)?"i686-pc-windows-msvc-elf":"x86_64-pc-windows-msvc-elf";
    // Note: MCJIT currently works only through the ELF object format, hence we
    //       are appending "-elf"...
#elif defined(Q_OS_LINUX)
    targetTriple = (sizeof(void *) == 4)?"i686-pc-linux-gnu":"x86_64-pc-linux-gnu";
#elif defined(Q_OS_MAC)
    targetTriple = "x86_64-apple-darwin"+std::to_string(QSysInfo::MacintoshVersion+2);
#else
    #error Unsupported platform
#endif

    // Get a driver to compile our code

#ifdef QT_DEBUG
    llvm::raw_ostream &outputStream = llvm::outs();
#else
    llvm::raw_ostream &outputStream = llvm::nulls();
#endif
    llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagnosticOptions = new clang::DiagnosticOptions();

    clang::DiagnosticsEngine diagnosticsEngine(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(new clang::DiagnosticIDs()),
                                               &*diagnosticOptions,
                                               new clang::TextDiagnosticPrinter(outputStream, &*diagnosticOptions));

    clang::driver::Driver driver("clang", targetTriple, diagnosticsEngine);

    driver.setCheckInputsExist(false);

    // Get a compilation object to which we pass some arguments

    llvm::StringRef dummyFileName("dummyFile.c");

    llvm::SmallVector<const char *, 16> compilationArguments;

    compilationArguments.push_back("clang");
    compilationArguments.push_back("-fsyntax-only");
    compilationArguments.push_back("-O3");
    compilationArguments.push_back("-ffast-math");
    compilationArguments.push_back("-Werror");
    compilationArguments.push_back(dummyFileName.data());

    std::unique_ptr<clang::driver::Compilation> compilation(driver.BuildCompilation(compilationArguments));

    if (!compilation) {
        mError = tr("the compilation object could not be created");

        return false;
    }

    // The compilation object should have only one command, so if it doesn't
    // then something went wrong

    const clang::driver::JobList &jobList = compilation->getJobs();

    if (    (jobList.size() != 1)
        || !llvm::isa<clang::driver::Command>(*jobList.begin())) {
        mError = tr("the compilation object must contain only one command");

        return false;
    }

    // Retrieve the command job

    const clang::driver::Command &command = llvm::cast<clang::driver::Command>(*jobList.begin());
    QString commandName = command.getCreator().getName();

    if (commandName.compare("clang")) {
        mError = tr("a clang command was expected, but a %1 command was found instead").arg(commandName);

        return false;
    }

    // Create a compiler invocation using our command's arguments

    const clang::driver::ArgStringList &commandArguments = command.getArguments();
    std::unique_ptr<clang::CompilerInvocation> compilerInvocation(new clang::CompilerInvocation());

    clang::CompilerInvocation::CreateFromArgs(*compilerInvocation,
                                              commandArguments.data(),
                                              commandArguments.data()+commandArguments.size(),
                                              diagnosticsEngine);

    // Map our dummy file to a memory buffer

    QByteArray codeByteArray = pCode.toUtf8();

    compilerInvocation->getPreprocessorOpts().addRemappedFile(dummyFileName, llvm::MemoryBuffer::getMemBuffer(codeByteArray.constData()).release());

    // Create a compiler instance to handle the actual work

    clang::CompilerInstance compilerInstance;

    compilerInstance.setInvocation(compilerInvocation.release());

    // Create the compiler instance's diagnostics engine

    compilerInstance.createDiagnostics();

    if (!compilerInstance.hasDiagnostics()) {
        mError = tr("the diagnostics engine could not be created");

        return false;
    }

    // Create and execute the frontend to generate an LLVM bitcode module
    // Note: the LLVM team has been meaning to modify
    //       CompilerInstance::ExecuteAction() so that we could specify the
    //       output stream we want to use (rather than always use llvm::errs()),
    //       but they have yet to actually do it, so we modified it ourselves...

    std::unique_ptr<clang::CodeGenAction> codeGenerationAction(new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext()));

    if (!compilerInstance.ExecuteAction(*codeGenerationAction, outputStream)) {
        mError = tr("the code could not be compiled");

        reset(false);

        return false;
    }

    // Retrieve the LLVM bitcode module

    std::unique_ptr<llvm::Module> module = codeGenerationAction->takeModule();

    // Initialise the native target (and its ASM printer), so not only can we
    // then create an execution engine, but more importantly its data layout
    // will match that of our target platform

    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();

    // Create and keep track of an execution engine

    mExecutionEngine = std::unique_ptr<llvm::ExecutionEngine>(llvm::EngineBuilder(std::move(module)).setEngineKind(llvm::EngineKind::JIT).create());

    if (!mExecutionEngine) {
        mError = tr("the execution engine could not be created");

        delete module.release();

        return false;
    }

    return true;
}

//==============================================================================

void * CompilerEngine::getFunction(const QString &pFunctionName)
{
    // Return the address of the requested function

    if (mExecutionEngine)
        return (void *) mExecutionEngine->getFunctionAddress(qPrintable(pFunctionName));
    else
        return 0;
}

//==============================================================================

}   // namespace Compiler
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014-2015 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#include <iostream>
#include <limits>

#include "consolebotview.hpp"

void ConsoleBotView::view() const {
    while (true) {
    }
}

void ConsoleBotView::start() const {
    std::cout << "*** BIN_GAME ***" << std::endl;
    std::cout << "----------------" << std::endl;
    std::cout << "t: time mode | w: play for score | s: "
                 "play while not lose" << std::endl;
    std::cout << ">>> ";
}

void ConsoleBotView::outputGeneral() const {
    const GameDesk* desk = getDesk();
    Point point;
    for (int i = desk->getRowNumber() - 1; i >= 0; i--) {
        for (int x = 0; x < desk->getRowNumber(); x++) {
            point.col = i;
            point.row = x;
            char prev_fill = std::cout.fill(' ');
            int prev_width = std::cout.width(5);
            std::cout << desk->getDeskNumber(point);
            std::cout.width(prev_width);
            std::cout.fill(prev_fill);
        }
        std::cout << std::endl;
    }
}

void ConsoleBotView::sendHelpMessage_impl() const {
    std::cout << "To play this game you must use the options: -w for play to win\n"
              "-t for game with real time and -s to play while not lose." << std::endl;
}

void ConsoleBotView::finish_impl(bool check_fail, int score, int steps_number) const {
    if (check_fail) {
        std::cout << "You are loser... Your score is " << score << std::endl;
    } else {
        std::cout << "You are winner! Your score is " << score << std::endl;
    }
    std::cout << "You have completed the game in " << steps_number << " steps." << std::endl;
}

void ConsoleBotView::typeError_impl() const {
    std::cout << "Error: you must enter the NUMBER" << std::endl;
    std::cout << "Try again: " << std::endl;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<int>::max(), '\n');
}

void ConsoleBotView::indexError_impl() const {
    std::cout << "Error: wrong index of numbers." << std::endl;
}
<commit_msg>In ConsoleBotView::start(): add quit info<commit_after>/*
 * Copyright (C) 2014-2015 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#include <iostream>
#include <limits>

#include "consolebotview.hpp"

void ConsoleBotView::view() const {
    while (true) {
    }
}

void ConsoleBotView::start() const {
    std::cout << "*** BIN_GAME ***" << std::endl;
    std::cout << "----------------" << std::endl;
    std::cout << "t: time mode | w: play for score | s: "
                 "play while not lose" << std::endl;
    std::cout << "q: quit" << std::endl;
    std::cout << ">>> ";
}

void ConsoleBotView::outputGeneral() const {
    const GameDesk* desk = getDesk();
    Point point;
    for (int i = desk->getRowNumber() - 1; i >= 0; i--) {
        for (int x = 0; x < desk->getRowNumber(); x++) {
            point.col = i;
            point.row = x;
            char prev_fill = std::cout.fill(' ');
            int prev_width = std::cout.width(5);
            std::cout << desk->getDeskNumber(point);
            std::cout.width(prev_width);
            std::cout.fill(prev_fill);
        }
        std::cout << std::endl;
    }
}

void ConsoleBotView::sendHelpMessage_impl() const {
    std::cout << "To play this game you must use the options: -w for play to win\n"
              "-t for game with real time and -s to play while not lose." << std::endl;
}

void ConsoleBotView::finish_impl(bool check_fail, int score, int steps_number) const {
    if (check_fail) {
        std::cout << "You are loser... Your score is " << score << std::endl;
    } else {
        std::cout << "You are winner! Your score is " << score << std::endl;
    }
    std::cout << "You have completed the game in " << steps_number << " steps." << std::endl;
}

void ConsoleBotView::typeError_impl() const {
    std::cout << "Error: you must enter the NUMBER" << std::endl;
    std::cout << "Try again: " << std::endl;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<int>::max(), '\n');
}

void ConsoleBotView::indexError_impl() const {
    std::cout << "Error: wrong index of numbers." << std::endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/net/http/HttpHeader.h"

#include "db/util/StringTools.h"

#include <cstdlib>
#include <cstring>

using namespace std;
using namespace db::io;
using namespace db::net::http;
using namespace db::util;

// define CRLF
const char* HttpHeader::CRLF = "\r\n";

HttpHeader::HttpHeader()
{
   mVersion = NULL;
   mFieldsSize = 0;
}

HttpHeader::~HttpHeader()
{
   if(mVersion != NULL)
   {
      free(mVersion);
   }

   for(FieldMap::iterator i = mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }
}

bool HttpHeader::parseStartLine(const char* str, unsigned int length)
{
   // no start line
   return true;
}

void HttpHeader::getStartLine(string& line)
{
   // no start line
   line.erase();
}

bool HttpHeader::hasStartLine()
{
   // no start line
   return false;
}

void HttpHeader::setVersion(const char* version)
{
   if(mVersion != NULL)
   {
      free(mVersion);
   }
   mVersion = strdup(version);
}

const char* HttpHeader::getVersion()
{
   if(mVersion == NULL)
   {
      // default to HTTP/1.1
      mVersion = strdup("HTTP/1.1");
   }

   return mVersion;
}

void HttpHeader::setField(const char* name, long long value)
{
   char temp[25];
   sprintf(temp, "%lli", value);
   setField(name, temp);
}

void HttpHeader::setField(const char* name, const string& value)
{
   // update old field if possible
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      mFieldsSize -= i->second.length();
      i->second = value;
   }
   else
   {
      // set new field
      mFieldsSize += strlen(name);
      mFieldsSize += value.length();
      mFields.insert(make_pair(strdup(name), value));
   }
}

void HttpHeader::addField(const char* name, const string& value)
{
   // get existing value
   string existing;
   if(getField(name, existing))
   {
      // append to existing value
      existing.append(", ");
   }

   existing.append(value);
   setField(name, existing);
}

void HttpHeader::removeField(const char* name)
{
   // erase field
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      mFieldsSize -= strlen(name);
      mFieldsSize -= i->second.length();
      mFields.erase(i);
   }
}

void HttpHeader::clearFields()
{
   for(FieldMap::iterator i = mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }

   mFieldsSize = 0;
   mFields.clear();
}

bool HttpHeader::getField(const char* name, long long& value)
{
   bool rval = false;

   string str;
   if(getField(name, str))
   {
      char* endptr = NULL;
      value = strtoll(str.c_str(), &endptr, 10);
      rval = endptr != str.c_str() && *endptr == '\0';
   }

   return rval;
}

bool HttpHeader::getField(const char* name, string& value)
{
   bool rval = false;

   // find field entry
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      // get value
      value = i->second;
      rval = true;
   }

   return rval;
}

bool HttpHeader::hasField(const char* name)
{
   bool rval = false;

   // find field entry
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      rval = true;
   }

   return rval;
}

bool HttpHeader::parse(const string& str)
{
   bool rval = false;

   // clear fields
   clearFields();

   bool startLine = hasStartLine();
   const char* start = str.c_str();
   char* cr;
   char* colon;
   while((cr = strchr(start, '\r')) != NULL)
   {
      // look for CRLF
      if(strchr(cr, '\n') == cr + 1)
      {
         if(startLine)
         {
            rval = parseStartLine(start, cr - start);
            startLine = false;
         }
         else
         {
            // found a CRLF, now find colon
            if((colon = strchr(start, ':')) != NULL && colon < cr)
            {
               // get field name
               char name[(colon - start) + 1];
               memcpy(name, start, colon - start);
               name[colon - start] = 0;

               // skip whitespace
               colon++;
               for(; *colon == ' ' && colon < cr; colon++);

               // get field value
               char value[cr - colon + 1];
               strncpy(value, colon, cr - colon);
               value[(cr - colon)] = 0;

               // set field
               setField(name, value);
            }
         }

         start = cr + 2;
      }
      else
      {
         start = cr + 1;
      }
   }

   return rval;
}

string HttpHeader::toString()
{
   string str;
   str.reserve(512);

   // get the start line
   getStartLine(str);

   // determine total fields size:
   // (CRLF + fields size + fields * (": " + CRLF))
   char fields[2 + mFieldsSize + mFields.size() * 4];
   char* s = fields;

   // append CRLF if there is a start line
   if(str.length() > 0)
   {
      s[0] = '\r';
      s[1] = '\n';
      s += 2;
   }

   // append all fields
   int length;
   for(FieldMap::iterator i = mFields.begin(); i != mFields.end(); i++)
   {
      // get field name and bicapitalize it
      biCapitalize((char*)i->first, &length);

      // append name
      memcpy(s, i->first, length);
      s += length;

      // append delimiter
      s[0] = ':';
      s[1] = ' ';
      s += 2;

      // append value
      memcpy(s, i->second.c_str(), i->second.length());
      s += i->second.length();

      // append CRLF
      s[0] = '\r';
      s[1] = '\n';
      s += 2;
   }

   // add CRLF
   s[0] = '\r';
   s[1] = '\n';
   s += 2;

   // append fields
   str.append(fields, s - fields);

   return str;
}

bool HttpHeader::write(OutputStream* os)
{
   bool rval = true;

   // get the start line
   string line;
   getStartLine(line);

   // write the start line and CRLF if one exists
   if(line.length() > 0)
   {
      rval =
         os->write(line.c_str(), line.length()) &&
         os->write(CRLF, 2);
   }

   // write all fields
   int length;
   for(FieldMap::iterator i = mFields.begin(); rval && i != mFields.end(); i++)
   {
      // get field name and bicapitalize it
      biCapitalize((char*)i->first, &length);

      // write name, delimiter, value, and CRLF
      rval =
         os->write(i->first, length) &&
         os->write(": ", 2) &&
         os->write(i->second.c_str(), i->second.length()) &&
         os->write(CRLF, 2);
   }

   // write ending CRLF
   rval = rval && os->write(CRLF, 2);

   return rval;
}

void HttpHeader::setDate(Date* date)
{
   // get GMT time zone
   TimeZone gmt = TimeZone::getTimeZone("GMT");
   string str;
   const char* format = "%a, %d %b %Y %H:%M:%S GMT";

   if(date == NULL)
   {
      // get current date
      Date now;
      now.format(str, format, "c", &gmt);
   }
   else
   {
      date->format(str, format, "c", &gmt);
   }

   // set date field
   setField("Date", str);
}

bool HttpHeader::getDate(Date& date)
{
   bool rval = false;

   string str;
   if(getField("Date", str))
   {
      // get GMT time zone
      TimeZone gmt = TimeZone::getTimeZone("GMT");
      rval = date.parse(str, "%a, %d %b %Y %H:%M:%S", "c", &gmt);
   }

   return rval;
}

void HttpHeader::biCapitalize(char* name, int* length)
{
   // store start of name
   char* start = name;

   // 97 = 'a', 122 = 'z'
   if(*name > 96 && *name < 123)
   {
      // capitalize letter
      *name -= 32;
   }

   // capitalize letters after hyphens, decapitalize other letters
   name++;
   for(; *name != 0; name++)
   {
      if(*(name - 1) == '-')
      {
         if(*name > 96 && *name < 123)
         {
            // capitalize
            *name -= 32;
         }
      }
      else
      {
         // 65 = 'A', 90 = 'Z'
         if(*name > 64 && *name < 90)
         {
            // decapitalize
            *name += 32;
         }
      }
   }

   // return name length if desired
   if(length != NULL)
   {
      *length = (name - start);
   }
}
<commit_msg>Added bug fix to header field size change, optimization to bicapitalization.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/net/http/HttpHeader.h"

#include "db/util/StringTools.h"

#include <cstdlib>
#include <cstring>

using namespace std;
using namespace db::io;
using namespace db::net::http;
using namespace db::util;

// define CRLF
const char* HttpHeader::CRLF = "\r\n";

HttpHeader::HttpHeader()
{
   mVersion = NULL;
   mFieldsSize = 0;
}

HttpHeader::~HttpHeader()
{
   if(mVersion != NULL)
   {
      free(mVersion);
   }

   for(FieldMap::iterator i = mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }
}

bool HttpHeader::parseStartLine(const char* str, unsigned int length)
{
   // no start line
   return true;
}

void HttpHeader::getStartLine(string& line)
{
   // no start line
   line.erase();
}

bool HttpHeader::hasStartLine()
{
   // no start line
   return false;
}

void HttpHeader::setVersion(const char* version)
{
   if(mVersion != NULL)
   {
      free(mVersion);
   }
   mVersion = strdup(version);
}

const char* HttpHeader::getVersion()
{
   if(mVersion == NULL)
   {
      // default to HTTP/1.1
      mVersion = strdup("HTTP/1.1");
   }

   return mVersion;
}

void HttpHeader::setField(const char* name, long long value)
{
   char temp[25];
   sprintf(temp, "%lli", value);
   setField(name, temp);
}

void HttpHeader::setField(const char* name, const string& value)
{
   // update old field if possible
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      mFieldsSize -= i->second.length();
      i->second = value;
      mFieldsSize += value.length();
   }
   else
   {
      // set new field
      mFieldsSize += strlen(name);
      mFieldsSize += value.length();
      char* fieldName = strdup(name);
      biCapitalize(fieldName, NULL);
      mFields.insert(make_pair(fieldName, value));
   }
}

void HttpHeader::addField(const char* name, const string& value)
{
   // get existing value
   string existing;
   if(getField(name, existing))
   {
      // append to existing value
      existing.append(", ");
   }

   existing.append(value);
   setField(name, existing);
}

void HttpHeader::removeField(const char* name)
{
   // erase field
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      mFieldsSize -= strlen(name);
      mFieldsSize -= i->second.length();
      mFields.erase(i);
   }
}

void HttpHeader::clearFields()
{
   for(FieldMap::iterator i = mFields.begin(); i != mFields.end(); i++)
   {
      free((char*)i->first);
   }

   mFieldsSize = 0;
   mFields.clear();
}

bool HttpHeader::getField(const char* name, long long& value)
{
   bool rval = false;

   string str;
   if(getField(name, str))
   {
      char* endptr = NULL;
      value = strtoll(str.c_str(), &endptr, 10);
      rval = endptr != str.c_str() && *endptr == '\0';
   }

   return rval;
}

bool HttpHeader::getField(const char* name, string& value)
{
   bool rval = false;

   // find field entry
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      // get value
      value = i->second;
      rval = true;
   }

   return rval;
}

bool HttpHeader::hasField(const char* name)
{
   bool rval = false;

   // find field entry
   FieldMap::iterator i = mFields.find(name);
   if(i != mFields.end())
   {
      rval = true;
   }

   return rval;
}

bool HttpHeader::parse(const string& str)
{
   bool rval = false;

   // clear fields
   clearFields();

   bool startLine = hasStartLine();
   const char* start = str.c_str();
   char* cr;
   char* colon;
   while((cr = strchr(start, '\r')) != NULL)
   {
      // look for CRLF
      if(strchr(cr, '\n') == cr + 1)
      {
         if(startLine)
         {
            rval = parseStartLine(start, cr - start);
            startLine = false;
         }
         else
         {
            // found a CRLF, now find colon
            if((colon = strchr(start, ':')) != NULL && colon < cr)
            {
               // get field name
               char name[(colon - start) + 1];
               memcpy(name, start, colon - start);
               name[colon - start] = 0;

               // skip whitespace
               colon++;
               for(; *colon == ' ' && colon < cr; colon++);

               // get field value
               char value[cr - colon + 1];
               strncpy(value, colon, cr - colon);
               value[(cr - colon)] = 0;

               // set field
               setField(name, value);
            }
         }

         start = cr + 2;
      }
      else
      {
         start = cr + 1;
      }
   }

   return rval;
}

string HttpHeader::toString()
{
   string str;
   str.reserve(512);

   // get the start line
   getStartLine(str);

   // determine total fields size:
   // (CRLF + fields size + fields * (": " + CRLF))
   char fields[2 + mFieldsSize + mFields.size() * 4];
   char* s = fields;

   // append CRLF if there is a start line
   if(str.length() > 0)
   {
      s[0] = '\r';
      s[1] = '\n';
      s += 2;
   }

   // append all fields
   int length;
   for(FieldMap::iterator i = mFields.begin(); i != mFields.end(); i++)
   {
      // get field name length
      length = strlen(i->first);

      // append name
      memcpy(s, i->first, length);
      s += length;

      // append delimiter
      s[0] = ':';
      s[1] = ' ';
      s += 2;

      // append value
      memcpy(s, i->second.c_str(), i->second.length());
      s += i->second.length();

      // append CRLF
      s[0] = '\r';
      s[1] = '\n';
      s += 2;
   }

   // add CRLF
   s[0] = '\r';
   s[1] = '\n';
   s += 2;

   // append fields
   str.append(fields, s - fields);

   return str;
}

bool HttpHeader::write(OutputStream* os)
{
   bool rval = true;

   // get the start line
   string line;
   getStartLine(line);

   // write the start line and CRLF if one exists
   if(line.length() > 0)
   {
      rval =
         os->write(line.c_str(), line.length()) &&
         os->write(CRLF, 2);
   }

   // write all fields
   for(FieldMap::iterator i = mFields.begin(); rval && i != mFields.end(); i++)
   {
      // write name, delimiter, value, and CRLF
      rval =
         os->write(i->first, strlen(i->first)) &&
         os->write(": ", 2) &&
         os->write(i->second.c_str(), i->second.length()) &&
         os->write(CRLF, 2);
   }

   // write ending CRLF
   rval = rval && os->write(CRLF, 2);

   return rval;
}

void HttpHeader::setDate(Date* date)
{
   // get GMT time zone
   TimeZone gmt = TimeZone::getTimeZone("GMT");
   string str;
   const char* format = "%a, %d %b %Y %H:%M:%S GMT";

   if(date == NULL)
   {
      // get current date
      Date now;
      now.format(str, format, "c", &gmt);
   }
   else
   {
      date->format(str, format, "c", &gmt);
   }

   // set date field
   setField("Date", str);
}

bool HttpHeader::getDate(Date& date)
{
   bool rval = false;

   string str;
   if(getField("Date", str))
   {
      // get GMT time zone
      TimeZone gmt = TimeZone::getTimeZone("GMT");
      rval = date.parse(str, "%a, %d %b %Y %H:%M:%S", "c", &gmt);
   }

   return rval;
}

void HttpHeader::biCapitalize(char* name, int* length)
{
   // start at beginning of name
   char* ptr = name;

   // 97 = 'a', 122 = 'z'
   if(ptr[0] > 96 && ptr[0] < 123)
   {
      // capitalize letter
      ptr[0] -= 32;
   }

   // capitalize letters after hyphens, decapitalize other letters
   ptr++;
   for(; ptr[0] != 0; ptr++)
   {
      if((ptr - 1)[0] == '-')
      {
         if(ptr[0] > 96 && ptr[0] < 123)
         {
            // capitalize
            ptr[0] -= 32;
         }
      }
      else
      {
         // 65 = 'A', 90 = 'Z'
         if(ptr[0] > 64 && ptr[0] < 90)
         {
            // decapitalize
            ptr[0] += 32;
         }
      }
   }

   // return name length if desired
   if(length != NULL)
   {
      *length = (ptr - name);
   }
}
<|endoftext|>


<commit_before>//compile g++ stats.cpp -std=c++11 -pthread -DLOCAL_ATOMIC -o fast

// atomic::exchange example
#include <iostream>       // std::cout
#include <atomic>         // std::atomic
#include <thread>         // std::thread
#include <vector>         // std::vector
#include <unordered_set>
#include <unordered_map>
#include <mutex>
#include <map>
#include <chrono>
#include "ThreadStorage.h"
#include <stdio.h>      /* printf */
#include <stdarg.h>

/* define  LOCAL_ATOMIC to 1 if you want to test distributed local stats */
//#define LOCAL_ATOMIC 1

void lprint(const char* format, ...)
{

   static  std::mutex _mtx;
    va_list argptr;
    va_start(argptr, format);
    {
      std::lock_guard<std::mutex> lck (_mtx);
      vfprintf(stdout, format, argptr);
    }
    va_end(argptr);

}
class NCA /* no Copy and assignment */
{
      public:
         NCA() {}
      private:
         NCA(NCA const&) = delete;
         NCA& operator=(NCA const&) = delete;
};

class Singleton: public NCA
{
  protected:
    Singleton() {};
  private:

};

enum class StatType
{
  GLOBAL_STATS = 1, /* global stat id, similar to uint32_t globalStat */
  ARRAY_OF_STATS  = 2 /* collection of same stat id with different identifier, like std::vector< {id, counter} > */
};

struct State {
  enum Type {
    NONE = 0,     //< The stat hasn't been changed
    UPDATED = 1,  //< The stat was either incremented or decremented
    SET = 2       //< The stat was set
  };
};

/* all the stats counters must implement from StatCounter */
class StatCounter
{
  public:
     StatCounter()
      : _value(0), _state(State::Type::NONE)
     {}
     StatCounter( const StatCounter& counter)
      : _value(counter.getStatValue()),
        _state(counter.getState())
     {
     }
     StatCounter& operator=(const StatCounter& other)
     {
       if (this == &other) return *this;
       _value = other.getStatValue();
        _state = other.getState();
       return *this;
     }
     StatCounter& operator+=(StatCounter& other)
     {
       if (this != &other)
       {
          // lprint("%ld BEFORE += total statId: %ld, new: %ld\n",pthread_self(), getStatValue(), other.getStatValue());
         _state = other.getState();
         _value.fetch_add(other._value);
         //lprint("%ld AFTRE += total statId: %ld\n",pthread_self(), getStatValue());
       }
       return *this;
     }
     void copyAndReset(StatCounter& other)
     {
       if (this != &other)
       {
         _state = other.getState();
         _value =+ other.reset();
       }
     }
     void inc(uint64_t val) { _value+= val; _state =State::UPDATED; }
     void dec(uint64_t val) { _value-= val ;_state =State::UPDATED; }
     void set(uint64_t val) { _value = val ; _state =State::SET; }
     //TODO, ASH we need to reset instead of just get value
     uint64_t reset() { _state = State::NONE; return _value.exchange(0); }
     //uint64_t reset() { _state = State::NONE; return getStatValue(); }
     uint64_t getStatValue() const  { return _value.load(std::memory_order_relaxed); }
     State::Type getState() const { return _state; }
   protected:
     std::atomic<uint64_t> _value;
     State::Type _state;
};

/* StatsMap is a singleton globals  stats structure used by collector to collect and local variables to register */
class StatsMap
{

    public:
     StatsMap() : _usable(true)
     {
        //lprint("%ld:%p Ctr called\n", pthread_self(), this);
     }
     ~StatsMap()
     {
        //lprint("%ld:%p Dtr called\n", pthread_self(), this);
     }
     StatsMap(const StatsMap& other)
      : _usable(other.isUsable())
      , _statsIds(other.getStatsMap())
     {
        //lprint("%ld:%p CopyCtr called\n", pthread_self(), this);
     }
     StatsMap(StatsMap&& other)
      : _usable(other.isUsable())
      , _statsIds(std::move(other.getStatsMap()))
     {
        //lprint("%ld:%p MoveCtr called\n", pthread_self(), this);
     }
     StatsMap& operator=(StatsMap&& other) noexcept
     {
        //lprint("%ld:%p MoveOpreator called\n", pthread_self(), this);
        if (this != &other)
        {
          this->_statsIds = std::move(other.getStatsMap());
          this->_usable = other.isUsable();
        }
        return *this;
     }
     StatsMap& operator+=(StatsMap& stats)
     {
        uint64_t totalStats = 0;
        for(auto& stat: stats.getStatsMap())
        {
           StatCounter& current = getStats(stat.first);
           //lprint("%ld BEFORE += total statId: %ld, new: %ld\n",pthread_self(), current.getStatValue(), stat.second.getStatValue());
           current += stat.second;
           //lprint("%ld AFTER += total statId: %ld, \n",pthread_self(), current.getStatValue());
           totalStats += current.getStatValue();
        }
        //lprint("%ld OP += total statId: %d, Total value: %ld \n",pthread_self(), _statsIds.size(), totalStats;
        return *this;
     }
     void copyAndResetStats(StatsMap& stats)
     {
        uint64_t totalStats = 0;
        for(auto& stat: stats.getStatsMap())
        {
           StatCounter& current = getStats(stat.first);
           current.copyAndReset(stat.second);
           //current += stat.second;
           totalStats += current.getStatValue();
        }
        //lprint("%ld OP += total statId: %d, Total value: %ld \n",pthread_self(), _statsIds.size(), totalStats);
     }
     void print()
     {
        uint64_t totalStats = 0;
        for(auto& stat: _statsIds)
        {
           uint64_t value = stat.second.getStatValue();
           totalStats += value;
           //std::cout<<"statId: "<<stat.first<< "value: "<< value<<std::endl;

        }
        lprint("%ld STATS MAP: total statId: %d, Total value: %ld \n",pthread_self(), _statsIds.size(), totalStats);
     }
     void set(uint64_t key, uint64_t val = 0) { StatCounter& stat = getStats(key); stat.set(val);}
     void inc(uint64_t key, uint64_t val = 1) { StatCounter& stat = getStats(key); stat.inc(val );}
     void dec(uint64_t key, uint64_t val = -1) { StatCounter& stat = getStats(key); stat.dec(val );}
     StatCounter& getStats(uint64_t key) { return _statsIds[key];};
     bool isUsable() const { return _usable; }
     void setUnusable() { _usable = false; }
     std::unordered_map<uint64_t, StatCounter>& getStatsMap() { return _statsIds;}
     const std::unordered_map<uint64_t, StatCounter>& getStatsMap() const { return _statsIds;}
    protected:
      bool _usable;
      std::unordered_map<uint64_t, StatCounter> _statsIds;

};

/* ThreadStatsMapContainer is a singleton globals  stats structure used by collector to collect and local variables to register */
class ThreadStatsMapContainer : public Singleton
{
   public:
      __attribute__((noinline)) StatsMap aggregate()
      {
        //std::cout<<pthread_self()<<" enetring aggregatep"<<std::endl;
        StatsMap statsAggr;
        //lprint("%ld:%p Created Aggr Stats Map\n",pthread_self(), &statsAggr);
        std::lock_guard<std::mutex> lck (_mtx);
        auto it = _statsMap.begin();
        auto end = _statsMap.end();
        while(it != end)
        {
           statsAggr.copyAndResetStats(it->second);
           if(!it->second.isUsable())
           {
             //lprint("%ld:%p Aggr deleting stats map\n",pthread_self(), &(it->second));
              _statsMap.erase(it++);
           }
           else
           {
             ++it;
           }

        }
        //lprint("%ld returning from aggr \n",pthread_self());
        return std::move(statsAggr);
     }

      __attribute__((noinline)) void del()
      {
        lprint("%ld in delete statsmap\n",pthread_self());
        StatsMap* statsCntr  = _statsTLS.data();
        if(statsCntr)
        {
           statsCntr->setUnusable();
           lprint("%ld object: %p is unusable\n" ,pthread_self(), statsCntr);
        }
        //std::cout<<pthread_self()<<" exiting del"<<std::endl;
      }
      __attribute__((noinline)) StatsMap* createStats()
      {
        lprint("%ld in create statsmap\n" ,pthread_self());
        std::lock_guard<std::mutex> lck (_mtx);
        StatsMap& stat = _statsMap[pthread_self()];
        //lprint("%ld:%p Created statsMap\n",pthread_self(), &stat);
        //std::cout<<pthread_self()<<": Created new StatsMap size: "<<_statsMap.size()<<std::endl;
        return &stat;
      }
      static ThreadStatsMapContainer& getInstance()
      {
            static ThreadStatsMapContainer instance;
            return instance;
      }
    static StatsMap& getStatsCtxt()
    {
        StatsMap* statsCntr  = _statsTLS.data();
        if(nullptr == statsCntr)
        {
            lprint("%ld createing a new TLS \n" ,pthread_self());
            statsCntr =  getInstance().createStats();
            _statsTLS.data(statsCntr);
        }
        return *statsCntr;
    }
    static void i_set(uint64_t key, uint64_t val) {getStatsCtxt().set(key,val) ;};
    static void i_increment(uint64_t key, uint64_t val){getStatsCtxt().inc(key,val); };
    static void i_decrement(uint64_t key, uint64_t val) {getStatsCtxt().dec(key,val); };

      struct ThreadDestructor
      {
      public:
          void operator ()(StatsMap* value) {
              lprint("%ld IN ThreadDestructor \n" ,pthread_self());
              ThreadStatsMapContainer::getInstance().del();
          }
      };
    protected:
      std::unordered_map<pthread_t, StatsMap> _statsMap;
      std::mutex _mtx;
      static ThreadStorage<StatsMap*, ThreadDestructor>  _statsTLS;
};

ThreadStorage<StatsMap*, ThreadStatsMapContainer::ThreadDestructor> ThreadStatsMapContainer::_statsTLS;

//TEST code starts here
//testing
/*
 * all thread waits until it is ready object. stats are incremented once this value is set to true.
 * collector signals thread to stop incrementing counter by sresetting ready value;
 */
bool ready = false;
//dumpCollectedStats - collector starts dumping aggregated stats to console
bool dumpCollectedStats = false;

//collectstats - start collecting stats and print aggregated values
void collectstats()
{
   StatsMap aggr;
   lprint("%ld:%p Collect Stats\n",pthread_self(), &aggr);
   uint32_t maxcount = 15;
   while(!ready) {}
   while(maxcount--)
   {
     /* fetch stats every 1 second */
     std::this_thread::sleep_for(std::chrono::seconds(1));
     StatsMap stats = ThreadStatsMapContainer::getInstance().aggregate();
     aggr+= stats;
     //aggr.print();
   }
   ready = false;
   //std::cout << "Enering Final collection \n";
   while(!dumpCollectedStats) {} //wait for all threads to finish
   StatsMap stats = ThreadStatsMapContainer::getInstance().aggregate();
   aggr+= stats;

   aggr.print();
   //std::cout << "Exiting collector \n";

}

uint64_t globalCount = 0;
//golbalStatFunc - increment global variables
void golbalStatFunc (int threadid, int id) {

  int64_t count = 0;
  while (!ready) {} // wait for the ready signal
  //lprint("%d Thread: %d started Race \n" ,pthread_self(), threadid);
  while(ready) //increment stats until it is ready
  {
    //std::cout <<threadid<<" ready : "<<ready<<std::endl;
    int64_t start = id*25;
    int64_t end = start+25;
    for(;start<end;++start)
    {
          ThreadStatsMapContainer::i_increment(start, 1);
          ++count;
    }
    //std::this_thread::sleep_for(std::chrono::seconds(1));
  }
  lprint("%d Thread: %d executed INC : %d  times \n" ,pthread_self(), threadid, count);
   static  std::mutex _gmtx;
   std::lock_guard<std::mutex> lck (_gmtx);
   globalCount += count;
};

//to test performance set macro LOCAL_ATOMIC to 0 for global stats  and 1  for localized stats
int main ()
{
  //lprint("pawning global threads \n" ,);
  std::vector<std::thread> globalStatsThreads;
  //for (int i=1; i<=2; ++i) globalStatsThreads.push_back(std::thread(golbalStatFunc,i, i%2));
  for (int i=0; i<4; ++i) globalStatsThreads.push_back(std::thread(golbalStatFunc,i, i));//last param is statid

  //start collector thread
  std::thread collector (collectstats);

  std::this_thread::sleep_for(std::chrono::seconds(1));
  auto start = std::chrono::high_resolution_clock::now();
  ready = true; //lets start the race

  //wait for all gloabl threads
  for (auto& th : globalStatsThreads) { th.join(); }
  //std::cout << "completed global join  \n";

  //wait for all collection threads

  auto end = std::chrono::high_resolution_clock::now();
  std::chrono::duration<double, std::milli> elapsed = end-start;
  std::cout << "Waited " << elapsed.count() << " ms\n";

  //its the time for display data
  dumpCollectedStats = true;

  //now wait for collector thread
  collector.join();
  std::cout<<globalCount<<" number of stats incremented in "<<elapsed.count() << " ms\n";
  //std::cout << "completed collector join  \n";
}

<commit_msg>StatsMap was not deleting when thread exit, fixed it<commit_after>//compile g++ stats.cpp -std=c++11 -pthread -DLOCAL_ATOMIC -o fast

// atomic::exchange example
#include <iostream>       // std::cout
#include <atomic>         // std::atomic
#include <thread>         // std::thread
#include <vector>         // std::vector
#include <unordered_set>
#include <unordered_map>
#include <mutex>
#include <map>
#include <chrono>
#include "ThreadStorage.h"
#include <stdio.h>      /* printf */
#include <stdarg.h>

/* define  LOCAL_ATOMIC to 1 if you want to test distributed local stats */
//#define LOCAL_ATOMIC 1

void lprint(const char* format, ...)
{

   static  std::mutex _mtx;
    va_list argptr;
    va_start(argptr, format);
    {
      std::lock_guard<std::mutex> lck (_mtx);
      vfprintf(stdout, format, argptr);
    }
    va_end(argptr);

}
class NCA /* no Copy and assignment */
{
      public:
         NCA() {}
      private:
         NCA(NCA const&) = delete;
         NCA& operator=(NCA const&) = delete;
};

class Singleton: public NCA
{
  protected:
    Singleton() {};
  private:

};

enum class StatType
{
  GLOBAL_STATS = 1, /* global stat id, similar to uint32_t globalStat */
  ARRAY_OF_STATS  = 2 /* collection of same stat id with different identifier, like std::vector< {id, counter} > */
};

struct State {
  enum Type {
    NONE = 0,     //< The stat hasn't been changed
    UPDATED = 1,  //< The stat was either incremented or decremented
    SET = 2       //< The stat was set
  };
};

/* all the stats counters must implement from StatCounter */
class StatCounter
{
  public:
     StatCounter()
      : _value(0), _state(State::Type::NONE)
     {}
     StatCounter( const StatCounter& counter)
      : _value(counter.getStatValue()),
        _state(counter.getState())
     {
     }
     StatCounter& operator=(const StatCounter& other)
     {
       if (this == &other) return *this;
       _value = other.getStatValue();
        _state = other.getState();
       return *this;
     }
     StatCounter& operator+=(StatCounter& other)
     {
       if (this != &other)
       {
          // lprint("%ld BEFORE += total statId: %ld, new: %ld\n",pthread_self(), getStatValue(), other.getStatValue());
         _state = other.getState();
         _value.fetch_add(other._value);
         //lprint("%ld AFTRE += total statId: %ld\n",pthread_self(), getStatValue());
       }
       return *this;
     }
     void copyAndReset(StatCounter& other)
     {
       if (this != &other)
       {
         _state = other.getState();
         _value =+ other.reset();
       }
     }
     void inc(uint64_t val) { _value+= val; _state =State::UPDATED; }
     void dec(uint64_t val) { _value-= val ;_state =State::UPDATED; }
     void set(uint64_t val) { _value = val ; _state =State::SET; }
     //TODO, ASH we need to reset instead of just get value
     uint64_t reset() { _state = State::NONE; return _value.exchange(0); }
     //uint64_t reset() { _state = State::NONE; return getStatValue(); }
     uint64_t getStatValue() const  { return _value.load(std::memory_order_relaxed); }
     State::Type getState() const { return _state; }
   protected:
     std::atomic<uint64_t> _value;
     State::Type _state;
};

/* StatsMap is a singleton globals  stats structure used by collector to collect and local variables to register */
class StatsMap
{

    public:
     StatsMap() : _usable(true)
     {
        //lprint("%ld:%p Ctr called\n", pthread_self(), this);
     }
     ~StatsMap()
     {
        //lprint("%ld:%p Dtr called\n", pthread_self(), this);
     }
     StatsMap(const StatsMap& other)
      : _usable(other.isUsable())
      , _statsIds(other.getStatsMap())
     {
        //lprint("%ld:%p CopyCtr called\n", pthread_self(), this);
     }
     StatsMap(StatsMap&& other)
      : _usable(other.isUsable())
      , _statsIds(std::move(other.getStatsMap()))
     {
        //lprint("%ld:%p MoveCtr called\n", pthread_self(), this);
     }
     StatsMap& operator=(StatsMap&& other) noexcept
     {
        //lprint("%ld:%p MoveOpreator called\n", pthread_self(), this);
        if (this != &other)
        {
          this->_statsIds = std::move(other.getStatsMap());
          this->_usable = other.isUsable();
        }
        return *this;
     }
     StatsMap& operator+=(StatsMap& stats)
     {
        uint64_t totalStats = 0;
        for(auto& stat: stats.getStatsMap())
        {
           StatCounter& current = getStats(stat.first);
           //lprint("%ld BEFORE += total statId: %ld, new: %ld\n",pthread_self(), current.getStatValue(), stat.second.getStatValue());
           current += stat.second;
           //lprint("%ld AFTER += total statId: %ld, \n",pthread_self(), current.getStatValue());
           totalStats += current.getStatValue();
        }
        //lprint("%ld OP += total statId: %d, Total value: %ld \n",pthread_self(), _statsIds.size(), totalStats;
        return *this;
     }
     void copyAndResetStats(StatsMap& stats)
     {
        uint64_t totalStats = 0;
        for(auto& stat: stats.getStatsMap())
        {
           StatCounter& current = getStats(stat.first);
           current.copyAndReset(stat.second);
           //current += stat.second;
           totalStats += current.getStatValue();
        }
        //lprint("%ld OP += total statId: %d, Total value: %ld \n",pthread_self(), _statsIds.size(), totalStats);
     }
     void print()
     {
        uint64_t totalStats = 0;
        for(auto& stat: _statsIds)
        {
           uint64_t value = stat.second.getStatValue();
           totalStats += value;
           //std::cout<<"statId: "<<stat.first<< "value: "<< value<<std::endl;

        }
        lprint("%ld STATS MAP: total statId: %d, Total value: %ld \n",pthread_self(), _statsIds.size(), totalStats);
     }
     void set(uint64_t key, uint64_t val = 0) { StatCounter& stat = getStats(key); stat.set(val);}
     void inc(uint64_t key, uint64_t val = 1) { StatCounter& stat = getStats(key); stat.inc(val );}
     void dec(uint64_t key, uint64_t val = -1) { StatCounter& stat = getStats(key); stat.dec(val );}
     StatCounter& getStats(uint64_t key) { return _statsIds[key];};
     bool isUsable() const { return _usable; }
     void setUnusable() { _usable = false; }
     std::unordered_map<uint64_t, StatCounter>& getStatsMap() { return _statsIds;}
     const std::unordered_map<uint64_t, StatCounter>& getStatsMap() const { return _statsIds;}
    protected:
      bool _usable;
      std::unordered_map<uint64_t, StatCounter> _statsIds;

};

/* ThreadStatsMapContainer is a singleton globals  stats structure used by collector to collect and local variables to register */
class ThreadStatsMapContainer : public Singleton
{
   public:
      __attribute__((noinline)) StatsMap aggregate()
      {
        //std::cout<<pthread_self()<<" enetring aggregatep"<<std::endl;
        StatsMap statsAggr;
        //lprint("%ld:%p Created Aggr Stats Map\n",pthread_self(), &statsAggr);
        std::lock_guard<std::mutex> lck (_mtx);
        auto it = _statsMap.begin();
        auto end = _statsMap.end();
        while(it != end)
        {
           statsAggr.copyAndResetStats(it->second);
           if(!it->second.isUsable())
           {
             lprint("%ld:%p Aggr deleting stats map\n",pthread_self(), &(it->second));
              _statsMap.erase(it++);
           }
           else
           {
             ++it;
           }

        }
        //lprint("%ld returning from aggr \n",pthread_self());
        return std::move(statsAggr);
     }

      __attribute__((noinline)) StatsMap* createStats()
      {
        lprint("%ld in create statsmap\n" ,pthread_self());
        std::lock_guard<std::mutex> lck (_mtx);
        StatsMap& stat = _statsMap[pthread_self()];
        //lprint("%ld:%p Created statsMap\n",pthread_self(), &stat);
        //std::cout<<pthread_self()<<": Created new StatsMap size: "<<_statsMap.size()<<std::endl;
        return &stat;
      }
      static ThreadStatsMapContainer& getInstance()
      {
            static ThreadStatsMapContainer instance;
            return instance;
      }
    static StatsMap& getStatsCtxt()
    {
        StatsMap* statsCntr  = _statsTLS.data();
        if(nullptr == statsCntr)
        {
            lprint("%ld createing a new TLS \n" ,pthread_self());
            statsCntr =  getInstance().createStats();
            _statsTLS.data(statsCntr);
        }
        return *statsCntr;
    }
    static void i_set(uint64_t key, uint64_t val) {getStatsCtxt().set(key,val) ;};
    static void i_increment(uint64_t key, uint64_t val){getStatsCtxt().inc(key,val); };
    static void i_decrement(uint64_t key, uint64_t val) {getStatsCtxt().dec(key,val); };

      struct ThreadDestructor
      {
      public:
          void operator ()(StatsMap* value) {
              lprint("%ld IN ThreadDestructor \n" ,pthread_self());
              value->setUnusable();
          }
      };
    protected:
      std::unordered_map<pthread_t, StatsMap> _statsMap;
      std::mutex _mtx;
      static ThreadStorage<StatsMap*, ThreadDestructor>  _statsTLS;
};

ThreadStorage<StatsMap*, ThreadStatsMapContainer::ThreadDestructor> ThreadStatsMapContainer::_statsTLS;

//TEST code starts here
//testing
/*
 * all thread waits until it is ready object. stats are incremented once this value is set to true.
 * collector signals thread to stop incrementing counter by sresetting ready value;
 */
bool ready = false;
//dumpCollectedStats - collector starts dumping aggregated stats to console
bool dumpCollectedStats = false;

//collectstats - start collecting stats and print aggregated values
void collectstats()
{
   StatsMap aggr;
   lprint("%ld:%p Collect Stats\n",pthread_self(), &aggr);
   uint32_t maxcount = 15;
   while(!ready) {}
   while(maxcount--)
   {
     /* fetch stats every 1 second */
     std::this_thread::sleep_for(std::chrono::seconds(1));
     StatsMap stats = ThreadStatsMapContainer::getInstance().aggregate();
     aggr+= stats;
     //aggr.print();
   }
   ready = false;
   //std::cout << "Enering Final collection \n";
   while(!dumpCollectedStats) {} //wait for all threads to finish
   StatsMap stats = ThreadStatsMapContainer::getInstance().aggregate();
   aggr+= stats;

   aggr.print();
   //std::cout << "Exiting collector \n";

}

uint64_t globalCount = 0;
//golbalStatFunc - increment global variables
void golbalStatFunc (int threadid, int id) {

  int64_t count = 0;
  while (!ready) {} // wait for the ready signal
  //lprint("%d Thread: %d started Race \n" ,pthread_self(), threadid);
  while(ready) //increment stats until it is ready
  {
    //std::cout <<threadid<<" ready : "<<ready<<std::endl;
    int64_t start = id*100;
    int64_t end = start+100;
    for(;start<end;++start)
    {
          ThreadStatsMapContainer::i_increment(start, 1);
          ++count;
    }
    //std::this_thread::sleep_for(std::chrono::seconds(1));
  }
  lprint("%d Thread: %d executed INC : %d  times \n" ,pthread_self(), threadid, count);
   static  std::mutex _gmtx;
   std::lock_guard<std::mutex> lck (_gmtx);
   globalCount += count;
};

//to test performance set macro LOCAL_ATOMIC to 0 for global stats  and 1  for localized stats
int main ()
{
  //lprint("pawning global threads \n" ,);
  std::vector<std::thread> globalStatsThreads;
  //for (int i=1; i<=2; ++i) globalStatsThreads.push_back(std::thread(golbalStatFunc,i, i%2));
  for (int i=0; i<4; ++i) globalStatsThreads.push_back(std::thread(golbalStatFunc,i, i));//last param is statid

  //start collector thread
  std::thread collector (collectstats);

  std::this_thread::sleep_for(std::chrono::seconds(1));
  auto start = std::chrono::high_resolution_clock::now();
  ready = true; //lets start the race

  //wait for all gloabl threads
  for (auto& th : globalStatsThreads) { th.join(); }
  //std::cout << "completed global join  \n";

  //wait for all collection threads

  auto end = std::chrono::high_resolution_clock::now();
  std::chrono::duration<double, std::milli> elapsed = end-start;
  std::cout << "Waited " << elapsed.count() << " ms\n";

  //its the time for display data
  dumpCollectedStats = true;

  //now wait for collector thread
  collector.join();
  std::cout<<globalCount<<" number of stats incremented in "<<elapsed.count() << " ms\n";
  //std::cout << "completed collector join  \n";
}

<|endoftext|>


<commit_before>// Copyright (c) 2008 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.

// This command-line program dumps the contents of a set of cache files, either
// to stdout or to another set of cache files.

#include <stdio.h>
#include <string>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/process_util.h"
#include "base/scoped_handle.h"
#include "base/string_util.h"

#include "net/disk_cache/disk_format.h"

enum Errors {
  GENERIC = -1,
  ALL_GOOD = 0,
  INVALID_ARGUMENT = 1,
  FILE_ACCESS_ERROR,
  UNKNOWN_VERSION,
  TOOL_NOT_FOUND,
};

int GetMajorVersion(const std::wstring input_path);
int DumpContents(const std::wstring input_path);
int DumpHeaders(const std::wstring input_path);
int RunSlave(const std::wstring input_path, const std::wstring pipe_number);
int Upgrade(const std::wstring output_path, HANDLE pipe);
HANDLE CreateServer(std::wstring* pipe_number);

const char kUpgradeHelp[] =
    "\nIn order to use the upgrade function, a version of this tool that\n"
    "understands the file format of the files to upgrade is needed. For\n"
    "instance, to upgrade files saved with file format 3.4 to version 5.2,\n"
    "a version of this program that was compiled with version 3.4 has to be\n"
    "located beside this executable, and named dump_cache_3.exe, and this\n"
    "executable should be compiled with version 5.2 being the current one.";

// Folders to read and write cache files.
const wchar_t kInputPath[] = L"input";
const wchar_t kOutputPath[] = L"output";

// Dumps the file headers to stdout.
const wchar_t kDumpHeaders[] = L"dump-headers";

// Dumps all entries to stdout.
const wchar_t kDumpContents[] = L"dump-contents";

// Upgrade an old version to the current one.
const wchar_t kUpgrade[] = L"upgrade";

// Internal use:
const wchar_t kSlave[] = L"slave";
const wchar_t kPipe[] = L"pipe";

int Help() {
  printf("warning: input files are modified by this tool\n");
  printf("dump_cache --input=path1 [--output=path2]\n");
  printf("--dump-headers: display file headers\n");
  printf("--dump-contents: display all entries\n");
  printf("--upgrade: copy contents to the output path\n");
  return INVALID_ARGUMENT;
}

// Starts a new process, to generate the files.
int LaunchSlave(const CommandLine &command_line, const std::wstring pipe_number,
                int version) {
  std::wstring new_command_line = command_line.command_line_string();
  const std::wstring old_exe(L"dump_cache.exe");
  size_t to_remove = new_command_line.find(old_exe);
  new_command_line.erase(to_remove, old_exe.size());

  std::wstring new_program = StringPrintf(L"%ls%d.exe", L"dump_cache_",
                                          version);
  new_command_line.insert(to_remove, new_program);
  if (command_line.HasSwitch(kUpgrade))
    CommandLine::AppendSwitch(&new_command_line, kSlave);

  CommandLine::AppendSwitchWithValue(&new_command_line, kPipe, pipe_number);
  if (!base::LaunchApp(new_command_line, false, false, NULL)) {
    printf("Unable to launch the needed version of this tool: %ls\n",
           new_program.c_str());
    printf(kUpgradeHelp);
    return TOOL_NOT_FOUND;
  }
  return ALL_GOOD;
}

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

int main(int argc, const char* argv[]) {
  // Setup an AtExitManager so Singleton objects will be destroyed.
  base::AtExitManager at_exit_manager;

  CommandLine command_line;
  std::wstring input_path = command_line.GetSwitchValue(kInputPath);
  if (input_path.empty())
    return Help();

  bool upgrade = false;
  bool slave_required = false;
  std::wstring output_path;
  if (command_line.HasSwitch(kUpgrade)) {
    output_path = command_line.GetSwitchValue(kOutputPath);
    if (output_path.empty())
      return Help();
    slave_required = true;
    upgrade = true;
  }

  int version = GetMajorVersion(input_path);
  if (!version)
    return FILE_ACCESS_ERROR;

  if (version != disk_cache::kCurrentVersion >> 16) {
    if (command_line.HasSwitch(kSlave)) {
      printf("Unknown version\n");
      return UNKNOWN_VERSION;
    }
    slave_required = true;
  }

  std::wstring pipe_number = command_line.GetSwitchValue(kPipe);
  if (command_line.HasSwitch(kSlave) && slave_required)
    return RunSlave(input_path, pipe_number);

  ScopedHandle server;
  if (slave_required) {
    server.Set(CreateServer(&pipe_number));
    if (!server.IsValid()) {
      printf("Unable to create the server pipe\n");
      return -1;
    }

    int ret = LaunchSlave(command_line, pipe_number, version);
    if (ret)
      return ret;
  }

  if (upgrade)
    return Upgrade(output_path, server);

  if (slave_required) {
    // Wait until the slave starts dumping data before we quit. Lazy "fix" for a
    // console quirk.
    Sleep(500);
    return ALL_GOOD;
  }

  if (command_line.HasSwitch(kDumpContents))
    return DumpContents(input_path);
  if (command_line.HasSwitch(kDumpHeaders))
    return DumpHeaders(input_path);
  return Help();
}

<commit_msg>Fix dump_cache build.<commit_after>// Copyright (c) 2008 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.

// This command-line program dumps the contents of a set of cache files, either
// to stdout or to another set of cache files.

#include <stdio.h>
#include <string>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/process_util.h"
#include "base/scoped_handle.h"
#include "base/string_util.h"

#include "net/disk_cache/disk_format.h"

enum Errors {
  GENERIC = -1,
  ALL_GOOD = 0,
  INVALID_ARGUMENT = 1,
  FILE_ACCESS_ERROR,
  UNKNOWN_VERSION,
  TOOL_NOT_FOUND,
};

int GetMajorVersion(const std::wstring input_path);
int DumpContents(const std::wstring input_path);
int DumpHeaders(const std::wstring input_path);
int RunSlave(const std::wstring input_path, const std::wstring pipe_number);
int Upgrade(const std::wstring output_path, HANDLE pipe);
HANDLE CreateServer(std::wstring* pipe_number);

const char kUpgradeHelp[] =
    "\nIn order to use the upgrade function, a version of this tool that\n"
    "understands the file format of the files to upgrade is needed. For\n"
    "instance, to upgrade files saved with file format 3.4 to version 5.2,\n"
    "a version of this program that was compiled with version 3.4 has to be\n"
    "located beside this executable, and named dump_cache_3.exe, and this\n"
    "executable should be compiled with version 5.2 being the current one.";

// Folders to read and write cache files.
const wchar_t kInputPath[] = L"input";
const wchar_t kOutputPath[] = L"output";

// Dumps the file headers to stdout.
const wchar_t kDumpHeaders[] = L"dump-headers";

// Dumps all entries to stdout.
const wchar_t kDumpContents[] = L"dump-contents";

// Upgrade an old version to the current one.
const wchar_t kUpgrade[] = L"upgrade";

// Internal use:
const wchar_t kSlave[] = L"slave";
const wchar_t kPipe[] = L"pipe";

int Help() {
  printf("warning: input files are modified by this tool\n");
  printf("dump_cache --input=path1 [--output=path2]\n");
  printf("--dump-headers: display file headers\n");
  printf("--dump-contents: display all entries\n");
  printf("--upgrade: copy contents to the output path\n");
  return INVALID_ARGUMENT;
}

// Starts a new process, to generate the files.
int LaunchSlave(const CommandLine& command_line, const std::wstring pipe_number,
                int version) {
  // TODO(port): remove this string-munging hackery.
  std::wstring hacked_command_line = command_line.command_line_string();
  const std::wstring old_exe(L"dump_cache.exe");
  size_t to_remove = hacked_command_line.find(old_exe);
  hacked_command_line.erase(to_remove, old_exe.size());

  std::wstring new_program = StringPrintf(L"%ls%d.exe", L"dump_cache_",
                                          version);
  hacked_command_line.insert(to_remove, new_program);

  CommandLine new_command_line(L"");
  new_command_line.ParseFromString(hacked_command_line);

  if (command_line.HasSwitch(kUpgrade))
    new_command_line.AppendSwitch(kSlave);

  new_command_line.AppendSwitchWithValue(kPipe, pipe_number);
  if (!base::LaunchApp(new_command_line, false, false, NULL)) {
    printf("Unable to launch the needed version of this tool: %ls\n",
           new_program.c_str());
    printf(kUpgradeHelp);
    return TOOL_NOT_FOUND;
  }
  return ALL_GOOD;
}

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

int main(int argc, const char* argv[]) {
  // Setup an AtExitManager so Singleton objects will be destroyed.
  base::AtExitManager at_exit_manager;

  CommandLine::Init(argc, argv);

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  std::wstring input_path = command_line.GetSwitchValue(kInputPath);
  if (input_path.empty())
    return Help();

  bool upgrade = false;
  bool slave_required = false;
  std::wstring output_path;
  if (command_line.HasSwitch(kUpgrade)) {
    output_path = command_line.GetSwitchValue(kOutputPath);
    if (output_path.empty())
      return Help();
    slave_required = true;
    upgrade = true;
  }

  int version = GetMajorVersion(input_path);
  if (!version)
    return FILE_ACCESS_ERROR;

  if (version != disk_cache::kCurrentVersion >> 16) {
    if (command_line.HasSwitch(kSlave)) {
      printf("Unknown version\n");
      return UNKNOWN_VERSION;
    }
    slave_required = true;
  }

  std::wstring pipe_number = command_line.GetSwitchValue(kPipe);
  if (command_line.HasSwitch(kSlave) && slave_required)
    return RunSlave(input_path, pipe_number);

  ScopedHandle server;
  if (slave_required) {
    server.Set(CreateServer(&pipe_number));
    if (!server.IsValid()) {
      printf("Unable to create the server pipe\n");
      return -1;
    }

    int ret = LaunchSlave(command_line, pipe_number, version);
    if (ret)
      return ret;
  }

  if (upgrade)
    return Upgrade(output_path, server);

  if (slave_required) {
    // Wait until the slave starts dumping data before we quit. Lazy "fix" for a
    // console quirk.
    Sleep(500);
    return ALL_GOOD;
  }

  if (command_line.HasSwitch(kDumpContents))
    return DumpContents(input_path);
  if (command_line.HasSwitch(kDumpHeaders))
    return DumpHeaders(input_path);
  return Help();
}

<|endoftext|>