text:
#include <Storages/RabbitMQ/StorageRabbitMQ.h>
#include <DataStreams/IBlockInputStream.h>
#include <DataStreams/ConvertingBlockInputStream.h>
#include <DataStreams/LimitBlockInputStream.h>
#include <DataStreams/UnionBlockInputStream.h>
#include <DataStreams/copyData.h>
#include <DataTypes/DataTypeDateTime.h>
#include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeString.h>
#include <Interpreters/InterpreterInsertQuery.h>
#include <Interpreters/evaluateConstantExpression.h>
#include <Parsers/ASTCreateQuery.h>
#include <Parsers/ASTExpressionList.h>
#include <Parsers/ASTInsertQuery.h>
#include <Parsers/ASTLiteral.h>
#include <Storages/RabbitMQ/RabbitMQBlockInputStream.h>
#include <Storages/RabbitMQ/RabbitMQBlockOutputStream.h>
#include <Storages/RabbitMQ/WriteBufferToRabbitMQProducer.h>
#include <Storages/RabbitMQ/RabbitMQHandler.h>
#include <Storages/StorageFactory.h>
#include <Storages/StorageMaterializedView.h>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <Common/Exception.h>
#include <Common/Macros.h>
#include <Common/config_version.h>
#include <Common/setThreadName.h>
#include <Common/typeid_cast.h>
#include <common/logger_useful.h>
#include <Common/quoteString.h>
#include <Common/parseAddress.h>
#include <Processors/Sources/SourceFromInputStream.h>
#include <amqpcpp.h>

namespace DB
{

static const auto CONNECT_SLEEP = 200;
static const auto RETRIES_MAX = 20;
static const auto HEARTBEAT_RESCHEDULE_MS = 3000;
static const uint32_t QUEUE_SIZE = 100000;

namespace ErrorCodes
{
    extern const int LOGICAL_ERROR;
    extern const int BAD_ARGUMENTS;
    extern const int CANNOT_CONNECT_RABBITMQ;
    extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
    extern const int CANNOT_BIND_RABBITMQ_EXCHANGE;
    extern const int CANNOT_DECLARE_RABBITMQ_EXCHANGE;
    extern const int CANNOT_REMOVE_RABBITMQ_EXCHANGE;
}

namespace ExchangeType
{
    /// Note that default here means default by implementation and not by rabbitmq settings
    static const String DEFAULT = "default";
    static const String FANOUT = "fanout";
    static const String DIRECT = "direct";
    static const String TOPIC = "topic";
    static const String HASH = "consistent_hash";
    static const String HEADERS = "headers";
}

StorageRabbitMQ::StorageRabbitMQ(
        const StorageID & table_id_,
        Context & context_,
        const ColumnsDescription & columns_,
        std::unique_ptr<RabbitMQSettings> rabbitmq_settings_)
        : IStorage(table_id_)
        , global_context(context_.getGlobalContext())
        , rabbitmq_context(Context(global_context))
        , rabbitmq_settings(std::move(rabbitmq_settings_))
        , exchange_name(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_exchange_name.value))
        , format_name(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_format.value))
        , exchange_type(defineExchangeType(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_exchange_type.value)))
        , routing_keys(parseRoutingKeys(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_routing_key_list.value)))
        , row_delimiter(rabbitmq_settings->rabbitmq_row_delimiter.value)
        , schema_name(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_schema.value))
        , num_consumers(rabbitmq_settings->rabbitmq_num_consumers.value)
        , num_queues(rabbitmq_settings->rabbitmq_num_queues.value)
        , queue_base(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_queue_base.value))
        , deadletter_exchange(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_deadletter_exchange.value))
        , persistent(rabbitmq_settings->rabbitmq_persistent.value)
        , hash_exchange(num_consumers > 1 || num_queues > 1)
        , log(&Poco::Logger::get("StorageRabbitMQ (" + table_id_.table_name + ")"))
        , address(global_context.getMacros()->expand(rabbitmq_settings->rabbitmq_host_port.value))
        , parsed_address(parseAddress(address, 5672))
        , login_password(std::make_pair(
                    global_context.getConfigRef().getString("rabbitmq.username"),
                    global_context.getConfigRef().getString("rabbitmq.password")))
        , semaphore(0, num_consumers)
        , unique_strbase(getRandomName())
        , queue_size(std::max(QUEUE_SIZE, static_cast<uint32_t>(getMaxBlockSize())))
{
    loop = std::make_unique<uv_loop_t>();
    uv_loop_init(loop.get());
    event_handler = std::make_shared<RabbitMQHandler>(loop.get(), log);

    if (!restoreConnection(false))
    {
        if (!connection->closed())
            connection->close(true);

        throw Exception("Cannot connect to RabbitMQ " + address, ErrorCodes::CANNOT_CONNECT_RABBITMQ);
    }

    StorageInMemoryMetadata storage_metadata;
    storage_metadata.setColumns(columns_);
    setInMemoryMetadata(storage_metadata);

    rabbitmq_context.makeQueryContext();
    rabbitmq_context = addSettings(rabbitmq_context);

    /// One looping task for all consumers as they share the same connection == the same handler == the same event loop
    event_handler->updateLoopState(Loop::STOP);
    looping_task = global_context.getSchedulePool().createTask("RabbitMQLoopingTask", [this]{ loopingFunc(); });
    looping_task->deactivate();

    streaming_task = global_context.getSchedulePool().createTask("RabbitMQStreamingTask", [this]{ streamingToViewsFunc(); });
    streaming_task->deactivate();

    heartbeat_task = global_context.getSchedulePool().createTask("RabbitMQHeartbeatTask", [this]{ heartbeatFunc(); });
    heartbeat_task->deactivate();

    if (queue_base.empty())
    {
        /* Make sure that local exchange name is unique for each table and is not the same as client's exchange name. It also needs to
         * be table-based and not just a random string, because local exchanges should be declared the same for same tables
         */
        sharding_exchange = getTableBasedName(exchange_name, table_id_);

        /* By default without a specified queue name in queue's declaration - its name will be generated by the library, but its better
         * to specify it unique for each table to reuse them once the table is recreated. So it means that queues remain the same for every
         * table unless queue_base table setting is specified (which allows to register consumers to specific queues). Now this is a base
         * for the names of later declared queues
         */
        queue_base = getTableBasedName("", table_id_);
    }
    else
    {
        /* In case different tables are used to register multiple consumers to the same queues (so queues are shared between tables) and
         * at the same time sharding exchange is needed (if there are multiple shared queues), then those tables also need to share
         * sharding exchange and bridge exchange
         */
        sharding_exchange = exchange_name + "_" + queue_base;
    }

    bridge_exchange = sharding_exchange + "_bridge";
}

Names StorageRabbitMQ::parseRoutingKeys(String routing_key_list)
{
    Names result;
    boost::split(result, routing_key_list, [](char c){ return c == ','; });
    for (String & key : result)
        boost::trim(key);

    return result;
}

AMQP::ExchangeType StorageRabbitMQ::defineExchangeType(String exchange_type_)
{
    AMQP::ExchangeType type;
    if (exchange_type_ != ExchangeType::DEFAULT)
    {
        if (exchange_type_ == ExchangeType::FANOUT)              type = AMQP::ExchangeType::fanout;
        else if (exchange_type_ == ExchangeType::DIRECT)         type = AMQP::ExchangeType::direct;
        else if (exchange_type_ == ExchangeType::TOPIC)          type = AMQP::ExchangeType::topic;
        else if (exchange_type_ == ExchangeType::HASH)           type = AMQP::ExchangeType::consistent_hash;
        else if (exchange_type_ == ExchangeType::HEADERS)        type = AMQP::ExchangeType::headers;
        else throw Exception("Invalid exchange type", ErrorCodes::BAD_ARGUMENTS);
    }
    else
    {
        type = AMQP::ExchangeType::fanout;
    }

    return type;
}

String StorageRabbitMQ::getTableBasedName(String name, const StorageID & table_id)
{
    std::stringstream ss;

    if (name.empty())
        ss << table_id.database_name << "_" << table_id.table_name;
    else
        ss << name << "_" << table_id.database_name << "_" << table_id.table_name;

    return ss.str();
}

Context StorageRabbitMQ::addSettings(Context context) const
{
    context.setSetting("input_format_skip_unknown_fields", true);
    context.setSetting("input_format_allow_errors_ratio", 0.);
    context.setSetting("input_format_allow_errors_num", rabbitmq_settings->rabbitmq_skip_broken_messages.value);

    if (!schema_name.empty())
        context.setSetting("format_schema", schema_name);

    return context;
}

void StorageRabbitMQ::heartbeatFunc()
{
    if (!stream_cancelled && event_handler->connectionRunning())
    {
        connection->heartbeat();
        heartbeat_task->scheduleAfter(HEARTBEAT_RESCHEDULE_MS);
    }
}

void StorageRabbitMQ::loopingFunc()
{
    if (event_handler->connectionRunning())
        event_handler->startLoop();
}

/* Need to deactivate this way because otherwise might get a deadlock when first deactivate streaming task in shutdown and then
 * inside streaming task try to deactivate any other task
 */
void StorageRabbitMQ::deactivateTask(BackgroundSchedulePool::TaskHolder & task, bool wait, bool stop_loop)
{
    if (stop_loop)
        event_handler->updateLoopState(Loop::STOP);

    std::unique_lock<std::mutex> lock(task_mutex, std::defer_lock);
    if (lock.try_lock())
    {
        task->deactivate();
        lock.unlock();
    }
    else if (wait) /// Wait only if deactivating from shutdown
    {
        lock.lock();
        task->deactivate();
    }
}

size_t StorageRabbitMQ::getMaxBlockSize() const
 {
     return rabbitmq_settings->rabbitmq_max_block_size.changed
         ? rabbitmq_settings->rabbitmq_max_block_size.value
         : (global_context.getSettingsRef().max_insert_block_size.value / num_consumers);
 }

void StorageRabbitMQ::initExchange()
{
    /* Binding scheme is the following: client's exchange -> key bindings by routing key list -> bridge exchange (fanout) ->
     * -> sharding exchange (only if needed) -> queues
     */
    setup_channel->declareExchange(exchange_name, exchange_type, AMQP::durable)
    .onError([&](const char * message)
    {
        /* This error can be a result of attempt to declare exchange if it was already declared but
         * 1) with different exchange type. In this case can
         * - manually delete previously declared exchange and create a new one.
         * - throw an error that the exchange with this name but another type is already declared and ask client to delete it himself
         *   if it is not needed anymore or use another exchange name.
         * 2) with different exchange settings. This can only happen if client himself declared exchange with the same name and
         * specified its own settings, which differ from this implementation.
         */
        throw Exception("Unable to declare exchange. Make sure specified exchange is not already declared. Error: "
                + std::string(message), ErrorCodes::CANNOT_DECLARE_RABBITMQ_EXCHANGE);
    });

    /// Bridge exchange is needed to easily disconnect consumer queues and also simplifies queue bindings
    setup_channel->declareExchange(bridge_exchange, AMQP::fanout, AMQP::durable + AMQP::autodelete)
    .onError([&](const char * message)
    {
        /// This error is not supposed to happen as this exchange name is always unique to type and its settings
        throw Exception(
            ErrorCodes::CANNOT_DECLARE_RABBITMQ_EXCHANGE, "Unable to declare bridge exchange ({}). Reason: {}", bridge_exchange, std::string(message));
    });

    if (!hash_exchange)
    {
        consumer_exchange = bridge_exchange;
        return;
    }

    /* Change hash property because by default it will be routing key, which has to be an integer, but with support for any exchange
     * type - routing keys might be of any type
     */
    AMQP::Table binding_arguments;
    binding_arguments["hash-property"] = "message_id";

    /// Declare exchange for sharding.
    setup_channel->declareExchange(sharding_exchange, AMQP::consistent_hash, AMQP::durable + AMQP::autodelete, binding_arguments)
    .onError([&](const char * message)
    {
        /* This error can be a result of same reasons as above for exchange_name, i.e. it will mean that sharding exchange name appeared
         * to be the same as some other exchange (which purpose is not for sharding). So probably actual error reason: queue_base parameter
         * is bad.
         */
        throw Exception(
           ErrorCodes::CANNOT_DECLARE_RABBITMQ_EXCHANGE, "Unable to declare sharding exchange ({}). Reason: {}", sharding_exchange, std::string(message));
    });

    setup_channel->bindExchange(bridge_exchange, sharding_exchange, routing_keys[0])
    .onError([&](const char * message)
    {
        throw Exception(
            ErrorCodes::CANNOT_BIND_RABBITMQ_EXCHANGE,
            "Unable to bind bridge exchange ({}) to sharding exchange ({}). Reason: {}",
            bridge_exchange,
            sharding_exchange,
            std::string(message));
    });

    consumer_exchange = sharding_exchange;
}

void StorageRabbitMQ::bindExchange()
{
    std::atomic<bool> binding_created = false;
    size_t bound_keys = 0;

    if (exchange_type == AMQP::ExchangeType::headers)
    {
        AMQP::Table bind_headers;
        for (const auto & header : routing_keys)
        {
            std::vector<String> matching;
            boost::split(matching, header, [](char c){ return c == '='; });
            bind_headers[matching[0]] = matching[1];
        }

        setup_channel->bindExchange(exchange_name, bridge_exchange, routing_keys[0], bind_headers)
        .onSuccess([&]() { binding_created = true; })
        .onError([&](const char * message)
        {
            throw Exception(
                ErrorCodes::CANNOT_BIND_RABBITMQ_EXCHANGE,
                "Unable to bind exchange {} to bridge exchange ({}). Reason: {}",
                exchange_name,
                bridge_exchange,
                std::string(message));
        });
    }
    else if (exchange_type == AMQP::ExchangeType::fanout || exchange_type == AMQP::ExchangeType::consistent_hash)
    {
        setup_channel->bindExchange(exchange_name, bridge_exchange, routing_keys[0])
        .onSuccess([&]() { binding_created = true; })
        .onError([&](const char * message)
        {
            throw Exception(
                ErrorCodes::CANNOT_BIND_RABBITMQ_EXCHANGE,
                "Unable to bind exchange {} to bridge exchange ({}). Reason: {}",
                exchange_name,
                bridge_exchange,
                std::string(message));
        });
    }
    else
    {
        for (const auto & routing_key : routing_keys)
        {
            setup_channel->bindExchange(exchange_name, bridge_exchange, routing_key)
            .onSuccess([&]()
            {
                ++bound_keys;
                if (bound_keys == routing_keys.size())
                    binding_created = true;
            })
            .onError([&](const char * message)
            {
                throw Exception(
                    ErrorCodes::CANNOT_BIND_RABBITMQ_EXCHANGE,
                    "Unable to bind exchange {} to bridge exchange ({}). Reason: {}",
                    exchange_name,
                    bridge_exchange,
                    std::string(message));
            });
        }
    }

    while (!binding_created)
    {
        event_handler->iterateLoop();
    }
}

bool StorageRabbitMQ::restoreConnection(bool reconnecting)
{
    size_t cnt_retries = 0;

    if (reconnecting)
    {
        deactivateTask(heartbeat_task, false, false);
        connection->close(); /// Connection might be unusable, but not closed

        /* Connection is not closed immediately (firstly, all pending operations are completed, and then
         * an AMQP closing-handshake is  performed). But cannot open a new connection untill previous one is properly closed
         */
        while (!connection->closed() && ++cnt_retries != RETRIES_MAX)
            event_handler->iterateLoop();

        /// This will force immediate closure if not yet closed
        if (!connection->closed())
            connection->close(true);

        LOG_TRACE(log, "Trying to restore connection to " + address);
    }

    connection = std::make_unique<AMQP::TcpConnection>(event_handler.get(),
            AMQP::Address(parsed_address.first, parsed_address.second, AMQP::Login(login_password.first, login_password.second), "/"));

    cnt_retries = 0;
    while (!connection->ready() && !stream_cancelled && ++cnt_retries != RETRIES_MAX)
    {
        event_handler->iterateLoop();
        std::this_thread::sleep_for(std::chrono::milliseconds(CONNECT_SLEEP));
    }

    return event_handler->connectionRunning();
}

void StorageRabbitMQ::updateChannel(ChannelPtr & channel)
{
    channel = std::make_shared<AMQP::TcpChannel>(connection.get());
}

void StorageRabbitMQ::unbindExchange()
{
    /* This is needed because with RabbitMQ (without special adjustments) can't, for example, properly make mv if there was insert query
     * on the same table before, and in another direction it will make redundant copies, but most likely nobody will do that.
     * As publishing is done to exchange, publisher never knows to which queues the message will go, every application interested in
     * consuming from certain exchange - declares its owns exchange-bound queues, messages go to all such exchange-bound queues, and as
     * input streams are always created at startup, then they will also declare its own exchange bound queues, but they will not be visible
     * externally - client declares its own exchange-bound queues, from which to consume, so this means that if not disconnecting this local
     * queues, then messages will go both ways and in one of them they will remain not consumed. So need to disconnect local exchange
     * bindings to remove redunadant message copies, but after that mv cannot work unless those bindings are recreated. Recreating them is
     * not difficult but very ugly and as probably nobody will do such thing - bindings will not be recreated.
     */
    std::call_once(flag, [&]()
    {
        heartbeat_task->deactivate();
        streaming_task->deactivate();
        event_handler->updateLoopState(Loop::STOP);
        looping_task->deactivate();

        setup_channel->removeExchange(bridge_exchange)
        .onSuccess([&]()
        {
            exchange_removed.store(true);
        })
        .onError([&](const char * message)
        {
            throw Exception("Unable to remove exchange. Reason: " + std::string(message), ErrorCodes::CANNOT_REMOVE_RABBITMQ_EXCHANGE);
        });

        while (!exchange_removed.load())
        {
            event_handler->iterateLoop();
        }
    });
}

Pipe StorageRabbitMQ::read(
        const Names & column_names,
        const StorageMetadataPtr & metadata_snapshot,
        const SelectQueryInfo & /* query_info */,
        const Context & context,
        QueryProcessingStage::Enum /* processed_stage */,
        size_t /* max_block_size */,
        unsigned /* num_streams */)
{
    if (num_created_consumers == 0)
        return {};

    auto sample_block = metadata_snapshot->getSampleBlockForColumns(column_names, getVirtuals(), getStorageID());

    auto modified_context = addSettings(context);
    auto block_size = getMaxBlockSize();

    bool update_channels = false;
    if (!event_handler->connectionRunning())
    {
        if (event_handler->loopRunning())
            deactivateTask(looping_task, false, true);

        update_channels = restoreConnection(true);
        if (update_channels)
            heartbeat_task->scheduleAfter(HEARTBEAT_RESCHEDULE_MS);
    }

    Pipes pipes;
    pipes.reserve(num_created_consumers);

    for (size_t i = 0; i < num_created_consumers; ++i)
    {
        auto rabbit_stream = std::make_shared<RabbitMQBlockInputStream>(
                *this, metadata_snapshot, modified_context, column_names, block_size);

        /* It is a possible but rare case when channel gets into error state and does not also close connection, so need manual update.
         * But I believe that in current context and with local rabbitmq settings this will never happen and any channel error will also
         * close connection, but checking anyway (in second condition of if statement). This must be done here (and also in streamToViews())
         * and not in readPrefix as it requires to stop heartbeats and looping tasks to avoid race conditions inside the library
         */
        if (event_handler->connectionRunning() && (update_channels || rabbit_stream->needChannelUpdate()))
        {
            if (event_handler->loopRunning())
            {
                deactivateTask(looping_task, false, true);
                deactivateTask(heartbeat_task, false, false);
            }

            rabbit_stream->updateChannel();
        }

        auto converting_stream = std::make_shared<ConvertingBlockInputStream>(
            rabbit_stream, sample_block, ConvertingBlockInputStream::MatchColumnsMode::Name);
        pipes.emplace_back(std::make_shared<SourceFromInputStream>(converting_stream));
    }

    if (!event_handler->loopRunning() && event_handler->connectionRunning())
        looping_task->activateAndSchedule();

    LOG_DEBUG(log, "Starting reading {} streams", pipes.size());
    return Pipe::unitePipes(std::move(pipes));
}

BlockOutputStreamPtr StorageRabbitMQ::write(const ASTPtr &, const StorageMetadataPtr & metadata_snapshot, const Context & context)
{
    return std::make_shared<RabbitMQBlockOutputStream>(*this, metadata_snapshot, context);
}

void StorageRabbitMQ::startup()
{
    setup_channel = std::make_shared<AMQP::TcpChannel>(connection.get());
    initExchange();
    bindExchange();

    for (size_t i = 0; i < num_consumers; ++i)
    {
        try
        {
            pushReadBuffer(createReadBuffer());
            ++num_created_consumers;
        }
        catch (const AMQP::Exception & e)
        {
            LOG_ERROR(log, "Got AMQ exception {}", e.what());
            throw;
        }
    }

    event_handler->updateLoopState(Loop::RUN);
    streaming_task->activateAndSchedule();
    heartbeat_task->activateAndSchedule();
}

void StorageRabbitMQ::shutdown()
{
    stream_cancelled = true;
    wait_confirm = false;

    deactivateTask(streaming_task, true, false);
    deactivateTask(looping_task, true, true);
    deactivateTask(heartbeat_task, true, false);

    connection->close();

    size_t cnt_retries = 0;
    while (!connection->closed() && ++cnt_retries != RETRIES_MAX)
        event_handler->iterateLoop();

    /// Should actually force closure, if not yet closed, but it generates distracting error logs
    //if (!connection->closed())
    //    connection->close(true);

    for (size_t i = 0; i < num_created_consumers; ++i)
        popReadBuffer();
}

void StorageRabbitMQ::pushReadBuffer(ConsumerBufferPtr buffer)
{
    std::lock_guard lock(buffers_mutex);
    buffers.push_back(buffer);
    semaphore.set();
}

ConsumerBufferPtr StorageRabbitMQ::popReadBuffer()
{
    return popReadBuffer(std::chrono::milliseconds::zero());
}

ConsumerBufferPtr StorageRabbitMQ::popReadBuffer(std::chrono::milliseconds timeout)
{
    // Wait for the first free buffer
    if (timeout == std::chrono::milliseconds::zero())
        semaphore.wait();
    else
    {
        if (!semaphore.tryWait(timeout.count()))
            return nullptr;
    }

    // Take the first available buffer from the list
    std::lock_guard lock(buffers_mutex);
    auto buffer = buffers.back();
    buffers.pop_back();

    return buffer;
}

ConsumerBufferPtr StorageRabbitMQ::createReadBuffer()
{
    ChannelPtr consumer_channel = std::make_shared<AMQP::TcpChannel>(connection.get());

    return std::make_shared<ReadBufferFromRabbitMQConsumer>(
        consumer_channel, setup_channel, event_handler, consumer_exchange, ++consumer_id,
        unique_strbase, queue_base, log, row_delimiter, hash_exchange, num_queues,
        deadletter_exchange, queue_size, stream_cancelled);
}

ProducerBufferPtr StorageRabbitMQ::createWriteBuffer()
{
    return std::make_shared<WriteBufferToRabbitMQProducer>(
        parsed_address, global_context, login_password, routing_keys, exchange_name, exchange_type,
        producer_id.fetch_add(1), persistent, wait_confirm, log,
        row_delimiter ? std::optional<char>{row_delimiter} : std::nullopt, 1, 1024);
}

bool StorageRabbitMQ::checkDependencies(const StorageID & table_id)
{
    // Check if all dependencies are attached
    auto dependencies = DatabaseCatalog::instance().getDependencies(table_id);
    if (dependencies.empty())
        return true;

    // Check the dependencies are ready?
    for (const auto & db_tab : dependencies)
    {
        auto table = DatabaseCatalog::instance().tryGetTable(db_tab, global_context);
        if (!table)
            return false;

        // If it materialized view, check it's target table
        auto * materialized_view = dynamic_cast<StorageMaterializedView *>(table.get());
        if (materialized_view && !materialized_view->tryGetTargetTable())
            return false;

        // Check all its dependencies
        if (!checkDependencies(db_tab))
            return false;
    }

    return true;
}

void StorageRabbitMQ::streamingToViewsFunc()
{
    try
    {
        auto table_id = getStorageID();
        // Check if at least one direct dependency is attached
        size_t dependencies_count = DatabaseCatalog::instance().getDependencies(table_id).size();

        if (dependencies_count)
        {
            // Keep streaming as long as there are attached views and streaming is not cancelled
            while (!stream_cancelled && num_created_consumers > 0)
            {
                if (!checkDependencies(table_id))
                    break;

                LOG_DEBUG(log, "Started streaming to {} attached views", dependencies_count);

                if (!streamToViews())
                    break;
            }
        }
    }
    catch (...)
    {
        tryLogCurrentException(__PRETTY_FUNCTION__);
    }

    /// Wait for attached views
    if (!stream_cancelled)
        streaming_task->schedule();
}

bool StorageRabbitMQ::streamToViews()
{
    auto table_id = getStorageID();
    auto table = DatabaseCatalog::instance().getTable(table_id, global_context);
    if (!table)
        throw Exception("Engine table " + table_id.getNameForLogs() + " doesn't exist.", ErrorCodes::LOGICAL_ERROR);

    // Create an INSERT query for streaming data
    auto insert = std::make_shared<ASTInsertQuery>();
    insert->table_id = table_id;

    // Only insert into dependent views and expect that input blocks contain virtual columns
    InterpreterInsertQuery interpreter(insert, rabbitmq_context, false, true, true);
    auto block_io = interpreter.execute();

    auto metadata_snapshot = getInMemoryMetadataPtr();
    auto column_names = block_io.out->getHeader().getNames();
    auto sample_block = metadata_snapshot->getSampleBlockForColumns(column_names, getVirtuals(), getStorageID());

    /* event_handler->connectionRunning() does not guarantee that connnection is not closed in case loop was not running before, but
     * need to anyway start the loop to activate error callbacks and update connection state, because even checking with
     * connection->usable() will not give correct answer before callbacks are activated.
     */
    if (!event_handler->loopRunning() && event_handler->connectionRunning())
        looping_task->activateAndSchedule();

    auto block_size = getMaxBlockSize();

    // Create a stream for each consumer and join them in a union stream
    BlockInputStreams streams;
    streams.reserve(num_created_consumers);

    for (size_t i = 0; i < num_created_consumers; ++i)
    {
        auto stream = std::make_shared<RabbitMQBlockInputStream>(
                *this, metadata_snapshot, rabbitmq_context, column_names, block_size, false);
        streams.emplace_back(stream);

        // Limit read batch to maximum block size to allow DDL
        IBlockInputStream::LocalLimits limits;

        limits.speed_limits.max_execution_time = rabbitmq_settings->rabbitmq_flush_interval_ms.changed
                                                  ? rabbitmq_settings->rabbitmq_flush_interval_ms
                                                  : global_context.getSettingsRef().stream_flush_interval_ms;

        limits.timeout_overflow_mode = OverflowMode::BREAK;

        stream->setLimits(limits);
    }

    // Join multiple streams if necessary
    BlockInputStreamPtr in;
    if (streams.size() > 1)
        in = std::make_shared<UnionBlockInputStream>(streams, nullptr, streams.size());
    else
        in = streams[0];

    std::atomic<bool> stub = {false};
    copyData(*in, *block_io.out, &stub);

    /* Need to stop loop even if connection is ok, because sending ack() with loop running in another thread will lead to a lot of data
     * races inside the library, but only in case any error occurs or connection is lost while ack is being sent
     */
    if (event_handler->loopRunning())
        deactivateTask(looping_task, false, true);

    if (!event_handler->connectionRunning())
    {
        if (!stream_cancelled && restoreConnection(true))
        {
            for (auto & stream : streams)
                stream->as<RabbitMQBlockInputStream>()->updateChannel();
        }
        else
        {
            /// Reschedule if unable to connect to rabbitmq or quit if cancelled
            return false;
        }
    }
    else
    {
        deactivateTask(heartbeat_task, false, false);

        /// Commit
        for (auto & stream : streams)
        {
            /* false is returned by the sendAck function in only two cases:
             * 1) if connection failed. In this case all channels will be closed and will be unable to send ack. Also ack is made based on
             *    delivery tags, which are unique to channels, so if channels fail, those delivery tags will become invalid and there is
             *    no way to send specific ack from a different channel. Actually once the server realises that it has messages in a queue
             *    waiting for confirm from a channel which suddenly closed, it will immediately make those messages accessible to other
             *    consumers. So in this case duplicates are inevitable.
             * 2) size of the sent frame (libraries's internal request interface) exceeds max frame - internal library error. This is more
             *    common for message frames, but not likely to happen to ack frame I suppose. So I do not believe it is likely to happen.
             *    Also in this case if channel didn't get closed - it is ok if failed to send ack, because the next attempt to send ack on
             *    the same channel will also commit all previously not-committed messages. Anyway I do not think that for ack frame this
             *    will ever happen.
             */
            if (!stream->as<RabbitMQBlockInputStream>()->sendAck())
            {
                /// Iterate loop to activate error callbacks if they happened
                event_handler->iterateLoop();

                if (event_handler->connectionRunning())
                {
                    /* Almost any error with channel will lead to connection closure, but if so happens that channel errored and
                     * connection is not closed - also need to restore channels
                     */
                    if (!stream->as<RabbitMQBlockInputStream>()->needChannelUpdate())
                        stream->as<RabbitMQBlockInputStream>()->updateChannel();
                }
                else
                {
                    break;
                }
            }
        }
    }

    event_handler->updateLoopState(Loop::RUN);
    looping_task->activateAndSchedule();
    heartbeat_task->scheduleAfter(HEARTBEAT_RESCHEDULE_MS); /// It is also deactivated in restoreConnection(), so reschedule anyway

    // Check whether the limits were applied during query execution
    bool limits_applied = false;
    const BlockStreamProfileInfo & info = in->getProfileInfo();
    limits_applied = info.hasAppliedLimit();

    return limits_applied;
}

void registerStorageRabbitMQ(StorageFactory & factory)
{
    auto creator_fn = [](const StorageFactory::Arguments & args)
    {
        ASTs & engine_args = args.engine_args;
        size_t args_count = engine_args.size();
        bool has_settings = args.storage_def->settings;

        auto rabbitmq_settings = std::make_unique<RabbitMQSettings>();
        if (has_settings)
            rabbitmq_settings->loadFromQuery(*args.storage_def);

        // Check arguments and settings
        #define CHECK_RABBITMQ_STORAGE_ARGUMENT(ARG_NUM, ARG_NAME)                                           \
            /* One of the three required arguments is not specified */                                       \
            if (args_count < (ARG_NUM) && (ARG_NUM) <= 3 && !rabbitmq_settings->ARG_NAME.changed)            \
            {                                                                                \
                throw Exception("Required parameter '" #ARG_NAME "' for storage RabbitMQ not specified",     \
                    ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);                                           \
            }                                                                                \
            if (args_count >= (ARG_NUM))                                                                     \
            {                                                                                \
                if (rabbitmq_settings->ARG_NAME.changed) /* The same argument is given in two places */      \
                {                                                                                \
                    throw Exception("The argument №" #ARG_NUM " of storage RabbitMQ "                        \
                        "and the parameter '" #ARG_NAME "' is duplicated", ErrorCodes::BAD_ARGUMENTS);       \
                }                                                                                \
            }

        CHECK_RABBITMQ_STORAGE_ARGUMENT(1, rabbitmq_host_port)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(2, rabbitmq_exchange_name)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(3, rabbitmq_format)

        CHECK_RABBITMQ_STORAGE_ARGUMENT(4, rabbitmq_exchange_type)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(5, rabbitmq_routing_key_list)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(6, rabbitmq_row_delimiter)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(7, rabbitmq_schema)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(8, rabbitmq_num_consumers)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(9, rabbitmq_num_queues)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(10, rabbitmq_queue_base)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(11, rabbitmq_deadletter_exchange)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(12, rabbitmq_persistent)

        CHECK_RABBITMQ_STORAGE_ARGUMENT(13, rabbitmq_skip_broken_messages)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(14, rabbitmq_max_block_size)
        CHECK_RABBITMQ_STORAGE_ARGUMENT(15, rabbitmq_flush_interval_ms)

        #undef CHECK_RABBITMQ_STORAGE_ARGUMENT

        return StorageRabbitMQ::create(args.table_id, args.context, args.columns, std::move(rabbitmq_settings));
    };

    factory.registerStorage("RabbitMQ", creator_fn, StorageFactory::StorageFeatures{ .supports_settings = true, });
}

NamesAndTypesList StorageRabbitMQ::getVirtuals() const
{
    return NamesAndTypesList{
            {"_exchange_name", std::make_shared<DataTypeString>()},
            {"_channel_id", std::make_shared<DataTypeString>()},
            {"_delivery_tag", std::make_shared<DataTypeUInt64>()},
            {"_redelivered", std::make_shared<DataTypeUInt8>()},
            {"_message_id", std::make_shared<DataTypeString>()}
    };
}

}

max_stars_repo_name: fuwhu/ClickHouse

max_issues_repo_name: cloudflare/ClickHouse

max_forks_repo_name: cloudflare/ClickHouse


text: #include <boost/phoenix/fusion.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include<iostream>
#include<vector>
#include<cstdlib>
#include<mpi.h>
#include <sys/time.h>
#include <ctime>
#include <boost/multi_array.hpp>

double getTime() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return double(tv.tv_sec)+double(tv.tv_usec)/1000000.0;
}

void mySum(void *in_, void *out_, int *len, MPI_Datatype *dtype) {
  double* in = reinterpret_cast<double*>(in_);
  double* out = reinterpret_cast<double*>(out_);
  MPI_Aint sz,lb;
  MPI_Type_get_extent(*dtype,&lb,&sz);
  for(int i=0, iend=sz/sizeof(double); i<iend; i++)
    out[i] += in[i];
}

using std::cout;
using std::cin;
using std::endl;
using boost::extents;

// run with 4 procs
int main(int argc,char* argv[])
{

  MPI_Init(&argc,&argv);;

  int global_rank, global_size;
  MPI_Comm_size(MPI_COMM_WORLD, &global_size);
  MPI_Comm_rank(MPI_COMM_WORLD, &global_rank);

  MPI_Info info;
  MPI_Comm MPI_COMM_NODE_LOCAL;
  MPI_Comm_split_type(MPI_COMM_WORLD,MPI_COMM_TYPE_SHARED,global_rank,info,&MPI_COMM_NODE_LOCAL);

  int local_rank,local_size;
  MPI_Comm_size(MPI_COMM_NODE_LOCAL, &local_size);
  MPI_Comm_rank(MPI_COMM_NODE_LOCAL, &local_rank);

  MPI_Comm MPI_COMM_GROUP;
  MPI_Comm_split(MPI_COMM_WORLD,local_rank,global_rank,&MPI_COMM_GROUP);

  int rank,size;
  MPI_Comm_size(MPI_COMM_GROUP, &size);
  MPI_Comm_rank(MPI_COMM_GROUP, &rank);

  if(size*local_size != global_size) {
    std::cerr<<" Proc split error. \n";
    exit(1);
  }

  int nw=16;
  int ni=10000/local_size;
  double t1,t2;
  int blk=ni;
  if(argc>1) blk=atoi(argv[1]);
  std::vector<int> nr{1,10,25,50,75};

  boost::multi_array<std::complex<double>,2> A(extents[ni*75][nw*size]);  // 2x2 matrix
  boost::multi_array<std::complex<double>,2> A_(extents[ni*75][nw*size]);  // 2x2 matrix
  boost::multi_array<std::complex<double>,2> B(extents[ni*75][nw]);  // 2x2 matrix
  boost::multi_array<std::complex<double>,2> C(extents[ni*75][nw]);  // 2x2 matrix

  for(int n=0; n<nr.size(); n++) {

  int ni_ = ni*nr[n];
  if(blk > ni_) continue;
  int nblk = ni_/blk;
  ni_ = nblk*blk;

  MPI_Allreduce(A_.data(),A.data(),2*ni_*nw*size,MPI_DOUBLE,MPI_SUM,MPI_COMM_GROUP);

  int nt=4;
  MPI_Barrier(MPI_COMM_WORLD);
  t1=getTime();
  for(int i=0; i<nt; i++)
    MPI_Allreduce(A_.data(),A.data(),2*ni_*nw*size,MPI_DOUBLE,MPI_SUM,MPI_COMM_GROUP);
  MPI_Barrier(MPI_COMM_WORLD);
  t2=getTime();
  double tv1=(t2-t1)/nt;

  int nmmax=4096;
  std::vector<MPI_Request> req(nmmax);
  std::vector<MPI_Status> st(nmmax);
  MPI_Barrier(MPI_COMM_WORLD);
  t1=getTime();
  for(int i=0; i<nt; i++) {
    int cnt=0;
    for(int b=0; b<nblk; b++) {
      for(int r=0; r<size; r++) {
        if(rank==r)
          MPI_Ireduce(C.data()+b*blk,B.data()+b*blk,2*blk*nw,MPI_DOUBLE,MPI_SUM,r,MPI_COMM_GROUP,&req[cnt++]);
        else
          MPI_Ireduce(C.data()+b*blk,B.data()+b*blk,2*blk*nw,MPI_DOUBLE,MPI_SUM,r,MPI_COMM_GROUP,&req[cnt++]);
      }
      if(cnt==nmmax) {
        MPI_Waitall(cnt,req.data(),st.data());
        cnt=0;
      }
    }
    if(cnt>0) {
      MPI_Waitall(cnt,req.data(),st.data());
      cnt=0;
    }
  }
  MPI_Barrier(MPI_COMM_WORLD);
  t2=getTime();
  double tv5=(t2-t1)/nt;

  if(global_rank==0) cout<<" n, times (Allreduce, multiple IReduce): " <<ni_*local_size <<" " <<ni_ <<" " <<tv1 <<" " <<tv5 <<endl;

  }

  MPI_Finalize();

  return 0;
}

ext: cpp

max_stars_repo_name: djstaros/qmcpack

max_issues_repo_name: djstaros/qmcpack

max_forks_repo_name: djstaros/qmcpack


text:
#include "App/MainConsole.h"
#include "Config/ConfigHelper.h"
#include "Message/Dispatcher.h"
#include "Timer/Clock.h"
#include "Input/InputManager.h"
#include <boost/bind.hpp>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

namespace eg {

#if 0
MainConsole::MainConsole(const std::string& title, const wxPoint& /*pos*/, const wxSize& /*size*/)
: mQuit(false)
, mAppConsole(wxAppConsole::GetInstance())
{
    ::SetConsoleTitle(title.c_str());

    ClockManager& cm = REGISTRATE(ClockManager);
    mClock.reset(new Clock(cm));
}

MainConsole::~MainConsole()
{
}

int MainConsole::Run()
{
    InputActionCallback_t inputCallbackQuit = boost::bind(&MainConsole::InputCallback_Quit, this, _1, _2, _3, _4);
    InputManager::Key *input = new InputManager::Key(InputTypes::kButtonDown, 27);
    InputManager& im = REGISTRATE(InputManager);
    im.RegisterAction("Quit App", input, 0, inputCallbackQuit);

    HANDLE hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD inputRec = {0};

    while (!mQuit)
    {
        //TickSystem();
        float deltaTime = static_cast<float>(mClock->GetFrameDuration());
        double currTime = mClock->GetTime();

        inputRec.EventType = 0;
        DWORD numRead = 0;
        DWORD numPendingInputs = 0;
        ::GetNumberOfConsoleInputEvents(hStdInput, &numPendingInputs);
        if (numPendingInputs)
        {
            if (::ReadConsoleInput(hStdInput, &inputRec, 1, &numRead))
            {
            }
            else
            {
                wxLogError("Could not read input from Console Application.");
            }
        }

        switch (inputRec.EventType)
        {
        case KEY_EVENT:
            {
                bool altPressed = (inputRec.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED) ? true : false;
                if (inputRec.Event.KeyEvent.dwControlKeyState & RIGHT_ALT_PRESSED)
                {
                    altPressed = true;
                }

                bool ctrlPressed = (inputRec.Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED) ? true : false;
                if (inputRec.Event.KeyEvent.dwControlKeyState & RIGHT_CTRL_PRESSED)
                {
                    ctrlPressed = true;
                }

                bool shiftPressed = (inputRec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) ? true : false;
                uint32_t flags = altPressed ? InputTypes::kButtonAlt : 0;
                flags |= ctrlPressed ? InputTypes::kButtonCtrl : 0;
                flags |= shiftPressed ? InputTypes::kButtonShift : 0;

                if (inputRec.Event.KeyEvent.bKeyDown)
                {
                    flags |= InputTypes::kButtonDown;
                }
                else
                {
                    flags |= InputTypes::kButtonDown;
                }

                InputManager& im = REGISTRATE(InputManager);
                int keyValue = im.MapKey(inputRec.Event.KeyEvent.uChar.AsciiChar);
                InputManager::Key *pKey = new InputManager::Key(static_cast<const uint32_t>(currTime * 1000.0f), flags, keyValue);
                im.ProcessInput(pKey);
            }

            break;
        }

        assert(0, "Fix me");
        //Message(mtype::kFrameTick, deltaTime).Send();
        Tick(deltaTime);
    }

    im.UnregisterAction("Quit App");

    //Message(mtype::kShutdownBegin).Send();
    //Message(mtype::kFrameTick, 0.0f).Send();
    return 0;
}

void MainConsole::InputCallback_Quit(const std::string& /*actionName*/, uint32_t /*timeStamp*/, int32_t /*mouseX*/, int32_t /*mouseY*/)
{
    mQuit = true;
}
#endif // 0

//This will clear the console while setting the forground and
//  background colors.
void MainConsole::ClearConsole(int ForgC, int BackC)
{
    WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);
    //Get the handle to the current output buffer...
    HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
    //This is used to reset the carat/cursor to the top left.
    COORD coord = {0, 0};
    //A return value... indicating how many chars were written
    //   not used but we need to capture this since it will be
    //   written anyway (passing NULL causes an access violation).
    DWORD count;

    //This is a structure containing all of the console info
    // it is used here to find the size of the console.
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    //Here we will set the current color
    ::SetConsoleTextAttribute(hStdOut, wColor);
    if(::GetConsoleScreenBufferInfo(hStdOut, &csbi))
    {
        //This fills the buffer with a given character (in this case 32=space).
        ::FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);

        ::FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count );
        //This will set our cursor position for the next print statement.
        ::SetConsoleCursorPosition(hStdOut, coord);
    }
    return;
}

//This will clear the console.
void MainConsole::ClearConsole()
{
    //Get the handle to the current output buffer...
    HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
    //This is used to reset the carat/cursor to the top left.
    COORD coord = {0, 0};
    //A return value... indicating how many chars were written
    //   not used but we need to capture this since it will be
    //   written anyway (passing NULL causes an access violation).
    DWORD count;
    //This is a structure containing all of the console info
    // it is used here to find the size of the console.
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    //Here we will set the current color
    if(::GetConsoleScreenBufferInfo(hStdOut, &csbi))
    {
        //This fills the buffer with a given character (in this case 32=space).
        ::FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
        ::FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count );
        //This will set our cursor position for the next print statement.
        ::SetConsoleCursorPosition(hStdOut, coord);
    }
    return;
}

//This will set the position of the cursor
void MainConsole::gotoXY(int x, int y)
{
    //Initialize the coordinates
    COORD coord = {x, y};
    //Set the position
    ::SetConsoleCursorPosition(::GetStdHandle(STD_OUTPUT_HANDLE), coord);
    return;
}

//This will set the forground color for printing in a console window.
void MainConsole::SetColor(int ForgC)
{
    WORD wColor;
    //We will need this handle to get the current background attribute
    HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO csbi;

    //We use csbi for the wAttributes word.
    if(::GetConsoleScreenBufferInfo(hStdOut, &csbi))
    {
        //Mask out all but the background attribute, and add in the forgournd color
        wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
        ::SetConsoleTextAttribute(hStdOut, wColor);
    }
    return;
}

//This will set the forground and background color for printing in a console window.
void MainConsole::SetColor(int ForgC, int BackC)
{
    WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);;
    ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), wColor);
    return;
}

//Direct console output
void MainConsole::ConPrint(const char *pCharBuffer, int len)
{
    DWORD count;
    ::WriteConsole(::GetStdHandle(STD_OUTPUT_HANDLE), pCharBuffer, len, &count, NULL);
    return;
}

//Direct Console output at a particular coordinate.
void MainConsole::ConPrintAt(int x, int y, const char *pCharBuffer, int len)
{
    DWORD count;
    COORD coord = {x, y};
    HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
    ::SetConsoleCursorPosition(hStdOut, coord);
    ::WriteConsole(hStdOut, pCharBuffer, len, &count, NULL);
    return;
}

//Hides the console cursor
void MainConsole::HideCursor()
{
    CONSOLE_CURSOR_INFO cciCursor;
    HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);

    if(::GetConsoleCursorInfo(hStdOut, &cciCursor))
    {
        cciCursor.bVisible=FALSE;
    }
    return;
}

//Shows the console cursor
void MainConsole::ShowCursor()
{
    CONSOLE_CURSOR_INFO cciCursor;
    HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);

    if(::GetConsoleCursorInfo(hStdOut, &cciCursor))
    {
        cciCursor.bVisible=TRUE;
    }
    return;
}

/*
void MainConsole::Tick(float deltaTime);

#include "ServerBase.h"
#include "Timer/Clock.h"
#include "Registrate.h"
#include "MessageInterface.h"
#include "BaseDLLs.h"

#include <windows.h>
#include <stdio.h>

void ConPrint(char *CharBuffer, int len);
void ConPrintAt(int x, int y, char *CharBuffer, int len);
void gotoXY(int x, int y);
void ClearConsole();
void ClearConsole(int ForgC, int BackC);
void SetColor(int ForgC, int BackC);
void SetColor(int ForgC);
void HideCursor();
void ShowCursor();

using namespace eg;
int main(int argc, char* argv[])
{
    wxInitializer initializerObject(argc, argv);
    Message(mtype::kAppValid).Send();
    ClockManager& cm = REGISTRATE(ClockManager);
    HideCursor();
    ClearConsole(15, 1);
    ClearConsole();
    gotoXY(1,1);
    SetColor(14);
    printf("This is a test...\n");
    Sleep(1000);
    ShowCursor();
    SetColor(15,12);
    ConPrint("This is also a test...\n", 23);
    SetColor(1, 7);
    ConPrintAt(22, 15, "This is also a test...\n", 23);
    gotoXY(0, 24);
    SetColor(7,1);

    Message(mtype::kShutdownBegin).Send();
    Message(mtype::kShutdownEnd).Send();

    return 0;
}

*/
} // namespace eg

max_stars_repo_name: eglowacki/zloty

max_issues_repo_name: eglowacki/zloty

max_forks_repo_name: eglowacki/zloty


text:
/*
 * Copyright 2018, Gepetto team, LAAS-CNRS
 *
 * This file is part of sot-talos-balance.
 * sot-talos-balance is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * sot-talos-balance 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 sot-talos-balance.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __sot_talos_balance_commands_helper_H__
#define __sot_talos_balance_commands_helper_H__

/* --- COMMON INCLUDE -------------------------------------------------- */
#include <dynamic-graph/command.h>
#include <dynamic-graph/command-direct-setter.h>
#include <dynamic-graph/command-direct-getter.h>
#include <dynamic-graph/command-bind.h>

#include <boost/function.hpp>

/* --- HELPER ---------------------------------------------------------- */
namespace dynamicgraph {
  namespace sot {
    namespace talos_balance {
      using ::dynamicgraph::command::makeDirectGetter;
      using ::dynamicgraph::command::docDirectGetter;
      using ::dynamicgraph::command::makeDirectSetter;
      using ::dynamicgraph::command::docDirectSetter;
      using ::dynamicgraph::command::makeCommandVoid0;
      using ::dynamicgraph::command::docCommandVoid0;
      using ::dynamicgraph::command::makeCommandVoid1;
      using ::dynamicgraph::command::docCommandVoid1;
      using ::dynamicgraph::command::makeCommandVoid2;
      using ::dynamicgraph::command::docCommandVoid2;
      using ::dynamicgraph::command::makeCommandVerbose;
      using ::dynamicgraph::command::docCommandVerbose;
    } // namespace talos_balance
  } // namespace sot
} // namespace dynamicgraph

namespace dynamicgraph {
  namespace command {

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5>
    struct CommandVoid5
        : public Command
    {
      typedef boost::function<void(const T1&,const T2&,const T3&,const T4&,const T5&)> function_t;
      typedef boost::function<void(E*,const T1&,const T2&,const T3&,const T4&,const T5&)> memberFunction_t;
      typedef void (E::*memberFunction_ptr_t) (const T1&,const T2&,const T3&,const T4&,const T5&);

      CommandVoid5(E& entity, function_t function,
                   const std::string& docString)
        :Command(entity,
                 boost::assign::list_of
                 (ValueHelper<T1>::TypeID)
                 (ValueHelper<T2>::TypeID)
                 (ValueHelper<T3>::TypeID)
                 (ValueHelper<T4>::TypeID)
                 (ValueHelper<T5>::TypeID)
                 , docString)
        ,fptr(function)
      {}

    protected:
      virtual Value doExecute()
      {
        assert( getParameterValues().size() == 5 );
        T1 val1 = getParameterValues()[0].value();
        T2 val2 = getParameterValues()[1].value();
        T3 val3 = getParameterValues()[2].value();
        T4 val4 = getParameterValues()[3].value();
        T5 val5 = getParameterValues()[4].value();
        fptr(val1,val2,val3,val4,val5);
        return Value(); // void
      }
    private:
      function_t fptr;
    };

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5>
    CommandVoid5<E,T1,T2,T3,T4,T5>*
    makeCommandVoid5(E& entity,
                     typename CommandVoid5<E,T1,T2,T3,T4,T5>::function_t function ,
                     const std::string& docString)
    {
      return new CommandVoid5<E,T1,T2,T3,T4,T5>( entity,function,docString );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5>
    CommandVoid5<E,T1,T2,T3,T4,T5>*
    makeCommandVoid5(E& entity,
                     boost::function<void(E*,const T1&,const T2&,const T3&,const T4&,const T5&)> function,
                     const std::string& docString)
    {
      return new CommandVoid5<E,T1,T2,T3,T4,T5>( entity,
                                                    boost::bind(function,&entity,_1,_2,_3,_4,_5),docString );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5>
    CommandVoid5<E,T1,T2,T3,T4,T5>*
    makeCommandVoid5(E& entity,
                     void (E::*function) (const T1&,const T2&,const T3&,const T4&,const T5&),
                     const std::string& docString)
    {
      return new CommandVoid5<E,T1,T2,T3,T4,T5>( entity,
                                                    boost::bind(function,&entity,_1,_2,_3,_4,_5),
                                                    docString );
      return NULL;
    }

    inline std::string docCommandVoid5( const std::string& doc,
                                        const std::string& type1,
                                        const std::string& type2,
                                        const std::string& type3,
                                        const std::string& type4,
                                        const std::string& type5)
    {
      return (std::string("\n")+doc+"\n\n"
              +"Input:\n - A "+type1+".\n"
              +"Input:\n - A "+type2+".\n"
              +"Input:\n - A "+type3+".\n"
              +"Input:\n - A "+type4+".\n"
              +"Input:\n - A "+type5+".\n"
              +"Void return.\n\n" );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6 >
    struct CommandVoid6
        : public Command
    {
      typedef boost::function<void(const T1&,const T2&,const T3&,const T4&,const T5&,const T6&)> function_t;
      typedef boost::function<void(E*,const T1&,const T2&,const T3&,const T4&,const T5&,const T6&)> memberFunction_t;
      typedef void (E::*memberFunction_ptr_t) (const T1&,const T2&,const T3&,const T4&,const T5&,const T6&);

      CommandVoid6(E& entity, function_t function,
                   const std::string& docString)
        :Command(entity,
                 boost::assign::list_of
                 (ValueHelper<T1>::TypeID)
                 (ValueHelper<T2>::TypeID)
                 (ValueHelper<T3>::TypeID)
                 (ValueHelper<T4>::TypeID)
                 (ValueHelper<T5>::TypeID)
                 (ValueHelper<T6>::TypeID)
                 , docString)
        ,fptr(function)
      {}

    protected:
      virtual Value doExecute()
      {
        assert( getParameterValues().size() == 6 );
        T1 val1 = getParameterValues()[0].value();
        T2 val2 = getParameterValues()[1].value();
        T3 val3 = getParameterValues()[2].value();
        T4 val4 = getParameterValues()[3].value();
        T5 val5 = getParameterValues()[4].value();
        T6 val6 = getParameterValues()[5].value();
        fptr(val1,val2,val3,val4,val5,val6);
        return Value(); // void
      }
    private:
      function_t fptr;
    };

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6 >
    CommandVoid6<E,T1,T2,T3,T4,T5,T6>*
    makeCommandVoid6(E& entity,
                     typename CommandVoid6<E,T1,T2,T3,T4,T5,T6>::function_t function ,
                     const std::string& docString)
    {
      return new CommandVoid6<E,T1,T2,T3,T4,T5,T6>( entity,function,docString );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6 >
    CommandVoid6<E,T1,T2,T3,T4,T5,T6>*
    makeCommandVoid6(E& entity,
                     boost::function<void(E*,const T1&,const T2&,const T3&,const T4&,const T5&,const T6&)> function,
                     const std::string& docString)
    {
      return new CommandVoid6<E,T1,T2,T3,T4,T5,T6>( entity,
                                                    boost::bind(function,&entity,_1,_2,_3,_4,_5,_6),docString );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6 >
    CommandVoid6<E,T1,T2,T3,T4,T5,T6>*
    makeCommandVoid6(E& entity,
                     void (E::*function) (const T1&,const T2&,const T3&,const T4&,const T5&,const T6&),
                     const std::string& docString)
    {
      return new CommandVoid6<E,T1,T2,T3,T4,T5,T6>( entity,
                                                    boost::bind(function,&entity,_1,_2,_3,_4,_5,_6),
                                                    docString );
      return NULL;
    }

    inline std::string docCommandVoid6( const std::string& doc,
                                        const std::string& type1,
                                        const std::string& type2,
                                        const std::string& type3,
                                        const std::string& type4,
                                        const std::string& type5,
                                        const std::string& type6)
    {
      return (std::string("\n")+doc+"\n\n"
              +"Input:\n - A "+type1+".\n"
              +"Input:\n - A "+type2+".\n"
              +"Input:\n - A "+type3+".\n"
              +"Input:\n - A "+type4+".\n"
              +"Input:\n - A "+type5+".\n"
              +"Input:\n - A "+type6+".\n"
              +"Void return.\n\n" );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7 >
    struct CommandVoid7
        : public Command
    {
      typedef boost::function<void(const T1&,const T2&,const T3&,const T4&,const T5&,const T6&,const T7&)> function_t;
      typedef boost::function<void(E*,const T1&,const T2&,const T3&,const T4&,const T5&,const T6&,const T7&)> memberFunction_t;
      typedef void (E::*memberFunction_ptr_t) (const T1&,const T2&,const T3&,const T4&,const T5&,const T6&,const T7&);

      CommandVoid7(E& entity, function_t function,
                   const std::string& docString)
        :Command(entity,
                 boost::assign::list_of
                 (ValueHelper<T1>::TypeID)
                 (ValueHelper<T2>::TypeID)
                 (ValueHelper<T3>::TypeID)
                 (ValueHelper<T4>::TypeID)
                 (ValueHelper<T5>::TypeID)
                 (ValueHelper<T6>::TypeID)
                 (ValueHelper<T7>::TypeID)
                 , docString)
        ,fptr(function)
      {}

    protected:
      virtual Value doExecute()
      {
        assert( getParameterValues().size() == 7 );
        T1 val1 = getParameterValues()[0].value();
        T2 val2 = getParameterValues()[1].value();
        T3 val3 = getParameterValues()[2].value();
        T4 val4 = getParameterValues()[3].value();
        T5 val5 = getParameterValues()[4].value();
        T6 val6 = getParameterValues()[5].value();
        T7 val7 = getParameterValues()[6].value();
        fptr(val1,val2,val3,val4,val5,val6,val7);
        return Value(); // void
      }
    private:
      function_t fptr;
    };

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7 >
    CommandVoid7<E,T1,T2,T3,T4,T5,T6,T7>*
    makeCommandVoid7(E& entity,
                     typename CommandVoid7<E,T1,T2,T3,T4,T5,T6,T7>::function_t function ,
                     const std::string& docString)
    {
      return new CommandVoid7<E,T1,T2,T3,T4,T5,T6,T7>( entity,function,docString );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7 >
    CommandVoid7<E,T1,T2,T3,T4,T5,T6,T7>*
    makeCommandVoid7(E& entity,
                     boost::function<void(E*,const T1&,const T2&,const T3&,const T4&,const T5&,const T6&,const T7&)> function,
                     const std::string& docString)
    {
      return new CommandVoid7<E,T1,T2,T3,T4,T5,T6,T7>( entity,
                                                    boost::bind(function,&entity,_1,_2,_3,_4,_5,_6,_7),docString );
    }

    template <class E,typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7 >
    CommandVoid7<E,T1,T2,T3,T4,T5,T6,T7>*
    makeCommandVoid7(E& entity,
                     void (E::*function) (const T1&,const T2&,const T3&,const T4&,const T5&,const T6&,const T7&),
                     const std::string& docString)
    {
      return new CommandVoid7<E,T1,T2,T3,T4,T5,T6,T7>( entity,
                                                          boost::bind(function,&entity,_1,_2,_3,_4,_5,_6,_7),
                                                          docString );
      return NULL;
    }

    inline std::string docCommandVoid7( const std::string& doc,
                                        const std::string& type1,
                                        const std::string& type2,
                                        const std::string& type3,
                                        const std::string& type4,
                                        const std::string& type5,
                                        const std::string& type6,
                                        const std::string& type7)
    {
      return (std::string("\n")+doc+"\n\n"
              +"Input:\n - A "+type1+".\n"
              +"Input:\n - A "+type2+".\n"
              +"Input:\n - A "+type3+".\n"
              +"Input:\n - A "+type4+".\n"
              +"Input:\n - A "+type5+".\n"
              +"Input:\n - A "+type6+".\n"
              +"Input:\n - A "+type7+".\n"
              +"Void return.\n\n" );
    }

  } // namespace command
} // namespace dynamicgraph

#endif // __sot_talos_balance_commands_helper_H__

ext: hh

max_stars_repo_name: olivier-stasse/sot-talos-balance

max_issues_repo_name: olivier-stasse/sot-talos-balance

max_forks_repo_name: olivier-stasse/sot-talos-balance


text:
// test_main.cpp
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE ApplicationPlugInTest

#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_CASE(Main) {
    BOOST_CHECK(true);
}

// EOF

max_stars_repo_name: Zuehlke/BiZEPS

max_issues_repo_name: Zuehlke/BiZEPS

max_forks_repo_name: Zuehlke/BiZEPS


text:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>

using namespace std;
namespace mp = boost::multiprecision;

mp::cpp_int sum_of_digits(mp::cpp_int num) {
	mp::cpp_int sum = 0;
	while(num) {
		sum += num % 10;
		num /= 10;
	}
	return sum;
}

int main(int argc, char *argv[]) {
	cout << sum_of_digits(mp::pow((mp::cpp_int)2, 1000)) << endl;
	return 0;
}

max_stars_repo_name: kitegi/Edmonton

max_issues_repo_name: kitegi/Edmonton

max_forks_repo_name: kitegi/Edmonton


text:
#include <gtest/gtest.h>
#include <qi/periodictask.hpp>
#include "test_future.hpp"
#include <qi/testutils/testutils.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>

void empty() {}

TEST(TestPeriodicTask, Exception)
{
  {
    qi::PeriodicTask pt;
    EXPECT_ANY_THROW(pt.start());
    EXPECT_ANY_THROW(pt.setUsPeriod(-123));
    pt.setUsPeriod(1000);
    EXPECT_ANY_THROW(pt.start());
  }
  {
    qi::PeriodicTask pt;
    pt.setCallback(&empty);
    EXPECT_ANY_THROW(pt.start()); // interval not set
  }
}

void inc(qi::Atomic<int>& tgt)
{
  ++tgt;
}

TEST(TestPeriodicTask, FutureFuck)
{
  for (unsigned i=0; i<500; ++i)
  {
    qi::Future<void> f;
    qi::Promise<void> p;
    f = p.future();
    p.setValue(0);
    f.wait();
  }
}

TEST(TestPeriodicTask, Basic)
{
  static const std::chrono::milliseconds sleepDuration { 100 }; // big enough to not block the periodic task too much
  static const qi::MilliSeconds period{ 10 };
  static const int assertCount = 20;
  std::vector<bool> assertions;
  {
    qi::SteadyClockTimePoint last;
    qi::Strand strand;
    qi::PeriodicTask pt;
    pt.setPeriod(period);
    pt.setCallback([&] {
      strand.async([&] {
        const auto now = qi::SteadyClock::now();
        const auto success = now - last >= period;
        assertions.push_back(success);
        last = now;
      }).value();
    });
    pt.start(false); // false = not immediately
    while (strand.async([&]{ return assertions.size(); }).value() < assertCount)
      std::this_thread::sleep_for(sleepDuration);
    pt.stop();
  }
  EXPECT_TRUE(boost::algorithm::all_of(assertions, ka::id_transfo_t{}))
      << boost::join(assertions | boost::adaptors::transformed(
                                   [](bool v) -> std::string { return v ? "true" : "false"; }),
                     ", ");
}

TEST(TestPeriodicTask, Stop)
{
  qi::PeriodicTask pt;
  pt.setCallback([]{ std::this_thread::sleep_for(std::chrono::milliseconds{500}); });
  pt.setUsPeriod(10000000);
  pt.start();
  std::this_thread::sleep_for(std::chrono::milliseconds{100}); // wait for actual start
  qi::int64_t now = qi::os::ustime();
  pt.stop();
  EXPECT_LE(300000, qi::os::ustime() - now);
}

TEST(TestPeriodicTask, StopFromTask)
{
  qi::PeriodicTask pt;
  pt.setCallback(boost::bind(&qi::PeriodicTask::stop, boost::ref(pt)));
  pt.setUsPeriod(10000000);
  pt.start();
  std::this_thread::sleep_for(std::chrono::milliseconds{100}); // wait for actual start
  qi::int64_t now = qi::os::ustime();
  pt.stop();
  EXPECT_GE(100000, qi::os::ustime() - now);
}

TEST(TestPeriodicTask, DeadLock)
{
  qi::Atomic<int> a;
  for (unsigned i=0; i<500; ++i)
  {
    qi::PeriodicTask pt;
    pt.setCallback(&inc, std::ref(a));
    pt.setUsPeriod(0);
    pt.start();
    std::this_thread::sleep_for(std::chrono::milliseconds{i % 20}); // wait for actual start
    pt.stop();
  }
}

TEST(TestPeriodicTask, StartIsNoop)
{
  qi::Promise<void> prom;
  qi::PeriodicTask pt;
  pt.setCallback(&block, 99, prom.future());
  pt.setUsPeriod(100);
  std::vector<qi::Future<void> > futs;
  // multiple start is no-op, this should not deadlock
  for (unsigned i=0; i<20; ++i)
    futs.push_back(qi::async(boost::function<void()>(boost::bind(&qi::PeriodicTask::start, &pt, true))));
  for (unsigned i=0; i<20; ++i)
    futs[i].wait();

  prom.setValue(0);
  pt.stop();
}

static void loopTrigger(qi::PeriodicTask& pt)
{
  for (int i = 0; i < 1000; ++i)
  {
    pt.trigger();
    std::this_thread::sleep_for(std::chrono::milliseconds{1});
  }
}

TEST(TestPeriodicTask, Trigger)
{
  // just test that there is no segfault or deadlock
  qi::PeriodicTask pt;
  qi::Atomic<int> a;
  pt.setCallback(&inc, std::ref(a));
  pt.setUsPeriod(1000);
  pt.start();
  std::vector<qi::Future<void> > futures;
  futures.push_back(qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))));
  futures.push_back(qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))));
  futures.push_back(qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))));
  futures.push_back(qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))));
  for (unsigned int i = 0; i < futures.size(); ++i)
    futures[i].wait();
  pt.stop();
}

TEST(TestPeriodicTask, TriggerStartStop)
{
  // just test that there is no segfault or deadlock
  qi::PeriodicTask pt;
  qi::Atomic<int> a;
  pt.setCallback(&inc, std::ref(a));
  pt.setUsPeriod(1000);
  qi::Future<void> futures[] {
    qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))),
    qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))),
    qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))),
    qi::getEventLoop()->async(boost::bind(&loopTrigger, std::ref(pt))),
  };
  while(true)
  {
    if (boost::algorithm::all_of(futures, [](qi::Future<void> fut) {
          return fut.wait(0) == qi::FutureState_FinishedWithValue;
        }))
    {
        break;
    }
    pt.start();
    std::this_thread::sleep_for(std::chrono::milliseconds{10});
    pt.stop();
  }
}

TEST(TestPeriodicTask, DoesNotDeadlockWhenStartedWithStrandInsideStrandContext)
{
  qi::Strand strand;
  qi::PeriodicTask pt;
  pt.setStrand(&strand);
  pt.setCallback([]{ /* dummy callback */ });
  pt.setUsPeriod(100000);
  auto futStart = strand.async([&]{ pt.start(); }); // call start from inside the start
  ASSERT_TRUE(test::finishesWithValue(futStart));
  strand.join(); // join it before PeriodicTask is destroyed
}

max_stars_repo_name: arntanguy/libqi

max_issues_repo_name: arntanguy/libqi

max_forks_repo_name: arntanguy/libqi


text:
//
// detail/local_resolve_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright 2017 Igor Peshansky (igorp@google.com).
// Copyright 2017 Google, Inc.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_DETAIL_LOCAL_RESOLVE_OP_HPP
#define BOOST_ASIO_DETAIL_LOCAL_RESOLVE_OP_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/config.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/basic_resolver_iterator.hpp>
#include <boost/asio/ip/basic_resolver_query.hpp>
#include <boost/asio/local/stream_protocol.hpp>
#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/resolve_op.hpp>
#include <network/uri/detail/decode.hpp>
#include <sstream>
#include <sys/stat.h>

#include "../logging.h"

#include <boost/asio/detail/push_options.hpp>

namespace boost {
namespace asio {
namespace detail {

#define Protocol boost::asio::local::stream_protocol

template<typename Handler>
class resolve_op<Protocol, Handler> : public operation
{
public:
  BOOST_ASIO_DEFINE_HANDLER_PTR(resolve_op);

  typedef boost::asio::ip::basic_resolver_query<Protocol> query_type;
  typedef boost::asio::ip::basic_resolver_iterator<Protocol> iterator_type;

  resolve_op(socket_ops::weak_cancel_token_type cancel_token,
      const query_type& query, io_service_impl& ios, Handler& handler)
    : operation(&resolve_op::do_complete),
      cancel_token_(cancel_token),
      query_(query),
      io_service_impl_(ios),
      handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
  {
  }

  ~resolve_op()
  {
  }

  static void do_complete(io_service_impl* owner, operation* base,
      const boost::system::error_code& /*ec*/,
      std::size_t /*bytes_transferred*/)
  {
    // Take ownership of the operation object.
    resolve_op* o(static_cast<resolve_op*>(base));
    ptr p = { boost::asio::detail::addressof(o->handler_), o, o };

    if (owner && owner != &o->io_service_impl_)
    {
      // The operation is being run on the worker io_service. Time to perform
      // the resolver operation.

      // Perform the blocking host resolution operation.
      if (o->cancel_token_.expired())
        o->ec_ = boost::asio::error::operation_aborted;
      else {
        //LOG(ERROR) << "async_resolve() " << o->query_.host_name();
        std::string path = ::network::detail::decode(o->query_.host_name());
        //LOG(ERROR) << "decoded " << path;
        struct stat buffer;
        int result = stat(path.c_str(), &buffer);
        if (result || !S_ISSOCK(buffer.st_mode)) {
          LOG(ERROR) << "resolve: unable to stat or not a socket " << path;
          o->ec_ = boost::asio::error::host_not_found;
        } else {
          //LOG(ERROR) << "resolve: everything ok with " << path;
          o->ec_ = boost::system::error_code();
        }
      }

      // Pass operation back to main io_service for completion.
      o->io_service_impl_.post_deferred_completion(o);
      p.v = p.p = 0;
    }
    else
    {
      // The operation has been returned to the main io_service. The completion
      // handler is ready to be delivered.

      BOOST_ASIO_HANDLER_COMPLETION((o));

      // Make a copy of the handler so that the memory can be deallocated
      // before the upcall is made. Even if we're not about to make an upcall,
      // a sub-object of the handler may be the true owner of the memory
      // associated with the handler. Consequently, a local copy of the handler
      // is required to ensure that any owning sub-object remains valid until
      // after we have deallocated the memory here.
      detail::binder2<Handler, boost::system::error_code, iterator_type>
        handler(o->handler_, o->ec_, iterator_type());
      p.h = boost::asio::detail::addressof(handler.handler_);
      if (!o->ec_)
      {
        std::string path = ::network::detail::decode(o->query_.host_name());
        handler.arg2_ = iterator_type::create(
            Protocol::endpoint(path),
            path, o->query_.service_name());
      }
      p.reset();

      if (owner)
      {
        fenced_block b(fenced_block::half);
        BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
        boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
        BOOST_ASIO_HANDLER_INVOCATION_END;
      }
    }
  }

private:
  socket_ops::weak_cancel_token_type cancel_token_;
  query_type query_;
  io_service_impl& io_service_impl_;
  Handler handler_;
  boost::system::error_code ec_;
};

#undef Protocol

} // namespace detail
} // namespace asio
} // namespace boost

#include <boost/asio/detail/pop_options.hpp>

#endif // BOOST_ASIO_DETAIL_LOCAL_RESOLVE_OP_HPP

max_stars_repo_name: StevenYCChou/metadata-agent

max_issues_repo_name: Stackdriver/metadata-agent

max_forks_repo_name: StevenYCChou/metadata-agent


text:
// Boost.Units - A C++ library for zero-overhead dimensional analysis and
// unit/quantity manipulation and conversion
//
// Copyright (C) 2014 Erik Erlandson
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include <iostream>
#include <sstream>

#include <boost/units/quantity.hpp>
#include <boost/units/conversion.hpp>
#include <boost/units/io.hpp>

#include <boost/units/systems/si/prefixes.hpp>
#include <boost/units/systems/si/time.hpp>

// All information systems definitions
#include <boost/units/systems/information.hpp>

using std::cout;
using std::cerr;
using std::endl;
using std::stringstream;

namespace bu = boost::units;
namespace si = boost::units::si;

using bu::quantity;

using bu::information::bit_base_unit;
using bu::information::byte_base_unit;
using bu::information::nat_base_unit;
using bu::information::hartley_base_unit;
using bu::information::shannon_base_unit;

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

#include <boost/multiprecision/cpp_int.hpp>

const double close_fraction = 0.0000001;

// checks that cf(u2,u1) == expected
// also checks invariant property that cf(u2,u1) * cf(u1,u2) == 1
#define CHECK_DIRECT_CF(u1, u2, expected) \
    BOOST_CHECK_CLOSE_FRACTION(bu::conversion_factor((u2), (u1)), (expected), close_fraction); \
    BOOST_CHECK_CLOSE_FRACTION(bu::conversion_factor((u2), (u1)) * bu::conversion_factor((u1), (u2)), 1.0, close_fraction);

// check transitive conversion factors
// invariant:  cf(u1,u3) = cf(u1,u2)*cf(u2,u3)
#define CHECK_TRANSITIVE_CF(u1, u2, u3) { \
    double cf12 = bu::conversion_factor((u2), (u1)) ; \
    double cf23 = bu::conversion_factor((u3), (u2)) ; \
    double cf13 = bu::conversion_factor((u3), (u1)) ; \
    BOOST_CHECK_CLOSE_FRACTION(cf13, cf12*cf23, close_fraction); \
    double cf32 = bu::conversion_factor((u2), (u3)) ; \
    double cf21 = bu::conversion_factor((u1), (u2)) ; \
    double cf31 = bu::conversion_factor((u1), (u3)) ; \
    BOOST_CHECK_CLOSE_FRACTION(cf31, cf32*cf21, close_fraction); \
}

BOOST_AUTO_TEST_CASE(test_cf_bit_byte) {
    CHECK_DIRECT_CF(bit_base_unit::unit_type(), byte_base_unit::unit_type(), 8.0);
}

BOOST_AUTO_TEST_CASE(test_cf_bit_nat) {
    CHECK_DIRECT_CF(bit_base_unit::unit_type(), nat_base_unit::unit_type(), 1.442695040888964);
}

BOOST_AUTO_TEST_CASE(test_cf_bit_hartley) {
    CHECK_DIRECT_CF(bit_base_unit::unit_type(), hartley_base_unit::unit_type(), 3.321928094887363);
}

BOOST_AUTO_TEST_CASE(test_cf_bit_shannon) {
    CHECK_DIRECT_CF(bit_base_unit::unit_type(), shannon_base_unit::unit_type(), 1.0);
}

/////////////////////////////////////////////////////////////////////////////////////
// spot-check that these are automatically transitive, thru central "hub unit" bit:
// basic pattern is to test invariant property:  cf(c,a) = cf(c,b)*cf(b,a)

BOOST_AUTO_TEST_CASE(test_transitive_byte_nat) {
    CHECK_TRANSITIVE_CF(byte_base_unit::unit_type(), bit_base_unit::unit_type(), nat_base_unit::unit_type());
}
BOOST_AUTO_TEST_CASE(test_transitive_nat_hartley) {
    CHECK_TRANSITIVE_CF(nat_base_unit::unit_type(), bit_base_unit::unit_type(), hartley_base_unit::unit_type());
}
BOOST_AUTO_TEST_CASE(test_transitive_hartley_shannon) {
    CHECK_TRANSITIVE_CF(hartley_base_unit::unit_type(), bit_base_unit::unit_type(), shannon_base_unit::unit_type());
}
BOOST_AUTO_TEST_CASE(test_transitive_shannon_byte) {
    CHECK_TRANSITIVE_CF(shannon_base_unit::unit_type(), bit_base_unit::unit_type(), byte_base_unit::unit_type());
}

// test transitive factors, none of which are bit, just for good measure
BOOST_AUTO_TEST_CASE(test_transitive_byte_nat_hartley) {
    CHECK_TRANSITIVE_CF(byte_base_unit::unit_type(), nat_base_unit::unit_type(), hartley_base_unit::unit_type());
}

BOOST_AUTO_TEST_CASE(test_byte_quantity_is_default) {
    using namespace bu::information;
    quantity<info, double> qd(2 * byte);
    BOOST_CHECK_EQUAL(qd.value(), double(2));
    quantity<info, long> ql(2 * byte);
    BOOST_CHECK_EQUAL(ql.value(), long(2));
}

BOOST_AUTO_TEST_CASE(test_byte_quantity_explicit) {
    using namespace bu::information;
    quantity<hu::byte::info, double> qd(2 * byte);
    BOOST_CHECK_EQUAL(qd.value(), double(2));
    quantity<hu::byte::info, long> ql(2 * byte);
    BOOST_CHECK_EQUAL(ql.value(), long(2));
}

BOOST_AUTO_TEST_CASE(test_bit_quantity) {
    using namespace bu::information;
    quantity<hu::bit::info, double> qd(2 * bit);
    BOOST_CHECK_EQUAL(qd.value(), double(2));
    quantity<hu::bit::info, long> ql(2 * bit);
    BOOST_CHECK_EQUAL(ql.value(), long(2));
}

BOOST_AUTO_TEST_CASE(test_nat_quantity) {
    using namespace bu::information;
    quantity<hu::nat::info, double> qd(2 * nat);
    BOOST_CHECK_EQUAL(qd.value(), double(2));
    quantity<hu::nat::info, long> ql(2 * nat);
    BOOST_CHECK_EQUAL(ql.value(), long(2));
}

BOOST_AUTO_TEST_CASE(test_hartley_quantity) {
    using namespace bu::information;
    quantity<hu::hartley::info, double> qd(2 * hartley);
    BOOST_CHECK_EQUAL(qd.value(), double(2));
    quantity<hu::hartley::info, long> ql(2 * hartley);
    BOOST_CHECK_EQUAL(ql.value(), long(2));
}

BOOST_AUTO_TEST_CASE(test_shannon_quantity) {
    using namespace bu::information;
    quantity<hu::shannon::info, double> qd(2 * shannon);
    BOOST_CHECK_EQUAL(qd.value(), double(2));
    quantity<hu::shannon::info, long> ql(2 * shannon);
    BOOST_CHECK_EQUAL(ql.value(), long(2));
}

BOOST_AUTO_TEST_CASE(test_mixed_hu) {
    using namespace bu::information;
    const double cf = 0.001;
    BOOST_CHECK_CLOSE_FRACTION((quantity<hu::bit::info>(1.0 * bits)).value(), 1.0, cf);
    BOOST_CHECK_CLOSE_FRACTION((quantity<hu::byte::info>(1.0 * bits)).value(), 1.0/8.0, cf);
    BOOST_CHECK_CLOSE_FRACTION((quantity<hu::nat::info>(1.0 * bits)).value(), 0.69315, cf);
    BOOST_CHECK_CLOSE_FRACTION((quantity<hu::hartley::info>(1.0 * bits)).value(), 0.30102, cf);
    BOOST_CHECK_CLOSE_FRACTION((quantity<hu::shannon::info>(1.0 * bits)).value(), 1.0, cf);
}

BOOST_AUTO_TEST_CASE(test_info_prefixes) {
    using namespace bu::information;
    quantity<info, long long> q10(1LL * kibi * byte);
    BOOST_CHECK_EQUAL(q10.value(), 1024LL);

    quantity<info, long long> q20(1LL * mebi * byte);
    BOOST_CHECK_EQUAL(q20.value(), 1048576LL);

    quantity<info, long long> q30(1LL * gibi * byte);
    BOOST_CHECK_EQUAL(q30.value(), 1073741824LL);

    quantity<info, long long> q40(1LL * tebi * byte);
    BOOST_CHECK_EQUAL(q40.value(), 1099511627776LL);

    quantity<info, long long> q50(1LL * pebi * byte);
    BOOST_CHECK_EQUAL(q50.value(), 1125899906842624LL);

    quantity<info, long long> q60(1LL * exbi * byte);
    BOOST_CHECK_EQUAL(q60.value(), 1152921504606846976LL);

    using boost::multiprecision::int128_t;

    quantity<info, int128_t> q70(1LL * zebi * byte);
    BOOST_CHECK_EQUAL(q70.value(), int128_t("1180591620717411303424"));

    quantity<info, int128_t> q80(1LL * yobi * byte);
    BOOST_CHECK_EQUAL(q80.value(), int128_t("1208925819614629174706176"));

    // sanity check: si prefixes should also operate
    quantity<info, long long> q1e3(1LL * si::kilo * byte);
    BOOST_CHECK_EQUAL(q1e3.value(), 1000LL);

    quantity<info, long long> q1e6(1LL * si::mega * byte);
    BOOST_CHECK_EQUAL(q1e6.value(), 1000000LL);
}

BOOST_AUTO_TEST_CASE(test_unit_constant_io) {
    using namespace bu::information;

    std::stringstream ss;
    ss << bu::symbol_format << bytes;
    BOOST_CHECK_EQUAL(ss.str(), "B");

    ss.str("");
    ss << bu::name_format << bytes;
    BOOST_CHECK_EQUAL(ss.str(), "byte");

    ss.str("");
    ss << bu::symbol_format << bits;
    BOOST_CHECK_EQUAL(ss.str(), "b");

    ss.str("");
    ss << bu::name_format << bits;
    BOOST_CHECK_EQUAL(ss.str(), "bit");

    ss.str("");
    ss << bu::symbol_format << nats;
    BOOST_CHECK_EQUAL(ss.str(), "nat");

    ss.str("");
    ss << bu::name_format << nats;
    BOOST_CHECK_EQUAL(ss.str(), "nat");

    ss.str("");
    ss << bu::symbol_format << hartleys;
    BOOST_CHECK_EQUAL(ss.str(), "Hart");

    ss.str("");
    ss << bu::name_format << hartleys;
    BOOST_CHECK_EQUAL(ss.str(), "hartley");

    ss.str("");
    ss << bu::symbol_format << shannons;
    BOOST_CHECK_EQUAL(ss.str(), "Sh");

    ss.str("");
    ss << bu::name_format << shannons;
    BOOST_CHECK_EQUAL(ss.str(), "shannon");
}

max_stars_repo_name: lijgame/boost


text:
#pragma once

#include <boost/config.hpp>

#include <string>

#include <xul/data/tchar.hpp>

#if defined(BOOST_WINDOWS)
inline int strncasecmp(const char* s1, const char* s2, size_t size)
{
    return _strnicmp(s1, s2, size);
}
#else
#include <strings.h>
#endif

namespace xul {

#ifdef UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif

}

max_stars_repo_name: hindsights/xul

max_issues_repo_name: hindsights/xul

max_forks_repo_name: hindsights/xul


text:
// Copyright (c) 2014-2018 Bauhaus-Universitaet Weimar
// This Software is distributed under the Modified BSD License, see license.txt.
//
// Virtual Reality and Visualization Research Group
// Faculty of Media, Bauhaus-Universitaet Weimar
// http://www.uni-weimar.de/medien/vr

#include <algorithm>
#include <string>
#include <vector>
#include <chrono>
#include <fstream>

#include <lamure/pvs/visibility_test.h>
#include <lamure/pvs/visibility_test_id_histogram_renderer.h>
#include <lamure/pvs/visibility_test_id_histogram_renderer_corners.h>
#include <lamure/pvs/visibility_test_simple_randomized_id_histogram_renderer.h>

#include <lamure/pvs/grid.h>
#include <lamure/pvs/grid_octree.h>
#include <lamure/pvs/grid_octree_compressed.h>
#include <lamure/pvs/grid_octree_hierarchical.h>
#include <lamure/pvs/grid_octree_hierarchical_v2.h>
#include <lamure/pvs/grid_irregular.h>
#include <lamure/pvs/grid_irregular_compressed.h>

#include <lamure/pvs/grid_optimizer_octree.h>
#include <lamure/pvs/grid_optimizer_octree_hierarchical.h>
#include <lamure/pvs/grid_optimizer_irregular.h>

#include <lamure/pvs/pvs_bounds_extrapolator_from_outer_cells.h>

#include <lamure/pvs/pvs_database.h>
#include <lamure/pvs/pvs_utils.h>

#include <lamure/ren/model_database.h>

#include <boost/program_options.hpp>

#define PVS_MAIN_MEASURE_PERFORMANCE
#define PVS_MAIN_MEASURE_VISIBILITY           // Will output some info on the calculated visibility into a special file.

int main(int argc, char** argv)
{
#ifdef PVS_MAIN_MEASURE_PERFORMANCE
    std::chrono::time_point<std::chrono::system_clock> start_time_complete, end_time_complete;
    start_time_complete = std::chrono::system_clock::now();
#endif

    // Read additional data from input parameters.
    std::string pvs_output_file_path = "";
    std::string visibility_test_type = "";
    std::string grid_type = "";
    unsigned int grid_size = 1;
    unsigned int num_steps = 11;
    double oversize_factor = 1.5;
    float optimization_threshold = 1.0f;

    namespace po = boost::program_options;
    namespace fs = boost::filesystem;

    const std::string exec_name = (argc > 0) ? fs::basename(argv[0]) : "";
    //scm::shared_ptr<scm::core> scm_core(new scm::core(1, argv));

    putenv((char *)"__GL_SYNC_TO_VBLANK=0");

    std::string resource_file_path = "";

    po::options_description desc("Usage: " + exec_name + " [OPTION]... INPUT\n\n"
                               "Allowed Options");
    desc.add_options()
      ("pvs-file,p", po::value<std::string>(&pvs_output_file_path), "specify output file of calculated pvs data (.pvs)")
      ("vistest", po::value<std::string>(&visibility_test_type)->default_value("hrc"), "specify type of visibility test to be used. Default is histogram renderer with corners. (histogram renderer 'hr', histogram renderer with corners 'hrc', simple randomized histogram renderer 'srhr')")
      ("gridtype", po::value<std::string>(&grid_type)->default_value("irregular_compressed"), "specify type of grid to store visibility data. Default is irregular compressed grid. ('regular', 'regular_compressed', 'irregular', 'irregular_compressed', octree', 'octree_compressed', octree_hierarchical', 'octree_hierarchical_v2', 'octree_hierarchical_v3')")
      ("gridsize", po::value<unsigned int>(&grid_size)->default_value(1), "specify size/depth of the grid used for the visibility test (depends on chosen grid type)")
      ("oversize", po::value<double>(&oversize_factor)->default_value(1.5), "factor the grid bounds will be scaled by. Default is 1.5 (so grid bounds will exceed scene bounds by factor of 1.5)")
      ("optithresh", po::value<float>(&optimization_threshold)->default_value(-1.0f), "specify the threshold at which common data are converged (percent value between 0 and 1). Negative values will deactivate optimization process. Default value is -1.0, so grid optimization is deactivated.")
      ("numsteps,n", po::value<unsigned int>(&num_steps)->default_value(11), "specify the number of intervals the occlusion values will be split into (visibility analysis only). Default value is 11.");
      ;

    // Parse additonal passed parameters.
    po::variables_map vm;
    auto parsed_options = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
    po::store(parsed_options, vm);
    po::notify(vm);

    // Check for valid file path to save pvs-file to.
    if(pvs_output_file_path == "")
    {
        std::cout << "Please specifiy PVS output file path.\n" << desc;
        return 0;
    }

    // Load scene and analyze scene size by choosing and analyzing the visibility test.
    lamure::pvs::visibility_test* vt = nullptr;

    if(visibility_test_type == "hr")
    {
        vt = new lamure::pvs::visibility_test_id_histogram_renderer();
    }
    else if(visibility_test_type == "hrc")
    {
        vt = new lamure::pvs::visibility_test_id_histogram_renderer_corners();
    }
    else if(visibility_test_type == "srhr")
    {
        vt = new lamure::pvs::visibility_test_simple_randomized_id_histogram_renderer();
    }
    else
    {
        std::cout << "Invalid visibility test: " << visibility_test_type << ".\n" << desc;
        return 0;
    }

    vt->initialize(argc, argv);
    lamure::vec3r scene_dimensions = vt->get_scene_bounds().get_dimensions();

    lamure::ren::model_database* database = lamure::ren::model_database::get_instance();

    // Models may have their own translation, so calculate their center and add it to the scene bounds calculated from the bounding boxes.
    lamure::vec3r translation_center(0.0, 0.0, 0.0);
    for(lamure::model_t model_index = 0; model_index < database->num_models(); ++model_index)
    {
        translation_center += database->get_model(model_index)->get_bvh()->get_translation();
    }
    translation_center /= database->num_models();

    lamure::vec3r center_bounds = vt->get_scene_bounds().get_center();
    scm::math::vec3d center(center_bounds);

    // Knowledge about how many models containing how many nodes is required to save pvs data.
    std::vector<lamure::node_t> ids;
    ids.resize(database->num_models());
    for(lamure::model_t model_index = 0; model_index < ids.size(); ++model_index)
    {
        ids.at(model_index) = database->get_model(model_index)->get_bvh()->get_num_nodes();
    }

    // Create grid based on scene size.
    lamure::pvs::grid* test_grid = nullptr;

    // Note how num_cells is interpreted by grid itself (e.g. octrees use it as depth, regular grids as cells per dimension)
    size_t num_cells = grid_size;
    double grid_bounds_size = std::max(scene_dimensions.x, std::max(scene_dimensions.y, scene_dimensions.z)) * oversize_factor;

    // TODO: calculate num cells of each axis for irregular grid here.
    double cell_size = grid_bounds_size / (double)num_cells;
    size_t cells_x = std::ceil((scene_dimensions.x * oversize_factor) / cell_size);
    size_t cells_y = std::ceil((scene_dimensions.y * oversize_factor) / cell_size);
    size_t cells_z = std::ceil((scene_dimensions.z * oversize_factor) / cell_size);

    test_grid = lamure::pvs::pvs_database::get_instance()->create_grid_by_type(grid_type, cells_x, cells_y, cells_z, grid_bounds_size, center, ids);

    if(test_grid == nullptr)
    {
        std::cout << "Unsupported grid type: " << grid_type << std::endl << desc;
        return 0;
    }

    // Make sure optimization threshold is within certain bounds (0-100% or disabled).
    if(optimization_threshold > 1.0f)
    {
        optimization_threshold = 1.0f;
    }
    else if(optimization_threshold < 0.0f)
    {
        optimization_threshold = -1.0f;
    }

    /*std::string pvs_grid_output_file_path = pvs_output_file_path;
    if(pvs_grid_output_file_path != "")
    {
        pvs_grid_output_file_path.resize(pvs_grid_output_file_path.length() - 3);
        pvs_grid_output_file_path = pvs_grid_output_file_path + "grid";
    }

    lamure::pvs::pvs_database* pvs_db = lamure::pvs::pvs_database::get_instance();
    pvs_db->load_pvs_from_file(pvs_output_file_path, pvs_grid_output_file_path);*/

#ifdef PVS_MAIN_MEASURE_PERFORMANCE
    std::chrono::time_point<std::chrono::system_clock> start_time, end_time;
    start_time = std::chrono::system_clock::now();
#endif

    // Run visibility test on given scene and grid.
    vt->test_visibility(test_grid);

#ifdef PVS_MAIN_MEASURE_PERFORMANCE
    end_time = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed_seconds = end_time - start_time;
    double visibility_test_time = elapsed_seconds.count();
#endif

    // Save grid containing visibility information to file.
    std::string pvs_grid_output_file_path = pvs_output_file_path;
    if(pvs_grid_output_file_path != "")
    {
        pvs_grid_output_file_path.resize(pvs_grid_output_file_path.length() - 3);
        pvs_grid_output_file_path = pvs_grid_output_file_path + "grid";
    }

#ifdef PVS_MAIN_MEASURE_PERFORMANCE
    start_time = std::chrono::system_clock::now();
#endif

    if(optimization_threshold >= 0.0f)
    {
        // Optimize grid by reducing amount of view cells if possible.
        std::cout << "Start grid optimization..." << std::endl;

        if(grid_type == lamure::pvs::grid_octree::get_grid_identifier() ||
            grid_type == lamure::pvs::grid_octree_compressed::get_grid_identifier())
        {
            lamure::pvs::grid_optimizer_octree optimizer;
            optimizer.optimize_grid(test_grid, optimization_threshold);
        }
        else if(grid_type == lamure::pvs::grid_octree_hierarchical::get_grid_identifier() ||
            grid_type == lamure::pvs::grid_octree_hierarchical_v2::get_grid_identifier())
        {
            lamure::pvs::grid_optimizer_octree_hierarchical optimizer;
            optimizer.optimize_grid(test_grid, optimization_threshold);
        }
        else if(grid_type == lamure::pvs::grid_irregular::get_grid_identifier() ||
            grid_type == lamure::pvs::grid_irregular_compressed::get_grid_identifier())
        {
            lamure::pvs::grid_optimizer_irregular optimizer;
            optimizer.optimize_grid(test_grid, optimization_threshold);
        }

        std::cout << "Finished grid optimization." << std::endl;
    }
    else
    {
        std::cout << "Skipping grid optimization." << std::endl;
    }

#ifdef PVS_MAIN_MEASURE_PERFORMANCE
    end_time = std::chrono::system_clock::now();
    elapsed_seconds = end_time - start_time;
    double grid_optimization_time = elapsed_seconds.count();
    start_time = std::chrono::system_clock::now();
#endif

#ifdef PVS_MAIN_MEASURE_VISIBILITY
    // Write collected visibility data to file.
    std::string visibility_file_path = pvs_output_file_path;
    visibility_file_path.resize(visibility_file_path.size() - 4);
    visibility_file_path += "_visibility.txt";

    lamure::pvs::analyze_grid_visibility(test_grid, num_steps, visibility_file_path);
#endif

#ifdef PVS_MAIN_MEASURE_PERFORMANCE
    end_time = std::chrono::system_clock::now();
    elapsed_seconds = end_time - start_time;
    double visibility_analysis_time = elapsed_seconds.count();
    start_time = std::chrono::system_clock::now();
#endif

    // Write grid and contained visibility data to files.
    std::cout << "Start writing grid file..." << std::endl;
    test_grid->save_grid_to_file(pvs_grid_output_file_path);
    std::cout << "Finished writing grid file.\nStart writing pvs file..." << std::endl;
    test_grid->save_visibility_to_file(pvs_output_file_path);
    std::cout << "Finished writing pvs file." << std::endl;

    std::cout << "Creating and saving bounding visibility data..." << std::endl;
    lamure::pvs::pvs_bounds_extrapolator_from_outer_cells extrapolator;
    lamure::pvs::grid* bounding_grid = extrapolator.extrapolate_from_grid(test_grid);

    std::string bounding_pvs_output_file_path = pvs_output_file_path;
    bounding_pvs_output_file_path.resize(bounding_pvs_output_file_path.size() - 4);
    bounding_pvs_output_file_path += "_bounding.pvs";

    bounding_grid->save_visibility_to_file(bounding_pvs_output_file_path);
    std::cout << "Finished saving bounding visibility data." << std::endl;

#ifdef PVS_MAIN_MEASURE_PERFORMANCE
    end_time = std::chrono::system_clock::now();
    elapsed_seconds = end_time - start_time;
    double save_file_time = elapsed_seconds.count();

    end_time_complete = std::chrono::system_clock::now();
    elapsed_seconds = end_time_complete - start_time_complete;
    double complete_time = elapsed_seconds.count();

    std::string performance_file_path = pvs_output_file_path;
    performance_file_path.resize(performance_file_path.size() - 4);
    performance_file_path += "_performance.txt";

    std::ofstream file_out;
    file_out.open(performance_file_path, std::ios::app);

    file_out << "---------- main performance in seconds ----------" << std::endl;
    file_out << "initialization: " << complete_time - (visibility_test_time + grid_optimization_time + visibility_analysis_time + save_file_time) << std::endl;
    file_out << "visibility test: " << visibility_test_time << std::endl;
    file_out << "grid optimization: " << grid_optimization_time << std::endl;
#ifdef PVS_MAIN_MEASURE_VISIBILITY
    file_out << "visibility analysis: " << visibility_analysis_time << std::endl;
#endif
    file_out << "save file: " << save_file_time << std::endl;
    file_out << "complete execution: " << complete_time << std::endl;

    file_out.close();
#endif

    vt->shutdown();

    delete test_grid;
    delete vt;

    return 0;
}


text: #include <boost/type_traits/has_bit_or_assign.hpp>