<commit_before>/*
 * semilinSetExp.cpp
 *
 *  Created on: 20.09.2012
 *      Author: maxi
 */

#include <algorithm>
#include <cassert>

#include "semilinSetExp.h"

// adding two Var-maps componentwise... could be put in a util-class ?
VecSparse operator+(const VecSparse& a, const VecSparse& b) {
	VecSparse result = a;
	for(VecSparse::const_iterator it = b.begin(); it!=b.end(); ++it) {
		if(result.count(it->first) > 0)
			result[it->first] += it->second;
		else
			result[it->first] = it->second;
	}

    return result;
}

LinSet operator * (const LinSet& ls1, const LinSet& ls2) {
	//assert(!ls1.empty() && !ls2.empty());

	//union on the generators
	std::set<VecSparse> gens;
	std::insert_iterator<std::set<VecSparse> > it(gens, gens.begin());
	set_union(ls1.second.begin(), ls1.second.end(), ls2.second.begin(), ls2.second.end(), it);

	LinSet result;

	//add the offsets
	result.first = ls1.first + ls2.first;
	result.second = gens;
	return result;
}

std::ostream& operator<<(std::ostream& os, const VecSparse& v) {
	os << "<";
    for (typename std::map<VarPtr, unsigned int>::const_iterator it = v.begin(); it != v.end(); ++it)
    {
        os << it->first << ":" << it->second << ", ";
    }
    os << ">";
    return os;
}

std::ostream& operator<<(std::ostream& os, const LinSet& ls) {
	os << ls.first;

	for(std::set<VecSparse>::const_iterator it_veclist = ls.second.begin(); it_veclist != ls.second.end(); ++it_veclist) {
		os << "+" << *it_veclist;
	}
    return os;
}

SemilinSetExp::SemilinSetExp() {
	this->val = std::set<LinSet>();
}

SemilinSetExp::SemilinSetExp(VarPtr var) {
	this->val = std::set<LinSet>();
	LinSet ls = LinSet();
	VecSparse offset;
	offset.insert(std::make_pair(var, 1));
	ls.first = offset;
	ls.second = std::set<VecSparse>();
	this->val.insert(ls);
}

SemilinSetExp::SemilinSetExp(std::set<LinSet> val) {
	this->val = std::set<LinSet>(val.begin(),val.end());
}

SemilinSetExp::~SemilinSetExp() {
	// do NOT delete static pointers!!!
}

SemilinSetExp SemilinSetExp::null() {
	if(!SemilinSetExp::elem_null)
		SemilinSetExp::elem_null = std::shared_ptr<SemilinSetExp>(new SemilinSetExp(std::set<LinSet>()));
	return *SemilinSetExp::elem_null;
}

SemilinSetExp SemilinSetExp::one() {
	if(!SemilinSetExp::elem_one) {
		std::set<LinSet> elone = std::set<LinSet>();
		LinSet ls = LinSet();
		ls.first = VecSparse();
		ls.second = std::set<VecSparse>();
		elone.insert(ls);
		SemilinSetExp::elem_one = std::shared_ptr<SemilinSetExp>(new SemilinSetExp(elone));
	}
	return *SemilinSetExp::elem_one;
}

SemilinSetExp SemilinSetExp::operator += (const SemilinSetExp& sl) {
	std::set<LinSet> result;

	std::insert_iterator<std::set<LinSet> > it(result, result.begin());
	std::set_union(this->val.begin(),this->val.end(),sl.val.begin(),sl.val.end(),it);

	*this = SemilinSetExp(result);
	return *this;
}

SemilinSetExp SemilinSetExp::operator *= (const SemilinSetExp& sl) {
	std::set<LinSet> result;
	for(std::set<LinSet>::const_iterator it_arg = sl.val.begin(); it_arg != sl.val.end(); ++it_arg) {
		for(std::set<LinSet>::const_iterator it_m = this->val.begin(); it_m != this->val.end(); ++it_m) {
					result.insert((*it_arg) * (*it_m));
		}
	}
	*this = SemilinSetExp(result);
	return *this;
}

std::set<LinSet> SemilinSetExp::getVal() const {
	return val;
}

//TODO: semantic equivalence check or at least some more sophisticated check
bool SemilinSetExp::operator == (const SemilinSetExp& sl) const {
	return (this->val == sl.getVal());
}

// TODO: multiple points of return might kill RVO ... try returning a pointer instead?
std::set<LinSet> SemilinSetExp::star(LinSet ls) {

	// if we do not have any generators, i.e. ls = w for some word w, just return w* (instead of 1 + ww*)
	if(ls.second.empty()) {
		LinSet r = ls;
		// if w is not the one-element, move w to the generators
		if(ls.first != VecSparse()) {
			r.second.insert(ls.first);
			r.first = VecSparse();
		}
		std::set<LinSet> res;
		res.insert(r);
		return res;
	}

	SemilinSetExp tmp_one = one();
	std::set<LinSet> v = tmp_one.getVal();
	std::set<LinSet> result = std::set<LinSet>(v.begin(),v.end());

	// star of a linear set is a semilinear set:
	// (w_0.w_1*.w_2*...w_n*)* = 1 +  (w_0.w_0*.w_1*.w_2*...w_n*)

	VecSparse new_gen = ls.first;
	LinSet ls_tmp = ls;
	ls_tmp.second.insert(new_gen);
	result.insert(ls_tmp);

	return result;
}

SemilinSetExp SemilinSetExp::star() const {
	SemilinSetExp result = SemilinSetExp::one();
	for(std::set<LinSet>::const_iterator it_m = val.begin(); it_m != val.end(); ++it_m) {
		std::set<LinSet> star_ls = star(*it_m);
		result = result * SemilinSetExp(star_ls);
	}
	return result;
}

std::string SemilinSetExp::string() const {
	std::stringstream ss;
	ss << "[" << '\n';
	for(std::set<LinSet>::const_iterator it_ls = this->val.begin(); it_ls != this->val.end(); ++it_ls) {
		ss << *it_ls;
		ss << '\n';
	}
	ss << "]" << '\n';
	return ss.str();
}

std::ostream& SemilinSetExp::operator<<(std::ostream& os) const {
	return os << this->string();
}

bool SemilinSetExp::is_idempotent = true;
bool SemilinSetExp::is_commutative = true;
std::shared_ptr<SemilinSetExp> SemilinSetExp::elem_null;
std::shared_ptr<SemilinSetExp> SemilinSetExp::elem_one;
<commit_msg>semilinear: convert the .cpp file to 2 space indent<commit_after>/*
 * semilinSetExp.cpp
 *
 *  Created on: 20.09.2012
 *      Author: maxi
 */

#include <algorithm>
#include <cassert>

#include "semilinSetExp.h"

// adding two Var-maps componentwise... could be put in a util-class ?
VecSparse operator+(const VecSparse& a, const VecSparse& b) {
  VecSparse result = a;
  for(VecSparse::const_iterator it = b.begin(); it!=b.end(); ++it) {
    if(result.count(it->first) > 0)
      result[it->first] += it->second;
    else
      result[it->first] = it->second;
  }

    return result;
}

LinSet operator * (const LinSet& ls1, const LinSet& ls2) {
  //assert(!ls1.empty() && !ls2.empty());

  //union on the generators
  std::set<VecSparse> gens;
  std::insert_iterator<std::set<VecSparse> > it(gens, gens.begin());
  set_union(ls1.second.begin(), ls1.second.end(), ls2.second.begin(), ls2.second.end(), it);

  LinSet result;

  //add the offsets
  result.first = ls1.first + ls2.first;
  result.second = gens;
  return result;
}

std::ostream& operator<<(std::ostream& os, const VecSparse& v) {
  os << "<";
    for (typename std::map<VarPtr, unsigned int>::const_iterator it = v.begin(); it != v.end(); ++it)
    {
        os << it->first << ":" << it->second << ", ";
    }
    os << ">";
    return os;
}

std::ostream& operator<<(std::ostream& os, const LinSet& ls) {
  os << ls.first;

  for(std::set<VecSparse>::const_iterator it_veclist = ls.second.begin(); it_veclist != ls.second.end(); ++it_veclist) {
    os << "+" << *it_veclist;
  }
    return os;
}

SemilinSetExp::SemilinSetExp() {
  this->val = std::set<LinSet>();
}

SemilinSetExp::SemilinSetExp(VarPtr var) {
  this->val = std::set<LinSet>();
  LinSet ls = LinSet();
  VecSparse offset;
  offset.insert(std::make_pair(var, 1));
  ls.first = offset;
  ls.second = std::set<VecSparse>();
  this->val.insert(ls);
}

SemilinSetExp::SemilinSetExp(std::set<LinSet> val) {
  this->val = std::set<LinSet>(val.begin(),val.end());
}

SemilinSetExp::~SemilinSetExp() {
  // do NOT delete static pointers!!!
}

SemilinSetExp SemilinSetExp::null() {
  if(!SemilinSetExp::elem_null)
    SemilinSetExp::elem_null = std::shared_ptr<SemilinSetExp>(new SemilinSetExp(std::set<LinSet>()));
  return *SemilinSetExp::elem_null;
}

SemilinSetExp SemilinSetExp::one() {
  if(!SemilinSetExp::elem_one) {
    std::set<LinSet> elone = std::set<LinSet>();
    LinSet ls = LinSet();
    ls.first = VecSparse();
    ls.second = std::set<VecSparse>();
    elone.insert(ls);
    SemilinSetExp::elem_one = std::shared_ptr<SemilinSetExp>(new SemilinSetExp(elone));
  }
  return *SemilinSetExp::elem_one;
}

SemilinSetExp SemilinSetExp::operator += (const SemilinSetExp& sl) {
  std::set<LinSet> result;

  std::insert_iterator<std::set<LinSet> > it(result, result.begin());
  std::set_union(this->val.begin(),this->val.end(),sl.val.begin(),sl.val.end(),it);

  *this = SemilinSetExp(result);
  return *this;
}

SemilinSetExp SemilinSetExp::operator *= (const SemilinSetExp& sl) {
  std::set<LinSet> result;
  for(std::set<LinSet>::const_iterator it_arg = sl.val.begin(); it_arg != sl.val.end(); ++it_arg) {
    for(std::set<LinSet>::const_iterator it_m = this->val.begin(); it_m != this->val.end(); ++it_m) {
          result.insert((*it_arg) * (*it_m));
    }
  }
  *this = SemilinSetExp(result);
  return *this;
}

std::set<LinSet> SemilinSetExp::getVal() const {
  return val;
}

//TODO: semantic equivalence check or at least some more sophisticated check
bool SemilinSetExp::operator == (const SemilinSetExp& sl) const {
  return (this->val == sl.getVal());
}

// TODO: multiple points of return might kill RVO ... try returning a pointer instead?
std::set<LinSet> SemilinSetExp::star(LinSet ls) {

  // if we do not have any generators, i.e. ls = w for some word w, just return w* (instead of 1 + ww*)
  if(ls.second.empty()) {
    LinSet r = ls;
    // if w is not the one-element, move w to the generators
    if(ls.first != VecSparse()) {
      r.second.insert(ls.first);
      r.first = VecSparse();
    }
    std::set<LinSet> res;
    res.insert(r);
    return res;
  }

  SemilinSetExp tmp_one = one();
  std::set<LinSet> v = tmp_one.getVal();
  std::set<LinSet> result = std::set<LinSet>(v.begin(),v.end());

  // star of a linear set is a semilinear set:
  // (w_0.w_1*.w_2*...w_n*)* = 1 +  (w_0.w_0*.w_1*.w_2*...w_n*)

  VecSparse new_gen = ls.first;
  LinSet ls_tmp = ls;
  ls_tmp.second.insert(new_gen);
  result.insert(ls_tmp);

  return result;
}

SemilinSetExp SemilinSetExp::star() const {
  SemilinSetExp result = SemilinSetExp::one();
  for(std::set<LinSet>::const_iterator it_m = val.begin(); it_m != val.end(); ++it_m) {
    std::set<LinSet> star_ls = star(*it_m);
    result = result * SemilinSetExp(star_ls);
  }
  return result;
}

std::string SemilinSetExp::string() const {
  std::stringstream ss;
  ss << "[" << '\n';
  for(std::set<LinSet>::const_iterator it_ls = this->val.begin(); it_ls != this->val.end(); ++it_ls) {
    ss << *it_ls;
    ss << '\n';
  }
  ss << "]" << '\n';
  return ss.str();
}

std::ostream& SemilinSetExp::operator<<(std::ostream& os) const {
  return os << this->string();
}

bool SemilinSetExp::is_idempotent = true;
bool SemilinSetExp::is_commutative = true;
std::shared_ptr<SemilinSetExp> SemilinSetExp::elem_null;
std::shared_ptr<SemilinSetExp> SemilinSetExp::elem_one;
<|endoftext|>


<commit_before>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "frtconnection.h"
#include <vespa/config/common/errorcode.h>
#include <vespa/fnet/frt/supervisor.h>
#include <vespa/fnet/frt/target.h>
#include <vespa/fnet/frt/rpcrequest.h>

#include <vespa/log/log.h>
LOG_SETUP(".config.frt.frtconnection");

using namespace vespalib;

namespace config {

FRTConnection::FRTConnection(const vespalib::string& address, FRT_Supervisor& supervisor, const TimingValues & timingValues)
    : _address(address),
      _supervisor(supervisor),
      _target(0),
      _suspendedUntil(),
      _suspendWarned(),
      _transientFailures(0),
      _fatalFailures(0),
      _transientDelay(timingValues.transientDelay),
      _fatalDelay(timingValues.fatalDelay)
{
}

FRTConnection::~FRTConnection()
{
    if (_target != nullptr) {
        _target->SubRef();
        _target = nullptr;
    }
}

FRT_Target *
FRTConnection::getTarget()
{
    if (_target == nullptr) {
        _target = _supervisor.GetTarget(_address.c_str());
    } else if ( ! _target->IsValid()) {
        _target->SubRef();
        _target = _supervisor.GetTarget(_address.c_str());
    }
    return _target;
}

void
FRTConnection::invoke(FRT_RPCRequest * req, duration timeout, FRT_IRequestWait * waiter)
{
    getTarget()->InvokeAsync(req, vespalib::to_s(timeout), waiter);
}

void
FRTConnection::setError(int errorCode)
{
    switch(errorCode) {
    case FRTE_RPC_CONNECTION:
    case FRTE_RPC_TIMEOUT:
        calculateSuspension(TRANSIENT); break;
    case ErrorCode::UNKNOWN_CONFIG:
    case ErrorCode::UNKNOWN_DEFINITION:
    case ErrorCode::UNKNOWN_VERSION:
    case ErrorCode::UNKNOWN_CONFIGID:
    case ErrorCode::UNKNOWN_DEF_MD5:
    case ErrorCode::ILLEGAL_NAME:
    case ErrorCode::ILLEGAL_VERSION:
    case ErrorCode::ILLEGAL_CONFIGID:
    case ErrorCode::ILLEGAL_DEF_MD5:
    case ErrorCode::ILLEGAL_CONFIG_MD5:
    case ErrorCode::ILLEGAL_TIMEOUT:
    case ErrorCode::OUTDATED_CONFIG:
    case ErrorCode::INTERNAL_ERROR:
        calculateSuspension(FATAL); break;
    }
}

void FRTConnection::setSuccess()
{
    _transientFailures = 0;
    _fatalFailures = 0;
    _suspendedUntil = system_time();
}

void FRTConnection::calculateSuspension(ErrorType type)
{
    duration delay = duration::zero();
    switch(type) {
    case TRANSIENT:
        _transientFailures.fetch_add(1);
        delay = _transientFailures.load(std::memory_order_relaxed) * getTransientDelay();
        if (delay > getMaxTransientDelay()) {
            delay = getMaxTransientDelay();
        }
        LOG(warning, "Connection to %s failed or timed out", _address.c_str());
        break;
    case FATAL:
        _fatalFailures.fetch_add(1);
        delay = _fatalFailures.load(std::memory_order_relaxed) * getFatalDelay();
        if (delay > getMaxFatalDelay()) {
            delay = getMaxFatalDelay();
        }
        break;
    }
    system_time now = system_clock::now();
    _suspendedUntil = now + std::chrono::duration_cast<system_time::duration>(delay);
    if (_suspendWarned < (now - 5s)) {
        LOG(warning, "FRT Connection %s suspended until %s", _address.c_str(), vespalib::to_string(_suspendedUntil).c_str());
        _suspendWarned = now;
    }
}

FRT_RPCRequest *
FRTConnection::allocRPCRequest() {
    return _supervisor.AllocRPCRequest();
}

}
<commit_msg>Add comment about why duration_cast is needed.<commit_after>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "frtconnection.h"
#include <vespa/config/common/errorcode.h>
#include <vespa/fnet/frt/supervisor.h>
#include <vespa/fnet/frt/target.h>
#include <vespa/fnet/frt/rpcrequest.h>

#include <vespa/log/log.h>
LOG_SETUP(".config.frt.frtconnection");

using namespace vespalib;

namespace config {

FRTConnection::FRTConnection(const vespalib::string& address, FRT_Supervisor& supervisor, const TimingValues & timingValues)
    : _address(address),
      _supervisor(supervisor),
      _target(0),
      _suspendedUntil(),
      _suspendWarned(),
      _transientFailures(0),
      _fatalFailures(0),
      _transientDelay(timingValues.transientDelay),
      _fatalDelay(timingValues.fatalDelay)
{
}

FRTConnection::~FRTConnection()
{
    if (_target != nullptr) {
        _target->SubRef();
        _target = nullptr;
    }
}

FRT_Target *
FRTConnection::getTarget()
{
    if (_target == nullptr) {
        _target = _supervisor.GetTarget(_address.c_str());
    } else if ( ! _target->IsValid()) {
        _target->SubRef();
        _target = _supervisor.GetTarget(_address.c_str());
    }
    return _target;
}

void
FRTConnection::invoke(FRT_RPCRequest * req, duration timeout, FRT_IRequestWait * waiter)
{
    getTarget()->InvokeAsync(req, vespalib::to_s(timeout), waiter);
}

void
FRTConnection::setError(int errorCode)
{
    switch(errorCode) {
    case FRTE_RPC_CONNECTION:
    case FRTE_RPC_TIMEOUT:
        calculateSuspension(TRANSIENT); break;
    case ErrorCode::UNKNOWN_CONFIG:
    case ErrorCode::UNKNOWN_DEFINITION:
    case ErrorCode::UNKNOWN_VERSION:
    case ErrorCode::UNKNOWN_CONFIGID:
    case ErrorCode::UNKNOWN_DEF_MD5:
    case ErrorCode::ILLEGAL_NAME:
    case ErrorCode::ILLEGAL_VERSION:
    case ErrorCode::ILLEGAL_CONFIGID:
    case ErrorCode::ILLEGAL_DEF_MD5:
    case ErrorCode::ILLEGAL_CONFIG_MD5:
    case ErrorCode::ILLEGAL_TIMEOUT:
    case ErrorCode::OUTDATED_CONFIG:
    case ErrorCode::INTERNAL_ERROR:
        calculateSuspension(FATAL); break;
    }
}

void FRTConnection::setSuccess()
{
    _transientFailures = 0;
    _fatalFailures = 0;
    _suspendedUntil = system_time();
}

void FRTConnection::calculateSuspension(ErrorType type)
{
    duration delay = duration::zero();
    switch(type) {
    case TRANSIENT:
        _transientFailures.fetch_add(1);
        delay = _transientFailures.load(std::memory_order_relaxed) * getTransientDelay();
        if (delay > getMaxTransientDelay()) {
            delay = getMaxTransientDelay();
        }
        LOG(warning, "Connection to %s failed or timed out", _address.c_str());
        break;
    case FATAL:
        _fatalFailures.fetch_add(1);
        delay = _fatalFailures.load(std::memory_order_relaxed) * getFatalDelay();
        if (delay > getMaxFatalDelay()) {
            delay = getMaxFatalDelay();
        }
        break;
    }
    system_time now = system_clock::now();
    /*
     * On Darwin, the std::chrono::steady_clock period (std::nano) is
     * not exactly divisible by the std::chrono::system_clock period
     * (std::micro). Thus we need to use std::chrono::duration_cast to
     * convert from steady_time::duration to system_time::duration.
     */
    _suspendedUntil = now + std::chrono::duration_cast<system_time::duration>(delay);
    if (_suspendWarned < (now - 5s)) {
        LOG(warning, "FRT Connection %s suspended until %s", _address.c_str(), vespalib::to_string(_suspendedUntil).c_str());
        _suspendWarned = now;
    }
}

FRT_RPCRequest *
FRTConnection::allocRPCRequest() {
    return _supervisor.AllocRPCRequest();
}

}
<|endoftext|>


<commit_before>#ifndef TOML11_VERSION_HPP
#define TOML11_VERSION_HPP

// This file checks C++ version.

#ifndef __cplusplus
#    error "__cplusplus is not defined"
#endif

// Since MSVC does not define `__cplusplus` correctly unless you pass
// `/Zc:__cplusplus` when compiling, the workaround macros are added.
// Those enables you to define version manually or to use MSVC specific
// version macro automatically.
//
// The value of `__cplusplus` macro is defined in the C++ standard spec, but
// MSVC ignores the value, maybe because of backward compatibility. Instead,
// MSVC defines _MSVC_LANG that has the same value as __cplusplus defined in
// the C++ standard. First we check the manual version definition, and then
// we check if _MSVC_LANG is defined. If neither, use normal `__cplusplus`.
//
// FYI: https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=msvc-170
//      https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170
//
#if   defined(TOML11_ENFORCE_CXX11)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201103L
#elif defined(TOML11_ENFORCE_CXX14)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201402L
#elif defined(TOML11_ENFORCE_CXX17)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201703L
#elif defined(TOML11_ENFORCE_CXX20)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 202002L
#elif defined(_MSVC_LANG) && defined(_MSC_VER) && 1910 <= _MSC_VER
#  define TOML11_CPLUSPLUS_STANDARD_VERSION _MSVC_LANG
#else
#  define TOML11_CPLUSPLUS_STANDARD_VERSION __cplusplus
#endif

#if TOML11_CPLUSPLUS_STANDARD_VERSION < 201103L
#    error "toml11 requires C++11 or later."
#endif

#endif// TOML11_VERSION_HPP
<commit_msg>fix: Allow MSVC to have old version<commit_after>#ifndef TOML11_VERSION_HPP
#define TOML11_VERSION_HPP

// This file checks C++ version.

#ifndef __cplusplus
#    error "__cplusplus is not defined"
#endif

// Since MSVC does not define `__cplusplus` correctly unless you pass
// `/Zc:__cplusplus` when compiling, the workaround macros are added.
// Those enables you to define version manually or to use MSVC specific
// version macro automatically.
//
// The value of `__cplusplus` macro is defined in the C++ standard spec, but
// MSVC ignores the value, maybe because of backward compatibility. Instead,
// MSVC defines _MSVC_LANG that has the same value as __cplusplus defined in
// the C++ standard. First we check the manual version definition, and then
// we check if _MSVC_LANG is defined. If neither, use normal `__cplusplus`.
//
// FYI: https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=msvc-170
//      https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170
//
#if   defined(TOML11_ENFORCE_CXX11)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201103L
#elif defined(TOML11_ENFORCE_CXX14)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201402L
#elif defined(TOML11_ENFORCE_CXX17)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201703L
#elif defined(TOML11_ENFORCE_CXX20)
#  define TOML11_CPLUSPLUS_STANDARD_VERSION 202002L
#elif defined(_MSVC_LANG) && defined(_MSC_VER) && 1910 <= _MSC_VER
#  define TOML11_CPLUSPLUS_STANDARD_VERSION _MSVC_LANG
#else
#  define TOML11_CPLUSPLUS_STANDARD_VERSION __cplusplus
#endif

#if TOML11_CPLUSPLUS_STANDARD_VERSION < 201103L && _MSC_VER < 1900
#    error "toml11 requires C++11 or later."
#endif

#endif// TOML11_VERSION_HPP
<|endoftext|>


<commit_before>/*************************************************************************/
/*  gdscript_cache.cpp                                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "gdscript_cache.h"

#include "core/io/file_access.h"
#include "core/templates/vector.h"
#include "gdscript.h"
#include "gdscript_analyzer.h"
#include "gdscript_parser.h"

bool GDScriptParserRef::is_valid() const {
	return parser != nullptr;
}

GDScriptParserRef::Status GDScriptParserRef::get_status() const {
	return status;
}

GDScriptParser *GDScriptParserRef::get_parser() const {
	return parser;
}

Error GDScriptParserRef::raise_status(Status p_new_status) {
	ERR_FAIL_COND_V(parser == nullptr, ERR_INVALID_DATA);

	Error result = OK;

	while (p_new_status > status) {
		switch (status) {
			case EMPTY:
				result = parser->parse(GDScriptCache::get_source_code(path), path, false);
				status = PARSED;
				break;
			case PARSED: {
				analyzer = memnew(GDScriptAnalyzer(parser));
				Error inheritance_result = analyzer->resolve_inheritance();
				status = INHERITANCE_SOLVED;
				if (result == OK) {
					result = inheritance_result;
				}
			} break;
			case INHERITANCE_SOLVED: {
				Error interface_result = analyzer->resolve_interface();
				status = INTERFACE_SOLVED;
				if (result == OK) {
					result = interface_result;
				}
			} break;
			case INTERFACE_SOLVED: {
				Error body_result = analyzer->resolve_body();
				status = FULLY_SOLVED;
				if (result == OK) {
					result = body_result;
				}
			} break;
			case FULLY_SOLVED: {
				return result;
			}
		}
		if (result != OK) {
			if (parser != nullptr) {
				memdelete(parser);
				parser = nullptr;
			}
			if (analyzer != nullptr) {
				memdelete(analyzer);
				analyzer = nullptr;
			}
			return result;
		}
	}

	return result;
}

GDScriptParserRef::~GDScriptParserRef() {
	if (parser != nullptr) {
		memdelete(parser);
	}
	if (analyzer != nullptr) {
		memdelete(analyzer);
	}
	MutexLock lock(GDScriptCache::singleton->lock);
	GDScriptCache::singleton->parser_map.erase(path);
}

GDScriptCache *GDScriptCache::singleton = nullptr;

void GDScriptCache::remove_script(const String &p_path) {
	MutexLock lock(singleton->lock);
	singleton->shallow_gdscript_cache.erase(p_path);
	singleton->full_gdscript_cache.erase(p_path);
}

Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptParserRef::Status p_status, Error &r_error, const String &p_owner) {
	MutexLock lock(singleton->lock);
	Ref<GDScriptParserRef> ref;
	if (p_owner != String()) {
		singleton->dependencies[p_owner].insert(p_path);
	}
	if (singleton->parser_map.has(p_path)) {
		ref = Ref<GDScriptParserRef>(singleton->parser_map[p_path]);
	} else {
		if (!FileAccess::exists(p_path)) {
			r_error = ERR_FILE_NOT_FOUND;
			return ref;
		}
		GDScriptParser *parser = memnew(GDScriptParser);
		ref.instantiate();
		ref->parser = parser;
		ref->path = p_path;
		singleton->parser_map[p_path] = ref.ptr();
	}

	r_error = ref->raise_status(p_status);

	return ref;
}

String GDScriptCache::get_source_code(const String &p_path) {
	Vector<uint8_t> source_file;
	Error err;
	FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
	if (err) {
		ERR_FAIL_COND_V(err, "");
	}

	uint64_t len = f->get_length();
	source_file.resize(len + 1);
	uint64_t r = f->get_buffer(source_file.ptrw(), len);
	f->close();
	ERR_FAIL_COND_V(r != len, "");
	source_file.write[len] = 0;

	String source;
	if (source.parse_utf8((const char *)source_file.ptr())) {
		ERR_FAIL_V_MSG("", "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
	}
	return source;
}

Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const String &p_owner) {
	MutexLock lock(singleton->lock);
	if (p_owner != String()) {
		singleton->dependencies[p_owner].insert(p_path);
	}
	if (singleton->full_gdscript_cache.has(p_path)) {
		return singleton->full_gdscript_cache[p_path];
	}
	if (singleton->shallow_gdscript_cache.has(p_path)) {
		return singleton->shallow_gdscript_cache[p_path];
	}

	Ref<GDScript> script;
	script.instantiate();
	script->set_path(p_path, true);
	script->set_script_path(p_path);
	script->load_source_code(p_path);

	singleton->shallow_gdscript_cache[p_path] = script.ptr();
	return script;
}

Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner) {
	MutexLock lock(singleton->lock);

	if (p_owner != String()) {
		singleton->dependencies[p_owner].insert(p_path);
	}

	r_error = OK;
	if (singleton->full_gdscript_cache.has(p_path)) {
		return singleton->full_gdscript_cache[p_path];
	}
	Ref<GDScript> script = get_shallow_script(p_path);

	r_error = script->load_source_code(p_path);

	if (r_error) {
		return script;
	}

	r_error = script->reload();
	if (r_error) {
		return script;
	}

	singleton->full_gdscript_cache[p_path] = script.ptr();
	singleton->shallow_gdscript_cache.erase(p_path);

	return script;
}

Error GDScriptCache::finish_compiling(const String &p_owner) {
	// Mark this as compiled.
	Ref<GDScript> script = get_shallow_script(p_owner);
	singleton->full_gdscript_cache[p_owner] = script.ptr();
	singleton->shallow_gdscript_cache.erase(p_owner);

	Set<String> depends = singleton->dependencies[p_owner];

	Error err = OK;
	for (const Set<String>::Element *E = depends.front(); E != nullptr; E = E->next()) {
		Error this_err = OK;
		// No need to save the script. We assume it's already referenced in the owner.
		get_full_script(E->get(), this_err);

		if (this_err != OK) {
			err = this_err;
		}
	}

	singleton->dependencies.erase(p_owner);

	return err;
}

GDScriptCache::GDScriptCache() {
	singleton = this;
}

GDScriptCache::~GDScriptCache() {
	parser_map.clear();
	shallow_gdscript_cache.clear();
	full_gdscript_cache.clear();
	singleton = nullptr;
}
<commit_msg>Fix crash when failing to load script from cache<commit_after>/*************************************************************************/
/*  gdscript_cache.cpp                                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "gdscript_cache.h"

#include "core/io/file_access.h"
#include "core/templates/vector.h"
#include "gdscript.h"
#include "gdscript_analyzer.h"
#include "gdscript_parser.h"

bool GDScriptParserRef::is_valid() const {
	return parser != nullptr;
}

GDScriptParserRef::Status GDScriptParserRef::get_status() const {
	return status;
}

GDScriptParser *GDScriptParserRef::get_parser() const {
	return parser;
}

Error GDScriptParserRef::raise_status(Status p_new_status) {
	ERR_FAIL_COND_V(parser == nullptr, ERR_INVALID_DATA);

	Error result = OK;

	while (p_new_status > status) {
		switch (status) {
			case EMPTY:
				result = parser->parse(GDScriptCache::get_source_code(path), path, false);
				status = PARSED;
				break;
			case PARSED: {
				analyzer = memnew(GDScriptAnalyzer(parser));
				Error inheritance_result = analyzer->resolve_inheritance();
				status = INHERITANCE_SOLVED;
				if (result == OK) {
					result = inheritance_result;
				}
			} break;
			case INHERITANCE_SOLVED: {
				Error interface_result = analyzer->resolve_interface();
				status = INTERFACE_SOLVED;
				if (result == OK) {
					result = interface_result;
				}
			} break;
			case INTERFACE_SOLVED: {
				Error body_result = analyzer->resolve_body();
				status = FULLY_SOLVED;
				if (result == OK) {
					result = body_result;
				}
			} break;
			case FULLY_SOLVED: {
				return result;
			}
		}
		if (result != OK) {
			if (parser != nullptr) {
				memdelete(parser);
				parser = nullptr;
			}
			if (analyzer != nullptr) {
				memdelete(analyzer);
				analyzer = nullptr;
			}
			return result;
		}
	}

	return result;
}

GDScriptParserRef::~GDScriptParserRef() {
	if (parser != nullptr) {
		memdelete(parser);
	}
	if (analyzer != nullptr) {
		memdelete(analyzer);
	}
	MutexLock lock(GDScriptCache::singleton->lock);
	GDScriptCache::singleton->parser_map.erase(path);
}

GDScriptCache *GDScriptCache::singleton = nullptr;

void GDScriptCache::remove_script(const String &p_path) {
	MutexLock lock(singleton->lock);
	singleton->shallow_gdscript_cache.erase(p_path);
	singleton->full_gdscript_cache.erase(p_path);
}

Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptParserRef::Status p_status, Error &r_error, const String &p_owner) {
	MutexLock lock(singleton->lock);
	Ref<GDScriptParserRef> ref;
	if (p_owner != String()) {
		singleton->dependencies[p_owner].insert(p_path);
	}
	if (singleton->parser_map.has(p_path)) {
		ref = Ref<GDScriptParserRef>(singleton->parser_map[p_path]);
	} else {
		if (!FileAccess::exists(p_path)) {
			r_error = ERR_FILE_NOT_FOUND;
			return ref;
		}
		GDScriptParser *parser = memnew(GDScriptParser);
		ref.instantiate();
		ref->parser = parser;
		ref->path = p_path;
		singleton->parser_map[p_path] = ref.ptr();
	}

	r_error = ref->raise_status(p_status);

	return ref;
}

String GDScriptCache::get_source_code(const String &p_path) {
	Vector<uint8_t> source_file;
	Error err;
	FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
	if (err) {
		ERR_FAIL_COND_V(err, "");
	}

	uint64_t len = f->get_length();
	source_file.resize(len + 1);
	uint64_t r = f->get_buffer(source_file.ptrw(), len);
	f->close();
	ERR_FAIL_COND_V(r != len, "");
	source_file.write[len] = 0;

	String source;
	if (source.parse_utf8((const char *)source_file.ptr())) {
		ERR_FAIL_V_MSG("", "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
	}
	return source;
}

Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const String &p_owner) {
	MutexLock lock(singleton->lock);
	if (p_owner != String()) {
		singleton->dependencies[p_owner].insert(p_path);
	}
	if (singleton->full_gdscript_cache.has(p_path)) {
		return singleton->full_gdscript_cache[p_path];
	}
	if (singleton->shallow_gdscript_cache.has(p_path)) {
		return singleton->shallow_gdscript_cache[p_path];
	}

	Ref<GDScript> script;
	script.instantiate();
	script->set_path(p_path, true);
	script->set_script_path(p_path);
	script->load_source_code(p_path);

	singleton->shallow_gdscript_cache[p_path] = script.ptr();
	return script;
}

Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner) {
	MutexLock lock(singleton->lock);

	if (p_owner != String()) {
		singleton->dependencies[p_owner].insert(p_path);
	}

	r_error = OK;
	if (singleton->full_gdscript_cache.has(p_path)) {
		return singleton->full_gdscript_cache[p_path];
	}

	Ref<GDScript> script = get_shallow_script(p_path);
	ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>());

	r_error = script->load_source_code(p_path);

	if (r_error) {
		return script;
	}

	r_error = script->reload();
	if (r_error) {
		return script;
	}

	singleton->full_gdscript_cache[p_path] = script.ptr();
	singleton->shallow_gdscript_cache.erase(p_path);

	return script;
}

Error GDScriptCache::finish_compiling(const String &p_owner) {
	// Mark this as compiled.
	Ref<GDScript> script = get_shallow_script(p_owner);
	singleton->full_gdscript_cache[p_owner] = script.ptr();
	singleton->shallow_gdscript_cache.erase(p_owner);

	Set<String> depends = singleton->dependencies[p_owner];

	Error err = OK;
	for (const Set<String>::Element *E = depends.front(); E != nullptr; E = E->next()) {
		Error this_err = OK;
		// No need to save the script. We assume it's already referenced in the owner.
		get_full_script(E->get(), this_err);

		if (this_err != OK) {
			err = this_err;
		}
	}

	singleton->dependencies.erase(p_owner);

	return err;
}

GDScriptCache::GDScriptCache() {
	singleton = this;
}

GDScriptCache::~GDScriptCache() {
	parser_map.clear();
	shallow_gdscript_cache.clear();
	full_gdscript_cache.clear();
	singleton = nullptr;
}
<|endoftext|>


<commit_before>#include "common/library_main.h"
#include "common/main_delegate.h"

#include "content/public/app/content_main.h"
#include "sandbox/win/src/sandbox_types.h"

#if defined(OS_WIN)

#include "content/public/app/startup_helper_win.h"
#include <Windows.h>

int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) {
  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);
  brightray_example::MainDelegate delegate;
  return content::ContentMain(instance, &sandbox_info, &delegate);
}

#elif defined(OS_MACOSX)

int main(int argc, const char* argv[]) {
  return BrightrayExampleMain(argc, argv);
}

#else // OS_LINUX

int main(int argc, const char* argv[]) {
  brightray_example::MainDelegate delegate;
  return content::ContentMain(argc, argv, &delegate);
}

#endif
<commit_msg>Update for content::ContentMain changes<commit_after>#include "common/library_main.h"
#include "common/main_delegate.h"

#include "content/public/app/content_main.h"
#include "sandbox/win/src/sandbox_types.h"

#if defined(OS_WIN)

#include "content/public/app/startup_helper_win.h"
#include <Windows.h>

int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) {
  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);
  brightray_example::MainDelegate delegate;

  content::ContentMainParams params(&delegate);
  params.instance = instance;
  params.sandbox_info = &sandbox_info;
  return content::ContentMain(params);
}

#elif defined(OS_MACOSX)

int main(int argc, const char* argv[]) {
  return BrightrayExampleMain(argc, argv);
}

#else // OS_LINUX

int main(int argc, const char* argv[]) {
  brightray_example::MainDelegate delegate;
  content::ContentMainParams params(&delegate);
  params.argc = argc;
  params.argv = argv;
  return content::ContentMain(params);
}

#endif
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
//
//
// Jet fragmentation transverse momentum (j_T) analysis task
//
// Author: Beomkyu Kim, Beomsu Chang, Dongjo Kim

#include <TClonesArray.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TH3F.h>
#include <TList.h>
#include <TProfile.h>
#include <TLorentzVector.h>
#include <TVector.h>
#include <TGraphErrors.h>
#include <TGrid.h>
#include <TSystem.h>
#include <TFile.h>

#include "AliCentrality.h"

#include "AliVCluster.h"
#include "AliAODCaloCluster.h"
#include "AliESDCaloCluster.h"
#include "AliVTrack.h"
#include "AliAODTrack.h"
#include "AliEmcalJet.h"
#include "AliRhoParameter.h"
#include "AliLog.h"
#include "AliJetContainer.h"
#include "AliParticleContainer.h"
#include "AliClusterContainer.h"
#include "AliPicoTrack.h"
#include "AliJBaseTrack.h"
#include "AliJMCTrack.h"
#include "AliJJet.h"
#include "AliJJetTask.h"
#include "AliEmcalTrackSelectionAOD.h"

ClassImp(AliJJetTask);

//________________________________________________________________________
AliJJetTask::AliJJetTask() :
  AliAnalysisTaskEmcalJet("AliJJetTask", kTRUE),
  fJetsCont(),
  fTrackOrMCParticle(),
  fJTracks("AliJBaseTrack",1000),
  fJClusters("AliJBaseTrack",1000),
  fJMCTracks("AliJMCTrack",1000),
  fJJets(),
  fTaskEntry(-1),
  fJetFinderString(),
  fTrackArrayName("nonejk"),
  fNJetFinder(0),
  debug(0),
  fIsMC(0)

{
  // Default constructor.

  SetMakeGeneralHistograms(kTRUE);
}

//________________________________________________________________________
AliJJetTask::AliJJetTask(const char *name, const int nJetFinder) :
  AliAnalysisTaskEmcalJet(name, kTRUE),
  fJetsCont(nJetFinder),
  fTrackOrMCParticle(nJetFinder,kJUndefined),
  fJTracks("AliJBaseTrack",1000),
  fJClusters("AliJBaseTrack",1000),
  fJMCTracks("AliJMCTrack",1000),
  fJJets(),
  fTaskEntry(-1),
  fJetFinderString(nJetFinder),
  fTrackArrayName("nonejk"),
  fNJetFinder(nJetFinder),
  debug(0),
  fIsMC(0)
{
  SetMakeGeneralHistograms(kTRUE);
}

AliJJetTask::AliJJetTask(const AliJJetTask& ap) :
  AliAnalysisTaskEmcalJet(ap.fName, kTRUE),
  fJetsCont(ap.fJetsCont),
  //fCaloClustersCont(ap.fCaloClustersCont),
  fTrackOrMCParticle(ap.fTrackOrMCParticle),
  fJTracks(ap.fJTracks),
  fJMCTracks(ap.fJMCTracks),
  fJClusters(ap.fJClusters),
  fJJets(ap.fJJets),
  fTaskEntry(ap.fTaskEntry),
  fJetFinderString(ap.fJetFinderString),
  fTrackArrayName(ap.fTrackArrayName),
  fNJetFinder(ap.fNJetFinder),
  debug(ap.debug),
  fIsMC(ap.fIsMC)
{

}

AliJJetTask& AliJJetTask::operator = (const AliJJetTask& ap)
{

  this->~AliJJetTask();
  new(this) AliJJetTask(ap);
  return *this;
}

//________________________________________________________________________
AliJJetTask::~AliJJetTask()
{
  // Destructor.

  //delete[] fJJets;
}

//________________________________________________________________________
void AliJJetTask::UserCreateOutputObjects()
{
  // Create user output.

  //== Init Variables
  fJJets.clear();
  fJJets.resize( fNJetFinder, TClonesArray("AliJJet",1000) );
  fJetsCont.resize( fNJetFinder );
  //fCaloClustersCont.resize( fNJetFinder );

  AliAnalysisTaskEmcalJet::UserCreateOutputObjects();

  fJetFinderString.clear();

  cout << "fNJetFinder: " << fNJetFinder << endl;
  for (int i=0; i<fNJetFinder; i++){
    fJetsCont[i]           = GetJetContainer(i);
    fJetFinderString.push_back(fJetsCont[i]->GetArrayName());
    cout << i <<"\t" << fJetFinderString[i] << endl;
  }

}

//________________________________________________________________________
Bool_t AliJJetTask::FillHistograms()
{
  // FIXME : We assume that we have only one of each. be  carefull. This must be fixed later, See for example AliEmcalJetTask.cxx FindJets()
  //== AliJTrack
  //FIXME Search by container name
  AliParticleContainer *tracksCont = GetParticleContainer("tracks");
  if(debug > 0){
    cout << "AliParticleContainer name: " << tracksCont->GetName() << endl;
    cout << "NParticles(): " << tracksCont->GetNParticles() << endl;
  }
  if( tracksCont ){
    for (int itrack = 0; itrack<tracksCont->GetNParticles(); itrack++){
      AliAODTrack *track = static_cast<AliAODTrack*>(tracksCont->GetParticle(itrack));
      if(!track) continue;
      new (fJTracks[itrack]) AliJBaseTrack(track->Px(),track->Py(), track->Pz(), track->E(), itrack,0,track->Charge());
      AliJBaseTrack * particle = static_cast<AliJBaseTrack*>(fJTracks[itrack]);
      particle->SetLabel(track->GetLabel());
      if(track->IsHybridGlobalConstrainedGlobal()){
        particle->SetFlag(1,kTRUE);
      }
    }
  }

  //FIXME Search by container name
  AliMCParticleContainer * mcTracksCont = GetMCParticleContainer("mcparticles");
  if(debug > 0){
    cout << "MCParticleContainer name: " << mcTracksCont->GetName() << endl;
  }
  if( mcTracksCont ){
    if(debug > 0){
      cout << "mcTracksCont->GetNParticles(): " << mcTracksCont->GetNParticles() << endl;
    }
    int tracks = 0;
    for (int itrack = 0; itrack<mcTracksCont->GetNParticles(); itrack++){
      AliAODMCParticle *track = static_cast<AliAODMCParticle*>(mcTracksCont->GetParticle(itrack));
      new (fJMCTracks[itrack]) AliJMCTrack(track->Px(),track->Py(), track->Pz(), track->E(), itrack,0,track->Charge());
      tracks++;
      AliJMCTrack * particle = static_cast<AliJMCTrack*>(fJMCTracks[itrack]);
      if(track->IsPhysicalPrimary()){
        particle->SetPrimary();
      }
      particle->SetPdgCode(track->GetPdgCode());
      particle->SetLabel(track->GetLabel());
      particle->SetMother(track->GetMother(),track->GetMother());
    }
    if(debug > 0){
      cout << "Number of accepted tracks: " << tracks << endl;
    }
  }

  AliClusterContainer *clusterCont = GetClusterContainer(0);
  if( clusterCont ){
    for (int itrack = 0; itrack<clusterCont->GetNClusters(); itrack++){
      AliAODCaloCluster *track = static_cast<AliAODCaloCluster*>(clusterCont->GetCluster(itrack));
      TLorentzVector momentum;
      Double_t vertex[3] = {0,0,0}; //FIXME Get the true collision vertex
      track->GetMomentum(momentum,vertex); //FIXME Find the right way of getting the momentum
      new (fJClusters[itrack]) AliJBaseTrack(momentum.Px(),momentum.Py(), momentum.Pz(), track->E(), itrack,0,0); //No charge in AliAODCaloCluster //FIXME Particle type?
      // FIXME: AliJPhoton instead of JBaseTrack?
    }
  }

  for (int i=0; i<fNJetFinder; i++){
    if( ! fJetsCont[i] ){
      // FIXME: Give Warning!
      continue;
    }

    fJetsCont[i]->ResetCurrentID(); // FIXME:Comments me //Needed to reset internal iterator
    AliEmcalJet *jet = fJetsCont[i]->GetNextAcceptJet();
    int iJet =0;

    //fills fJJets[icontainer][ijet] and histograms
    while(jet){
      TClonesArray & jets = fJJets[i]; // just alias for AliJJet array
      new (jets[iJet]) AliJJet(jet->Px(),jet->Py(), jet->Pz(), jet->E(), jet->GetLabel(),0,0);
      AliJJet * j = (AliJJet*) fJJets[i][iJet];
      j->SetArea( jet->Area() );

      //== TRACK or Particle
      int nTrack = jet->GetNumberOfTracks();
      for (int it=0; it<nTrack; it++){
        int iTrack = jet->TrackAt(it);
        if( fTrackOrMCParticle[i] == kJRecoTrack ){
          j->AddConstituent(fJTracks[iTrack]); // Save as pointers
        } else {
          j->AddConstituent(fJMCTracks[iTrack]); // Save as pointers
          if(debug > 0){
            cout << "iTrack: " << iTrack << endl;
          }
        }
      }
      //Particle type is kJCluster, set particle type§
      int nCluster = jet->GetNumberOfClusters();
      for (int it=0; it<nCluster; it++){
        int iTrack = jet->ClusterAt(it);
        j->AddConstituent(fJClusters[iTrack]); // Save as pointers
      }

      Int_t nConstituents = jet->GetNumberOfConstituents();

      if (debug>0) {
        cout
          << "    iContainer    : " << i
          << "    iJet          : " << iJet
          << "    iTrack        : " << nTrack
          << "    iCluster      : " << nCluster
          << "    nConstituents : " << nConstituents
          << endl;
      }

      //Goes to the next jet
      jet = fJetsCont[i]->GetNextAcceptJet();
      if (debug>0) {
        cout
          << "  fJJets N lists : "     << fJJets[i].GetEntries()
          << "  fJJets constituents : "<< ((AliJJet*)fJJets[i][iJet])->GetConstituents()->GetEntries()
          <<endl;
      }
      iJet++;
    }
  }
  return kTRUE;

}

//________________________________________________________________________
void AliJJetTask::ExecOnce() {

  if(debug > 0){
    cout << "AliJJetTask::ExecOnce(): " << endl;
  }
  AliAnalysisTaskEmcalJet::ExecOnce();

  for (int i=0; i<fNJetFinder; i++){
    if (fJetsCont[i] && fJetsCont[i]->GetArray() == 0) fJetsCont[i] = 0;
  }
}

//________________________________________________________________________
Bool_t AliJJetTask::Run()
{
  // Run analysis code here, if needed. It will be executed before FillHistograms().
  fTaskEntry = fEntry; // FIXME: Comments me

  //== Clear Before Fill Histogram
  for (int i=0; i<fNJetFinder; i++) { fJJets[i]. Clear();
    fJTracks.Clear();
    fJMCTracks.Clear();

  }
  if (debug >0 && Entry()%1000 ==0 ) cout<<Entry()<<endl;
  return kTRUE;  // If return kFALSE FillHistogram() will NOT be executed.
}

//________________________________________________________________________
void AliJJetTask::Terminate(Option_t *)
{
  // Called once at the end of the analysis.
}

<commit_msg>Fix bug with MC Particle container that crashed AliJJetTask when running with data<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
//
//
// Jet fragmentation transverse momentum (j_T) analysis task
//
// Author: Beomkyu Kim, Beomsu Chang, Dongjo Kim

#include <TClonesArray.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TH3F.h>
#include <TList.h>
#include <TProfile.h>
#include <TLorentzVector.h>
#include <TVector.h>
#include <TGraphErrors.h>
#include <TGrid.h>
#include <TSystem.h>
#include <TFile.h>

#include "AliCentrality.h"

#include "AliVCluster.h"
#include "AliAODCaloCluster.h"
#include "AliESDCaloCluster.h"
#include "AliVTrack.h"
#include "AliAODTrack.h"
#include "AliEmcalJet.h"
#include "AliRhoParameter.h"
#include "AliLog.h"
#include "AliJetContainer.h"
#include "AliParticleContainer.h"
#include "AliClusterContainer.h"
#include "AliPicoTrack.h"
#include "AliJBaseTrack.h"
#include "AliJMCTrack.h"
#include "AliJJet.h"
#include "AliJJetTask.h"
#include "AliEmcalTrackSelectionAOD.h"

ClassImp(AliJJetTask);

//________________________________________________________________________
AliJJetTask::AliJJetTask() :
  AliAnalysisTaskEmcalJet("AliJJetTask", kTRUE),
  fJetsCont(),
  fTrackOrMCParticle(),
  fJTracks("AliJBaseTrack",1000),
  fJClusters("AliJBaseTrack",1000),
  fJMCTracks("AliJMCTrack",1000),
  fJJets(),
  fTaskEntry(-1),
  fJetFinderString(),
  fTrackArrayName("nonejk"),
  fNJetFinder(0),
  debug(0),
  fIsMC(0)

{
  // Default constructor.

  SetMakeGeneralHistograms(kTRUE);
}

//________________________________________________________________________
AliJJetTask::AliJJetTask(const char *name, const int nJetFinder) :
  AliAnalysisTaskEmcalJet(name, kTRUE),
  fJetsCont(nJetFinder),
  fTrackOrMCParticle(nJetFinder,kJUndefined),
  fJTracks("AliJBaseTrack",1000),
  fJClusters("AliJBaseTrack",1000),
  fJMCTracks("AliJMCTrack",1000),
  fJJets(),
  fTaskEntry(-1),
  fJetFinderString(nJetFinder),
  fTrackArrayName("nonejk"),
  fNJetFinder(nJetFinder),
  debug(0),
  fIsMC(0)
{
  SetMakeGeneralHistograms(kTRUE);
}

AliJJetTask::AliJJetTask(const AliJJetTask& ap) :
  AliAnalysisTaskEmcalJet(ap.fName, kTRUE),
  fJetsCont(ap.fJetsCont),
  //fCaloClustersCont(ap.fCaloClustersCont),
  fTrackOrMCParticle(ap.fTrackOrMCParticle),
  fJTracks(ap.fJTracks),
  fJMCTracks(ap.fJMCTracks),
  fJClusters(ap.fJClusters),
  fJJets(ap.fJJets),
  fTaskEntry(ap.fTaskEntry),
  fJetFinderString(ap.fJetFinderString),
  fTrackArrayName(ap.fTrackArrayName),
  fNJetFinder(ap.fNJetFinder),
  debug(ap.debug),
  fIsMC(ap.fIsMC)
{

}

AliJJetTask& AliJJetTask::operator = (const AliJJetTask& ap)
{

  this->~AliJJetTask();
  new(this) AliJJetTask(ap);
  return *this;
}

//________________________________________________________________________
AliJJetTask::~AliJJetTask()
{
  // Destructor.

  //delete[] fJJets;
}

//________________________________________________________________________
void AliJJetTask::UserCreateOutputObjects()
{
  // Create user output.

  //== Init Variables
  fJJets.clear();
  fJJets.resize( fNJetFinder, TClonesArray("AliJJet",1000) );
  fJetsCont.resize( fNJetFinder );
  //fCaloClustersCont.resize( fNJetFinder );

  AliAnalysisTaskEmcalJet::UserCreateOutputObjects();

  fJetFinderString.clear();

  cout << "fNJetFinder: " << fNJetFinder << endl;
  for (int i=0; i<fNJetFinder; i++){
    fJetsCont[i]           = GetJetContainer(i);
    fJetFinderString.push_back(fJetsCont[i]->GetArrayName());
    cout << i <<"\t" << fJetFinderString[i] << endl;
  }

}

//________________________________________________________________________
Bool_t AliJJetTask::FillHistograms()
{
  // FIXME : We assume that we have only one of each. be  carefull. This must be fixed later, See for example AliEmcalJetTask.cxx FindJets()
  //== AliJTrack
  //FIXME Search by container name
  AliParticleContainer *tracksCont = GetParticleContainer("tracks");
  if(debug > 0){
    cout << "AliParticleContainer name: " << tracksCont->GetName() << endl;
    cout << "NParticles(): " << tracksCont->GetNParticles() << endl;
  }
  if( tracksCont ){
    for (int itrack = 0; itrack<tracksCont->GetNParticles(); itrack++){
      AliAODTrack *track = static_cast<AliAODTrack*>(tracksCont->GetParticle(itrack));
      if(!track) continue;
      new (fJTracks[itrack]) AliJBaseTrack(track->Px(),track->Py(), track->Pz(), track->E(), itrack,0,track->Charge());
      AliJBaseTrack * particle = static_cast<AliJBaseTrack*>(fJTracks[itrack]);
      particle->SetLabel(track->GetLabel());
      if(track->IsHybridGlobalConstrainedGlobal()){
        particle->SetFlag(1,kTRUE);
      }
    }
  }

  //FIXME Search by container name
  if(fIsMC){
    AliMCParticleContainer * mcTracksCont = GetMCParticleContainer("mcparticles");
    if( mcTracksCont ){
      if(debug > 0){
        cout << "MCParticleContainer name: " << mcTracksCont->GetName() << endl;
        cout << "mcTracksCont->GetNParticles(): " << mcTracksCont->GetNParticles() << endl;
      }
      int tracks = 0;
      for (int itrack = 0; itrack<mcTracksCont->GetNParticles(); itrack++){
        AliAODMCParticle *track = static_cast<AliAODMCParticle*>(mcTracksCont->GetParticle(itrack));
        new (fJMCTracks[itrack]) AliJMCTrack(track->Px(),track->Py(), track->Pz(), track->E(), itrack,0,track->Charge());
        tracks++;
        AliJMCTrack * particle = static_cast<AliJMCTrack*>(fJMCTracks[itrack]);
        if(track->IsPhysicalPrimary()){
          particle->SetPrimary();
        }
        particle->SetPdgCode(track->GetPdgCode());
        particle->SetLabel(track->GetLabel());
        particle->SetMother(track->GetMother(),track->GetMother());
      }
      if(debug > 0){
        cout << "Number of accepted tracks: " << tracks << endl;
      }
    }
  }

  AliClusterContainer *clusterCont = GetClusterContainer(0);
  if( clusterCont ){
    for (int itrack = 0; itrack<clusterCont->GetNClusters(); itrack++){
      AliAODCaloCluster *track = static_cast<AliAODCaloCluster*>(clusterCont->GetCluster(itrack));
      TLorentzVector momentum;
      Double_t vertex[3] = {0,0,0}; //FIXME Get the true collision vertex
      track->GetMomentum(momentum,vertex); //FIXME Find the right way of getting the momentum
      new (fJClusters[itrack]) AliJBaseTrack(momentum.Px(),momentum.Py(), momentum.Pz(), track->E(), itrack,0,0); //No charge in AliAODCaloCluster //FIXME Particle type?
      // FIXME: AliJPhoton instead of JBaseTrack?
    }
  }

  for (int i=0; i<fNJetFinder; i++){
    if( ! fJetsCont[i] ){
      // FIXME: Give Warning!
      continue;
    }

    fJetsCont[i]->ResetCurrentID(); // FIXME:Comments me //Needed to reset internal iterator
    AliEmcalJet *jet = fJetsCont[i]->GetNextAcceptJet();
    int iJet =0;

    //fills fJJets[icontainer][ijet] and histograms
    while(jet){
      TClonesArray & jets = fJJets[i]; // just alias for AliJJet array
      new (jets[iJet]) AliJJet(jet->Px(),jet->Py(), jet->Pz(), jet->E(), jet->GetLabel(),0,0);
      AliJJet * j = (AliJJet*) fJJets[i][iJet];
      j->SetArea( jet->Area() );

      //== TRACK or Particle
      int nTrack = jet->GetNumberOfTracks();
      for (int it=0; it<nTrack; it++){
        int iTrack = jet->TrackAt(it);
        if( fTrackOrMCParticle[i] == kJRecoTrack ){
          j->AddConstituent(fJTracks[iTrack]); // Save as pointers
        } else {
          j->AddConstituent(fJMCTracks[iTrack]); // Save as pointers
          if(debug > 0){
            cout << "iTrack: " << iTrack << endl;
          }
        }
      }
      //Particle type is kJCluster, set particle type§
      int nCluster = jet->GetNumberOfClusters();
      for (int it=0; it<nCluster; it++){
        int iTrack = jet->ClusterAt(it);
        j->AddConstituent(fJClusters[iTrack]); // Save as pointers
      }

      Int_t nConstituents = jet->GetNumberOfConstituents();

      if (debug>0) {
        cout
          << "    iContainer    : " << i
          << "    iJet          : " << iJet
          << "    iTrack        : " << nTrack
          << "    iCluster      : " << nCluster
          << "    nConstituents : " << nConstituents
          << endl;
      }

      //Goes to the next jet
      jet = fJetsCont[i]->GetNextAcceptJet();
      if (debug>0) {
        cout
          << "  fJJets N lists : "     << fJJets[i].GetEntries()
          << "  fJJets constituents : "<< ((AliJJet*)fJJets[i][iJet])->GetConstituents()->GetEntries()
          <<endl;
      }
      iJet++;
    }
  }
  return kTRUE;

}

//________________________________________________________________________
void AliJJetTask::ExecOnce() {

  if(debug > 0){
    cout << "AliJJetTask::ExecOnce(): " << endl;
  }
  AliAnalysisTaskEmcalJet::ExecOnce();

  for (int i=0; i<fNJetFinder; i++){
    if (fJetsCont[i] && fJetsCont[i]->GetArray() == 0) fJetsCont[i] = 0;
  }
}

//________________________________________________________________________
Bool_t AliJJetTask::Run()
{
  // Run analysis code here, if needed. It will be executed before FillHistograms().
  fTaskEntry = fEntry; // FIXME: Comments me

  //== Clear Before Fill Histogram
  for (int i=0; i<fNJetFinder; i++) { fJJets[i]. Clear();
    fJTracks.Clear();
    fJMCTracks.Clear();

  }
  if (debug >0 && Entry()%1000 ==0 ) cout<<Entry()<<endl;
  return kTRUE;  // If return kFALSE FillHistogram() will NOT be executed.
}

//________________________________________________________________________
void AliJJetTask::Terminate(Option_t *)
{
  // Called once at the end of the analysis.
}

<|endoftext|>


<commit_before>#include "ParticleSystem.h"
#include <algorithm>
#include "Gl/glew.h"
#include "Particle.h"
#include "Object.h"
#include "Times.h"
#include "CameraManager.h"
#include "Camera.h"
#include "ShaderManager.h"

using namespace mwm;

const Vector3F ParticleSystem::g_vertex_buffer_data[4] = {
	Vector3F(-0.5f, -0.5f, 0.0f),
	Vector3F(0.5f, -0.5f, 0.0f),
	Vector3F(-0.5f, 0.5f, 0.0f),
	Vector3F(0.5f, 0.5f, 0.0f),
};

ParticleSystem::ParticleSystem(int MaxParticles, int emissionRate)
{
	this->LastUsedParticle = 0;
	this->MaxParticles = MaxParticles;
	ParticlesContainer = new Particle[MaxParticles];
	g_particule_position_size_data = new Vector4F[MaxParticles];
	g_particule_color_data = new Vector4F[MaxParticles];
	for (int i = 0; i < MaxParticles; i++){
		ParticlesContainer[i].lifeTime = -1.0f;
		ParticlesContainer[i].cameraDistance = -1.0;
	}
	EmissionRate = emissionRate;
	Color = Vector4F(1.f, 1.f, 1.f, 0.8f);
	Size = 1.f;
	LifeTime = 0.2;
	Direction = Vector3F(0.0f, 10.0f, 0.0f);
	Spread = 1.5f;
	aliveParticles = 0;
	SetUp();
	additive = true;
	Force = Vector3(0.0, -9.81, 0.0);
}

ParticleSystem::~ParticleSystem()
{
	glBindVertexArray(0);
	glDeleteVertexArrays(1, &vaoHandle);
	glDeleteBuffers(1, &billboard_vertex_buffer);
	glDeleteBuffers(1, &particles_position_buffer);
	glDeleteBuffers(1, &particles_color_buffer);
	delete[] ParticlesContainer;
	delete[] g_particule_position_size_data;
	delete[] g_particule_color_data;
}

int ParticleSystem::FindUnusedParticle()
{
	for (int i = LastUsedParticle; i < MaxParticles; i++){
		if (ParticlesContainer[i].lifeTime < 0.0){
			LastUsedParticle = i;
			return i;
		}
	}

	for (int i = 0; i < LastUsedParticle; i++){
		if (ParticlesContainer[i].lifeTime < 0.0){
			LastUsedParticle = i;
			return i;
		}
	}

	return (MaxParticles-1);
}

void ParticleSystem::UpdateParticles(double deltaTime, const mwm::Vector3& camPos)
{
	aliveParticles = 0;
	for (int i = 0; i < MaxParticles; i++){

		Particle& p = ParticlesContainer[i];

		if (p.lifeTime < 0.0)
		{
			// Particles that just died will be put at the end of the buffer in SortParticles();
			p.cameraDistance = -1.0;
		}
		else{
			p.lifeTime -= deltaTime;

			// Simulate simple physics : gravity only, no collisions
			p.speed += Force * deltaTime * 0.5;
			p.pos += p.speed * deltaTime;
			p.cameraDistance = (p.pos - camPos).squareMag();
			//p.size -= (float)deltaTime*3.5f;
			//if (p.size < 0.f) p.size = 0.f; p.lifeTime = 0.f;
			// Fill the GPU buffer
			g_particule_position_size_data[aliveParticles] = Vector4F(p.pos.toFloat(), p.size);
			g_particule_color_data[aliveParticles] = p.color;

			aliveParticles++;
		}
	}
}

void ParticleSystem::SortParticles(){
	std::sort(&ParticlesContainer[0], &ParticlesContainer[MaxParticles]);
}

void ParticleSystem::SetUp()
{
	//Create VAO
	glGenVertexArrays(1, &vaoHandle);
	//Bind VAO
	glBindVertexArray(vaoHandle);

	glGenBuffers(1, &billboard_vertex_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
	glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(Vector3F), g_vertex_buffer_data, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
	glEnableVertexAttribArray(0);

	// The VBO containing the positions and sizes of the particles
	glGenBuffers(1, &particles_position_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
	// Initialize with empty (NULL) buffer : it will be updated later, each frame.
	glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4F), NULL, GL_STREAM_DRAW);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
	glEnableVertexAttribArray(1);

	// The VBO containing the colors of the particles
	glGenBuffers(1, &particles_color_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
	// Initialize with empty (NULL) buffer : it will be updated later, each frame.
	glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4F), NULL, GL_STREAM_DRAW);
	glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
	glEnableVertexAttribArray(2);

	// These functions are specific to glDrawArrays*Instanced*.
	// The first parameter is the attribute buffer we're talking about.
	// The second parameter is the "rate at which generic vertex attributes advance when rendering multiple instances"
	// http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribDivisor.xml
	glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0
	glVertexAttribDivisor(1, 1); // positions : one per quad (its center)                 -> 1
	glVertexAttribDivisor(2, 1); // color : one per quad                                  -> 1

	//Unbind the VAO now that the VBOs have been set up
	glBindVertexArray(0);
}

void ParticleSystem::UpdateBuffers()
{
	//Bind VAO
	glBindVertexArray(vaoHandle);

	glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
	//glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4), g_particule_position_size_data, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details.
	glBufferSubData(GL_ARRAY_BUFFER, 0, aliveParticles * sizeof(Vector4F), g_particule_position_size_data);

	glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
	//glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4), g_particule_position_size_data, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details.
	glBufferSubData(GL_ARRAY_BUFFER, 0, aliveParticles * sizeof(Vector4F), g_particule_color_data);
}

int ParticleSystem::Draw(Matrix4F& ViewProjection, GLuint currentShaderID, const Vector3F& cameraUp, const Vector3F& cameraRight)
{
	UpdateBuffers();

	glEnable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
	// Use additive blending to give it a 'glow' effect
	if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	CameraRightHandle = glGetUniformLocation(currentShaderID, "CameraRight");
	CameraUpHandle = glGetUniformLocation(currentShaderID, "CameraUp");
	ViewProjectionHandle = glGetUniformLocation(currentShaderID, "VP");
	// Same as the billboards tutorial

	glUniform3fv(CameraRightHandle, 1, &cameraRight.x);
	glUniform3fv(CameraUpHandle, 1, & cameraUp.x);

	glUniformMatrix4fv(ViewProjectionHandle, 1, GL_FALSE, &ViewProjection[0][0]);

	// Bind our texture in Texture Unit 0
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, TextureID);
	TextureSamplerHandle = glGetUniformLocation(currentShaderID, "myTextureSampler");
	glUniform1i(TextureSamplerHandle, 0);

	glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, aliveParticles);

	// Don't forget to reset to default blending mode
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glDisable(GL_BLEND);

	return aliveParticles;
}

void ParticleSystem::SetTexture(GLuint textureID)
{
	this->TextureID = textureID;
}

void ParticleSystem::GenerateNewParticles(double deltaTime)
{
	// Generate 10 new particule each millisecond,
	// but limit this to 16 ms (60 fps), or if you have 1 long frame (1sec),
	// newparticles will be huge and the next frame even longer.
	newparticles = ceil(deltaTime*EmissionRate);
	if (newparticles > (int)(0.016*EmissionRate))
		newparticles = (int)(0.016*EmissionRate);

	for (int i = 0; i < newparticles; i++){
		int particleIndex = FindUnusedParticle();

		ParticlesContainer[particleIndex].lifeTime = LifeTime; // This particle will live 5 seconds.
		ParticlesContainer[particleIndex].pos = object->GetWorldPosition(); //Vector3();
		//printf("%d p: %f %f %f\n", particleIndex, ParticlesContainer[particleIndex].pos.x, ParticlesContainer[particleIndex].pos.y, ParticlesContainer[particleIndex].pos.z);

		// Very bad way to generate a random direction;
		// See for instance http://stackoverflow.com/questions/5408276/python-uniform-spherical-distribution instead,
		// combined with some user-controlled parameters (main direction, spread, etc)
		Vector3F randomdir = Vector3F(
			(rand() % 2000 - 1000.0f) / 1000.0f,
			(rand() % 2000 - 1000.0f) / 1000.0f,
			(rand() % 2000 - 1000.0f) / 1000.0f
			);
		randomdir = Direction + randomdir*Spread;
		ParticlesContainer[particleIndex].speed = Vector3(randomdir.x, randomdir.y, randomdir.z);
		ParticlesContainer[particleIndex].color = Color;

		ParticlesContainer[particleIndex].size = Size;//(float)((rand() % 1000) / 2000.0f + 0.1f);
	}
}

void ParticleSystem::SetEmissionRate(int emissionRate)
{
	EmissionRate = emissionRate;
}

void ParticleSystem::SetColor(const mwm::Vector4F& color)
{
	Color = color;
}

void ParticleSystem::SetSize(float size)
{
	Size = size;
}

void ParticleSystem::Update()
{
	GenerateNewParticles(Times::Instance()->deltaTime);
	UpdateParticles(Times::Instance()->deltaTime, CameraManager::Instance()->GetCurrentCamera()->GetPosition2());
	if (!additive) SortParticles();
}

void ParticleSystem::SetLifeTime(double lifetime)
{
	LifeTime = lifetime;
}

void ParticleSystem::SetDirection(const mwm::Vector3F& direction)
{
	Direction = direction;
}

void ParticleSystem::SetSpread(float spread)
{
	Spread = spread;
}

void ParticleSystem::SetForce(mwm::Vector3 & force)
{
	Force = force;
}<commit_msg>particle system will reuse particles with lowest lifetime if it can't find any unused ones<commit_after>#include "ParticleSystem.h"
#include <algorithm>
#include "Gl/glew.h"
#include "Particle.h"
#include "Object.h"
#include "Times.h"
#include "CameraManager.h"
#include "Camera.h"
#include "ShaderManager.h"

using namespace mwm;

const Vector3F ParticleSystem::g_vertex_buffer_data[4] = {
	Vector3F(-0.5f, -0.5f, 0.0f),
	Vector3F(0.5f, -0.5f, 0.0f),
	Vector3F(-0.5f, 0.5f, 0.0f),
	Vector3F(0.5f, 0.5f, 0.0f),
};

ParticleSystem::ParticleSystem(int MaxParticles, int emissionRate)
{
	this->LastUsedParticle = 0;
	this->MaxParticles = MaxParticles;
	ParticlesContainer = new Particle[MaxParticles];
	g_particule_position_size_data = new Vector4F[MaxParticles];
	g_particule_color_data = new Vector4F[MaxParticles];
	for (int i = 0; i < MaxParticles; i++){
		ParticlesContainer[i].lifeTime = -1.0f;
		ParticlesContainer[i].cameraDistance = -1.0;
	}
	EmissionRate = emissionRate;
	Color = Vector4F(1.f, 1.f, 1.f, 0.8f);
	Size = 1.f;
	LifeTime = 0.2;
	Direction = Vector3F(0.0f, 10.0f, 0.0f);
	Spread = 1.5f;
	aliveParticles = 0;
	SetUp();
	additive = true;
	Force = Vector3(0.0, -9.81, 0.0);
}

ParticleSystem::~ParticleSystem()
{
	glBindVertexArray(0);
	glDeleteVertexArrays(1, &vaoHandle);
	glDeleteBuffers(1, &billboard_vertex_buffer);
	glDeleteBuffers(1, &particles_position_buffer);
	glDeleteBuffers(1, &particles_color_buffer);
	delete[] ParticlesContainer;
	delete[] g_particule_position_size_data;
	delete[] g_particule_color_data;
}

int ParticleSystem::FindUnusedParticle()
{
	int particleWithLowestLifeTime = 0;
	double lowestParticleLifeTime = 10000.0;
	for (int i = LastUsedParticle; i < MaxParticles; i++){
		if (ParticlesContainer[i].lifeTime < 0.0){
			LastUsedParticle = i;
			return i;
		}
		else if(ParticlesContainer[i].lifeTime < lowestParticleLifeTime)
		{
			particleWithLowestLifeTime = i;
			lowestParticleLifeTime = ParticlesContainer[i].lifeTime;
		}
	}

	for (int i = 0; i < LastUsedParticle; i++){
		if (ParticlesContainer[i].lifeTime < 0.0){
			LastUsedParticle = i;
			return i;
		}
		else if (ParticlesContainer[i].lifeTime < lowestParticleLifeTime)
		{
			particleWithLowestLifeTime = i;
			lowestParticleLifeTime = ParticlesContainer[i].lifeTime;
		}
	}

	return particleWithLowestLifeTime;
}

void ParticleSystem::UpdateParticles(double deltaTime, const mwm::Vector3& camPos)
{
	aliveParticles = 0;
	for (int i = 0; i < MaxParticles; i++){

		Particle& p = ParticlesContainer[i];

		if (p.lifeTime < 0.0)
		{
			// Particles that just died will be put at the end of the buffer in SortParticles();
			p.cameraDistance = -1.0;
		}
		else{
			p.lifeTime -= deltaTime;

			// Simulate simple physics : gravity only, no collisions
			p.speed += Force * deltaTime * 0.5;
			p.pos += p.speed * deltaTime;
			p.cameraDistance = (p.pos - camPos).squareMag();
			//p.size -= (float)deltaTime*3.5f;
			//if (p.size < 0.f) p.size = 0.f; p.lifeTime = 0.f;
			// Fill the GPU buffer
			g_particule_position_size_data[aliveParticles] = Vector4F(p.pos.toFloat(), p.size);
			g_particule_color_data[aliveParticles] = p.color;

			aliveParticles++;
		}
	}
}

void ParticleSystem::SortParticles(){
	std::sort(&ParticlesContainer[0], &ParticlesContainer[MaxParticles]);
}

void ParticleSystem::SetUp()
{
	//Create VAO
	glGenVertexArrays(1, &vaoHandle);
	//Bind VAO
	glBindVertexArray(vaoHandle);

	glGenBuffers(1, &billboard_vertex_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
	glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(Vector3F), g_vertex_buffer_data, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
	glEnableVertexAttribArray(0);

	// The VBO containing the positions and sizes of the particles
	glGenBuffers(1, &particles_position_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
	// Initialize with empty (NULL) buffer : it will be updated later, each frame.
	glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4F), NULL, GL_STREAM_DRAW);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
	glEnableVertexAttribArray(1);

	// The VBO containing the colors of the particles
	glGenBuffers(1, &particles_color_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
	// Initialize with empty (NULL) buffer : it will be updated later, each frame.
	glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4F), NULL, GL_STREAM_DRAW);
	glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
	glEnableVertexAttribArray(2);

	// These functions are specific to glDrawArrays*Instanced*.
	// The first parameter is the attribute buffer we're talking about.
	// The second parameter is the "rate at which generic vertex attributes advance when rendering multiple instances"
	// http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribDivisor.xml
	glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0
	glVertexAttribDivisor(1, 1); // positions : one per quad (its center)                 -> 1
	glVertexAttribDivisor(2, 1); // color : one per quad                                  -> 1

	//Unbind the VAO now that the VBOs have been set up
	glBindVertexArray(0);
}

void ParticleSystem::UpdateBuffers()
{
	//Bind VAO
	glBindVertexArray(vaoHandle);

	glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
	//glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4), g_particule_position_size_data, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details.
	glBufferSubData(GL_ARRAY_BUFFER, 0, aliveParticles * sizeof(Vector4F), g_particule_position_size_data);

	glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
	//glBufferData(GL_ARRAY_BUFFER, MaxParticles * sizeof(Vector4), g_particule_position_size_data, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details.
	glBufferSubData(GL_ARRAY_BUFFER, 0, aliveParticles * sizeof(Vector4F), g_particule_color_data);
}

int ParticleSystem::Draw(Matrix4F& ViewProjection, GLuint currentShaderID, const Vector3F& cameraUp, const Vector3F& cameraRight)
{
	UpdateBuffers();

	glEnable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
	// Use additive blending to give it a 'glow' effect
	if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	CameraRightHandle = glGetUniformLocation(currentShaderID, "CameraRight");
	CameraUpHandle = glGetUniformLocation(currentShaderID, "CameraUp");
	ViewProjectionHandle = glGetUniformLocation(currentShaderID, "VP");
	// Same as the billboards tutorial

	glUniform3fv(CameraRightHandle, 1, &cameraRight.x);
	glUniform3fv(CameraUpHandle, 1, & cameraUp.x);

	glUniformMatrix4fv(ViewProjectionHandle, 1, GL_FALSE, &ViewProjection[0][0]);

	// Bind our texture in Texture Unit 0
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, TextureID);
	TextureSamplerHandle = glGetUniformLocation(currentShaderID, "myTextureSampler");
	glUniform1i(TextureSamplerHandle, 0);

	glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, aliveParticles);

	// Don't forget to reset to default blending mode
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glDisable(GL_BLEND);

	return aliveParticles;
}

void ParticleSystem::SetTexture(GLuint textureID)
{
	this->TextureID = textureID;
}

void ParticleSystem::GenerateNewParticles(double deltaTime)
{
	// Generate 10 new particule each millisecond,
	// but limit this to 16 ms (60 fps), or if you have 1 long frame (1sec),
	// newparticles will be huge and the next frame even longer.
	newparticles = ceil(deltaTime*EmissionRate);
	if (newparticles > (int)(0.016*EmissionRate))
		newparticles = (int)(0.016*EmissionRate);

	for (int i = 0; i < newparticles; i++){
		int particleIndex = FindUnusedParticle();

		ParticlesContainer[particleIndex].lifeTime = LifeTime; // This particle will live 5 seconds.
		ParticlesContainer[particleIndex].pos = object->GetWorldPosition(); //Vector3();
		//printf("%d p: %f %f %f\n", particleIndex, ParticlesContainer[particleIndex].pos.x, ParticlesContainer[particleIndex].pos.y, ParticlesContainer[particleIndex].pos.z);

		// Very bad way to generate a random direction;
		// See for instance http://stackoverflow.com/questions/5408276/python-uniform-spherical-distribution instead,
		// combined with some user-controlled parameters (main direction, spread, etc)
		Vector3F randomdir = Vector3F(
			(rand() % 2000 - 1000.0f) / 1000.0f,
			(rand() % 2000 - 1000.0f) / 1000.0f,
			(rand() % 2000 - 1000.0f) / 1000.0f
			);
		randomdir = Direction + randomdir*Spread;
		ParticlesContainer[particleIndex].speed = Vector3(randomdir.x, randomdir.y, randomdir.z);
		ParticlesContainer[particleIndex].color = Color;

		ParticlesContainer[particleIndex].size = Size;//(float)((rand() % 1000) / 2000.0f + 0.1f);
	}
}

void ParticleSystem::SetEmissionRate(int emissionRate)
{
	EmissionRate = emissionRate;
}

void ParticleSystem::SetColor(const mwm::Vector4F& color)
{
	Color = color;
}

void ParticleSystem::SetSize(float size)
{
	Size = size;
}

void ParticleSystem::Update()
{
	GenerateNewParticles(Times::Instance()->deltaTime);
	UpdateParticles(Times::Instance()->deltaTime, CameraManager::Instance()->GetCurrentCamera()->GetPosition2());
	if (!additive) SortParticles();
}

void ParticleSystem::SetLifeTime(double lifetime)
{
	LifeTime = lifetime;
}

void ParticleSystem::SetDirection(const mwm::Vector3F& direction)
{
	Direction = direction;
}

void ParticleSystem::SetSpread(float spread)
{
	Spread = spread;
}

void ParticleSystem::SetForce(mwm::Vector3 & force)
{
	Force = force;
}
<|endoftext|>