<commit_before>/*

Copyright (c) 2007, 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_ASSERT

#include "libtorrent/config.hpp"

#if (!defined TORRENT_DEBUG && !TORRENT_PRODUCTION_ASSERTS && TORRENT_RELEASE_ASSERTS) \
	|| TORRENT_NO_ASSERTS
#define TORRENT_ASSERT(a) do {} while(false)
#define TORRENT_ASSERT_VAL(a, b) do {} while(false)
#else

#if TORRENT_PRODUCTION_ASSERTS
extern char const* libtorrent_assert_log;
#endif

#include <string>

#ifdef __GNUC__
std::string demangle(char const* name);
#endif

#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !TORRENT_USE_SYSTEM_ASSERT

#if TORRENT_USE_IOSTREAM
#include <sstream>
#endif

TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function, char const* val);
#define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, 0); } while (false)
#if TORRENT_USE_IOSTREAM
#define TORRENT_ASSERT_VAL(x, y) do { if (x) {} else { std::stringstream __s__; __s__ << #y ": " << y; assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, __s__.str().c_str()); } } while (false)
#else
#define TORRENT_ASSERT_VAL(x, y) TORRENT_ASSERT(x)
#endif

#else
#include <cassert>
#define TORRENT_ASSERT(x) assert(x)
#define TORRENT_ASSERT_VAL(x, y) assert(x)
#endif

#endif

#endif

<commit_msg>fixed typo in release assert support<commit_after>/*

Copyright (c) 2007, 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_ASSERT

#include "libtorrent/config.hpp"

#if (!defined TORRENT_DEBUG && !TORRENT_PRODUCTION_ASSERTS && !TORRENT_RELEASE_ASSERTS) \
	|| TORRENT_NO_ASSERTS
#define TORRENT_ASSERT(a) do {} while(false)
#define TORRENT_ASSERT_VAL(a, b) do {} while(false)
#else

#if TORRENT_PRODUCTION_ASSERTS
extern char const* libtorrent_assert_log;
#endif

#include <string>

#ifdef __GNUC__
std::string demangle(char const* name);
#endif

#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !TORRENT_USE_SYSTEM_ASSERT

#if TORRENT_USE_IOSTREAM
#include <sstream>
#endif

TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function, char const* val);
#define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, 0); } while (false)
#if TORRENT_USE_IOSTREAM
#define TORRENT_ASSERT_VAL(x, y) do { if (x) {} else { std::stringstream __s__; __s__ << #y ": " << y; assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, __s__.str().c_str()); } } while (false)
#else
#define TORRENT_ASSERT_VAL(x, y) TORRENT_ASSERT(x)
#endif

#else
#include <cassert>
#define TORRENT_ASSERT(x) assert(x)
#define TORRENT_ASSERT_VAL(x, y) assert(x)
#endif

#endif

#endif

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 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
 *
 *****************************************************************************/

//$Id: datasource.hpp 43 2005-04-22 18:52:47Z pavlenko $

#ifndef DATASOURCE_HPP
#define DATASOURCE_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/params.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/query.hpp>
#include <mapnik/feature_layer_desc.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
// stl
#include <map>
#include <string>

namespace mapnik {

typedef MAPNIK_DECL boost::shared_ptr<Feature> feature_ptr;

struct MAPNIK_DECL Featureset
{
    virtual feature_ptr next()=0;
    virtual ~Featureset() {};
};

typedef MAPNIK_DECL boost::shared_ptr<Featureset> featureset_ptr;

class MAPNIK_DECL datasource_exception : public std::exception
{
private:
    std::string message_;
public:
    datasource_exception(const std::string& message=std::string("no reason"))
        :message_(message) {}

    ~datasource_exception() throw() {}
    virtual const char* what() const throw()
    {
        return message_.c_str();
    }
};

class MAPNIK_DECL datasource : private boost::noncopyable
{
public:
    enum datasource_t {
        Vector,
        Raster
    };

    datasource (parameters const& params, bool bind=true)
        : params_(params),
          is_bound_(false)
        {}

    /*!
     * @brief Get the configuration parameters of the data source.
     *
     * These vary depending on the type of data source.
     *
     * @return The configuration parameters of the data source.
     */
    parameters const& params() const
    {
        return params_;
    }

    /*!
     * @brief Get the type of the datasource
     * @return The type of the datasource (Vector or Raster)
     */
    virtual int type() const=0;

    /*!
     * @brief Connect to the datasource
     */
    virtual void bind() const {};

    virtual featureset_ptr features(const query& q) const=0;
    virtual featureset_ptr features_at_point(coord2d const& pt) const=0;
    virtual box2d<double> envelope() const=0;
    virtual layer_descriptor get_descriptor() const=0;
    virtual ~datasource() {};
protected:
    parameters params_;
    mutable bool is_bound_;
};

typedef std::string datasource_name();
typedef datasource* create_ds(const parameters& params, bool bind);
typedef void destroy_ds(datasource *ds);

class datasource_deleter
{
public:
    void operator() (datasource* ds)
    {
        delete ds;
    }
};

typedef boost::shared_ptr<datasource> datasource_ptr;

#define DATASOURCE_PLUGIN(classname)                                    \
    extern "C" MAPNIK_EXP std::string datasource_name()                 \
    {                                                                   \
        return classname::name();                                       \
    }                                                                   \
    extern "C"  MAPNIK_EXP datasource* create(const parameters &params, bool bind) \
    {                                                                   \
        return new classname(params, bind);                             \
    }                                                                   \
    extern "C" MAPNIK_EXP void destroy(datasource *ds)                  \
    {                                                                   \
        delete ds;                                                      \
    }                                                                   \
    //
}

#endif //DATASOURCE_HPP
<commit_msg>+ remove 'bind' param   from datasource (base class) ctor   (FIXME: would be better to use parameters to           pass to specific options to concrete           datasource implementations)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 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
 *
 *****************************************************************************/

//$Id: datasource.hpp 43 2005-04-22 18:52:47Z pavlenko $

#ifndef DATASOURCE_HPP
#define DATASOURCE_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/params.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/query.hpp>
#include <mapnik/feature_layer_desc.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
// stl
#include <map>
#include <string>

namespace mapnik {

typedef MAPNIK_DECL boost::shared_ptr<Feature> feature_ptr;

struct MAPNIK_DECL Featureset
{
    virtual feature_ptr next()=0;
    virtual ~Featureset() {};
};

typedef MAPNIK_DECL boost::shared_ptr<Featureset> featureset_ptr;

class MAPNIK_DECL datasource_exception : public std::exception
{
private:
    std::string message_;
public:
    datasource_exception(const std::string& message=std::string("no reason"))
        :message_(message) {}

    ~datasource_exception() throw() {}
    virtual const char* what() const throw()
    {
        return message_.c_str();
    }
};

class MAPNIK_DECL datasource : private boost::noncopyable
{
public:
    enum datasource_t {
        Vector,
        Raster
    };

    datasource (parameters const& params)
        : params_(params),
          is_bound_(false)
        {}

    /*!
     * @brief Get the configuration parameters of the data source.
     *
     * These vary depending on the type of data source.
     *
     * @return The configuration parameters of the data source.
     */
    parameters const& params() const
    {
        return params_;
    }

    /*!
     * @brief Get the type of the datasource
     * @return The type of the datasource (Vector or Raster)
     */
    virtual int type() const=0;

    /*!
     * @brief Connect to the datasource
     */
    virtual void bind() const {};

    virtual featureset_ptr features(const query& q) const=0;
    virtual featureset_ptr features_at_point(coord2d const& pt) const=0;
    virtual box2d<double> envelope() const=0;
    virtual layer_descriptor get_descriptor() const=0;
    virtual ~datasource() {};
protected:
    parameters params_;
    mutable bool is_bound_;
};

typedef std::string datasource_name();
typedef datasource* create_ds(const parameters& params, bool bind);
typedef void destroy_ds(datasource *ds);

class datasource_deleter
{
public:
    void operator() (datasource* ds)
    {
        delete ds;
    }
};

typedef boost::shared_ptr<datasource> datasource_ptr;

#define DATASOURCE_PLUGIN(classname)                                    \
    extern "C" MAPNIK_EXP std::string datasource_name()                 \
    {                                                                   \
        return classname::name();                                       \
    }                                                                   \
    extern "C"  MAPNIK_EXP datasource* create(const parameters &params, bool bind) \
    {                                                                   \
        return new classname(params, bind);                             \
    }                                                                   \
    extern "C" MAPNIK_EXP void destroy(datasource *ds)                  \
    {                                                                   \
        delete ds;                                                      \
    }                                                                   \
    //
}

#endif //DATASOURCE_HPP
<|endoftext|>


<commit_before>/*
 * The NewReality Blockchain Project.
 * Copyright (C) 2013, 2016 Swirly Cloud Limited.
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if
 * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
#ifndef MVSD_MONGOOSE_HPP
#define MVSD_MONGOOSE_HPP

#include <bitcoin/bitcoin.hpp> // log
#include <bitcoin/explorer.hpp> // command-line

#include "mvs/http/Exception_error.hpp"

#include "mongoose/mongoose.h"

#include <mvs/http/String.hpp>

/**
 * @addtogroup Web
 * @{
 */

namespace http {
namespace mg {

inline std::string_view operator+(const mg_str& str) noexcept
{
    return {str.p, str.len};
}

inline std::string_view operator+(const websocket_message& msg) noexcept
{
    return {reinterpret_cast<char*>(msg.data), msg.size};
}

class ToCommandArg{
public:
    ToCommandArg() noexcept = default;
    virtual ~ToCommandArg() noexcept = default;
    ToCommandArg(const ToCommandArg&) noexcept = default;
    ToCommandArg(ToCommandArg&&) noexcept = default;
    ToCommandArg& operator=(const ToCommandArg&) noexcept = default;
    ToCommandArg& operator=(ToCommandArg&&) noexcept = default;

    auto argv() const noexcept { return argv_; }
    auto argc() const noexcept { return argc_; }
    void setargv0(std::string&& outside);

    static const int max_paramters{8};
protected:

    virtual void data_to_arg() noexcept = 0;
    const char* argv_[max_paramters]{{nullptr}};
    int argc_{0};

    std::vector<std::string> vargv_;
};

class HttpMessage : public ToCommandArg{
public:
    HttpMessage(http_message* impl) noexcept : impl_{impl} {}
    ~HttpMessage() noexcept = default;

    // Copy.
    // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1778
    HttpMessage(const HttpMessage&) noexcept = default;
    HttpMessage& operator=(const HttpMessage&) noexcept = default;

    // Move.
    HttpMessage(HttpMessage&&) noexcept = default;
    HttpMessage& operator=(HttpMessage&&) noexcept = default;

    auto get() const noexcept { return impl_; }
    auto method() const noexcept { return +impl_->method; }
    auto uri() const noexcept { return +impl_->uri; }
    auto proto() const noexcept { return +impl_->proto; }
    auto queryString() const noexcept { return +impl_->query_string; }
    auto header(const char* name) const noexcept
    {
      auto* val = mg_get_http_header(impl_, name);
      return val ? +*val : std::string_view{};
    }
    auto body() const noexcept { return +impl_->body; }

    void data_to_arg() noexcept override;

private:

    http_message* impl_;
};

class WebsocketMessage:public ToCommandArg { // connect to bx command-tool
public:
    WebsocketMessage(websocket_message* impl) noexcept : impl_{impl} {}
    ~WebsocketMessage() noexcept = default;

    // Copy.
    WebsocketMessage(const WebsocketMessage&) noexcept = default;
    WebsocketMessage& operator=(const WebsocketMessage&) noexcept = default;

    // Move.
    WebsocketMessage(WebsocketMessage&&) noexcept = default;
    WebsocketMessage& operator=(WebsocketMessage&&) noexcept = default;

    auto get() const noexcept { return impl_; }
    auto data() const noexcept { return reinterpret_cast<char*>(impl_->data); }
    auto size() const noexcept { return impl_->size; }

    void data_to_arg() noexcept override;
private:
    websocket_message* impl_;
};

template <typename DerivedT>
class Mgr {
public:
    // Copy.
    Mgr(const Mgr&) = delete;
    Mgr& operator=(const Mgr&) = delete;

    // Move.
    Mgr(Mgr&&) = delete;
    Mgr& operator=(Mgr&&) = delete;

    mg_connection& bind(const char* addr)
    {
      auto* conn = mg_bind(&mgr_, addr, handler);
      if (!conn)
        throw Error{"mg_bind() failed"};
      conn->user_data = this;
      return *conn;
    }
    time_t poll(int milli) { return mg_mgr_poll(&mgr_, milli); }

protected:
    Mgr() noexcept { mg_mgr_init(&mgr_, this); }
    ~Mgr() noexcept { mg_mgr_free(&mgr_); }

private:
    static void handler(mg_connection* conn, int event, void* data)
    {
       http_message* hm = static_cast<http_message*>(data);
       websocket_message* wm = static_cast<websocket_message*>(data);
       auto* self = static_cast<DerivedT*>(conn->user_data);

       switch (event) {
       case MG_EV_CLOSE:
            if (conn->flags & MG_F_IS_WEBSOCKET) {
                //self->websocketBroadcast(*conn, "left", 4);
            }else{
                conn->user_data = nullptr;
            }
            break;

       case MG_EV_HTTP_REQUEST:
            if (mg_ncasecmp((&hm->uri)->p, "/api", 4u) == 0) {
                self->httpRequest(*conn, hm);
            }else if (mg_ncasecmp((&hm->uri)->p, "/rpc", 4u) == 0){
                self->httpRpcRequest(*conn, hm);
            }else{
                self->httpStatic(*conn, hm);
                //conn->flags |= MG_F_SEND_AND_CLOSE;
            }
            break;

        case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
            self->websocketSend(conn, "connected", 9);
            break;

        case MG_EV_WEBSOCKET_FRAME:
            self->websocketBroadcast(*conn, wm);
            break;

       }
    }

    mg_mgr mgr_;
};

} // mg
} // http

/** @} */

#endif // MVSD_MONGOOSE_HPP
<commit_msg>fix gcc default noexcept as delete<commit_after>/*
 * The NewReality Blockchain Project.
 * Copyright (C) 2013, 2016 Swirly Cloud Limited.
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if
 * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
#ifndef MVSD_MONGOOSE_HPP
#define MVSD_MONGOOSE_HPP

#include <bitcoin/bitcoin.hpp> // log
#include <bitcoin/explorer.hpp> // command-line

#include "mvs/http/Exception_error.hpp"

#include "mongoose/mongoose.h"

#include <mvs/http/String.hpp>

/**
 * @addtogroup Web
 * @{
 */

namespace http {
namespace mg {

inline std::string_view operator+(const mg_str& str) noexcept
{
    return {str.p, str.len};
}

inline std::string_view operator+(const websocket_message& msg) noexcept
{
    return {reinterpret_cast<char*>(msg.data), msg.size};
}

class ToCommandArg{
public:
    auto argv() const noexcept { return argv_; }
    auto argc() const noexcept { return argc_; }
    void setargv0(std::string&& outside);

    static const int max_paramters{8};
protected:

    virtual void data_to_arg() noexcept = 0;
    const char* argv_[max_paramters]{{nullptr}};
    int argc_{0};

    std::vector<std::string> vargv_;
};

class HttpMessage : public ToCommandArg{
public:
    HttpMessage(http_message* impl) noexcept : impl_{impl} {}
    ~HttpMessage() noexcept = default;

    // Copy.
    // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1778
    HttpMessage(const HttpMessage&) noexcept = default;
    HttpMessage& operator=(const HttpMessage&) noexcept = default;

    // Move.
    HttpMessage(HttpMessage&&) noexcept = default;
    HttpMessage& operator=(HttpMessage&&) noexcept = default;

    auto get() const noexcept { return impl_; }
    auto method() const noexcept { return +impl_->method; }
    auto uri() const noexcept { return +impl_->uri; }
    auto proto() const noexcept { return +impl_->proto; }
    auto queryString() const noexcept { return +impl_->query_string; }
    auto header(const char* name) const noexcept
    {
      auto* val = mg_get_http_header(impl_, name);
      return val ? +*val : std::string_view{};
    }
    auto body() const noexcept { return +impl_->body; }

    void data_to_arg() noexcept override;

private:

    http_message* impl_;
};

class WebsocketMessage:public ToCommandArg { // connect to bx command-tool
public:
    WebsocketMessage(websocket_message* impl) noexcept : impl_{impl} {}
    ~WebsocketMessage() noexcept = default;

    // Copy.
    WebsocketMessage(const WebsocketMessage&) noexcept = default;
    WebsocketMessage& operator=(const WebsocketMessage&) noexcept = default;

    // Move.
    WebsocketMessage(WebsocketMessage&&) noexcept = default;
    WebsocketMessage& operator=(WebsocketMessage&&) noexcept = default;

    auto get() const noexcept { return impl_; }
    auto data() const noexcept { return reinterpret_cast<char*>(impl_->data); }
    auto size() const noexcept { return impl_->size; }

    void data_to_arg() noexcept override;
private:
    websocket_message* impl_;
};

template <typename DerivedT>
class Mgr {
public:
    // Copy.
    Mgr(const Mgr&) = delete;
    Mgr& operator=(const Mgr&) = delete;

    // Move.
    Mgr(Mgr&&) = delete;
    Mgr& operator=(Mgr&&) = delete;

    mg_connection& bind(const char* addr)
    {
      auto* conn = mg_bind(&mgr_, addr, handler);
      if (!conn)
        throw Error{"mg_bind() failed"};
      conn->user_data = this;
      return *conn;
    }
    time_t poll(int milli) { return mg_mgr_poll(&mgr_, milli); }

protected:
    Mgr() noexcept { mg_mgr_init(&mgr_, this); }
    ~Mgr() noexcept { mg_mgr_free(&mgr_); }

private:
    static void handler(mg_connection* conn, int event, void* data)
    {
       http_message* hm = static_cast<http_message*>(data);
       websocket_message* wm = static_cast<websocket_message*>(data);
       auto* self = static_cast<DerivedT*>(conn->user_data);

       switch (event) {
       case MG_EV_CLOSE:
            if (conn->flags & MG_F_IS_WEBSOCKET) {
                //self->websocketBroadcast(*conn, "left", 4);
            }else{
                conn->user_data = nullptr;
            }
            break;

       case MG_EV_HTTP_REQUEST:
            if (mg_ncasecmp((&hm->uri)->p, "/api", 4u) == 0) {
                self->httpRequest(*conn, hm);
            }else if (mg_ncasecmp((&hm->uri)->p, "/rpc", 4u) == 0){
                self->httpRpcRequest(*conn, hm);
            }else{
                self->httpStatic(*conn, hm);
                //conn->flags |= MG_F_SEND_AND_CLOSE;
            }
            break;

        case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
            self->websocketSend(conn, "connected", 9);
            break;

        case MG_EV_WEBSOCKET_FRAME:
            self->websocketBroadcast(*conn, wm);
            break;

       }
    }

    mg_mgr mgr_;
};

} // mg
} // http

/** @} */

#endif // MVSD_MONGOOSE_HPP
<|endoftext|>


<commit_before>#include <algorithm>
#include <fstream>
#include <iterator>
#include <sstream>
#include <string>
#include "tuning_runner.h"
#include "utility/ktt_utility.h"
#include "utility/logger.h"
#include "utility/timer.h"
#include "utility/result_loader.h"

namespace ktt
{

TuningRunner::TuningRunner(ArgumentManager* argumentManager, KernelManager* kernelManager, KernelRunner* kernelRunner) :
    argumentManager(argumentManager),
    kernelManager(kernelManager),
    kernelRunner(kernelRunner),
    resultValidator(std::make_unique<ResultValidator>(argumentManager, kernelRunner))
{}

std::vector<KernelResult> TuningRunner::tuneKernel(const KernelId id, std::unique_ptr<StopCondition> stopCondition)
{
    if (!kernelManager->isKernel(id))
    {
        throw std::runtime_error(std::string("Invalid kernel id: ") + std::to_string(id));
    }

    const Kernel& kernel = kernelManager->getKernel(id);
    if (hasWritableZeroCopyArguments(kernel))
    {
        throw std::runtime_error("Kernel tuning cannot be performed with writable zero-copy arguments");
    }

    resultValidator->computeReferenceResult(kernel);
    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelConfigurations(id));
    }

    size_t configurationCount = configurationManager.getConfigurationCount(id);
    if (stopCondition != nullptr)
    {
        stopCondition->initialize(configurationCount);
        configurationCount = std::min(configurationCount, stopCondition->getConfigurationCount());
    }

    std::vector<KernelResult> results;

    for (size_t i = 0; i < configurationCount; i++)
    {
        std::stringstream stream;
        stream << "Launching configuration " << i + 1 << "/" << configurationCount << " for kernel " << kernel.getName();
        Logger::getLogger().log(LoggingLevel::Info, stream.str());

        KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
        KernelResult result = kernelRunner->runKernel(id, currentConfiguration, std::vector<OutputDescriptor>{});

        if (validateResult(kernel, result))
        {
            results.push_back(result);
            configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, result.getComputationDuration());

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(static_cast<double>(result.getComputationDuration()));
            }
        }
        else
        {
            results.emplace_back(kernel.getName(), currentConfiguration, "Results differ");
            configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, UINT64_MAX);

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(std::numeric_limits<double>::max());
            }
        }

        kernelRunner->clearBuffers(ArgumentAccessType::ReadWrite);
        kernelRunner->clearBuffers(ArgumentAccessType::WriteOnly);
        if (kernel.hasTuningManipulator())
        {
            kernelRunner->clearBuffers(ArgumentAccessType::ReadOnly);
        }

        if (stopCondition != nullptr && stopCondition->isMet())
        {
            Logger::getLogger().log(LoggingLevel::Info, stopCondition->getStatusString());
            break;
        }
    }

    kernelRunner->clearBuffers();
    resultValidator->clearReferenceResults();
    configurationManager.clearKernelData(id, true, false);
    return results;
}

std::vector<KernelResult> TuningRunner::dryTuneKernel(const KernelId id, const std::string& filePath, const size_t iterations)
{
    if (!kernelManager->isKernel(id))
    {
        throw std::runtime_error(std::string("Invalid kernel id: ") + std::to_string(id));
    }

    ResultLoader resultLoader;
    if (!resultLoader.loadResults(filePath))
    {
        throw std::runtime_error(std::string("Unable to open file: ") + filePath);
    }

    const Kernel& kernel = kernelManager->getKernel(id);
    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelConfigurations(id));
    }

    size_t configurationCount = configurationManager.getConfigurationCount(id);
    std::vector<KernelResult> results;
    size_t tuningIterations;
    if (iterations == 0)
    {
        tuningIterations = configurationCount;
    }
    else
    {
        tuningIterations = std::min(configurationCount, iterations);
    }

    for (size_t i = 0; i < tuningIterations; i++)
    {
        KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
        KernelResult result(kernel.getName(), currentConfiguration);

        try
        {
            std::stringstream stream;
            stream << "Launching configuration " << i + 1 << "/" << configurationCount << " for kernel " << kernel.getName() << ": "
                << currentConfiguration;
            Logger::getLogger().log(LoggingLevel::Info, stream.str());

            result = resultLoader.readResult(currentConfiguration);
            result.setConfiguration(currentConfiguration);
        }
        catch (const std::runtime_error& error)
        {
            Logger::getLogger().log(LoggingLevel::Warning, std::string("Kernel run failed, reason: ") + error.what());
            results.emplace_back(kernel.getName(), currentConfiguration, std::string("Failed kernel run: ") + error.what());
        }

        configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, result.getComputationDuration());
        results.push_back(result);
    }

    configurationManager.clearKernelData(id, true, false);
    return results;
}

std::vector<KernelResult> TuningRunner::tuneComposition(const KernelId id, std::unique_ptr<StopCondition> stopCondition)
{
    if (!kernelManager->isComposition(id))
    {
        throw std::runtime_error(std::string("Invalid kernel composition id: ") + std::to_string(id));
    }

    const KernelComposition& composition = kernelManager->getKernelComposition(id);
    const Kernel compatibilityKernel = composition.transformToKernel();
    if (hasWritableZeroCopyArguments(compatibilityKernel))
    {
        throw std::runtime_error("Kernel composition tuning cannot be performed with writable zero-copy arguments");
    }

    resultValidator->computeReferenceResult(compatibilityKernel);
    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelCompositionConfigurations(id));
    }

    size_t configurationCount = configurationManager.getConfigurationCount(id);
    if (stopCondition != nullptr)
    {
        stopCondition->initialize(configurationCount);
        configurationCount = std::min(configurationCount, stopCondition->getConfigurationCount());
    }

    std::vector<KernelResult> results;

    for (size_t i = 0; i < configurationCount; i++)
    {
        std::stringstream stream;
        stream << "Launching configuration " << i + 1 << "/" << configurationCount << " for kernel composition " << composition.getName();
        Logger::getLogger().log(LoggingLevel::Info, stream.str());

        KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
        KernelResult result = kernelRunner->runComposition(id, currentConfiguration, std::vector<OutputDescriptor>{});

        if (validateResult(compatibilityKernel, result))
        {
            results.push_back(result);
            configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, result.getComputationDuration());

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(static_cast<double>(result.getComputationDuration()));
            }
        }
        else
        {
            results.emplace_back(composition.getName(), currentConfiguration, "Results differ");
            configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, UINT64_MAX);

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(std::numeric_limits<double>::max());
            }
        }

        kernelRunner->clearBuffers();

        if (stopCondition != nullptr && stopCondition->isMet())
        {
            Logger::getLogger().log(LoggingLevel::Info, stopCondition->getStatusString());
            break;
        }
    }

    resultValidator->clearReferenceResults();
    configurationManager.clearKernelData(id, true, false);
    return results;
}

KernelResult TuningRunner::tuneKernelByStep(const KernelId id, const std::vector<OutputDescriptor>& output, const bool recomputeReference)
{
    if (!kernelManager->isKernel(id))
    {
        throw std::runtime_error(std::string("Invalid kernel id: ") + std::to_string(id));
    }

    const Kernel& kernel = kernelManager->getKernel(id);
    if (recomputeReference)
    {
        resultValidator->clearReferenceResults(id);
        resultValidator->computeReferenceResult(kernel);
    }

    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelConfigurations(id));
    }

    KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
    KernelResult result = kernelRunner->runKernel(id, currentConfiguration, output);

    if (validateResult(kernel, result))
    {
        configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, result.getComputationDuration());
    }
    else
    {
        result.setValid(false);
        result.setErrorMessage("Results differ");
        configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, UINT64_MAX);
    }

    kernelRunner->clearBuffers();
    return result;
}

KernelResult TuningRunner::tuneCompositionByStep(const KernelId id, const std::vector<OutputDescriptor>& output, const bool recomputeReference)
{
    if (!kernelManager->isComposition(id))
    {
        throw std::runtime_error(std::string("Invalid kernel composition id: ") + std::to_string(id));
    }

    const KernelComposition& composition = kernelManager->getKernelComposition(id);
    const Kernel compatibilityKernel = composition.transformToKernel();
    if (recomputeReference)
    {
        resultValidator->clearReferenceResults(id);
        resultValidator->computeReferenceResult(compatibilityKernel);
    }

    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelCompositionConfigurations(id));
    }

    KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
    KernelResult result = kernelRunner->runComposition(id, currentConfiguration, output);

    if (validateResult(compatibilityKernel, result))
    {
        configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, result.getComputationDuration());
    }
    else
    {
        result.setValid(false);
        result.setErrorMessage("Results differ");
        configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, UINT64_MAX);
    }

    kernelRunner->clearBuffers();
    return result;
}

void TuningRunner::clearKernelData(const KernelId id, const bool clearConfigurations)
{
    configurationManager.clearKernelData(id, clearConfigurations, true);
}

void TuningRunner::setSearchMethod(const SearchMethod method, const std::vector<double>& arguments)
{
    configurationManager.setSearchMethod(method, arguments);
}

void TuningRunner::setValidationMethod(const ValidationMethod method, const double toleranceThreshold)
{
    resultValidator->setValidationMethod(method);
    resultValidator->setToleranceThreshold(toleranceThreshold);
}

void TuningRunner::setValidationRange(const ArgumentId id, const size_t range)
{
    resultValidator->setValidationRange(id, range);
}

void TuningRunner::setArgumentComparator(const ArgumentId id, const std::function<bool(const void*, const void*)>& comparator)
{
    resultValidator->setArgumentComparator(id, comparator);
}

void TuningRunner::setReferenceKernel(const KernelId id, const KernelId referenceId, const std::vector<ParameterPair>& referenceConfiguration,
    const std::vector<ArgumentId>& validatedArgumentIds)
{
    resultValidator->setReferenceKernel(id, referenceId, referenceConfiguration, validatedArgumentIds);
}

void TuningRunner::setReferenceClass(const KernelId id, std::unique_ptr<ReferenceClass> referenceClass,
    const std::vector<ArgumentId>& validatedArgumentIds)
{
    resultValidator->setReferenceClass(id, std::move(referenceClass), validatedArgumentIds);
}

ComputationResult TuningRunner::getBestComputationResult(const KernelId id) const
{
    return configurationManager.getBestComputationResult(id);
}

bool TuningRunner::validateResult(const Kernel& kernel, const KernelResult& result)
{
    if (!result.isValid())
    {
        return false;
    }

    bool resultIsCorrect = resultValidator->validateArgumentsWithClass(kernel);
    resultIsCorrect &= resultValidator->validateArgumentsWithKernel(kernel);

    if (resultIsCorrect)
    {
        Logger::getLogger().log(LoggingLevel::Info, std::string("Kernel run completed successfully in ")
            + std::to_string((result.getComputationDuration()) / 1'000'000) + "ms");
    }
    else
    {
        Logger::getLogger().log(LoggingLevel::Warning, "Kernel run completed successfully, but results differ");
    }

    return resultIsCorrect;
}

bool TuningRunner::hasWritableZeroCopyArguments(const Kernel& kernel)
{
    std::vector<KernelArgument*> arguments = argumentManager->getArguments(kernel.getArgumentIds());

    for (const auto argument : arguments)
    {
        if (argument->getMemoryLocation() == ArgumentMemoryLocation::HostZeroCopy && argument->getAccessType() != ArgumentAccessType::ReadOnly)
        {
            return true;
        }
    }

    return false;
}

} // namespace ktt
<commit_msg>Kernel configurations are no longer immediately cleared after offline tuning ends<commit_after>#include <algorithm>
#include <fstream>
#include <iterator>
#include <sstream>
#include <string>
#include "tuning_runner.h"
#include "utility/ktt_utility.h"
#include "utility/logger.h"
#include "utility/timer.h"
#include "utility/result_loader.h"

namespace ktt
{

TuningRunner::TuningRunner(ArgumentManager* argumentManager, KernelManager* kernelManager, KernelRunner* kernelRunner) :
    argumentManager(argumentManager),
    kernelManager(kernelManager),
    kernelRunner(kernelRunner),
    resultValidator(std::make_unique<ResultValidator>(argumentManager, kernelRunner))
{}

std::vector<KernelResult> TuningRunner::tuneKernel(const KernelId id, std::unique_ptr<StopCondition> stopCondition)
{
    if (!kernelManager->isKernel(id))
    {
        throw std::runtime_error(std::string("Invalid kernel id: ") + std::to_string(id));
    }

    const Kernel& kernel = kernelManager->getKernel(id);
    if (hasWritableZeroCopyArguments(kernel))
    {
        throw std::runtime_error("Kernel tuning cannot be performed with writable zero-copy arguments");
    }

    resultValidator->computeReferenceResult(kernel);
    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelConfigurations(id));
    }

    size_t configurationCount = configurationManager.getConfigurationCount(id);
    if (stopCondition != nullptr)
    {
        stopCondition->initialize(configurationCount);
        configurationCount = std::min(configurationCount, stopCondition->getConfigurationCount());
    }

    std::vector<KernelResult> results;

    for (size_t i = 0; i < configurationCount; i++)
    {
        std::stringstream stream;
        stream << "Launching configuration " << i + 1 << "/" << configurationCount << " for kernel " << kernel.getName();
        Logger::getLogger().log(LoggingLevel::Info, stream.str());

        KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
        KernelResult result = kernelRunner->runKernel(id, currentConfiguration, std::vector<OutputDescriptor>{});

        if (validateResult(kernel, result))
        {
            results.push_back(result);
            configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, result.getComputationDuration());

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(static_cast<double>(result.getComputationDuration()));
            }
        }
        else
        {
            results.emplace_back(kernel.getName(), currentConfiguration, "Results differ");
            configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, UINT64_MAX);

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(std::numeric_limits<double>::max());
            }
        }

        kernelRunner->clearBuffers(ArgumentAccessType::ReadWrite);
        kernelRunner->clearBuffers(ArgumentAccessType::WriteOnly);
        if (kernel.hasTuningManipulator())
        {
            kernelRunner->clearBuffers(ArgumentAccessType::ReadOnly);
        }

        if (stopCondition != nullptr && stopCondition->isMet())
        {
            Logger::getLogger().log(LoggingLevel::Info, stopCondition->getStatusString());
            break;
        }
    }

    kernelRunner->clearBuffers();
    resultValidator->clearReferenceResults();
    configurationManager.clearKernelData(id, false, false);
    return results;
}

std::vector<KernelResult> TuningRunner::dryTuneKernel(const KernelId id, const std::string& filePath, const size_t iterations)
{
    if (!kernelManager->isKernel(id))
    {
        throw std::runtime_error(std::string("Invalid kernel id: ") + std::to_string(id));
    }

    ResultLoader resultLoader;
    if (!resultLoader.loadResults(filePath))
    {
        throw std::runtime_error(std::string("Unable to open file: ") + filePath);
    }

    const Kernel& kernel = kernelManager->getKernel(id);
    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelConfigurations(id));
    }

    size_t configurationCount = configurationManager.getConfigurationCount(id);
    std::vector<KernelResult> results;
    size_t tuningIterations;
    if (iterations == 0)
    {
        tuningIterations = configurationCount;
    }
    else
    {
        tuningIterations = std::min(configurationCount, iterations);
    }

    for (size_t i = 0; i < tuningIterations; i++)
    {
        KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
        KernelResult result(kernel.getName(), currentConfiguration);

        try
        {
            std::stringstream stream;
            stream << "Launching configuration " << i + 1 << "/" << configurationCount << " for kernel " << kernel.getName() << ": "
                << currentConfiguration;
            Logger::getLogger().log(LoggingLevel::Info, stream.str());

            result = resultLoader.readResult(currentConfiguration);
            result.setConfiguration(currentConfiguration);
        }
        catch (const std::runtime_error& error)
        {
            Logger::getLogger().log(LoggingLevel::Warning, std::string("Kernel run failed, reason: ") + error.what());
            results.emplace_back(kernel.getName(), currentConfiguration, std::string("Failed kernel run: ") + error.what());
        }

        configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, result.getComputationDuration());
        results.push_back(result);
    }

    configurationManager.clearKernelData(id, false, false);
    return results;
}

std::vector<KernelResult> TuningRunner::tuneComposition(const KernelId id, std::unique_ptr<StopCondition> stopCondition)
{
    if (!kernelManager->isComposition(id))
    {
        throw std::runtime_error(std::string("Invalid kernel composition id: ") + std::to_string(id));
    }

    const KernelComposition& composition = kernelManager->getKernelComposition(id);
    const Kernel compatibilityKernel = composition.transformToKernel();
    if (hasWritableZeroCopyArguments(compatibilityKernel))
    {
        throw std::runtime_error("Kernel composition tuning cannot be performed with writable zero-copy arguments");
    }

    resultValidator->computeReferenceResult(compatibilityKernel);
    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelCompositionConfigurations(id));
    }

    size_t configurationCount = configurationManager.getConfigurationCount(id);
    if (stopCondition != nullptr)
    {
        stopCondition->initialize(configurationCount);
        configurationCount = std::min(configurationCount, stopCondition->getConfigurationCount());
    }

    std::vector<KernelResult> results;

    for (size_t i = 0; i < configurationCount; i++)
    {
        std::stringstream stream;
        stream << "Launching configuration " << i + 1 << "/" << configurationCount << " for kernel composition " << composition.getName();
        Logger::getLogger().log(LoggingLevel::Info, stream.str());

        KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
        KernelResult result = kernelRunner->runComposition(id, currentConfiguration, std::vector<OutputDescriptor>{});

        if (validateResult(compatibilityKernel, result))
        {
            results.push_back(result);
            configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, result.getComputationDuration());

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(static_cast<double>(result.getComputationDuration()));
            }
        }
        else
        {
            results.emplace_back(composition.getName(), currentConfiguration, "Results differ");
            configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, UINT64_MAX);

            if (stopCondition != nullptr)
            {
                stopCondition->updateStatus(std::numeric_limits<double>::max());
            }
        }

        kernelRunner->clearBuffers();

        if (stopCondition != nullptr && stopCondition->isMet())
        {
            Logger::getLogger().log(LoggingLevel::Info, stopCondition->getStatusString());
            break;
        }
    }

    resultValidator->clearReferenceResults();
    configurationManager.clearKernelData(id, false, false);
    return results;
}

KernelResult TuningRunner::tuneKernelByStep(const KernelId id, const std::vector<OutputDescriptor>& output, const bool recomputeReference)
{
    if (!kernelManager->isKernel(id))
    {
        throw std::runtime_error(std::string("Invalid kernel id: ") + std::to_string(id));
    }

    const Kernel& kernel = kernelManager->getKernel(id);
    if (recomputeReference)
    {
        resultValidator->clearReferenceResults(id);
        resultValidator->computeReferenceResult(kernel);
    }

    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelConfigurations(id));
    }

    KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
    KernelResult result = kernelRunner->runKernel(id, currentConfiguration, output);

    if (validateResult(kernel, result))
    {
        configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, result.getComputationDuration());
    }
    else
    {
        result.setValid(false);
        result.setErrorMessage("Results differ");
        configurationManager.calculateNextConfiguration(id, kernel.getName(), currentConfiguration, UINT64_MAX);
    }

    kernelRunner->clearBuffers();
    return result;
}

KernelResult TuningRunner::tuneCompositionByStep(const KernelId id, const std::vector<OutputDescriptor>& output, const bool recomputeReference)
{
    if (!kernelManager->isComposition(id))
    {
        throw std::runtime_error(std::string("Invalid kernel composition id: ") + std::to_string(id));
    }

    const KernelComposition& composition = kernelManager->getKernelComposition(id);
    const Kernel compatibilityKernel = composition.transformToKernel();
    if (recomputeReference)
    {
        resultValidator->clearReferenceResults(id);
        resultValidator->computeReferenceResult(compatibilityKernel);
    }

    if (!configurationManager.hasKernelConfigurations(id))
    {
        configurationManager.setKernelConfigurations(id, kernelManager->getKernelCompositionConfigurations(id));
    }

    KernelConfiguration currentConfiguration = configurationManager.getCurrentConfiguration(id);
    KernelResult result = kernelRunner->runComposition(id, currentConfiguration, output);

    if (validateResult(compatibilityKernel, result))
    {
        configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, result.getComputationDuration());
    }
    else
    {
        result.setValid(false);
        result.setErrorMessage("Results differ");
        configurationManager.calculateNextConfiguration(id, composition.getName(), currentConfiguration, UINT64_MAX);
    }

    kernelRunner->clearBuffers();
    return result;
}

void TuningRunner::clearKernelData(const KernelId id, const bool clearConfigurations)
{
    configurationManager.clearKernelData(id, clearConfigurations, true);
}

void TuningRunner::setSearchMethod(const SearchMethod method, const std::vector<double>& arguments)
{
    configurationManager.setSearchMethod(method, arguments);
}

void TuningRunner::setValidationMethod(const ValidationMethod method, const double toleranceThreshold)
{
    resultValidator->setValidationMethod(method);
    resultValidator->setToleranceThreshold(toleranceThreshold);
}

void TuningRunner::setValidationRange(const ArgumentId id, const size_t range)
{
    resultValidator->setValidationRange(id, range);
}

void TuningRunner::setArgumentComparator(const ArgumentId id, const std::function<bool(const void*, const void*)>& comparator)
{
    resultValidator->setArgumentComparator(id, comparator);
}

void TuningRunner::setReferenceKernel(const KernelId id, const KernelId referenceId, const std::vector<ParameterPair>& referenceConfiguration,
    const std::vector<ArgumentId>& validatedArgumentIds)
{
    resultValidator->setReferenceKernel(id, referenceId, referenceConfiguration, validatedArgumentIds);
}

void TuningRunner::setReferenceClass(const KernelId id, std::unique_ptr<ReferenceClass> referenceClass,
    const std::vector<ArgumentId>& validatedArgumentIds)
{
    resultValidator->setReferenceClass(id, std::move(referenceClass), validatedArgumentIds);
}

ComputationResult TuningRunner::getBestComputationResult(const KernelId id) const
{
    return configurationManager.getBestComputationResult(id);
}

bool TuningRunner::validateResult(const Kernel& kernel, const KernelResult& result)
{
    if (!result.isValid())
    {
        return false;
    }

    bool resultIsCorrect = resultValidator->validateArgumentsWithClass(kernel);
    resultIsCorrect &= resultValidator->validateArgumentsWithKernel(kernel);

    if (resultIsCorrect)
    {
        Logger::getLogger().log(LoggingLevel::Info, std::string("Kernel run completed successfully in ")
            + std::to_string((result.getComputationDuration()) / 1'000'000) + "ms");
    }
    else
    {
        Logger::getLogger().log(LoggingLevel::Warning, "Kernel run completed successfully, but results differ");
    }

    return resultIsCorrect;
}

bool TuningRunner::hasWritableZeroCopyArguments(const Kernel& kernel)
{
    std::vector<KernelArgument*> arguments = argumentManager->getArguments(kernel.getArgumentIds());

    for (const auto argument : arguments)
    {
        if (argument->getMemoryLocation() == ArgumentMemoryLocation::HostZeroCopy && argument->getAccessType() != ArgumentAccessType::ReadOnly)
        {
            return true;
        }
    }

    return false;
}

} // namespace ktt
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/pivoter.hpp"

#include "vast/command.hpp"
#include "vast/concept/parseable/to.hpp"
#include "vast/concept/parseable/vast/expression.hpp"
#include "vast/detail/string.hpp"
#include "vast/expression.hpp"
#include "vast/logger.hpp"
#include "vast/system/exporter.hpp"
#include "vast/table_slice.hpp"

#include <caf/atom.hpp>
#include <caf/event_based_actor.hpp>

namespace vast::system {

namespace {

caf::optional<record_field>
common_field(const pivoter_state& st, const record_type& indicator) {
  auto f = st.cache.find(indicator);
  if (f != st.cache.end())
    return f->second;
    // TODO: This algorithm can be enabled once we have a live updated
    //       type registry. (Switch the type of target to record_type.)
#if 0
  for (auto& t : target.fields) {
    for (auto& i : indicator.fields) {
      if (t.name == i.name) {
        st.cache.insert({indicator, i});
        return i;
      }
    }
  }
#else
  std::string edge;
  VAST_TRACE(st.self, VAST_ARG(st.target), VAST_ARG(indicator.name()));
  if (detail::starts_with(st.target, "suricata") || st.target == "pcap.packet")
    edge = "community_id";
  else if (detail::starts_with(st.target, "zeek")) {
    if (detail::starts_with(indicator.name(), "zeek"))
      edge = "uid";
    else
      edge = "community_id";
  }
  for (auto& i : indicator.fields) {
    if (i.name == edge) {
      st.cache.insert({indicator, i});
      return i;
    }
  }
#endif
  st.cache.insert({indicator, caf::none});
  VAST_WARNING(st.self, "got slice without shared column:", indicator.name());
  return caf::none;
}

} // namespace

pivoter_state::pivoter_state(caf::event_based_actor*) {
  // nop
}

caf::behavior pivoter(caf::stateful_actor<pivoter_state>* self, caf::actor node,
                      std::string target, expression expr) {
  auto& st = self->state;
  st.self = self;
  st.node = node;
  st.expr = std::move(expr);
  st.target = std::move(target);
  auto quit_if_done = [=]() {
    auto& st = self->state;
    if (st.initial_query_completed && st.running_exporters == 0)
      self->quit();
  };
  self->set_down_handler([=](const caf::down_msg& msg) {
    // Only the spawned EXPORTERs are expected to send down messages.
    auto& st = self->state;
    st.running_exporters--;
    VAST_DEBUG(self, "received DOWN from", msg.source,
               "outstanding requests:", st.running_exporters);
    quit_if_done();
  });
  return {[=](vast::table_slice_ptr slice) {
            auto& st = self->state;
            auto pivot_field = common_field(st, slice->layout());
            if (!pivot_field)
              return;
            VAST_DEBUG(self, "uses", *pivot_field, "to extract", st.target,
                       "events");
            auto pivot_field_name = pivot_field->name;
            auto column = slice->column(pivot_field_name);
            std::stringstream sstr;
            sstr << "#type == \"" << st.target << "\" && " << pivot_field_name
                 << " in [\"";
            size_t request_size = 0;
            for (size_t i = 0; i < column->rows(); ++i) {
              auto data = materialize((*column)[i]);
              auto x = caf::get_if<std::string>(&data);
              // Skip if no value
              if (!x)
                continue;
              // Skip if id was already requested
              if (st.requested_ids.count(*x) > 0)
                continue;
              if (request_size != 0)
                sstr << "\", \"";
              sstr << *x;
              st.requested_ids.insert(*x);
              request_size++;
            }
            VAST_DEBUG(self, "queries for", request_size, pivot_field_name);
            if (!request_size) {
              return;
            }
            sstr << "\"]";
            VAST_DEBUG(self, "spawns new exporter with query", sstr.str());
            auto exporter_invocation
              = command::invocation{{}, "spawn exporter", {sstr.str()}};
            self->send(st.node, exporter_invocation);
            st.running_exporters++;
          },
          [=](caf::actor exp) {
            VAST_DEBUG(self, "registers exporter", exp);
            auto& st = self->state;
            self->monitor(exp);
            self->send(exp, system::sink_atom::value, st.sink);
            self->send(exp, system::run_atom::value);
          },
          [=](std::string name, query_status) {
            VAST_DEBUG(self, "received final status from", name);
            self->state.initial_query_completed = true;
            quit_if_done();
          },
          [=](sink_atom, const caf::actor& sink) {
            VAST_DEBUG(self, "registers sink", sink);
            auto& st = self->state;
            st.sink = sink;
          },
          [=](const uuid& id, const query_status&) {
            VAST_IGNORE_UNUSED(id);
            VAST_INFO(self, "got query statistics from", id);
          }};
}

} // namespace vast::system
<commit_msg>Remove unnessecary braces<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/pivoter.hpp"

#include "vast/command.hpp"
#include "vast/concept/parseable/to.hpp"
#include "vast/concept/parseable/vast/expression.hpp"
#include "vast/detail/string.hpp"
#include "vast/expression.hpp"
#include "vast/logger.hpp"
#include "vast/system/exporter.hpp"
#include "vast/table_slice.hpp"

#include <caf/atom.hpp>
#include <caf/event_based_actor.hpp>

namespace vast::system {

namespace {

caf::optional<record_field>
common_field(const pivoter_state& st, const record_type& indicator) {
  auto f = st.cache.find(indicator);
  if (f != st.cache.end())
    return f->second;
    // TODO: This algorithm can be enabled once we have a live updated
    //       type registry. (Switch the type of target to record_type.)
#if 0
  for (auto& t : target.fields) {
    for (auto& i : indicator.fields) {
      if (t.name == i.name) {
        st.cache.insert({indicator, i});
        return i;
      }
    }
  }
#else
  std::string edge;
  VAST_TRACE(st.self, VAST_ARG(st.target), VAST_ARG(indicator.name()));
  if (detail::starts_with(st.target, "suricata") || st.target == "pcap.packet")
    edge = "community_id";
  else if (detail::starts_with(st.target, "zeek")) {
    if (detail::starts_with(indicator.name(), "zeek"))
      edge = "uid";
    else
      edge = "community_id";
  }
  for (auto& i : indicator.fields) {
    if (i.name == edge) {
      st.cache.insert({indicator, i});
      return i;
    }
  }
#endif
  st.cache.insert({indicator, caf::none});
  VAST_WARNING(st.self, "got slice without shared column:", indicator.name());
  return caf::none;
}

} // namespace

pivoter_state::pivoter_state(caf::event_based_actor*) {
  // nop
}

caf::behavior pivoter(caf::stateful_actor<pivoter_state>* self, caf::actor node,
                      std::string target, expression expr) {
  auto& st = self->state;
  st.self = self;
  st.node = node;
  st.expr = std::move(expr);
  st.target = std::move(target);
  auto quit_if_done = [=]() {
    auto& st = self->state;
    if (st.initial_query_completed && st.running_exporters == 0)
      self->quit();
  };
  self->set_down_handler([=](const caf::down_msg& msg) {
    // Only the spawned EXPORTERs are expected to send down messages.
    auto& st = self->state;
    st.running_exporters--;
    VAST_DEBUG(self, "received DOWN from", msg.source,
               "outstanding requests:", st.running_exporters);
    quit_if_done();
  });
  return {[=](vast::table_slice_ptr slice) {
            auto& st = self->state;
            auto pivot_field = common_field(st, slice->layout());
            if (!pivot_field)
              return;
            VAST_DEBUG(self, "uses", *pivot_field, "to extract", st.target,
                       "events");
            auto pivot_field_name = pivot_field->name;
            auto column = slice->column(pivot_field_name);
            std::stringstream sstr;
            sstr << "#type == \"" << st.target << "\" && " << pivot_field_name
                 << " in [\"";
            size_t request_size = 0;
            for (size_t i = 0; i < column->rows(); ++i) {
              auto data = materialize((*column)[i]);
              auto x = caf::get_if<std::string>(&data);
              // Skip if no value
              if (!x)
                continue;
              // Skip if id was already requested
              if (st.requested_ids.count(*x) > 0)
                continue;
              if (request_size != 0)
                sstr << "\", \"";
              sstr << *x;
              st.requested_ids.insert(*x);
              request_size++;
            }
            VAST_DEBUG(self, "queries for", request_size, pivot_field_name);
            if (!request_size)
              return;
            sstr << "\"]";
            VAST_DEBUG(self, "spawns new exporter with query", sstr.str());
            auto exporter_invocation
              = command::invocation{{}, "spawn exporter", {sstr.str()}};
            self->send(st.node, exporter_invocation);
            st.running_exporters++;
          },
          [=](caf::actor exp) {
            VAST_DEBUG(self, "registers exporter", exp);
            auto& st = self->state;
            self->monitor(exp);
            self->send(exp, system::sink_atom::value, st.sink);
            self->send(exp, system::run_atom::value);
          },
          [=](std::string name, query_status) {
            VAST_DEBUG(self, "received final status from", name);
            self->state.initial_query_completed = true;
            quit_if_done();
          },
          [=](sink_atom, const caf::actor& sink) {
            VAST_DEBUG(self, "registers sink", sink);
            auto& st = self->state;
            st.sink = sink;
          },
          [=](const uuid& id, const query_status&) {
            VAST_IGNORE_UNUSED(id);
            VAST_INFO(self, "got query statistics from", id);
          }};
}

} // namespace vast::system
<|endoftext|>


<commit_before>//Copyright (c) 2019 Ultimaker B.V.

#include "SingleBeadBeadingStrategy.h"

namespace arachne
{

SingleBeadBeadingStrategy::Beading SingleBeadBeadingStrategy::compute(coord_t thickness, coord_t bead_count) const
{
    Beading ret;

    ret.total_thickness = thickness;
    if (bead_count == 1)
    {
        ret.bead_widths.emplace_back(thickness);
        ret.toolpath_locations.emplace_back(thickness / 2);
    }
    if (bead_count > 1)
    {
        coord_t width = std::min(optimal_width, thickness / (bead_count - 1));
        ret.bead_widths.resize(bead_count, width);
        for (coord_t bead_idx = 0; bead_idx < bead_count; bead_idx++)
        {
            ret.toolpath_locations.emplace_back(width * (bead_idx * 2 + 1) / 2);
        }
        ret.left_over = thickness - bead_count * width;
    }
    else
    {
        ret.left_over = thickness;
    }
    return ret;
}

coord_t SingleBeadBeadingStrategy::getOptimalThickness(coord_t bead_count) const
{
    return bead_count * optimal_width - 10;
}

coord_t SingleBeadBeadingStrategy::getTransitionThickness(coord_t lower_bead_count) const
{
    if (lower_bead_count <= 0) return 0;
    else if (lower_bead_count == 1) return optimal_width;
    else return 9999999;
}

coord_t SingleBeadBeadingStrategy::getOptimalBeadCount(coord_t thickness) const
{
    if (thickness <= optimal_width) return 1;
    else return 2;
}

coord_t SingleBeadBeadingStrategy::getTransitioningLength(coord_t lower_bead_count) const
{
    return 20;
}

} // namespace arachne
<commit_msg>Minor codestyle fixes<commit_after>//Copyright (c) 2020 Ultimaker B.V.

#include "SingleBeadBeadingStrategy.h"

namespace arachne
{

SingleBeadBeadingStrategy::Beading SingleBeadBeadingStrategy::compute(coord_t thickness, coord_t bead_count) const
{
    Beading ret;

    ret.total_thickness = thickness;
    if (bead_count == 1)
    {
        ret.bead_widths.emplace_back(thickness);
        ret.toolpath_locations.emplace_back(thickness / 2);
    }
    if (bead_count > 1)
    {
        coord_t width = std::min(optimal_width, thickness / (bead_count - 1));
        ret.bead_widths.resize(bead_count, width);
        for (coord_t bead_idx = 0; bead_idx < bead_count; bead_idx++)
        {
            ret.toolpath_locations.emplace_back(width * (bead_idx * 2 + 1) / 2);
        }
        ret.left_over = thickness - bead_count * width;
    }
    else
    {
        ret.left_over = thickness;
    }
    return ret;
}

coord_t SingleBeadBeadingStrategy::getOptimalThickness(coord_t bead_count) const
{
    return bead_count * optimal_width - 10;
}

coord_t SingleBeadBeadingStrategy::getTransitionThickness(coord_t lower_bead_count) const
{
    if (lower_bead_count <= 0)
    {
        return 0;
    }
    else if (lower_bead_count == 1)
    {
        return optimal_width;
    }
    else
    {
        return 9999999;
    }
}

coord_t SingleBeadBeadingStrategy::getOptimalBeadCount(coord_t thickness) const
{
    if (thickness <= optimal_width)
    {
        return 1;
    }
    else
    {
        return 2;
    }
}

coord_t SingleBeadBeadingStrategy::getTransitioningLength(coord_t lower_bead_count) const
{
    return 20;
}

} // namespace arachne
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file  variant_tree.hpp
//----------------------------------------------------------------------------
/// \brief This file contains a tree class that can hold variant values.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-07-10
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file may be included in various open-source projects.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#ifndef _UTIL_VARIANT_TREE_HPP_
#define _UTIL_VARIANT_TREE_HPP_

#include <util/variant.hpp>
#include <util/typeinfo.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/throw_exception.hpp>
#include <boost/foreach.hpp>

namespace boost {
namespace property_tree {
    // Custom translator that works with util::variant instead of std::string.
    // This translator is used to read/write values from files.
    template <>
    struct translator_between<util::variant, std::string>
    {
        typedef translator_between<util::variant, std::string> type;
        typedef std::string     external_type;
        typedef util::variant   internal_type;

        boost::optional<external_type> get_value(const internal_type& value) const {
            return boost::optional<external_type>(
                value.type() == internal_type::TYPE_NULL ? "" : value.to_string());
        }

        boost::optional<internal_type> put_value(const external_type& value) const {
            try {
                long n = lexical_cast<long>(value);
                for(external_type::const_iterator it=value.begin(), end=value.end(); it!=end; ++it)
                    if (*it < '0' || *it > '9')
                        throw false;
                return boost::optional<internal_type>(n);
            } catch (...) {}
            try {
                double n = lexical_cast<double>(value);
                return boost::optional<internal_type>(n);
            } catch (...) {}
            if (value == "true" || value == "false")
                return boost::optional<internal_type>(value[0] == 't');
            return boost::optional<internal_type>(value);
        }
    };

} // namespace property_tree
} // namespace boost

namespace util {

namespace detail {

    // Custom translator that works with variant instead of std::string
    // This translator is used to get/put values through explicit get/put calls.
    template <class Ext>
    struct variant_translator
    {
        typedef Ext external_type;
        typedef variant internal_type;

        /*
        typedef boost::mpl::joint_view<variant::int_types,
                boost::mpl::vector<bool,double>
            > valid_non_string_types;
        */
        typedef variant::valid_types valid_types;

        external_type get_value(const internal_type& value) const {
            return value.get<external_type>();
        }

        template<typename T>
        typename boost::disable_if<
            boost::is_same<
                boost::mpl::end<valid_types>::type,
                boost::mpl::find<variant::valid_types, T>
            >,
            internal_type>::type
        put_value(T value) const {
            return variant(value);
        }
    };

    typedef boost::property_tree::basic_ptree<
            std::string,                    // Key type
            variant,                        // Data type
            std::less<std::string>          // Key comparison
    > basic_variant_tree;

} // namespace detail

class variant_tree : public detail::basic_variant_tree
{
    typedef detail::basic_variant_tree base;
    typedef variant_tree self_type;
public:
    typedef boost::property_tree::ptree_bad_path bad_path;
    typedef std::pair<const std::string, base> value_type;

    variant_tree() {}
    variant_tree(const detail::basic_variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}
    variant_tree(const variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}

    template <typename Source>
    static void read_info(Source& src, variant_tree& tree) {
        boost::property_tree::info_parser::read_info(src, static_cast<base&>(tree));
        boost::property_tree::translator_between<util::variant, std::string> tr;
        translate_data(tr, tree);
    }

    template <typename Target>
    static void write_info(Target& tar, variant_tree& tree) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree));
    }

    template <typename Target, typename Settings>
    static void write_info(Target& tar, variant_tree& tree, const Settings& tt) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree), tt);
    }

    template <class T>
    T get_value() const {
        using boost::throw_exception;

        if(boost::optional<T> o =
                base::get_value_optional<T>(detail::variant_translator<T>())) {
            return *o;
        }
        BOOST_PROPERTY_TREE_THROW(boost::property_tree::ptree_bad_data(
            std::string("conversion of data to type \"") +
            typeid(T).name() + "\" failed", base::data()));
    }

    template <class T>
    T get_value(const T& default_value) const {
        return base::get_value(default_value, detail::variant_translator<T>());
    }

    std::string get_value(const char* default_value) const {
        return base::get_value(std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_value_optional() const {
        return base::get_value(detail::variant_translator<T>());
    }

    template <class T>
    void put_value(const T& value) {
        base::put_value(value, detail::variant_translator<T>());
    }

    template <class T>
    T get(const path_type& path) const {
        try {
            return base::get_child(path).BOOST_NESTED_TEMPLATE
                get_value<T>(detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            std::stringstream s;
            s << "Cannot convert value to type '" << type_to_string<T>() << "'";
            throw bad_path(s.str(), path);
        }
    }

    template <class T>
    T get(const path_type& path, const T& default_value) const {
        try {
            return base::get(path, default_value, detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            throw bad_path("Wrong or missing value type", path);
        }
    }

    std::string get(const path_type& path, const char* default_value) const {
        return base::get(path, std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_optional(const path_type& path) const {
        return base::get_optional(path, detail::variant_translator<T>());
    }

    template <class T>
    void put(const path_type& path, const T& value) {
        base::put(path, value, detail::variant_translator<T>());
    }

    template <class T>
    self_type& add(const path_type& path, const T& value) {
        return static_cast<self_type&>(
            base::add(path, value, detail::variant_translator<T>()));
    }

    void swap(variant_tree& rhs) {
        base::swap(static_cast<base&>(rhs));
    }
    void swap(boost::property_tree::basic_ptree<
        std::string, variant, std::less<std::string> >& rhs) {
        base::swap(rhs);
    }

    self_type &get_child(const path_type &path) {
        return static_cast<self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or throw @c ptree_bad_path. */
    const self_type &get_child(const path_type &path) const {
        return static_cast<const self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or return @p default_value. */
    self_type &get_child(const path_type &path, self_type &default_value) {
        return static_cast<self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return @p default_value. */
    const self_type &get_child(const path_type &path,
                               const self_type &default_value) const {
        return static_cast<const self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<self_type &> get_child_optional(const path_type &path) {
        boost::optional<base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<self_type&>();
        return boost::optional<self_type&>(static_cast<self_type&>(*o));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<const self_type &>
    get_child_optional(const path_type &path) const {
        boost::optional<const base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<const self_type&>();
        return boost::optional<const self_type&>(static_cast<const self_type&>(*o));
    }

    self_type &put_child(const path_type &path, const self_type &value) {
        return static_cast<self_type&>(base::put_child(path, value));
    }

    std::ostream& dump(std::ostream& out, size_t a_level=0, size_t a_tab_width=2) const {
        size_t l_max = 0;
        BOOST_FOREACH(const util::variant_tree::value_type& v, *this) {
            size_t n = v.first.size() + strlen(v.second.data().type_str()) + 3;
            l_max = std::max(n, l_max);
        }
        BOOST_FOREACH(const util::variant_tree::value_type& v, *this) {
            out << std::string(a_level*a_tab_width, ' ')
                << v.first << " (" << v.second.data().type_str() << ") "
                << std::string(
                    l_max - v.first.size() - strlen(v.second.data().type_str()), ' ')
                << v.second.data().to_string() << std::endl;
            if (v.second.size())
                static_cast<const util::variant_tree&>(v.second).dump(out, a_level+1);
        }
        return out;
    }

    /// Merge current tree with \a a_tree by calling \a a_on_update function
    /// for every node in the \a a_tree.  The function accepts two parameters:
    /// and has the following signature:
    ///        variant (const variant_tree::path_type& a_path, const variant& a_data)
    template <typename T>
    void merge(const variant_tree& a_tree, const T& a_on_update) {
        merge(*this, "", a_tree, a_on_update);
    }

protected:
    template <typename T>
    static void translate_data(T& tr, base& tree) {
        for (variant_tree::iterator it=tree.begin(); it != tree.end(); it++)
            translate_data(tr, it->second);
        tree.data() = *tr.put_value(tree.get_value<std::string>());
    }

    /// This recursive function will call a_method for every node in the tree
    template<typename T>
    static void merge(
        variant_tree& a_parent,
        const variant_tree::path_type& a_child_path,
        const variant_tree& a_child,
        const T& a_on_update)
    {
        a_parent.put(a_child_path, a_on_update(a_child_path, a_child.data()));
        for(variant_tree::const_iterator
                it = a_child.begin(), end = a_child.end(); it != end; ++it) {
            variant_tree::path_type l_path =
                a_child_path / variant_tree::path_type(it->first);
            merge(a_parent, l_path, it->second, a_on_update);
        }
    }
};

} // namespace util

#endif // _UTIL_VARIANT_TREE_HPP_
<commit_msg>Added variant_tree:merge<commit_after>//----------------------------------------------------------------------------
/// \file  variant_tree.hpp
//----------------------------------------------------------------------------
/// \brief This file contains a tree class that can hold variant values.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-07-10
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file may be included in various open-source projects.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#ifndef _UTIL_VARIANT_TREE_HPP_
#define _UTIL_VARIANT_TREE_HPP_

#include <util/variant.hpp>
#include <util/typeinfo.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/throw_exception.hpp>
#include <boost/foreach.hpp>

namespace boost {
namespace property_tree {
    // Custom translator that works with util::variant instead of std::string.
    // This translator is used to read/write values from files.
    template <>
    struct translator_between<util::variant, std::string>
    {
        typedef translator_between<util::variant, std::string> type;
        typedef std::string     external_type;
        typedef util::variant   internal_type;

        boost::optional<external_type> get_value(const internal_type& value) const {
            return boost::optional<external_type>(
                value.type() == internal_type::TYPE_NULL ? "" : value.to_string());
        }

        boost::optional<internal_type> put_value(const external_type& value) const {
            try {
                long n = lexical_cast<long>(value);
                for(external_type::const_iterator it=value.begin(), end=value.end(); it!=end; ++it)
                    if (*it < '0' || *it > '9')
                        throw false;
                return boost::optional<internal_type>(n);
            } catch (...) {}
            try {
                double n = lexical_cast<double>(value);
                return boost::optional<internal_type>(n);
            } catch (...) {}
            if (value == "true" || value == "false")
                return boost::optional<internal_type>(value[0] == 't');
            return boost::optional<internal_type>(value);
        }
    };

} // namespace property_tree
} // namespace boost

namespace util {

namespace detail {

    // Custom translator that works with variant instead of std::string
    // This translator is used to get/put values through explicit get/put calls.
    template <class Ext>
    struct variant_translator
    {
        typedef Ext external_type;
        typedef variant internal_type;

        /*
        typedef boost::mpl::joint_view<variant::int_types,
                boost::mpl::vector<bool,double>
            > valid_non_string_types;
        */
        typedef variant::valid_types valid_types;

        external_type get_value(const internal_type& value) const {
            return value.get<external_type>();
        }

        template<typename T>
        typename boost::disable_if<
            boost::is_same<
                boost::mpl::end<valid_types>::type,
                boost::mpl::find<variant::valid_types, T>
            >,
            internal_type>::type
        put_value(T value) const {
            return variant(value);
        }
    };

    typedef boost::property_tree::basic_ptree<
            std::string,                    // Key type
            variant,                        // Data type
            std::less<std::string>          // Key comparison
    > basic_variant_tree;

} // namespace detail

class variant_tree : public detail::basic_variant_tree
{
    typedef detail::basic_variant_tree base;
    typedef variant_tree self_type;
public:
    typedef boost::property_tree::ptree_bad_path bad_path;
    typedef std::pair<const std::string, base> value_type;

    variant_tree() {}
    variant_tree(const detail::basic_variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}
    variant_tree(const variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}

    template <typename Source>
    static void read_info(Source& src, variant_tree& tree) {
        boost::property_tree::info_parser::read_info(src, static_cast<base&>(tree));
        boost::property_tree::translator_between<util::variant, std::string> tr;
        translate_data(tr, tree);
    }

    template <typename Target>
    static void write_info(Target& tar, variant_tree& tree) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree));
    }

    template <typename Target, typename Settings>
    static void write_info(Target& tar, variant_tree& tree, const Settings& tt) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree), tt);
    }

    template <class T>
    T get_value() const {
        using boost::throw_exception;

        if(boost::optional<T> o =
                base::get_value_optional<T>(detail::variant_translator<T>())) {
            return *o;
        }
        BOOST_PROPERTY_TREE_THROW(boost::property_tree::ptree_bad_data(
            std::string("conversion of data to type \"") +
            typeid(T).name() + "\" failed", base::data()));
    }

    template <class T>
    T get_value(const T& default_value) const {
        return base::get_value(default_value, detail::variant_translator<T>());
    }

    std::string get_value(const char* default_value) const {
        return base::get_value(std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_value_optional() const {
        return base::get_value(detail::variant_translator<T>());
    }

    template <class T>
    void put_value(const T& value) {
        base::put_value(value, detail::variant_translator<T>());
    }

    template <class T>
    T get(const path_type& path) const {
        try {
            return base::get_child(path).BOOST_NESTED_TEMPLATE
                get_value<T>(detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            std::stringstream s;
            s << "Cannot convert value to type '" << type_to_string<T>() << "'";
            throw bad_path(s.str(), path);
        }
    }

    template <class T>
    T get(const path_type& path, const T& default_value) const {
        try {
            return base::get(path, default_value, detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            throw bad_path("Wrong or missing value type", path);
        }
    }

    std::string get(const path_type& path, const char* default_value) const {
        return base::get(path, std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_optional(const path_type& path) const {
        return base::get_optional(path, detail::variant_translator<T>());
    }

    template <class T>
    void put(const path_type& path, const T& value) {
        base::put(path, value, detail::variant_translator<T>());
    }

    template <class T>
    self_type& add(const path_type& path, const T& value) {
        return static_cast<self_type&>(
            base::add(path, value, detail::variant_translator<T>()));
    }

    void swap(variant_tree& rhs) {
        base::swap(static_cast<base&>(rhs));
    }
    void swap(boost::property_tree::basic_ptree<
        std::string, variant, std::less<std::string> >& rhs) {
        base::swap(rhs);
    }

    self_type &get_child(const path_type &path) {
        return static_cast<self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or throw @c ptree_bad_path. */
    const self_type &get_child(const path_type &path) const {
        return static_cast<const self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or return @p default_value. */
    self_type &get_child(const path_type &path, self_type &default_value) {
        return static_cast<self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return @p default_value. */
    const self_type &get_child(const path_type &path,
                               const self_type &default_value) const {
        return static_cast<const self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<self_type &> get_child_optional(const path_type &path) {
        boost::optional<base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<self_type&>();
        return boost::optional<self_type&>(static_cast<self_type&>(*o));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<const self_type &>
    get_child_optional(const path_type &path) const {
        boost::optional<const base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<const self_type&>();
        return boost::optional<const self_type&>(static_cast<const self_type&>(*o));
    }

    self_type &put_child(const path_type &path, const self_type &value) {
        return static_cast<self_type&>(base::put_child(path, value));
    }

    std::ostream& dump(std::ostream& out, size_t a_level=0, size_t a_tab_width=2) const {
        size_t l_max = 0;
        BOOST_FOREACH(const util::variant_tree::value_type& v, *this) {
            size_t n = v.first.size() + strlen(v.second.data().type_str()) + 3;
            l_max = std::max(n, l_max);
        }
        BOOST_FOREACH(const util::variant_tree::value_type& v, *this) {
            out << std::string(a_level*a_tab_width, ' ')
                << v.first << " (" << v.second.data().type_str() << ") "
                << std::string(
                    l_max - v.first.size() - strlen(v.second.data().type_str()), ' ')
                << v.second.data().to_string() << std::endl;
            if (v.second.size())
                static_cast<const util::variant_tree&>(v.second).dump(out, a_level+1);
        }
        return out;
    }

    /// Merge current tree with \a a_tree by calling \a a_on_update function
    /// for every node in the \a a_tree.  The function accepts two parameters:
    /// and has the following signature:
    ///        variant (const variant_tree::path_type& a_path, const variant& a_data)
    template <typename T>
    void merge(const variant_tree& a_tree, const T& a_on_update) {
        merge(*this, "", a_tree, a_on_update);
    }

    void merge(const variant_tree& a_tree) { merge(*this, "", a_tree, &dummy_update); }

protected:
    template <typename T>
    static void translate_data(T& tr, base& tree) {
        for (variant_tree::iterator it=tree.begin(); it != tree.end(); it++)
            translate_data(tr, it->second);
        tree.data() = *tr.put_value(tree.get_value<std::string>());
    }

    /// This recursive function will call a_method for every node in the tree
    template<typename T>
    static void merge(
        variant_tree& a_parent,
        const variant_tree::path_type& a_child_path,
        const variant_tree& a_child,
        const T& a_on_update)
    {
        a_parent.put(a_child_path, a_on_update(a_child_path, a_child.data()));
        for(variant_tree::const_iterator
                it = a_child.begin(), end = a_child.end(); it != end; ++it) {
            variant_tree::path_type l_path =
                a_child_path / variant_tree::path_type(it->first);
            merge(a_parent, l_path, it->second, a_on_update);
        }
    }

private:
    static const variant& dummy_update(
        const variant_tree::path_type& a, const variant& v) { return v; }
};

} // namespace util

#endif // _UTIL_VARIANT_TREE_HPP_
<|endoftext|>


<commit_before>#pragma once

#ifndef RAZ_WORLD_HPP
#define RAZ_WORLD_HPP

#include "RaZ/Entity.hpp"
#include "RaZ/System.hpp"

namespace Raz {

class World {
public:
  explicit World(std::size_t entityCount) { m_entities.reserve(entityCount); }

  const std::vector<SystemPtr>& getSystems() const { return m_systems; }
  const std::vector<EntityPtr>& getEntities() const { return m_entities; }

  template <typename Sys> bool hasSystem() const;
  template <typename Sys> Sys& getSystem();
  template <typename Sys, typename... Args> Sys& addSystem(Args&&... args);
  template <typename Sys> std::tuple<Sys&> addSystems();
  template <typename Sys1, typename Sys2, typename... S> std::tuple<Sys1&, Sys2&, S...> addSystems();
  template <typename Sys> void removeSystem();
  Entity& addEntity(bool enabled = true);
  template <typename Comp, typename... Args> Entity& addEntityWithComponent(bool enabled = true, Args&&... args);
  template <typename... C> Entity& addEntityWithComponents(bool enabled = true);
  void update(float deltaTime);
  void refresh();
  void destroy();

private:
  std::vector<SystemPtr> m_systems {};
  std::vector<EntityPtr> m_entities {};
  std::size_t m_enabledEntityCount = 0;
  std::size_t m_maxEntityIndex = 0;
};

} // namespace Raz

#include "RaZ/World.inl"

#endif // RAZ_WORLD_HPP
<commit_msg>[Update] Added a no-parameter World::addEntityWithComponent() [Fix] Fixes a Clang bug with default argument value (cf. Travis)<commit_after>#pragma once

#ifndef RAZ_WORLD_HPP
#define RAZ_WORLD_HPP

#include "RaZ/Entity.hpp"
#include "RaZ/System.hpp"

namespace Raz {

class World {
public:
  explicit World(std::size_t entityCount) { m_entities.reserve(entityCount); }

  const std::vector<SystemPtr>& getSystems() const { return m_systems; }
  const std::vector<EntityPtr>& getEntities() const { return m_entities; }

  template <typename Sys> bool hasSystem() const;
  template <typename Sys> Sys& getSystem();
  template <typename Sys, typename... Args> Sys& addSystem(Args&&... args);
  template <typename Sys> std::tuple<Sys&> addSystems();
  template <typename Sys1, typename Sys2, typename... S> std::tuple<Sys1&, Sys2&, S...> addSystems();
  template <typename Sys> void removeSystem();
  Entity& addEntity(bool enabled = true);
  template <typename Comp, typename... Args> Entity& addEntityWithComponent(bool enabled, Args&&... args);
  template <typename Comp, typename... Args> Entity& addEntityWithComponent() { return addEntityWithComponent<Comp>(true); }
  template <typename... C> Entity& addEntityWithComponents(bool enabled = true);
  void update(float deltaTime);
  void refresh();
  void destroy();

private:
  std::vector<SystemPtr> m_systems {};
  std::vector<EntityPtr> m_entities {};
  std::size_t m_enabledEntityCount = 0;
  std::size_t m_maxEntityIndex = 0;
};

} // namespace Raz

#include "RaZ/World.inl"

#endif // RAZ_WORLD_HPP
<|endoftext|>