<commit_before>/*

Copyright (c) 2005, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_CONFIG_HPP_INCLUDED
#define TORRENT_CONFIG_HPP_INCLUDED

#include <boost/config.hpp>
#include <boost/version.hpp>
#include <stdio.h> // for snprintf

#ifndef WIN32
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif

#ifndef PRId64
#ifdef _WIN32
#define PRId64 "I64d"
#else
#define PRId64 "lld"
#endif
#endif

#if defined(__GNUC__) && __GNUC__ >= 4

#define TORRENT_DEPRECATED __attribute__ ((deprecated))

# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
#  define TORRENT_EXPORT __attribute__ ((visibility("default")))
# else
#  define TORRENT_EXPORT
# endif

#elif defined(__GNUC__)

# define TORRENT_EXPORT

#elif defined(BOOST_MSVC)

#pragma warning(disable: 4258)
#pragma warning(disable: 4251)

# if defined(TORRENT_BUILDING_SHARED)
#  define TORRENT_EXPORT __declspec(dllexport)
# elif defined(TORRENT_LINKING_SHARED)
#  define TORRENT_EXPORT __declspec(dllimport)
# else
#  define TORRENT_EXPORT
# endif

#else
# define TORRENT_EXPORT
#endif

#ifndef TORRENT_DEPRECATED
#define TORRENT_DEPRECATED
#endif

// set up defines for target environments
#if (defined __APPLE__ && __MACH__) || defined __FreeBSD__ || defined __NetBSD__ \
	|| defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \
	|| defined __FreeBSD_kernel__
#define TORRENT_BSD
#elif defined __linux__
#define TORRENT_LINUX
#elif defined __MINGW32__
#define TORRENT_MINGW
#elif defined WIN32
#define TORRENT_WINDOWS
#elif defined sun || defined __sun
#define TORRENT_SOLARIS
#else
#warning unkown OS, assuming BSD
#define TORRENT_BSD
#endif

#define TORRENT_USE_IPV6 1
#define TORRENT_USE_MLOCK 1
#define TORRENT_USE_READV 1
#define TORRENT_USE_WRITEV 1
#define TORRENT_USE_IOSTREAM 1

// should wpath or path be used?
#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY \
	&& BOOST_VERSION >= 103400 && !defined __APPLE__
#define TORRENT_USE_WPATH 1
#else
#define TORRENT_USE_WPATH 0
#endif

#ifdef TORRENT_WINDOWS
#include <stdarg.h>
// this is the maximum number of characters in a
// path element / filename on windows
#define NAME_MAX 255
inline int snprintf(char* buf, int len, char const* fmt, ...)
{
	va_list lp;
	va_start(lp, fmt);
	return vsnprintf_s(buf, len, _TRUNCATE, fmt, lp);
}
#define strtoll _strtoi64
#else
#include <limits.h>
#endif

#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defined (TORRENT_UPNP_LOGGING)
#define TORRENT_UPNP_LOGGING
#endif

#if !TORRENT_USE_WPATH && defined TORRENT_LINUX
// libiconv presnce, not implemented yet
#define TORRENT_USE_LOCALE_FILENAMES 1
#else
#define TORRENT_USE_LOCALE_FILENAMES 0
#endif

#if !defined(TORRENT_READ_HANDLER_MAX_SIZE)
# define TORRENT_READ_HANDLER_MAX_SIZE 256
#endif

#if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE)
# define TORRENT_WRITE_HANDLER_MAX_SIZE 256
#endif

// determine what timer implementation we can use

#if defined(__MACH__)
#define TORRENT_USE_ABSOLUTE_TIME 1
#elif defined(_WIN32)
#define TORRENT_USE_QUERY_PERFORMANCE_TIMER 1
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
#define TORRENT_USE_CLOCK_GETTIME 1
#else
#define TORRENT_USE_BOOST_DATE_TIME 1
#endif

#endif // TORRENT_CONFIG_HPP_INCLUDED

<commit_msg>attempt to make it build on windows<commit_after>/*

Copyright (c) 2005, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_CONFIG_HPP_INCLUDED
#define TORRENT_CONFIG_HPP_INCLUDED

#include <boost/config.hpp>
#include <boost/version.hpp>
#include <stdio.h> // for snprintf
#include <stdlib.h> // for _TRUNCATE (windows)
#include <stdarg.h>

#ifndef WIN32
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif

#ifndef PRId64
#ifdef _WIN32
#define PRId64 "I64d"
#else
#define PRId64 "lld"
#endif
#endif

#if defined(__GNUC__) && __GNUC__ >= 4

#define TORRENT_DEPRECATED __attribute__ ((deprecated))

# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
#  define TORRENT_EXPORT __attribute__ ((visibility("default")))
# else
#  define TORRENT_EXPORT
# endif

#elif defined(__GNUC__)

# define TORRENT_EXPORT

#elif defined(BOOST_MSVC)

#pragma warning(disable: 4258)
#pragma warning(disable: 4251)

# if defined(TORRENT_BUILDING_SHARED)
#  define TORRENT_EXPORT __declspec(dllexport)
# elif defined(TORRENT_LINKING_SHARED)
#  define TORRENT_EXPORT __declspec(dllimport)
# else
#  define TORRENT_EXPORT
# endif

#else
# define TORRENT_EXPORT
#endif

#ifndef TORRENT_DEPRECATED
#define TORRENT_DEPRECATED
#endif

// set up defines for target environments
#if (defined __APPLE__ && __MACH__) || defined __FreeBSD__ || defined __NetBSD__ \
	|| defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \
	|| defined __FreeBSD_kernel__
#define TORRENT_BSD
#elif defined __linux__
#define TORRENT_LINUX
#elif defined __MINGW32__
#define TORRENT_MINGW
#elif defined WIN32
#define TORRENT_WINDOWS
#elif defined sun || defined __sun
#define TORRENT_SOLARIS
#else
#warning unkown OS, assuming BSD
#define TORRENT_BSD
#endif

#define TORRENT_USE_IPV6 1
#define TORRENT_USE_MLOCK 1
#define TORRENT_USE_READV 1
#define TORRENT_USE_WRITEV 1
#define TORRENT_USE_IOSTREAM 1

// should wpath or path be used?
#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY \
	&& BOOST_VERSION >= 103400 && !defined __APPLE__
#define TORRENT_USE_WPATH 1
#else
#define TORRENT_USE_WPATH 0
#endif

#ifdef TORRENT_WINDOWS
#include <stdarg.h>
// this is the maximum number of characters in a
// path element / filename on windows
#define NAME_MAX 255
inline int snprintf(char* buf, int len, char const* fmt, ...)
{
	va_list lp;
	va_start(lp, fmt);
	return vsnprintf_s(buf, len, _TRUNCATE, fmt, lp);
}
#define strtoll _strtoi64
#else
#include <limits.h>
#endif

#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defined (TORRENT_UPNP_LOGGING)
#define TORRENT_UPNP_LOGGING
#endif

#if !TORRENT_USE_WPATH && defined TORRENT_LINUX
// libiconv presnce, not implemented yet
#define TORRENT_USE_LOCALE_FILENAMES 1
#else
#define TORRENT_USE_LOCALE_FILENAMES 0
#endif

#if !defined(TORRENT_READ_HANDLER_MAX_SIZE)
# define TORRENT_READ_HANDLER_MAX_SIZE 256
#endif

#if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE)
# define TORRENT_WRITE_HANDLER_MAX_SIZE 256
#endif

// determine what timer implementation we can use

#if defined(__MACH__)
#define TORRENT_USE_ABSOLUTE_TIME 1
#elif defined(_WIN32)
#define TORRENT_USE_QUERY_PERFORMANCE_TIMER 1
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
#define TORRENT_USE_CLOCK_GETTIME 1
#else
#define TORRENT_USE_BOOST_DATE_TIME 1
#endif

#endif // TORRENT_CONFIG_HPP_INCLUDED

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_VALUE_HASH_HPP
#define MAPNIK_VALUE_HASH_HPP

// mapnik
#include <mapnik/util/variant.hpp>
#include <mapnik/value_types.hpp>

// stl
#include <functional>
#include <cassert>

// icu
#include <unicode/unistr.h>

namespace mapnik { namespace detail {

template <class T>
inline void hash_combine(std::size_t & seed, T const& v)
{
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

struct value_hasher
{
    std::size_t operator() (value_null val) const
    {
        return hash_value(val);
    }

    std::size_t operator() (value_unicode_string const& val) const
    {
        assert(val.hashCode() > 0);
        return static_cast<std::size_t>(val.hashCode());
    }

    template <class T>
    std::size_t operator()(T const& val) const
    {
        std::hash<T> hasher;
        return hasher(val);
    }
};

} // namespace  detail

template <typename T>
std::size_t mapnik_hash_value(T const& val)
{
    std::size_t seed = util::apply_visitor(detail::value_hasher(), val);
    detail::hash_combine(seed, val.get_type_index());
    return seed;
}

} // namespace mapnik

#endif // MAPNIK_VALUE_HASH_HPP
<commit_msg>add std::hash specialization for mapnik::value<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_VALUE_HASH_HPP
#define MAPNIK_VALUE_HASH_HPP

// mapnik
#include <mapnik/util/variant.hpp>
#include <mapnik/value_types.hpp>

// stl
#include <functional>
#include <cassert>

// icu
#include <unicode/unistr.h>

namespace mapnik { namespace detail {

template <class T>
inline void hash_combine(std::size_t & seed, T const& v)
{
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

struct value_hasher
{
    std::size_t operator() (value_null val) const
    {
        return hash_value(val);
    }

    std::size_t operator() (value_unicode_string const& val) const
    {
        assert(val.hashCode() > 0);
        return static_cast<std::size_t>(val.hashCode());
    }

    template <class T>
    std::size_t operator()(T const& val) const
    {
        std::hash<T> hasher;
        return hasher(val);
    }
};

} // namespace  detail

template <typename T>
std::size_t mapnik_hash_value(T const& val)
{
    std::size_t seed = util::apply_visitor(detail::value_hasher(), val);
    detail::hash_combine(seed, val.get_type_index());
    return seed;
}

} // namespace mapnik

// support for std::unordered containers
namespace std
{
template <>
struct hash<mapnik::value>
{
    size_t operator()(const mapnik::value& val) const
    {
        return mapnik::mapnik_hash_value(val);
    }
};

#endif // MAPNIK_VALUE_HASH_HPP
<|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.                  *
 **************************************************************************/
/* $Id: $ */

//_________________________________________________________________________
// Analysis task that executes the analysis classes
// that depend on the PartCorr frame, frame for Particle identification and correlations.
// Specially designed for calorimeters but also can be used for charged tracks
// Input of this task is a configuration file that contains all the settings of the analyis
//
// -- Author: Gustavo Conesa (INFN-LNF)

// root
#include <TROOT.h>
#include <TInterpreter.h>
//#include <Riostream.h>

// analysis
#include "AliAnalysisTaskParticleCorrelation.h"
#include "AliAnaPartCorrMaker.h"
#include "AliCaloTrackReader.h"
#include "AliPDG.h"

ClassImp(AliAnalysisTaskParticleCorrelation)

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

  AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation():
    AliAnalysisTaskSE(),
    fAna(0x0),
    fOutputContainer(0x0),
    fConfigName(0)
{
  // Default constructor
}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation(const char* name):
  AliAnalysisTaskSE(name),
  fAna(0x0),
  fOutputContainer(0x0),
  fConfigName("")
{
  // Default constructor

  DefineOutput(1, TList::Class());

}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::~AliAnalysisTaskParticleCorrelation()
{
  // Remove all pointers

  if(fOutputContainer){
    fOutputContainer->Clear() ;
    delete fOutputContainer ;
  }

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserCreateOutputObjects()
{
  // Create the output container
  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::CreateOutputData() - Begin \n");

  //Get list of aod arrays, add each aod array to analysis frame
  TClonesArray * array = 0;
  TList * list = fAna->GetAODBranchList();
  for(Int_t iaod = 0; iaod < list->GetEntries(); iaod++){
    array = (TClonesArray*) list->At(iaod);
    AddAODBranch("TClonesArray", &array);
  }

  //Histograms container
  OpenFile(1);
  fOutputContainer = fAna->GetOutputContainer();
  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::CreateOutputData() - End \n");
}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Init()
{
  // Initialization

  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Init() - Begin \n");

  // Call configuration file if specified

  if (fConfigName.Length()) {
    printf("AliAnalysisTaskParticleCorrelation::Init() - ### Configuration file is %s.C ###", fConfigName.Data());
	gROOT->LoadMacro(fConfigName+".C");
	fAna = (AliAnaPartCorrMaker*) gInterpreter->ProcessLine("ConfigAnalysis()");
  }

  if(!fAna){
    printf("AliAnalysisTaskParticleCorrelation::Init() Analysis maker pointer not initialized, no analysis specified, abort analysis!\n");
    abort();
  }

  // Add different generator particles to PDG Data Base
  // to avoid problems when reading MC generator particles
  AliPDG::AddParticlesToPdgDataBase();

  // Initialise analysis
  fAna->Init();

  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Init() - End \n");

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserExec(Option_t */*option*/)
{
  // Execute analysis for current event
  //
  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Exec() - Begin \n");

  //Get the type of data, check if type is correct
  Int_t  datatype = fAna->GetReader()->GetDataType();
  if(datatype != AliCaloTrackReader::kESD && datatype != AliCaloTrackReader::kAOD &&
     datatype != AliCaloTrackReader::kMC){
    printf("AliAnalysisTaskParticleCorrelation::Exec() - Wrong type of data\n");
    return ;
  }
  fAna->GetReader()->SetInputOutputMCEvent(InputEvent(), AODEvent(), MCEvent());

  //Process event
  fAna->ProcessEvent((Int_t) Entry());

  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Exec() - End \n");

  PostData(1, fOutputContainer);

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Terminate(Option_t */*option*/)
{
  // Terminate analysis
  // Do some plots
  //

  fAna->Terminate();

}

<commit_msg>Include cstdlib to declare abort()<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.                  *
 **************************************************************************/
/* $Id: $ */

//_________________________________________________________________________
// Analysis task that executes the analysis classes
// that depend on the PartCorr frame, frame for Particle identification and correlations.
// Specially designed for calorimeters but also can be used for charged tracks
// Input of this task is a configuration file that contains all the settings of the analyis
//
// -- Author: Gustavo Conesa (INFN-LNF)

#include <cstdlib>
// root
#include <TROOT.h>
#include <TInterpreter.h>
//#include <Riostream.h>

// analysis
#include "AliAnalysisTaskParticleCorrelation.h"
#include "AliAnaPartCorrMaker.h"
#include "AliCaloTrackReader.h"
#include "AliPDG.h"

ClassImp(AliAnalysisTaskParticleCorrelation)

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

  AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation():
    AliAnalysisTaskSE(),
    fAna(0x0),
    fOutputContainer(0x0),
    fConfigName(0)
{
  // Default constructor
}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation(const char* name):
  AliAnalysisTaskSE(name),
  fAna(0x0),
  fOutputContainer(0x0),
  fConfigName("")
{
  // Default constructor

  DefineOutput(1, TList::Class());

}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::~AliAnalysisTaskParticleCorrelation()
{
  // Remove all pointers

  if(fOutputContainer){
    fOutputContainer->Clear() ;
    delete fOutputContainer ;
  }

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserCreateOutputObjects()
{
  // Create the output container
  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::CreateOutputData() - Begin \n");

  //Get list of aod arrays, add each aod array to analysis frame
  TClonesArray * array = 0;
  TList * list = fAna->GetAODBranchList();
  for(Int_t iaod = 0; iaod < list->GetEntries(); iaod++){
    array = (TClonesArray*) list->At(iaod);
    AddAODBranch("TClonesArray", &array);
  }

  //Histograms container
  OpenFile(1);
  fOutputContainer = fAna->GetOutputContainer();
  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::CreateOutputData() - End \n");
}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Init()
{
  // Initialization

  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Init() - Begin \n");

  // Call configuration file if specified

  if (fConfigName.Length()) {
    printf("AliAnalysisTaskParticleCorrelation::Init() - ### Configuration file is %s.C ###", fConfigName.Data());
	gROOT->LoadMacro(fConfigName+".C");
	fAna = (AliAnaPartCorrMaker*) gInterpreter->ProcessLine("ConfigAnalysis()");
  }

  if(!fAna){
    printf("AliAnalysisTaskParticleCorrelation::Init() Analysis maker pointer not initialized, no analysis specified, abort analysis!\n");
    abort();
  }

  // Add different generator particles to PDG Data Base
  // to avoid problems when reading MC generator particles
  AliPDG::AddParticlesToPdgDataBase();

  // Initialise analysis
  fAna->Init();

  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Init() - End \n");

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserExec(Option_t */*option*/)
{
  // Execute analysis for current event
  //
  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Exec() - Begin \n");

  //Get the type of data, check if type is correct
  Int_t  datatype = fAna->GetReader()->GetDataType();
  if(datatype != AliCaloTrackReader::kESD && datatype != AliCaloTrackReader::kAOD &&
     datatype != AliCaloTrackReader::kMC){
    printf("AliAnalysisTaskParticleCorrelation::Exec() - Wrong type of data\n");
    return ;
  }
  fAna->GetReader()->SetInputOutputMCEvent(InputEvent(), AODEvent(), MCEvent());

  //Process event
  fAna->ProcessEvent((Int_t) Entry());

  if (fDebug > 1) printf("AliAnalysisTaskParticleCorrelation::Exec() - End \n");

  PostData(1, fOutputContainer);

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Terminate(Option_t */*option*/)
{
  // Terminate analysis
  // Do some plots
  //

  fAna->Terminate();

}

<|endoftext|>


<commit_before>//=============================================================================
//
// *** AddTaskFemtoAzimtuhalHBT.C ***
//
// This macro initialize a complete AnalysisTask object for femtoscopy.
//
//=============================================================================

AliAnalysisTaskFemto *AddTaskFemtoAzimtuhalHBT(TString configMacroName, const char *containerName="femtolist", const char *configMacroParameters="" )
{
// Creates a proton analysis task and adds it to the analysis manager.

  // A. Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskFemtoAzimtuhalHBT", "No analysis manager to connect to.");
    return NULL;
  }
	TString inputDataType = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"
	Bool_t useEtaGap=kFALSE;
	Float_t etaGap=0.;
	Bool_t posTPCAOD=kFALSE;
	TString containername = "EPStat_ttd";

  // B. Check the analysis type using the event handlers connected to the analysis
  //    manager. The availability of MC handler cann also be checked here.
  //==============================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskFemtoAzimtuhalHBT", "This task requires an input event handler");
    return NULL;
  }
  TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"
 // cout << "Found " <<type << " event handler" << endl;

	//gROOT->LoadMacro("AliEPSelectionTask3.cxx+g");
	//gROOT->LoadMacro("AddTaskEventplane.C");
	//AliEPSelectionTask3* epsel = AddTaskEventplane();
	AliEPSelectionTask *eventplaneTask = new AliEPSelectionTask("EventplaneSelection4");
	eventplaneTask->SelectCollisionCandidates(AliVEvent::kMB | AliVEvent::kSemiCentral | AliVEvent::kCentral);
	if (inputDataType == "AOD"){
		eventplaneTask->SetInput("AOD");
	}
	eventplaneTask->SetTrackType("TPC");
	eventplaneTask->SetUsePtWeight();
	eventplaneTask->SetUsePhiWeight();
	eventplaneTask->SetSaveTrackContribution();
	if(useEtaGap){
		eventplaneTask->SetSubeventsSplitMethod(AliEPSelectionTask3::kEta);
		eventplaneTask->SetEtaGap(etaGap);
	}
	if(posTPCAOD){
		eventplaneTask->SetPersonalAODtrackCuts(128,0.,0.8,0.15,20.);
		eventplaneTask->SetSubeventsSplitMethod(AliEPSelectionTask3::kRandom);
	}

	mgr->AddTask(eventplaneTask);

  // C. Create the task, add it to manager.
  //===========================================================================
//  gSystem->SetIncludePath("-I$ROOTSYS/include  -I./PWG2AOD/AOD -I./PWG2femtoscopy/FEMTOSCOPY/AliFemto -I./PWG2femtoscopyUser/FEMTOSCOPY/AliFemtoUser -I$ALICE_ROOT/include");

  if (TProofMgr::GetListOfManagers()->GetEntries()) {
//     if (dynamic_cast<TProofLite *> gProof) {
//       char *macrocommand[10000];
//       sprintf(macrocommand, ".L %s", configMacroName);
//       gProof->Exec(macrocommand);
//     }
//     else
    gProof->Load(configMacroName);
  }
  //  gROOT->LoadMacro("ConfigFemtoAnalysis.C++");

  AliAnalysisTaskFemto *taskfemto = new AliAnalysisTaskFemto("TaskFemto","$ALICE_ROOT/"+configMacroName,configMacroParameters);
  	//taskfemto->SelectCollisionCandidates(AliVEvent::kMB | AliVEvent::kCentral | AliVEvent::kSemiCentral) ;

	mgr->AddTask(taskfemto);

  // D. Configure the analysis task. Extra parameters can be used via optional
  // arguments of the AddTaskXXX() function.
  //===========================================================================

  // E. Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================
  TString outputfile = AliAnalysisManager::GetCommonFileName();
 // outputfile += ":PWG2FEMTO";
  AliAnalysisDataContainer *cout_femto  = mgr->CreateContainer(containerName,  TList::Class(),
  							       AliAnalysisManager::kOutputContainer,outputfile);

   mgr->ConnectInput(taskfemto, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(taskfemto, 0, cout_femto);
	AliAnalysisDataContainer *cinput0 = mgr->GetCommonInputContainer();
	AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(containername,
															  TList::Class(), AliAnalysisManager::kOutputContainer,
															  "EventStat_temp.root");

	mgr->ConnectInput(eventplaneTask, 0, mgr->GetCommonInputContainer());
	mgr->ConnectOutput(eventplaneTask,1,coutput1);

   // Return task pointer at the end
   return taskfemto;
}
<commit_msg>All outputs in one file for Azimuthal HBT<commit_after>//=============================================================================
//
// *** AddTaskFemtoAzimtuhalHBT.C ***
//
// This macro initialize a complete AnalysisTask object for femtoscopy.
//
//=============================================================================

AliAnalysisTaskFemto *AddTaskFemtoAzimtuhalHBT(TString configMacroName, const char *containerName="femtolist", const char *configMacroParameters="" )
{
// Creates a proton analysis task and adds it to the analysis manager.

  // A. Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskFemtoAzimtuhalHBT", "No analysis manager to connect to.");
    return NULL;
  }
	TString inputDataType = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"
	Bool_t useEtaGap=kFALSE;
	Float_t etaGap=0.;
	Bool_t posTPCAOD=kFALSE;
	TString containername = "EPStat_ttd";

  // B. Check the analysis type using the event handlers connected to the analysis
  //    manager. The availability of MC handler cann also be checked here.
  //==============================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskFemtoAzimtuhalHBT", "This task requires an input event handler");
    return NULL;
  }
  TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"
 // cout << "Found " <<type << " event handler" << endl;

	//gROOT->LoadMacro("AliEPSelectionTask3.cxx+g");
	//gROOT->LoadMacro("AddTaskEventplane.C");
	//AliEPSelectionTask3* epsel = AddTaskEventplane();
	AliEPSelectionTask *eventplaneTask = new AliEPSelectionTask("EventplaneSelection4");
	eventplaneTask->SelectCollisionCandidates(AliVEvent::kMB | AliVEvent::kSemiCentral | AliVEvent::kCentral);
	if (inputDataType == "AOD"){
		eventplaneTask->SetInput("AOD");
	}
	eventplaneTask->SetTrackType("TPC");
	eventplaneTask->SetUsePtWeight();
	eventplaneTask->SetUsePhiWeight();
	eventplaneTask->SetSaveTrackContribution();
	if(useEtaGap){
		eventplaneTask->SetSubeventsSplitMethod(AliEPSelectionTask3::kEta);
		eventplaneTask->SetEtaGap(etaGap);
	}
	if(posTPCAOD){
		eventplaneTask->SetPersonalAODtrackCuts(128,0.,0.8,0.15,20.);
		eventplaneTask->SetSubeventsSplitMethod(AliEPSelectionTask3::kRandom);
	}

	mgr->AddTask(eventplaneTask);

  // C. Create the task, add it to manager.
  //===========================================================================
//  gSystem->SetIncludePath("-I$ROOTSYS/include  -I./PWG2AOD/AOD -I./PWG2femtoscopy/FEMTOSCOPY/AliFemto -I./PWG2femtoscopyUser/FEMTOSCOPY/AliFemtoUser -I$ALICE_ROOT/include");

  if (TProofMgr::GetListOfManagers()->GetEntries()) {
//     if (dynamic_cast<TProofLite *> gProof) {
//       char *macrocommand[10000];
//       sprintf(macrocommand, ".L %s", configMacroName);
//       gProof->Exec(macrocommand);
//     }
//     else
    gProof->Load(configMacroName);
  }
  //  gROOT->LoadMacro("ConfigFemtoAnalysis.C++");

  AliAnalysisTaskFemto *taskfemto = new AliAnalysisTaskFemto("TaskFemto","$ALICE_ROOT/"+configMacroName,configMacroParameters,kFALSE);
  	//taskfemto->SelectCollisionCandidates(AliVEvent::kMB | AliVEvent::kCentral | AliVEvent::kSemiCentral) ;

	mgr->AddTask(taskfemto);

  // D. Configure the analysis task. Extra parameters can be used via optional
  // arguments of the AddTaskXXX() function.
  //===========================================================================

  // E. Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================
  TString outputfile = AliAnalysisManager::GetCommonFileName();
 // outputfile += ":PWG2FEMTO";
  AliAnalysisDataContainer *cout_femto  = mgr->CreateContainer(containerName,  TList::Class(),
  							       AliAnalysisManager::kOutputContainer,outputfile);

   mgr->ConnectInput(taskfemto, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(taskfemto, 0, cout_femto);
   AliAnalysisDataContainer *cinput0 = mgr->GetCommonInputContainer();
   AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(containername, TList::Class(), AliAnalysisManager::kOutputContainer,outputfile);

   mgr->ConnectInput(eventplaneTask, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(eventplaneTask,1,coutput1);

   // Return task pointer at the end
   return taskfemto;
}
<|endoftext|>


<commit_before>/* Representation for raw, binary data.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead.
 *
 * Copyright (c) 2000-2020, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_BINARYSTRING
#define PQXX_H_BINARYSTRING

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <memory>
#include <string>
#include <string_view>

#include "pqxx/result.hxx"
#include "pqxx/strconv.hxx"

namespace pqxx
{
class binarystring;
template<> struct string_traits<binarystring>;

/// Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
/** @ingroup escaping-functions
 *
 * This class represents a binary string as stored in a field of type @c bytea.
 *
 * Internally a binarystring is zero-terminated, but it may also contain null
 * bytes, they're just like any other byte value.  So don't assume that it's
 * safe to treat the contents as a C-style string.
 *
 * The binarystring retains its value even if the result it was obtained from
 * is destroyed, but it cannot be copied or assigned.
 *
 * \relatesalso transaction_base::quote_raw
 *
 * To include a @c binarystring value in an SQL query, escape and quote it
 * using the transaction's @c quote_raw function.
 *
 * @warning This class is implemented as a reference-counting smart pointer.
 * Copying, swapping, and destroying binarystring objects that refer to the
 * same underlying data block is not thread-safe.  If you wish to pass
 * binarystrings around between threads, make sure that each of these
 * operations is protected against concurrency with similar operations on the
 * same object, or other objects pointing to the same data block.
 */
class PQXX_LIBEXPORT binarystring
{
public:
  using char_type = unsigned char;
  using value_type = std::char_traits<char_type>::char_type;
  using size_type = std::size_t;
  using difference_type = long;
  using const_reference = value_type const &;
  using const_pointer = value_type const *;
  using const_iterator = const_pointer;
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;

  binarystring(binarystring const &) = default;

  /// Read and unescape bytea field.
  /** The field will be zero-terminated, even if the original bytea field
   * isn't.
   * @param F the field to read; must be a bytea field
   */
  explicit binarystring(field const &);

  /// Copy binary data from std::string_view on binary data.
  /** This is inefficient in that it copies the data to a buffer allocated on
   * the heap.
   */
  explicit binarystring(std::string_view);

  /// Copy binary data of given length straight out of memory.
  binarystring(void const *, std::size_t);

  /// Efficiently wrap a buffer of binary data in a @c binarystring.
  binarystring(std::shared_ptr<value_type> ptr, size_type size) :
          m_buf{std::move(ptr)}, m_size{size}
  {}

  /// Size of converted string in bytes.
  [[nodiscard]] size_type size() const noexcept { return m_size; }
  /// Size of converted string in bytes.
  [[nodiscard]] size_type length() const noexcept { return size(); }
  [[nodiscard]] bool empty() const noexcept { return size() == 0; }

  [[nodiscard]] const_iterator begin() const noexcept { return data(); }
  [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
  [[nodiscard]] const_iterator end() const noexcept { return data() + m_size; }
  [[nodiscard]] const_iterator cend() const noexcept { return end(); }

  [[nodiscard]] const_reference front() const noexcept { return *begin(); }
  [[nodiscard]] const_reference back() const noexcept
  {
    return *(data() + m_size - 1);
  }

  [[nodiscard]] const_reverse_iterator rbegin() const
  {
    return const_reverse_iterator{end()};
  }
  [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); }
  [[nodiscard]] const_reverse_iterator rend() const
  {
    return const_reverse_iterator{begin()};
  }
  [[nodiscard]] const_reverse_iterator crend() const { return rend(); }

  /// Unescaped field contents.
  [[nodiscard]] value_type const *data() const noexcept { return m_buf.get(); }

  [[nodiscard]] const_reference operator[](size_type i) const noexcept
  {
    return data()[i];
  }

  [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const noexcept;
  [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept
  {
    return not operator==(rhs);
  }

  binarystring &operator=(binarystring const &);

  /// Index contained string, checking for valid index.
  const_reference at(size_type) const;

  /// Swap contents with other binarystring.
  void swap(binarystring &);

  /// Raw character buffer (no terminating zero is added).
  /** @warning No terminating zero is added!  If the binary data did not end in
   * a null character, you will not find one here.
   */
  [[nodiscard]] char const *get() const noexcept
  {
    return reinterpret_cast<char const *>(m_buf.get());
  }

  /// Read contents as a std::string_view.
  [[nodiscard]] std::string_view view() const noexcept
  {
    return std::string_view(get(), size());
  }

  /// Read as regular C++ string (may include null characters).
  /** This creates and returns a new string object.  Don't call this
   * repeatedly; retrieve your string once and keep it in a local variable.
   * Also, do not expect to be able to compare the string's address to that of
   * an earlier invocation.
   */
  [[nodiscard]] std::string str() const;

private:
  std::shared_ptr<value_type> m_buf;
  size_type m_size{0};
};

// TODO: Should binarystring have a default-constructed null value?
template<> struct nullness<binarystring> : no_null<binarystring>
{};

/// String conversion traits for @c binarystring.
/** Defines the conversions between a @c binarystring and its PostgreSQL
 * textual format, for communication with the database.
 *
 * These conversions rely on the "hex" format which was introduced in
 * PostgreSQL 9.0.  Both your libpq and the server must be recent enough to
 * speak this format.
 */
template<> struct string_traits<binarystring>
{
  static std::size_t size_buffer(binarystring const &value) noexcept
  {
    return internal::size_esc_bin(value.size());
  }

  static zview to_buf(char *begin, char *end, binarystring const &value)
  {
    auto const value_end{into_buf(begin, end, value)};
    return zview{begin, value_end - begin - 1};
  }

  static char *into_buf(char *begin, char *end, binarystring const &value)
  {
    auto const budget{size_buffer(value)};
    if (static_cast<std::size_t>(end - begin) < budget)
      throw conversion_overrun{
        "Not enough buffer space to escape binary data."};
    internal::esc_bin(value.view(), begin);
    return begin + budget;
  }

  static binarystring from_string(std::string_view text)
  {
    auto const size{pqxx::internal::size_unesc_bin(text.size())};
    std::shared_ptr<unsigned char> buf{
      new unsigned char[size], [](unsigned char const *x) { delete[] x; }};
    pqxx::internal::unesc_bin(text, reinterpret_cast<std::byte *>(buf.get()));
    return binarystring{std::move(buf), size};
  }
};
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<commit_msg>Deprecate `binarystring`.<commit_after>/* Representation for raw, binary data.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead.
 *
 * Copyright (c) 2000-2020, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_BINARYSTRING
#define PQXX_H_BINARYSTRING

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <memory>
#include <string>
#include <string_view>

#include "pqxx/result.hxx"
#include "pqxx/strconv.hxx"

namespace pqxx
{
class binarystring;
template<> struct string_traits<binarystring>;

/// Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
/** @ingroup escaping-functions
 * @deprecated Use @c std::basic_string<std::byte> and
 * @c std::basic_string_view<std::byte> for binary data.
 *
 * This class represents a binary string as stored in a field of type @c bytea.
 *
 * Internally a binarystring is zero-terminated, but it may also contain null
 * bytes, they're just like any other byte value.  So don't assume that it's
 * safe to treat the contents as a C-style string.
 *
 * The binarystring retains its value even if the result it was obtained from
 * is destroyed, but it cannot be copied or assigned.
 *
 * \relatesalso transaction_base::quote_raw
 *
 * To include a @c binarystring value in an SQL query, escape and quote it
 * using the transaction's @c quote_raw function.
 *
 * @warning This class is implemented as a reference-counting smart pointer.
 * Copying, swapping, and destroying binarystring objects that refer to the
 * same underlying data block is not thread-safe.  If you wish to pass
 * binarystrings around between threads, make sure that each of these
 * operations is protected against concurrency with similar operations on the
 * same object, or other objects pointing to the same data block.
 */
class PQXX_LIBEXPORT binarystring
{
public:
  using char_type = unsigned char;
  using value_type = std::char_traits<char_type>::char_type;
  using size_type = std::size_t;
  using difference_type = long;
  using const_reference = value_type const &;
  using const_pointer = value_type const *;
  using const_iterator = const_pointer;
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;

  binarystring(binarystring const &) = default;

  /// Read and unescape bytea field.
  /** The field will be zero-terminated, even if the original bytea field
   * isn't.
   * @param F the field to read; must be a bytea field
   */
  explicit binarystring(field const &);

  /// Copy binary data from std::string_view on binary data.
  /** This is inefficient in that it copies the data to a buffer allocated on
   * the heap.
   */
  explicit binarystring(std::string_view);

  /// Copy binary data of given length straight out of memory.
  binarystring(void const *, std::size_t);

  /// Efficiently wrap a buffer of binary data in a @c binarystring.
  binarystring(std::shared_ptr<value_type> ptr, size_type size) :
          m_buf{std::move(ptr)}, m_size{size}
  {}

  /// Size of converted string in bytes.
  [[nodiscard]] size_type size() const noexcept { return m_size; }
  /// Size of converted string in bytes.
  [[nodiscard]] size_type length() const noexcept { return size(); }
  [[nodiscard]] bool empty() const noexcept { return size() == 0; }

  [[nodiscard]] const_iterator begin() const noexcept { return data(); }
  [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
  [[nodiscard]] const_iterator end() const noexcept { return data() + m_size; }
  [[nodiscard]] const_iterator cend() const noexcept { return end(); }

  [[nodiscard]] const_reference front() const noexcept { return *begin(); }
  [[nodiscard]] const_reference back() const noexcept
  {
    return *(data() + m_size - 1);
  }

  [[nodiscard]] const_reverse_iterator rbegin() const
  {
    return const_reverse_iterator{end()};
  }
  [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); }
  [[nodiscard]] const_reverse_iterator rend() const
  {
    return const_reverse_iterator{begin()};
  }
  [[nodiscard]] const_reverse_iterator crend() const { return rend(); }

  /// Unescaped field contents.
  [[nodiscard]] value_type const *data() const noexcept { return m_buf.get(); }

  [[nodiscard]] const_reference operator[](size_type i) const noexcept
  {
    return data()[i];
  }

  [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const noexcept;
  [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept
  {
    return not operator==(rhs);
  }

  binarystring &operator=(binarystring const &);

  /// Index contained string, checking for valid index.
  const_reference at(size_type) const;

  /// Swap contents with other binarystring.
  void swap(binarystring &);

  /// Raw character buffer (no terminating zero is added).
  /** @warning No terminating zero is added!  If the binary data did not end in
   * a null character, you will not find one here.
   */
  [[nodiscard]] char const *get() const noexcept
  {
    return reinterpret_cast<char const *>(m_buf.get());
  }

  /// Read contents as a std::string_view.
  [[nodiscard]] std::string_view view() const noexcept
  {
    return std::string_view(get(), size());
  }

  /// Read as regular C++ string (may include null characters).
  /** This creates and returns a new string object.  Don't call this
   * repeatedly; retrieve your string once and keep it in a local variable.
   * Also, do not expect to be able to compare the string's address to that of
   * an earlier invocation.
   */
  [[nodiscard]] std::string str() const;

private:
  std::shared_ptr<value_type> m_buf;
  size_type m_size{0};
};

// TODO: Should binarystring have a default-constructed null value?
template<> struct nullness<binarystring> : no_null<binarystring>
{};

/// String conversion traits for @c binarystring.
/** Defines the conversions between a @c binarystring and its PostgreSQL
 * textual format, for communication with the database.
 *
 * These conversions rely on the "hex" format which was introduced in
 * PostgreSQL 9.0.  Both your libpq and the server must be recent enough to
 * speak this format.
 */
template<> struct string_traits<binarystring>
{
  static std::size_t size_buffer(binarystring const &value) noexcept
  {
    return internal::size_esc_bin(value.size());
  }

  static zview to_buf(char *begin, char *end, binarystring const &value)
  {
    auto const value_end{into_buf(begin, end, value)};
    return zview{begin, value_end - begin - 1};
  }

  static char *into_buf(char *begin, char *end, binarystring const &value)
  {
    auto const budget{size_buffer(value)};
    if (static_cast<std::size_t>(end - begin) < budget)
      throw conversion_overrun{
        "Not enough buffer space to escape binary data."};
    internal::esc_bin(value.view(), begin);
    return begin + budget;
  }

  static binarystring from_string(std::string_view text)
  {
    auto const size{pqxx::internal::size_unesc_bin(text.size())};
    std::shared_ptr<unsigned char> buf{
      new unsigned char[size], [](unsigned char const *x) { delete[] x; }};
    pqxx::internal::unesc_bin(text, reinterpret_cast<std::byte *>(buf.get()));
    return binarystring{std::move(buf), size};
  }
};
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<|endoftext|>


<commit_before>///
/// @file   config.hpp
/// @brief  primesieve compile time constants.
///
/// Copyright (C) 2021 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef CONFIG_HPP
#define CONFIG_HPP

#include <stdint.h>

namespace {
namespace config {

/// Fallback L1 data cache size per core (in bytes) that will
/// be used if the CpuInfo class is unable to detect the CPU's
/// L1 data cache size at runtime.
///
constexpr uint64_t L1D_CACHE_BYTES = 32 << 10;

/// Fallback sieve array size (in bytes) that will be used if
/// the CpuInfo class is unable to detect the CPU's cache sizes
/// at runtime and the user has not set the sieve size.
/// @see get_sieve_size() in api.cpp.
///
/// The best performance is usually achieved using a sieve
/// size that matches the CPU's L1 data cache size per core or
/// that is slightly larger than the CPU's L1 data cache size
/// but smaller than the L2 cache size per core.
///
constexpr uint64_t SIEVE_BYTES = L1D_CACHE_BYTES * 8;

/// Number of sieving primes per Bucket in EratSmall, EratMedium
/// and EratBig objects, affects performance by about 3%.
/// @pre BUCKET_BYTES must be a power of 2.
///
/// - For x86-64 CPUs after  2010 use 8192
/// - For x86-64 CPUs before 2010 use 4096
/// - For PowerPC G4 CPUs    2003 use 2048
///
constexpr uint64_t BUCKET_BYTES = 8 << 10;

/// The MemoryPool allocates at most MAX_ALLOC_BYTES of new
/// memory when it runs out of buckets.
///
constexpr uint64_t MAX_ALLOC_BYTES = 16 << 20;

/// iterator::prev_prime() caches at least MIN_CACHE_ITERATOR
/// bytes of primes. Larger is usually faster but also
/// requires more memory.
///
constexpr uint64_t MIN_CACHE_ITERATOR = 8 << 20;

/// iterator::prev_prime() maximum cache size in bytes, used
/// if pi(sqrt(n)) * 8 bytes > MAX_CACHE_ITERATOR.
///
constexpr uint64_t MAX_CACHE_ITERATOR = 1 << 30;

/// Each thread sieves at least a distance of MIN_THREAD_DISTANCE
/// in order to reduce the initialization overhead.
/// @pre MIN_THREAD_DISTANCE >= 100
///
constexpr uint64_t MIN_THREAD_DISTANCE = (uint64_t) 1e7;

/// Sieving primes <= (L1D_CACHE_BYTES * FACTOR_ERATSMALL)
/// are processed in EratSmall. The ideal value for
/// FACTOR_ERATSMALL has been determined experimentally by
/// running benchmarks near 10^10.
/// @pre FACTOR_ERATSMALL >= 0 && <= 4.5
///
constexpr double FACTOR_ERATSMALL = 0.2;

/// Sieving primes > (sieveSize in bytes * FACTOR_ERATSMALL)
/// and <= (sieveSize in bytes * FACTOR_ERATMEDIUM)
/// are processed in EratMedium.
///
/// When FACTOR_ERATMEDIUM is small fewer sieving primes are
/// processed in EratMedium.cpp and more sieving primes are
/// processed in EratBig.cpp. Generally a larger FACTOR_ERATMEDIUM
/// decreases the number of executed instructions, but increases
/// the number of branch mispredictions. On newer CPUs it is more
/// important to reduce the number of branch mispredictions than to
/// aim for the fewest number of executed instructions.
///
/// @pre FACTOR_ERATMEDIUM >= 0 && <= 4.5
/// FACTOR_ERATMEDIUM * max(sieveSize) / 30 * 6 + 6 <= max(multipleIndex)
/// FACTOR_ERATMEDIUM * 2^23 / 30 * 6 + 6 <= 2^23 - 1
/// FACTOR_ERATMEDIUM <= ((2^23 - 7) * 30) / (2^23 * 6)
/// FACTOR_ERATMEDIUM <= 4.99999582
///
constexpr double FACTOR_ERATMEDIUM = 1.75;

} // namespace config
} // namespace

#endif
<commit_msg>Tune MIN_CACHE_ITERATOR<commit_after>///
/// @file   config.hpp
/// @brief  primesieve compile time constants.
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef CONFIG_HPP
#define CONFIG_HPP

#include <stdint.h>

namespace {
namespace config {

/// Fallback L1 data cache size per core (in bytes) that will
/// be used if the CpuInfo class is unable to detect the CPU's
/// L1 data cache size at runtime.
///
constexpr uint64_t L1D_CACHE_BYTES = 32 << 10;

/// Fallback sieve array size (in bytes) that will be used if
/// the CpuInfo class is unable to detect the CPU's cache sizes
/// at runtime and the user has not set the sieve size.
/// @see get_sieve_size() in api.cpp.
///
/// The best performance is usually achieved using a sieve
/// size that matches the CPU's L1 data cache size per core or
/// that is slightly larger than the CPU's L1 data cache size
/// but smaller than the L2 cache size per core.
///
constexpr uint64_t SIEVE_BYTES = L1D_CACHE_BYTES * 8;

/// Number of sieving primes per Bucket in EratSmall, EratMedium
/// and EratBig objects, affects performance by about 3%.
/// @pre BUCKET_BYTES must be a power of 2.
///
/// - For x86-64 CPUs after  2010 use 8192
/// - For x86-64 CPUs before 2010 use 4096
/// - For PowerPC G4 CPUs    2003 use 2048
///
constexpr uint64_t BUCKET_BYTES = 8 << 10;

/// The MemoryPool allocates at most MAX_ALLOC_BYTES of new
/// memory when it runs out of buckets.
///
constexpr uint64_t MAX_ALLOC_BYTES = 16 << 20;

/// iterator::prev_prime() caches at least MIN_CACHE_ITERATOR
/// bytes of primes. Larger is usually faster but also
/// requires more memory.
///
constexpr uint64_t MIN_CACHE_ITERATOR = 4 << 20;

/// iterator::prev_prime() maximum cache size in bytes, used
/// if pi(sqrt(n)) * 8 bytes > MAX_CACHE_ITERATOR.
///
constexpr uint64_t MAX_CACHE_ITERATOR = 1 << 30;

/// Each thread sieves at least a distance of MIN_THREAD_DISTANCE
/// in order to reduce the initialization overhead.
/// @pre MIN_THREAD_DISTANCE >= 100
///
constexpr uint64_t MIN_THREAD_DISTANCE = (uint64_t) 1e7;

/// Sieving primes <= (L1D_CACHE_BYTES * FACTOR_ERATSMALL)
/// are processed in EratSmall. The ideal value for
/// FACTOR_ERATSMALL has been determined experimentally by
/// running benchmarks near 10^10.
/// @pre FACTOR_ERATSMALL >= 0 && <= 4.5
///
constexpr double FACTOR_ERATSMALL = 0.2;

/// Sieving primes > (sieveSize in bytes * FACTOR_ERATSMALL)
/// and <= (sieveSize in bytes * FACTOR_ERATMEDIUM)
/// are processed in EratMedium.
///
/// When FACTOR_ERATMEDIUM is small fewer sieving primes are
/// processed in EratMedium.cpp and more sieving primes are
/// processed in EratBig.cpp. Generally a larger FACTOR_ERATMEDIUM
/// decreases the number of executed instructions, but increases
/// the number of branch mispredictions. On newer CPUs it is more
/// important to reduce the number of branch mispredictions than to
/// aim for the fewest number of executed instructions.
///
/// @pre FACTOR_ERATMEDIUM >= 0 && <= 4.5
/// FACTOR_ERATMEDIUM * max(sieveSize) / 30 * 6 + 6 <= max(multipleIndex)
/// FACTOR_ERATMEDIUM * 2^23 / 30 * 6 + 6 <= 2^23 - 1
/// FACTOR_ERATMEDIUM <= ((2^23 - 7) * 30) / (2^23 * 6)
/// FACTOR_ERATMEDIUM <= 4.99999582
///
constexpr double FACTOR_ERATMEDIUM = 1.75;

} // namespace config
} // namespace

#endif
<|endoftext|>


<commit_before>#include "SimpleMemory.hh"

SimpleMemory::SimpleMemory(AstraNetworkAPI *NI,double access_latency,double npu_access_bw_GB,double nic_access_bw_GB){
        this->last_request_serviced=0;
        this->NI=NI;
        this->access_latency=access_latency;
        this->npu_access_bw_GB=npu_access_bw_GB;
        this->nic_access_bw_GB=nic_access_bw_GB;
}
void SimpleMemory::set_network_api(AstraNetworkAPI *astraNetworkApi){
    this->NI=astraNetworkApi;
}
uint64_t SimpleMemory::npu_mem_read(uint64_t size){
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);

}
uint64_t SimpleMemory::SimpleMemory::npu_mem_write(uint64_t size){
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_read(uint64_t size){
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_write(uint64_t size){
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::mem_read(uint64_t size){
    return nic_mem_read(size);
}
uint64_t SimpleMemory::mem_write(uint64_t size){
    return nic_mem_write(size);
}<commit_msg>updated<commit_after>#include "SimpleMemory.hh"

SimpleMemory::SimpleMemory(AstraNetworkAPI *NI,double access_latency,double npu_access_bw_GB,double nic_access_bw_GB){
        this->last_request_serviced=0;
        this->NI=NI;
        this->access_latency=access_latency;
        this->npu_access_bw_GB=npu_access_bw_GB;
        this->nic_access_bw_GB=nic_access_bw_GB;
}
void SimpleMemory::set_network_api(AstraNetworkAPI *astraNetworkApi){
    this->NI=astraNetworkApi;
}
uint64_t SimpleMemory::npu_mem_read(uint64_t size){
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);

}
uint64_t SimpleMemory::SimpleMemory::npu_mem_write(uint64_t size){
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_read(uint64_t size){
    std::cout<<"1";
    timespec_t time=NI->sim_get_time();
    std::cout<<"2";
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_write(uint64_t size){
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::mem_read(uint64_t size){
    return nic_mem_read(size);
}
uint64_t SimpleMemory::mem_write(uint64_t size){
    return nic_mem_write(size);
}<|endoftext|>


<commit_before>#ifndef MESSAGES_HPP_
#define MESSAGES_HPP_

#include <cstdint>

namespace protocol {
namespace message {

struct heartbeat_message_t {
  enum { ID = 0x00 };

  std::uint8_t seq;
} __attribute__((packed));

struct log_message_t {
  enum { ID = 0x01 };

  char data[255];
} __attribute__((packed));

struct attitude_message_t {
  enum { ID = 0x02 };

  float roll;
  float pitch;
  float yaw;
} __attribute__((packed));

struct set_control_mode_message_t {
  enum { ID = 0x03 };

  enum class ControlMode {
    MANUAL,
    OFFBOARD
  };

  ControlMode mode;
} __attribute__((packed));

struct offboard_attitude_control_message_t {
  enum { ID = 0x04 };

  float roll;
  float pitch;
  float yaw;
  float throttle;
} __attribute__((packed));

inline std::uint16_t length(int id) {
  // TODO(kyle): sizeof(empty struct) is 1 in C++...
  switch(id) {
    case heartbeat_message_t::ID:
      return sizeof(heartbeat_message_t);
    case log_message_t::ID:
      return sizeof(log_message_t);
    case attitude_message_t::ID:
      return sizeof(attitude_message_t);
    case set_control_mode_message_t::ID:
      return sizeof(set_control_mode_message_t);
    case offboard_attitude_control_message_t::ID:
      return sizeof(offboard_attitude_control_message_t);
  }

  return 0; // TODO(kyle): Return something more meaningful?
}

}
}

#endif // MESSAGES_HPP_

<commit_msg>Add set_arm_state message.<commit_after>#ifndef MESSAGES_HPP_
#define MESSAGES_HPP_

#include <cstdint>

namespace protocol {
namespace message {

struct heartbeat_message_t {
  enum { ID = 0x00 };

  std::uint8_t seq;
} __attribute__((packed));

struct log_message_t {
  enum { ID = 0x01 };

  char data[255];
} __attribute__((packed));

struct attitude_message_t {
  enum { ID = 0x02 };

  float roll;
  float pitch;
  float yaw;
} __attribute__((packed));

struct set_arm_state_message_t {
  enum { ID = 0x03 };

  bool armed;
} __attribute__((packed));

struct set_control_mode_message_t {
  enum { ID = 0x04 };

  enum class ControlMode {
    MANUAL,
    OFFBOARD
  };

  ControlMode mode;
} __attribute__((packed));

struct offboard_attitude_control_message_t {
  enum { ID = 0x05 };

  float roll;
  float pitch;
  float yaw;
  float throttle;
} __attribute__((packed));

inline std::uint16_t length(int id) {
  // TODO(kyle): sizeof(empty struct) is 1 in C++...
  switch(id) {
    case heartbeat_message_t::ID:
      return sizeof(heartbeat_message_t);
    case log_message_t::ID:
      return sizeof(log_message_t);
    case attitude_message_t::ID:
      return sizeof(attitude_message_t);
    case set_arm_state_message_t::ID:
      return sizeof(set_arm_state_message_t);
    case set_control_mode_message_t::ID:
      return sizeof(set_control_mode_message_t);
    case offboard_attitude_control_message_t::ID:
      return sizeof(offboard_attitude_control_message_t);
  }

  return 0; // TODO(kyle): Return something more meaningful?
}

}
}

#endif // MESSAGES_HPP_

<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include <bh.h>
#include <bh_dag.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/foreach.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <vector>
#include <map>
#include <iterator>

using namespace std;
using namespace boost;

typedef adjacency_list<setS, vecS, bidirectionalS, bh_ir_kernel> Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;

bool fuse_mask(const Graph &dag, const vector<Edge> edges2explore,
               const vector<bool> mask, Graph &new_dag)
{
    vector<Edge> edges2merge;
    unsigned int i=0;
    BOOST_FOREACH(const Edge &e, edges2explore)
    {
        if(mask[i++])
        {
            edges2merge.push_back(e);
        }
    }
    try
    {
        bh_dag_merge_vertices(dag, edges2merge, new_dag, true);
    }
    catch (const runtime_error &e)
    {
        return false;
    }

    if(bh_dag_cycles(new_dag))
        return false;

    return true;
}

int fuser_count=0;
void fuser(bh_ir &bhir)
{
    Graph dag;
    bh_dag_from_bhir(bhir, dag);
    bh_dag_transitive_reduction(dag);
    bh_dag_fuse_gentle(dag);

    //The list of edges that we should try to merge
    vector<Edge> edges2explore;
    BOOST_FOREACH(const Edge &e, edges(dag))
    {
        if(dag[target(e,dag)].fusible(dag[source(e,dag)]))
            edges2explore.push_back(e);
    }

    uint64_t best_cost = numeric_limits<uint64_t>().max();
    Graph best_dag;

    vector<bool> mask(edges2explore.size(), false);
    if(mask.size() == 0)
        return;

    if(mask.size() > 20)
    {
        cout << "FUSER-OPTIMAL: ABORT the size of the search space is too large: 2^";
        cout << mask.size() << "!" << endl;
        return;
    }
    else if(mask.size() > 10)
    {
        cout << "FUSER-OPTIMAL: the size of the search space is 2^" << mask.size() << "!" << endl;
    }

    bool not_finished = true;
    while(not_finished)
    {
        Graph new_dag;
        if(fuse_mask(dag, edges2explore, mask, new_dag))
        {
            const uint64_t c = bh_dag_cost(new_dag);
            if(best_cost > c)
            {
                best_cost = c;
                best_dag = new_dag;
#ifdef VERBOSE
                std::stringstream ss;
                ss << "new_dag-" << fuser_count << "-" << bh_dag_cost(new_dag);
                /*
                ss << "-";
                for(unsigned int i=0; i<mask.size(); ++i)
                {
                    if(mask[i])
                        ss << "1";
                    else
                        ss << "0";
                }
                */
                ss << ".dot";
                printf("write file: %s\n", ss.str().c_str());
                bh_dag_pprint(new_dag, ss.str().c_str());
#endif
            }
        }
        for(unsigned int i=mask.size()-1; i >= 0; --i)
        {
            if(mask[i])
            {
                if(i == 0)
                {
                    not_finished = false;
                    break;
                }
                mask[i] = false;
            }
            else
            {
                mask[i] = true;
                break;
            }
        }
    }
    if(best_cost < numeric_limits<uint64_t>().max())
    {
        bh_ir b;
        vector<Vertex> topological_order;
        topological_sort(best_dag, back_inserter(topological_order));
        BOOST_REVERSE_FOREACH(const Vertex &v, topological_order)
        {
            b.kernel_list.push_back(best_dag[v]);
        }
        b.instr_list = bhir.instr_list;
        bhir = b;
    }
}

<commit_msg>optimal-fuser: now calling recursive<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include <bh.h>
#include <bh_dag.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/foreach.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <vector>
#include <map>
#include <iterator>

using namespace std;
using namespace boost;

typedef adjacency_list<setS, vecS, bidirectionalS, bh_ir_kernel> Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;

void dag2kernel_list(const Graph &dag, vector<bh_ir_kernel> &kernel_list)
{
    vector<Vertex> topological_order;
    topological_sort(dag, back_inserter(topological_order));
    BOOST_REVERSE_FOREACH(const Vertex &v, topological_order)
    {
        kernel_list.push_back(dag[v]);
    }
}

bool fuse_mask(const Graph &dag, const vector<Edge> &edges2explore,
               const vector<bool> &mask, Graph &new_dag)
{
    vector<Edge> edges2merge;
    unsigned int i=0;
    BOOST_FOREACH(const Edge &e, edges2explore)
    {
        if(mask[i++])
        {
            edges2merge.push_back(e);
        }
    }
    try
    {
        bh_dag_merge_vertices(dag, edges2merge, new_dag, true);
    }
    catch (const runtime_error &e)
    {
        return false;
    }

    if(bh_dag_cycles(new_dag))
        return false;

    return true;
}

int fuser_count=0;
uint64_t best_cost = numeric_limits<uint64_t>().max();
Graph best_dag;
void fuse(const Graph &dag, const vector<Edge> &edges2explore,
          vector<bool> mask, unsigned int offset, bool merge_next)
{
    if(not merge_next)
    {
        Graph new_dag;
        mask[offset] = merge_next;
        if(fuse_mask(dag, edges2explore, mask, new_dag))
        {
            const uint64_t c = bh_dag_cost(new_dag);
            if(best_cost > c)
            {
                best_cost = c;
                best_dag = new_dag;
#ifdef VERBOSE
                std::stringstream ss;
                ss << "new_best_dag-" << fuser_count << "-" << bh_dag_cost(new_dag) << ".dot";
                printf("write file: %s\n", ss.str().c_str());
                bh_dag_pprint(new_dag, ss.str().c_str());
#endif
            }
        }
    }
    if(offset+1 < mask.size())
    {
        fuse(dag, edges2explore, mask, offset+1, true);
        fuse(dag, edges2explore, mask, offset+1, false);
    }
}

void fuser(bh_ir &bhir)
{
    Graph dag;
    bh_dag_from_bhir(bhir, dag);
    bh_dag_transitive_reduction(dag);
    bh_dag_fuse_gentle(dag);

    //The list of edges that we should try to merge
    vector<Edge> edges2explore;
    BOOST_FOREACH(const Edge &e, edges(dag))
    {
        if(dag[target(e,dag)].fusible(dag[source(e,dag)]))
            edges2explore.push_back(e);
    }

    vector<bool> mask(edges2explore.size(), true);
    if(mask.size() == 0)
        return;

    //First we check the trivial case where all kernels are merged
    {
        Graph new_dag;
        if(fuse_mask(dag, edges2explore, mask, new_dag))
        {
            dag2kernel_list(new_dag, bhir.kernel_list);
            return;
        }
    }

    if(mask.size() > 20)
    {
        cout << "FUSER-OPTIMAL: ABORT the size of the search space is too large: 2^";
        cout << mask.size() << "!" << endl;
        return;
    }
    else if(mask.size() > 10)
    {
        cout << "FUSER-OPTIMAL: the size of the search space is 2^" << mask.size() << "!" << endl;
    }

    fuse(dag, edges2explore, mask, 0, true);
    fuse(dag, edges2explore, mask, 0, false);

    if(best_cost < numeric_limits<uint64_t>().max())
    {
        dag2kernel_list(best_dag, bhir.kernel_list);
    }
}

<|endoftext|>


<commit_before>#ifndef MESSAGES_HPP_
#define MESSAGES_HPP_

#include <cstdint>

namespace protocol {
namespace message {

struct heartbeat_message_t {
  enum { ID = 0x00 };

  std::uint8_t seq;
} __attribute__((packed));

struct log_message_t {
  enum { ID = 0x01 };

  char data[255];
} __attribute__((packed));

struct attitude_message_t {
  enum { ID = 0x02 };

  float roll;
  float pitch;
  float yaw;
} __attribute__((packed));

struct set_control_mode_message_t {
  enum { ID = 0x03 };

  enum class ControlMode {
    MANUAL,
    OFFBOARD
  };

  ControlMode mode;
} __attribute__((packed));

inline std::uint16_t length(int id) {
  // TODO(kyle): sizeof(empty struct) is 1 in C++...
  switch(id) {
    case heartbeat_message_t::ID:
      return sizeof(heartbeat_message_t);
    case log_message_t::ID:
      return sizeof(log_message_t);
    case attitude_message_t::ID:
      return sizeof(attitude_message_t);
    case set_control_mode_message_t::ID:
      return sizeof(set_control_mode_message_t);
  }

  return 0; // TODO(kyle): Return something more meaningful?
}

}
}

#endif // MESSAGES_HPP_

<commit_msg>Add offboard control message.<commit_after>#ifndef MESSAGES_HPP_
#define MESSAGES_HPP_

#include <cstdint>

namespace protocol {
namespace message {

struct heartbeat_message_t {
  enum { ID = 0x00 };

  std::uint8_t seq;
} __attribute__((packed));

struct log_message_t {
  enum { ID = 0x01 };

  char data[255];
} __attribute__((packed));

struct attitude_message_t {
  enum { ID = 0x02 };

  float roll;
  float pitch;
  float yaw;
} __attribute__((packed));

struct set_control_mode_message_t {
  enum { ID = 0x03 };

  enum class ControlMode {
    MANUAL,
    OFFBOARD
  };

  ControlMode mode;
} __attribute__((packed));

struct offboard_attitutde_control_message_t {
  enum { ID = 0x04 };

  float roll;
  float pitch;
  float yaw;
  float throttle;
} __attribute__((packed));

inline std::uint16_t length(int id) {
  // TODO(kyle): sizeof(empty struct) is 1 in C++...
  switch(id) {
    case heartbeat_message_t::ID:
      return sizeof(heartbeat_message_t);
    case log_message_t::ID:
      return sizeof(log_message_t);
    case attitude_message_t::ID:
      return sizeof(attitude_message_t);
    case set_control_mode_message_t::ID:
      return sizeof(set_control_mode_message_t);
    case offboard_attitutde_control_message_t::ID:
      return sizeof(offboard_attitutde_control_message_t);
  }

  return 0; // TODO(kyle): Return something more meaningful?
}

}
}

#endif // MESSAGES_HPP_

<|endoftext|>


<commit_before>/**
 *  @author Koen Wolters <koen.wolters@cern.ch>
 *  @author Daniel Hynds <daniel.hynds@cern.ch>
 */

#include "ModuleFactory.hpp"
#include <dlfcn.h>

#include <utility>

using namespace allpix;

// Constructor and destructor
ModuleFactory::ModuleFactory() : config_(), messenger_(), geometry_manager_() {}
ModuleFactory::~ModuleFactory() = default;

void ModuleFactory::setConfiguration(Configuration conf) {
    config_ = std::move(conf);
}
Configuration& ModuleFactory::getConfiguration() {
    return config_;
}

void ModuleFactory::setMessenger(Messenger* messenger) {
    messenger_ = messenger;
}
Messenger* ModuleFactory::getMessenger() {
    return messenger_;
}

void ModuleFactory::setGeometryManager(GeometryManager* geo_manager) {
    geometry_manager_ = geo_manager;
}
GeometryManager* ModuleFactory::getGeometryManager() {
    return geometry_manager_;
}

// Function to create modules from the dynamic library passed from the Module Manager
std::vector<std::pair<ModuleIdentifier, Module*>> ModuleFactory::createModules(std::string name, void* library) {

    // Make the vector to return
    std::vector<std::pair<ModuleIdentifier, Module*>> moduleList;

    // Load an instance of the module from the library
    ModuleIdentifier identifier(name, "", 0);
    Module* module = NULL;

    void* generator = dlsym(library, "generator");
    char* err;
    if((err = dlerror()) != NULL) {
        // handle error, the symbol wasn't found
        throw allpix::DynamicLibraryError(name);
    } else {
        module = reinterpret_cast<Module* (*)(Configuration, Messenger*, GeometryManager*)>(generator)(
            getConfiguration(), getMessenger(), getGeometryManager());
    }

    moduleList.emplace_back(identifier, module);
    return moduleList;
}
<commit_msg>clean up of module loading errors<commit_after>/**
 *  @author Koen Wolters <koen.wolters@cern.ch>
 *  @author Daniel Hynds <daniel.hynds@cern.ch>
 */

#include "ModuleFactory.hpp"
#include <dlfcn.h>

#include <utility>

using namespace allpix;

// Constructor and destructor
ModuleFactory::ModuleFactory() : config_(), messenger_(), geometry_manager_() {}
ModuleFactory::~ModuleFactory() = default;

void ModuleFactory::setConfiguration(Configuration conf) {
    config_ = std::move(conf);
}
Configuration& ModuleFactory::getConfiguration() {
    return config_;
}

void ModuleFactory::setMessenger(Messenger* messenger) {
    messenger_ = messenger;
}
Messenger* ModuleFactory::getMessenger() {
    return messenger_;
}

void ModuleFactory::setGeometryManager(GeometryManager* geo_manager) {
    geometry_manager_ = geo_manager;
}
GeometryManager* ModuleFactory::getGeometryManager() {
    return geometry_manager_;
}

// Function to create modules from the dynamic library passed from the Module Manager
std::vector<std::pair<ModuleIdentifier, Module*>> ModuleFactory::createModules(std::string name, void* library) {

    // Make the vector to return
    std::vector<std::pair<ModuleIdentifier, Module*>> moduleList;

    // Load an instance of the module from the library
    ModuleIdentifier identifier(name, "", 0);
    Module* module = NULL;

    // Get the generator function for this module
    void* generator = dlsym(library, "generator");
    char* err = dlerror();
    // If the generator function was not found, throw an error
    if(err != NULL) {
        throw allpix::DynamicLibraryError(name);
    } else {
        // Otherwise initialise the module
        module = reinterpret_cast<Module* (*)(Configuration, Messenger*, GeometryManager*)>(generator)(
            getConfiguration(), getMessenger(), getGeometryManager());
    }

    // Store the module and return it to the Module Manager
    moduleList.emplace_back(identifier, module);
    return moduleList;
}
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/circular_buffer.hh>
#include <seastar/core/future.hh>
#include <queue>
#include <seastar/util/std-compat.hh>

namespace seastar {

/// Asynchronous single-producer single-consumer queue with limited capacity.
/// There can be at most one producer-side and at most one consumer-side operation active at any time.
/// Operations returning a future are considered to be active until the future resolves.
///
/// Note: queue requires the data type T to be nothrow move constructible as it's
/// returned as future<T> by \ref pop_eventually and seastar futurized data type
/// are required to be nothrow move-constructible.
template <typename T>
SEASTAR_CONCEPT(requires std::is_nothrow_move_constructible_v<T>)
class queue {
    std::queue<T, circular_buffer<T>> _q;
    size_t _max;
    std::optional<promise<>> _not_empty;
    std::optional<promise<>> _not_full;
    std::exception_ptr _ex = nullptr;
private:
    void notify_not_empty() noexcept;
    void notify_not_full() noexcept;
public:
    explicit queue(size_t size);

    /// \brief Push an item.
    ///
    /// Returns false if the queue was full and the item was not pushed.
    bool push(T&& a);

    /// \brief Pop an item.
    ///
    /// Popping from an empty queue will result in undefined behavior.
    T pop() noexcept;

    /// \brief access the front element in the queue
    ///
    /// Accessing the front of an empty or aborted queue will result in undefined
    /// behaviour.
    T& front() noexcept;

    /// Consumes items from the queue, passing them to \c func, until \c func
    /// returns false or the queue it empty
    ///
    /// Returns false if func returned false.
    template <typename Func>
    bool consume(Func&& func);

    /// Returns true when the queue is empty.
    bool empty() const noexcept;

    /// Returns true when the queue is full.
    bool full() const noexcept;

    /// Returns a future<> that becomes available when pop() or consume()
    /// can be called.
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<> not_empty();

    /// Returns a future<> that becomes available when push() can be called.
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> not_full();

    /// Pops element now or when there is some. Returns a future that becomes
    /// available when some element is available.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<T> pop_eventually();

    /// Pushes the element now or when there is room. Returns a future<> which
    /// resolves when data was pushed.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> push_eventually(T&& data);

    /// Returns the number of items currently in the queue.
    size_t size() const noexcept {
        // std::queue::size() has no reason to throw
        return _q.size();
    }

    /// Returns the size limit imposed on the queue during its construction
    /// or by a call to set_max_size(). If the queue contains max_size()
    /// items (or more), further items cannot be pushed until some are popped.
    size_t max_size() const noexcept { return _max; }

    /// Set the maximum size to a new value. If the queue's max size is reduced,
    /// items already in the queue will not be expunged and the queue will be temporarily
    /// bigger than its max_size.
    void set_max_size(size_t max) noexcept {
        _max = max;
        if (!full()) {
            notify_not_full();
        }
    }

    /// Destroy any items in the queue, and pass the provided exception to any
    /// waiting readers or writers - or to any later read or write attempts.
    void abort(std::exception_ptr ex) noexcept {
        // std::queue::empty() and pop() doesn't throw
        // since it just calls seastar::circular_buffer::pop_front
        // that is specified as noexcept.
        while (!_q.empty()) {
            _q.pop();
        }
        _ex = ex;
        if (_not_full) {
            _not_full->set_exception(ex);
            _not_full= std::nullopt;
        }
        if (_not_empty) {
            _not_empty->set_exception(std::move(ex));
            _not_empty = std::nullopt;
        }
    }

    /// \brief Check if there is an active consumer
    ///
    /// Returns true if another fiber waits for an item to be pushed into the queue
    bool has_blocked_consumer() const noexcept {
        return bool(_not_empty);
    }
};

template <typename T>
inline
queue<T>::queue(size_t size)
    : _max(size) {
}

template <typename T>
inline
void queue<T>::notify_not_empty() noexcept {
    if (_not_empty) {
        _not_empty->set_value();
        _not_empty = std::optional<promise<>>();
    }
}

template <typename T>
inline
void queue<T>::notify_not_full() noexcept {
    if (_not_full) {
        _not_full->set_value();
        _not_full = std::optional<promise<>>();
    }
}

template <typename T>
inline
bool queue<T>::push(T&& data) {
    if (_q.size() < _max) {
        _q.push(std::move(data));
        notify_not_empty();
        return true;
    } else {
        return false;
    }
}

template <typename T>
inline
T& queue<T>::front() noexcept {
    // std::queue::front() has no reason to throw
    return _q.front();
}

template <typename T>
inline
T queue<T>::pop() noexcept {
    if (_q.size() == _max) {
        notify_not_full();
    }
    // popping the front element must not throw
    // as T is required to be nothrow_move_constructible
    // and std::queue::pop won't throw since it uses
    // seastar::circular_beffer::pop_front.
    T data = std::move(_q.front());
    _q.pop();
    return data;
}

template <typename T>
inline
future<T> queue<T>::pop_eventually() {
    // seastar allows only nothrow_move_constructible types
    // to be returned as future<T>
    static_assert(std::is_nothrow_move_constructible_v<T>,
                  "Queue element type must be no-throw move constructible");

    if (_ex) {
        return make_exception_future<T>(_ex);
    }
    if (empty()) {
        return not_empty().then([this] {
            if (_ex) {
                return make_exception_future<T>(_ex);
            } else {
                return make_ready_future<T>(pop());
            }
        });
    } else {
        return make_ready_future<T>(pop());
    }
}

template <typename T>
inline
future<> queue<T>::push_eventually(T&& data) {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (full()) {
        return not_full().then([this, data = std::move(data)] () mutable {
            _q.push(std::move(data));
            notify_not_empty();
        });
    } else {
        _q.push(std::move(data));
        notify_not_empty();
        return make_ready_future<>();
    }
}

template <typename T>
template <typename Func>
inline
bool queue<T>::consume(Func&& func) {
    if (_ex) {
        std::rethrow_exception(_ex);
    }
    bool running = true;
    while (!_q.empty() && running) {
        running = func(std::move(_q.front()));
        _q.pop();
    }
    if (!full()) {
        notify_not_full();
    }
    return running;
}

template <typename T>
inline
bool queue<T>::empty() const noexcept {
    // std::queue::empty() has no reason to throw
    return _q.empty();
}

template <typename T>
inline
bool queue<T>::full() const noexcept {
    // std::queue::size() has no reason to throw
    return _q.size() >= _max;
}

template <typename T>
inline
future<> queue<T>::not_empty() {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!empty()) {
        return make_ready_future<>();
    } else {
        _not_empty = promise<>();
        return _not_empty->get_future();
    }
}

template <typename T>
inline
future<> queue<T>::not_full() {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!full()) {
        return make_ready_future<>();
    } else {
        _not_full = promise<>();
        return _not_full->get_future();
    }
}

}

<commit_msg>queue: mark not_empty and not_full noexcept<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/circular_buffer.hh>
#include <seastar/core/future.hh>
#include <queue>
#include <seastar/util/std-compat.hh>

namespace seastar {

/// Asynchronous single-producer single-consumer queue with limited capacity.
/// There can be at most one producer-side and at most one consumer-side operation active at any time.
/// Operations returning a future are considered to be active until the future resolves.
///
/// Note: queue requires the data type T to be nothrow move constructible as it's
/// returned as future<T> by \ref pop_eventually and seastar futurized data type
/// are required to be nothrow move-constructible.
template <typename T>
SEASTAR_CONCEPT(requires std::is_nothrow_move_constructible_v<T>)
class queue {
    std::queue<T, circular_buffer<T>> _q;
    size_t _max;
    std::optional<promise<>> _not_empty;
    std::optional<promise<>> _not_full;
    std::exception_ptr _ex = nullptr;
private:
    void notify_not_empty() noexcept;
    void notify_not_full() noexcept;
public:
    explicit queue(size_t size);

    /// \brief Push an item.
    ///
    /// Returns false if the queue was full and the item was not pushed.
    bool push(T&& a);

    /// \brief Pop an item.
    ///
    /// Popping from an empty queue will result in undefined behavior.
    T pop() noexcept;

    /// \brief access the front element in the queue
    ///
    /// Accessing the front of an empty or aborted queue will result in undefined
    /// behaviour.
    T& front() noexcept;

    /// Consumes items from the queue, passing them to \c func, until \c func
    /// returns false or the queue it empty
    ///
    /// Returns false if func returned false.
    template <typename Func>
    bool consume(Func&& func);

    /// Returns true when the queue is empty.
    bool empty() const noexcept;

    /// Returns true when the queue is full.
    bool full() const noexcept;

    /// Returns a future<> that becomes available when pop() or consume()
    /// can be called.
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<> not_empty() noexcept;

    /// Returns a future<> that becomes available when push() can be called.
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> not_full() noexcept;

    /// Pops element now or when there is some. Returns a future that becomes
    /// available when some element is available.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<T> pop_eventually();

    /// Pushes the element now or when there is room. Returns a future<> which
    /// resolves when data was pushed.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> push_eventually(T&& data);

    /// Returns the number of items currently in the queue.
    size_t size() const noexcept {
        // std::queue::size() has no reason to throw
        return _q.size();
    }

    /// Returns the size limit imposed on the queue during its construction
    /// or by a call to set_max_size(). If the queue contains max_size()
    /// items (or more), further items cannot be pushed until some are popped.
    size_t max_size() const noexcept { return _max; }

    /// Set the maximum size to a new value. If the queue's max size is reduced,
    /// items already in the queue will not be expunged and the queue will be temporarily
    /// bigger than its max_size.
    void set_max_size(size_t max) noexcept {
        _max = max;
        if (!full()) {
            notify_not_full();
        }
    }

    /// Destroy any items in the queue, and pass the provided exception to any
    /// waiting readers or writers - or to any later read or write attempts.
    void abort(std::exception_ptr ex) noexcept {
        // std::queue::empty() and pop() doesn't throw
        // since it just calls seastar::circular_buffer::pop_front
        // that is specified as noexcept.
        while (!_q.empty()) {
            _q.pop();
        }
        _ex = ex;
        if (_not_full) {
            _not_full->set_exception(ex);
            _not_full= std::nullopt;
        }
        if (_not_empty) {
            _not_empty->set_exception(std::move(ex));
            _not_empty = std::nullopt;
        }
    }

    /// \brief Check if there is an active consumer
    ///
    /// Returns true if another fiber waits for an item to be pushed into the queue
    bool has_blocked_consumer() const noexcept {
        return bool(_not_empty);
    }
};

template <typename T>
inline
queue<T>::queue(size_t size)
    : _max(size) {
}

template <typename T>
inline
void queue<T>::notify_not_empty() noexcept {
    if (_not_empty) {
        _not_empty->set_value();
        _not_empty = std::optional<promise<>>();
    }
}

template <typename T>
inline
void queue<T>::notify_not_full() noexcept {
    if (_not_full) {
        _not_full->set_value();
        _not_full = std::optional<promise<>>();
    }
}

template <typename T>
inline
bool queue<T>::push(T&& data) {
    if (_q.size() < _max) {
        _q.push(std::move(data));
        notify_not_empty();
        return true;
    } else {
        return false;
    }
}

template <typename T>
inline
T& queue<T>::front() noexcept {
    // std::queue::front() has no reason to throw
    return _q.front();
}

template <typename T>
inline
T queue<T>::pop() noexcept {
    if (_q.size() == _max) {
        notify_not_full();
    }
    // popping the front element must not throw
    // as T is required to be nothrow_move_constructible
    // and std::queue::pop won't throw since it uses
    // seastar::circular_beffer::pop_front.
    T data = std::move(_q.front());
    _q.pop();
    return data;
}

template <typename T>
inline
future<T> queue<T>::pop_eventually() {
    // seastar allows only nothrow_move_constructible types
    // to be returned as future<T>
    static_assert(std::is_nothrow_move_constructible_v<T>,
                  "Queue element type must be no-throw move constructible");

    if (_ex) {
        return make_exception_future<T>(_ex);
    }
    if (empty()) {
        return not_empty().then([this] {
            if (_ex) {
                return make_exception_future<T>(_ex);
            } else {
                return make_ready_future<T>(pop());
            }
        });
    } else {
        return make_ready_future<T>(pop());
    }
}

template <typename T>
inline
future<> queue<T>::push_eventually(T&& data) {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (full()) {
        return not_full().then([this, data = std::move(data)] () mutable {
            _q.push(std::move(data));
            notify_not_empty();
        });
    } else {
        _q.push(std::move(data));
        notify_not_empty();
        return make_ready_future<>();
    }
}

template <typename T>
template <typename Func>
inline
bool queue<T>::consume(Func&& func) {
    if (_ex) {
        std::rethrow_exception(_ex);
    }
    bool running = true;
    while (!_q.empty() && running) {
        running = func(std::move(_q.front()));
        _q.pop();
    }
    if (!full()) {
        notify_not_full();
    }
    return running;
}

template <typename T>
inline
bool queue<T>::empty() const noexcept {
    // std::queue::empty() has no reason to throw
    return _q.empty();
}

template <typename T>
inline
bool queue<T>::full() const noexcept {
    // std::queue::size() has no reason to throw
    return _q.size() >= _max;
}

template <typename T>
inline
future<> queue<T>::not_empty() noexcept {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!empty()) {
        return make_ready_future<>();
    } else {
        _not_empty = promise<>();
        return _not_empty->get_future();
    }
}

template <typename T>
inline
future<> queue<T>::not_full() noexcept {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!full()) {
        return make_ready_future<>();
    } else {
        _not_full = promise<>();
        return _not_full->get_future();
    }
}

}

<|endoftext|>