<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swdll.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 02:13:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SW_SWDLL_HXX
#define SW_SWDLL_HXX

class ResMgr;
class SvFactory;
class SotFactory;
class StatusBar;

class SfxMedium;
class SfxFilter;

#ifndef _SFXDEFS_HXX //autogen
#include <sfx2/sfxdefs.hxx>
#endif
#ifndef _SFXMODULE_HXX //autogen
#include <sfx2/module.hxx>
#endif

#include <tools/shl.hxx>

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

class SwDLL

/*  [Description]

    This class is a wrapper for a Load-On-Demand-DLL. One instance
    per SfxApplication will be created for the runtime of
    SfxApplication-subclass::Main().

    Remember: Do export this class! It is used by the application.
*/

{

    static void RegisterFactories();
    static void RegisterInterfaces();
    static void RegisterControls();
public:
                    // Ctor/Dtor must be linked to the application
                    SwDLL();
                    ~SwDLL();

    static void     Init();     // called directly after loading the DLL
    static void     Exit();     // called directly befor unloading the DLL

    static void     FillStatusBar(StatusBar &rBar);
};

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

#define SW_DLL() ( *(SwModule**) GetAppData(SHL_WRITER) )

#endif

<commit_msg>INTEGRATION: CWS writercorehandoff (1.3.810); FILE MERGED 2005/09/13 11:58:09 tra 1.3.810.2: RESYNC: (1.3-1.4); FILE MERGED 2005/06/07 14:10:20 fme 1.3.810.1: #i50348# General cleanup - removed unused header files, functions, members, declarations etc.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swdll.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-14 15:33:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef SW_SWDLL_HXX
#define SW_SWDLL_HXX

class StatusBar;

#ifndef _SFXDEFS_HXX //autogen
#include <sfx2/sfxdefs.hxx>
#endif
#ifndef _SFXMODULE_HXX //autogen
#include <sfx2/module.hxx>
#endif

#include <tools/shl.hxx>

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

class SwDLL

/*  [Description]

    This class is a wrapper for a Load-On-Demand-DLL. One instance
    per SfxApplication will be created for the runtime of
    SfxApplication-subclass::Main().

    Remember: Do export this class! It is used by the application.
*/

{

    static void RegisterFactories();
    static void RegisterInterfaces();
    static void RegisterControls();
public:
                    // Ctor/Dtor must be linked to the application
                    SwDLL();
                    ~SwDLL();

    static void     Init();     // called directly after loading the DLL
    static void     Exit();     // called directly befor unloading the DLL

    static void     FillStatusBar(StatusBar &rBar);
};

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

#define SW_DLL() ( *(SwModule**) GetAppData(SHL_WRITER) )

#endif

<|endoftext|>


<commit_before>#include <boost/asio.hpp>
#include <future>
#include <vector>
#include <string>

#include "EmptyPort.hpp"
#include "SocketWithLogging.hpp"
#include "TestServer.hpp"
#include "catch.hpp"

#include "bredis/Connection.hpp"

namespace r = bredis;
namespace asio = boost::asio;
namespace ep = empty_port;
namespace ts = test_server;

TEST_CASE("ping", "[connection]") {
    using socket_t = asio::ip::tcp::socket;
#ifdef BREDIS_DEBUG
    using next_layer_t = r::test::SocketWithLogging<socket_t>;
#else
    using next_layer_t = socket_t;
#endif
    using Buffer = boost::asio::dynamic_string_buffer<
        std::string::value_type,
        std::string::traits_type,
        std::string::allocator_type
    >;
    using Iterator =
        boost::asio::buffers_iterator<typename Buffer::const_buffers_type,
                                      char>;
    using Policy = r::parsing_policy::keep_result;
    using ParseResult = r::positive_parse_result_t<Iterator, Policy>;

    using result_t = void;
    using write_callback_t =
        std::function<void(const boost::system::error_code &error_code,
                           std::size_t bytes_transferred)>;
    using read_callback_t = std::function<void(
        const boost::system::error_code &error_code, ParseResult &&r)>;

    std::chrono::nanoseconds sleep_delay(1);

    size_t count = 1000;
    r::single_command_t ping_cmd("ping");
    r::command_container_t ping_cmds_container(count, ping_cmd);
    r::command_wrapper_t cmd(ping_cmds_container);

    uint16_t port = ep::get_random<ep::Kind::TCP>();
    auto port_str = boost::lexical_cast<std::string>(port);
    auto server = ts::make_server({"redis-server", "--port", port_str});
    ep::wait_port<ep::Kind::TCP>(port);
    asio::io_service io_service;

    asio::ip::tcp::endpoint end_point(
        asio::ip::address::from_string("127.0.0.1"), port);
    socket_t socket(io_service, end_point.protocol());
    socket.connect(end_point);

    r::Connection<next_layer_t> c(std::move(socket));
    std::promise<result_t> completion_promise;
    std::future<result_t> completion_future = completion_promise.get_future();

    std::string rx_backend;
    std::string tx_backend;
    auto rx_buff = Buffer(rx_backend);
    auto tx_buff = Buffer(tx_backend);
    read_callback_t read_callback =
        [&](const boost::system::error_code &error_code, ParseResult &&r) {
            if (error_code) {
                BREDIS_LOG_DEBUG("error: " << error_code.message());
                REQUIRE(!error_code);
            }
            REQUIRE(!error_code);
            auto &replies =
                boost::get<r::markers::array_holder_t<Iterator>>(r.result);
            BREDIS_LOG_DEBUG("callback, size: " << replies.elements.size());
            REQUIRE(replies.elements.size() == count);
            completion_promise.set_value();
            rx_buff.consume(r.consumed);
        };

    write_callback_t write_callback = [&](
        const boost::system::error_code &error_code, auto bytes_transferred) {
        (void)bytes_transferred;
        BREDIS_LOG_DEBUG("write_callback");
        if (error_code) {
            BREDIS_LOG_DEBUG("error: " << error_code.message());
            REQUIRE(!error_code);
        }
        REQUIRE(!error_code);
        tx_buff.consume(bytes_transferred);
    };

    c.async_read(rx_buff, read_callback, count);
    c.async_write(tx_buff, cmd, write_callback);

    while (completion_future.wait_for(sleep_delay) !=
           std::future_status::ready) {
        io_service.run_one();
    }
}
<commit_msg>fix test<commit_after>#include <boost/asio.hpp>
#include <future>
#include <vector>
#include <string>

#include "EmptyPort.hpp"
#include "SocketWithLogging.hpp"
#include "TestServer.hpp"
#include "catch.hpp"

#include "bredis/Connection.hpp"

namespace r = bredis;
namespace asio = boost::asio;
namespace ep = empty_port;
namespace ts = test_server;
namespace sys = boost::system;

TEST_CASE("ping", "[connection]") {
    using socket_t = asio::ip::tcp::socket;
#ifdef BREDIS_DEBUG
    using next_layer_t = r::test::SocketWithLogging<socket_t>;
#else
    using next_layer_t = socket_t;
#endif
    using Buffer = boost::asio::dynamic_string_buffer<
        std::string::value_type,
        std::string::traits_type,
        std::string::allocator_type
    >;
    using Iterator =
        boost::asio::buffers_iterator<typename Buffer::const_buffers_type,
                                      char>;
    using Policy = r::parsing_policy::keep_result;
    using ParseResult = r::positive_parse_result_t<Iterator, Policy>;

    using result_t = void;
    using write_callback_t =
        std::function<void(const boost::system::error_code &error_code,
                           std::size_t bytes_transferred)>;
    using read_callback_t = std::function<void(
        const boost::system::error_code &error_code, ParseResult &&r)>;

    std::chrono::nanoseconds sleep_delay(1);

    size_t count = 1000;
    r::single_command_t ping_cmd("ping");
    r::command_container_t ping_cmds_container(count, ping_cmd);
    r::command_wrapper_t cmd(ping_cmds_container);

    uint16_t port = ep::get_random<ep::Kind::TCP>();
    auto port_str = boost::lexical_cast<std::string>(port);
    auto server = ts::make_server({"redis-server", "--port", port_str});
    ep::wait_port<ep::Kind::TCP>(port);
    asio::io_service io_service;

    asio::ip::tcp::endpoint end_point(
        asio::ip::address::from_string("127.0.0.1"), port);
    socket_t socket(io_service, end_point.protocol());
    socket.connect(end_point);

    r::Connection<next_layer_t> c(std::move(socket));
    std::promise<result_t> completion_promise;
    std::future<result_t> completion_future = completion_promise.get_future();

    std::string rx_backend;
    std::string tx_backend;
    auto rx_buff = Buffer(rx_backend);
    auto tx_buff = Buffer(tx_backend);
    read_callback_t read_callback =
        [&](const sys::error_code &ec, ParseResult &&r) {
            if (ec) {
                BREDIS_LOG_DEBUG("error: " << error_code.message());
                REQUIRE(!ec);
            }
            REQUIRE(!ec);
            auto &replies =
                boost::get<r::markers::array_holder_t<Iterator>>(r.result);
            BREDIS_LOG_DEBUG("callback, size: " << replies.elements.size());
            REQUIRE(replies.elements.size() == count);
            completion_promise.set_value();
            rx_buff.consume(r.consumed);
        };

    write_callback_t write_callback = [&](
        const sys::error_code &ec, std::size_t bytes_transferred) {
        (void)bytes_transferred;
        BREDIS_LOG_DEBUG("write_callback");
        if (ec) {
            BREDIS_LOG_DEBUG("error: " << error_code.message());
            REQUIRE(!ec);
        }
        REQUIRE(!ec);
        tx_buff.consume(bytes_transferred);
    };

    c.async_read(rx_buff, read_callback, count);
    c.async_write(tx_buff, cmd, write_callback);

    while (completion_future.wait_for(sleep_delay) !=
           std::future_status::ready) {
        io_service.run_one();
    }
}
<|endoftext|>


<commit_before><commit_msg>Adds very low quality, race-condition infested video output.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2013-2015 Daniel Nicoletti <dantti12@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "dispatcher_p.h"

#include "common.h"
#include "application.h"
#include "engine.h"
#include "context.h"
#include "controller.h"
#include "controller_p.h"
#include "action.h"
#include "request_p.h"
#include "dispatchtypepath.h"
#include "dispatchtypechained.h"
#include "utils.h"

#include <QUrl>
#include <QMetaMethod>

using namespace Cutelyst;

Dispatcher::Dispatcher(QObject *parent) : QObject(parent)
  , d_ptr(new DispatcherPrivate(this))
{
    new DispatchTypePath(parent);
    new DispatchTypeChained(parent);
}

Dispatcher::~Dispatcher()
{
    delete d_ptr;
}

void Dispatcher::setupActions(const QVector<Controller*> &controllers, const QVector<Cutelyst::DispatchType *> &dispatchers, bool printActions)
{
    Q_D(Dispatcher);

    d->dispatchers = dispatchers;

    ActionList registeredActions;
    for (Controller *controller : controllers) {
        bool instanceUsed = false;
        const auto actions = controller->actions();
        for (Action *action : actions) {
            bool registered = false;
            if (!d->actions.contains(action->reverse())) {
                if (!action->attributes().contains(QLatin1String("Private"))) {
                    // Register the action with each dispatcher
                    for (DispatchType *dispatch : dispatchers) {
                        if (dispatch->registerAction(action)) {
                            registered = true;
                        }
                    }
                } else {
                    // We register private actions
                    registered = true;
                }
            }

            // The Begin, Auto, End actions are not
            // registered by Dispatchers but we need them
            // as private actions anyway
            if (registered) {
                d->actions.insert(action->ns() + QLatin1Char('/') + action->name(), action);
                d->actionContainer[action->ns()] << action;
                registeredActions.append(action);
                instanceUsed = true;
            } else {
                qCDebug(CUTELYST_DISPATCHER) << "The action" << action->name() << "of"
                                             << action->controller()->objectName()
                                             << "controller was not registered in any dispatcher."
                                                " If you still want to access it internally (via actionFor())"
                                                " you may make it's method private.";
            }
        }

        if (instanceUsed) {
            d->controllers.insert(controller->objectName(), controller);
        }
    }

    if (printActions) {
        d->printActions();
    }

    // Cache root actions, BEFORE the controllers set them
    d->rootActions = d->actionContainer.value(QLatin1String(""));

    for (Controller *controller : controllers) {
        controller->d_ptr->setupFinished();
    }

    // Unregister any dispatcher that is not in use
    int i = 0;
    while (i < d->dispatchers.size()) {
        DispatchType *type = d->dispatchers.at(i);
        if (!type->inUse()) {
            d->dispatchers.removeAt(i);
            continue;
        }
        ++i;
    }

    if (printActions) {
        // List all public actions
        for (DispatchType *dispatch : dispatchers) {
            qCDebug(CUTELYST_DISPATCHER) << dispatch->list().constData();
        }
    }
}

bool Dispatcher::dispatch(Context *c)
{
    Action *action = c->action();
    if (action) {
        return action->controller()->_DISPATCH(c);
    } else {
        const QString path = c->req()->path();
        if (path.isEmpty()) {
            c->error(c->translate("Cutelyst::Dispatcher", "No default action defined"));
        } else {
            c->error(c->translate("Cutelyst::Dispatcher", "Unknown resource '%1'.").arg(path));
        }
    }
    return false;
}

bool Dispatcher::forward(Context *c, Component *component)
{
    Q_ASSERT(component);
    // If the component was an Action
    // the dispatch() would call c->execute
    return c->execute(component);
}

bool Dispatcher::forward(Context *c, const QString &opname)
{
    Q_D(const Dispatcher);

    Action *action = d->command2Action(c, opname, c->request()->args());
    if (action) {
        return action->dispatch(c);
    }

    qCCritical(CUTELYST_DISPATCHER) << "Action not found" << opname << c->request()->args();
    return false;
}

void Dispatcher::prepareAction(Context *c)
{
    Q_D(Dispatcher);

    Request *request = c->request();
    d->prepareAction(c, request->path());

    static const auto &log = CUTELYST_DISPATCHER();
    if (log.isDebugEnabled()) {
        if (!request->match().isEmpty()) {
            qCDebug(log) << "Path is" << request->match();
        }

        if (!request->args().isEmpty()) {
            qCDebug(log) << "Arguments are" << request->args().join(QLatin1Char('/'));
        }
    }
}

void DispatcherPrivate::prepareAction(Context *c, const QString &requestPath) const
{
    QString path = normalizePath(requestPath);
    QStringList args;

    //  "foo/bar"
    //  "foo/" skip
    //  "foo"
    //  ""
    Q_FOREVER {
        // Check out the dispatch types to see if any
        // will handle the path at this level
        for (DispatchType *type : dispatchers) {
            if (type->match(c, path, args) == DispatchType::ExactMatch) {
                return;
            }
        }

        // leave the loop if we are at the root "/"
        if (path.isEmpty()) {
            break;
        }

        int pos = path.lastIndexOf(QLatin1Char('/'));

        QString arg = path.mid(pos + 1);
        args.prepend(Utils::decodePercentEncoding(&arg));

        path.resize(pos);
    }
}

Action *Dispatcher::getAction(const QString &name, const QString &nameSpace) const
{
    Q_D(const Dispatcher);

    if (name.isEmpty()) {
        return 0;
    }

    if (nameSpace.isEmpty()) {
        return d->actions.value(QLatin1Char('/') + name);
    }

    const QString ns = DispatcherPrivate::cleanNamespace(nameSpace);
    return d->actions.value(ns + QLatin1Char('/') + name);
}

Action *Dispatcher::getActionByPath(const QString &path) const
{
    Q_D(const Dispatcher);

    QString _path = path;
    if (_path.startsWith(QLatin1Char('/'))) {
        _path.remove(0, 1);
    }
    return d->actions.value(_path);
}

ActionList Dispatcher::getActions(const QString &name, const QString &nameSpace) const
{
    Q_D(const Dispatcher);

    ActionList ret;

    if (name.isEmpty()) {
        return ret;
    }

    const QString ns = DispatcherPrivate::cleanNamespace(nameSpace);
    const ActionList containers = d->getContainers(ns);

    for (Action *action : containers) {
        if (action->name() == name) {
            ret.prepend(action);
        }
    }
    return ret;
}

QMap<QString, Controller *> Dispatcher::controllers() const
{
    Q_D(const Dispatcher);
    return d->controllers;
}

QString Dispatcher::uriForAction(Action *action, const QStringList &captures) const
{
    Q_D(const Dispatcher);
    QString ret;
    for (DispatchType *dispatch : d->dispatchers) {
        ret = dispatch->uriForAction(action, captures);
        if (!ret.isNull()) {
            if (ret.isEmpty()) {
                ret = QStringLiteral("/");
            }
            break;
        }
    }
    return ret;
}

Action *Dispatcher::expandAction(Context *c, Action *action) const
{
    Q_D(const Dispatcher);
    for (DispatchType *dispatch : d->dispatchers) {
        Action *expandedAction = dispatch->expandAction(c, action);
        if (expandedAction) {
            return expandedAction;
        }
    }
    return action;
}

QVector<DispatchType *> Dispatcher::dispatchers() const
{
    Q_D(const Dispatcher);
    return d->dispatchers;
}

QString DispatcherPrivate::cleanNamespace(const QString &ns)
{
    QString ret = ns;
    bool lastWasSlash = true; // remove initial slash
    int nsSize = ns.size();
    for (int i = 0; i < nsSize; ++i) {
        // Mark if the last char was a slash
        // so that two or more consecutive slashes
        // could be converted to just one
        // "a///b" -> "a/b"
        if (ret.at(i) == QLatin1Char('/')) {
            if (lastWasSlash) {
                ret.remove(i, 1);
                --nsSize;
            } else {
                lastWasSlash = true;
            }
        } else {
            lastWasSlash = false;
        }
    }
    return ret;
}

QString DispatcherPrivate::normalizePath(const QString &path)
{
    QString ret = path;
    bool lastSlash = true;
    int i = 0;
    while (i < ret.size()) {
        if (ret.at(i) == QLatin1Char('/')) {
            if (lastSlash) {
                ret.remove(i, 1);
                continue;
            }
            lastSlash = true;
        } else {
            lastSlash = false;
        }
        ++i;
    }

    if (ret.endsWith(QLatin1Char('/'))) {
        ret.resize(ret.size() - 1);
    }
    return ret;
}

void DispatcherPrivate::printActions() const
{
    QVector<QStringList> table;

    QStringList keys = actions.keys();
    keys.sort(Qt::CaseInsensitive);
    for (const QString &key : keys) {
        Action *action = actions.value(key);
        QString path = key;
        if (!path.startsWith(QLatin1Char('/'))) {
            path.prepend(QLatin1Char('/'));
        }

        QStringList row;
        row.append(path);
        row.append(action->className());
        row.append(action->name());
        table.append(row);
    }

    qCDebug(CUTELYST_DISPATCHER) <<  Utils::buildTable(table, {
                                                           QLatin1String("Private"),
                                                           QLatin1String("Class"),
                                                           QLatin1String("Method")
                                                       },
                                                       QLatin1String("Loaded Private actions:")).constData();
}

ActionList DispatcherPrivate::getContainers(const QString &ns) const
{
    ActionList ret;

    if (ns != QLatin1String("/")) {
        int pos = ns.size();
//        qDebug() << pos << ns.mid(0, pos);
        while (pos > 0) {
//            qDebug() << pos << ns.mid(0, pos);
            ret.append(actionContainer.value(ns.mid(0, pos)));
            pos = ns.lastIndexOf(QLatin1Char('/'), pos - 1);
        }
    }
//    qDebug() << actionContainer.size() << rootActions;
    ret.append(rootActions);

    return ret;
}

Action *DispatcherPrivate::command2Action(Context *c, const QString &command, const QStringList &args) const
{
    auto it = actions.constFind(command);
    if (it != actions.constEnd()) {
        return it.value();
    }

    return invokeAsPath(c, command, args);
}

Action *DispatcherPrivate::invokeAsPath(Context *c, const QString &relativePath, const QStringList &args) const
{
    Q_Q(const Dispatcher);

    Action *ret;
    QString path = DispatcherPrivate::actionRel2Abs(c, relativePath);

    int pos = path.lastIndexOf(QLatin1Char('/'));
    int lastPos = path.size();
    do {
        if (pos == -1) {
            ret = q->getAction(path, QString());
            if (ret) {
                return ret;
            }
        } else {
            const QString name = path.mid(pos + 1, lastPos);
            path = path.mid(0, pos);
            ret = q->getAction(name, path);
            if (ret) {
                return ret;
            }
        }

        lastPos = pos;
        pos = path.indexOf(QLatin1Char('/'), pos - 1);
    } while (pos != -1);

    return 0;
}

QString DispatcherPrivate::actionRel2Abs(Context *c, const QString &path)
{
    QString ret;
    if (path.startsWith(QLatin1Char('/'))) {
        ret = path.mid(1);
        return ret;
    }

    const QString ns = qobject_cast<Action *>(c->stack().constLast())->ns();
    if (ns.isEmpty()) {
        ret = path;
    } else {
        ret = ns + QLatin1Char('/') + path;
    }
    return ret;
}

#include "moc_dispatcher.cpp"
<commit_msg>Core: Make sure Dispatcher::getActionByPath() behaves properly when it's an action on the empty namespace<commit_after>/*
 * Copyright (C) 2013-2015 Daniel Nicoletti <dantti12@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "dispatcher_p.h"

#include "common.h"
#include "application.h"
#include "engine.h"
#include "context.h"
#include "controller.h"
#include "controller_p.h"
#include "action.h"
#include "request_p.h"
#include "dispatchtypepath.h"
#include "dispatchtypechained.h"
#include "utils.h"

#include <QUrl>
#include <QMetaMethod>

using namespace Cutelyst;

Dispatcher::Dispatcher(QObject *parent) : QObject(parent)
  , d_ptr(new DispatcherPrivate(this))
{
    new DispatchTypePath(parent);
    new DispatchTypeChained(parent);
}

Dispatcher::~Dispatcher()
{
    delete d_ptr;
}

void Dispatcher::setupActions(const QVector<Controller*> &controllers, const QVector<Cutelyst::DispatchType *> &dispatchers, bool printActions)
{
    Q_D(Dispatcher);

    d->dispatchers = dispatchers;

    ActionList registeredActions;
    for (Controller *controller : controllers) {
        bool instanceUsed = false;
        const auto actions = controller->actions();
        for (Action *action : actions) {
            bool registered = false;
            if (!d->actions.contains(action->reverse())) {
                if (!action->attributes().contains(QLatin1String("Private"))) {
                    // Register the action with each dispatcher
                    for (DispatchType *dispatch : dispatchers) {
                        if (dispatch->registerAction(action)) {
                            registered = true;
                        }
                    }
                } else {
                    // We register private actions
                    registered = true;
                }
            }

            // The Begin, Auto, End actions are not
            // registered by Dispatchers but we need them
            // as private actions anyway
            if (registered) {
                d->actions.insert(action->ns() + QLatin1Char('/') + action->name(), action);
                d->actionContainer[action->ns()] << action;
                registeredActions.append(action);
                instanceUsed = true;
            } else {
                qCDebug(CUTELYST_DISPATCHER) << "The action" << action->name() << "of"
                                             << action->controller()->objectName()
                                             << "controller was not registered in any dispatcher."
                                                " If you still want to access it internally (via actionFor())"
                                                " you may make it's method private.";
            }
        }

        if (instanceUsed) {
            d->controllers.insert(controller->objectName(), controller);
        }
    }

    if (printActions) {
        d->printActions();
    }

    // Cache root actions, BEFORE the controllers set them
    d->rootActions = d->actionContainer.value(QLatin1String(""));

    for (Controller *controller : controllers) {
        controller->d_ptr->setupFinished();
    }

    // Unregister any dispatcher that is not in use
    int i = 0;
    while (i < d->dispatchers.size()) {
        DispatchType *type = d->dispatchers.at(i);
        if (!type->inUse()) {
            d->dispatchers.removeAt(i);
            continue;
        }
        ++i;
    }

    if (printActions) {
        // List all public actions
        for (DispatchType *dispatch : dispatchers) {
            qCDebug(CUTELYST_DISPATCHER) << dispatch->list().constData();
        }
    }
}

bool Dispatcher::dispatch(Context *c)
{
    Action *action = c->action();
    if (action) {
        return action->controller()->_DISPATCH(c);
    } else {
        const QString path = c->req()->path();
        if (path.isEmpty()) {
            c->error(c->translate("Cutelyst::Dispatcher", "No default action defined"));
        } else {
            c->error(c->translate("Cutelyst::Dispatcher", "Unknown resource '%1'.").arg(path));
        }
    }
    return false;
}

bool Dispatcher::forward(Context *c, Component *component)
{
    Q_ASSERT(component);
    // If the component was an Action
    // the dispatch() would call c->execute
    return c->execute(component);
}

bool Dispatcher::forward(Context *c, const QString &opname)
{
    Q_D(const Dispatcher);

    Action *action = d->command2Action(c, opname, c->request()->args());
    if (action) {
        return action->dispatch(c);
    }

    qCCritical(CUTELYST_DISPATCHER) << "Action not found" << opname << c->request()->args();
    return false;
}

void Dispatcher::prepareAction(Context *c)
{
    Q_D(Dispatcher);

    Request *request = c->request();
    d->prepareAction(c, request->path());

    static const auto &log = CUTELYST_DISPATCHER();
    if (log.isDebugEnabled()) {
        if (!request->match().isEmpty()) {
            qCDebug(log) << "Path is" << request->match();
        }

        if (!request->args().isEmpty()) {
            qCDebug(log) << "Arguments are" << request->args().join(QLatin1Char('/'));
        }
    }
}

void DispatcherPrivate::prepareAction(Context *c, const QString &requestPath) const
{
    QString path = normalizePath(requestPath);
    QStringList args;

    //  "foo/bar"
    //  "foo/" skip
    //  "foo"
    //  ""
    Q_FOREVER {
        // Check out the dispatch types to see if any
        // will handle the path at this level
        for (DispatchType *type : dispatchers) {
            if (type->match(c, path, args) == DispatchType::ExactMatch) {
                return;
            }
        }

        // leave the loop if we are at the root "/"
        if (path.isEmpty()) {
            break;
        }

        int pos = path.lastIndexOf(QLatin1Char('/'));

        QString arg = path.mid(pos + 1);
        args.prepend(Utils::decodePercentEncoding(&arg));

        path.resize(pos);
    }
}

Action *Dispatcher::getAction(const QString &name, const QString &nameSpace) const
{
    Q_D(const Dispatcher);

    if (name.isEmpty()) {
        return 0;
    }

    if (nameSpace.isEmpty()) {
        return d->actions.value(QLatin1Char('/') + name);
    }

    const QString ns = DispatcherPrivate::cleanNamespace(nameSpace);
    return d->actions.value(ns + QLatin1Char('/') + name);
}

Action *Dispatcher::getActionByPath(const QString &path) const
{
    Q_D(const Dispatcher);

    QString _path = path;
    if (_path.startsWith(QLatin1Char('/'))) {
        _path.remove(0, 1);
    }
    if (!_path.contains(QLatin1Char('/'))) {
        _path.prepend(QLatin1Char('/'));
    }
    return d->actions.value(_path);
}

ActionList Dispatcher::getActions(const QString &name, const QString &nameSpace) const
{
    Q_D(const Dispatcher);

    ActionList ret;

    if (name.isEmpty()) {
        return ret;
    }

    const QString ns = DispatcherPrivate::cleanNamespace(nameSpace);
    const ActionList containers = d->getContainers(ns);

    for (Action *action : containers) {
        if (action->name() == name) {
            ret.prepend(action);
        }
    }
    return ret;
}

QMap<QString, Controller *> Dispatcher::controllers() const
{
    Q_D(const Dispatcher);
    return d->controllers;
}

QString Dispatcher::uriForAction(Action *action, const QStringList &captures) const
{
    Q_D(const Dispatcher);
    QString ret;
    for (DispatchType *dispatch : d->dispatchers) {
        ret = dispatch->uriForAction(action, captures);
        if (!ret.isNull()) {
            if (ret.isEmpty()) {
                ret = QStringLiteral("/");
            }
            break;
        }
    }
    return ret;
}

Action *Dispatcher::expandAction(Context *c, Action *action) const
{
    Q_D(const Dispatcher);
    for (DispatchType *dispatch : d->dispatchers) {
        Action *expandedAction = dispatch->expandAction(c, action);
        if (expandedAction) {
            return expandedAction;
        }
    }
    return action;
}

QVector<DispatchType *> Dispatcher::dispatchers() const
{
    Q_D(const Dispatcher);
    return d->dispatchers;
}

QString DispatcherPrivate::cleanNamespace(const QString &ns)
{
    QString ret = ns;
    bool lastWasSlash = true; // remove initial slash
    int nsSize = ns.size();
    for (int i = 0; i < nsSize; ++i) {
        // Mark if the last char was a slash
        // so that two or more consecutive slashes
        // could be converted to just one
        // "a///b" -> "a/b"
        if (ret.at(i) == QLatin1Char('/')) {
            if (lastWasSlash) {
                ret.remove(i, 1);
                --nsSize;
            } else {
                lastWasSlash = true;
            }
        } else {
            lastWasSlash = false;
        }
    }
    return ret;
}

QString DispatcherPrivate::normalizePath(const QString &path)
{
    QString ret = path;
    bool lastSlash = true;
    int i = 0;
    while (i < ret.size()) {
        if (ret.at(i) == QLatin1Char('/')) {
            if (lastSlash) {
                ret.remove(i, 1);
                continue;
            }
            lastSlash = true;
        } else {
            lastSlash = false;
        }
        ++i;
    }

    if (ret.endsWith(QLatin1Char('/'))) {
        ret.resize(ret.size() - 1);
    }
    return ret;
}

void DispatcherPrivate::printActions() const
{
    QVector<QStringList> table;

    QStringList keys = actions.keys();
    keys.sort(Qt::CaseInsensitive);
    for (const QString &key : keys) {
        Action *action = actions.value(key);
        QString path = key;
        if (!path.startsWith(QLatin1Char('/'))) {
            path.prepend(QLatin1Char('/'));
        }

        QStringList row;
        row.append(path);
        row.append(action->className());
        row.append(action->name());
        table.append(row);
    }

    qCDebug(CUTELYST_DISPATCHER) <<  Utils::buildTable(table, {
                                                           QLatin1String("Private"),
                                                           QLatin1String("Class"),
                                                           QLatin1String("Method")
                                                       },
                                                       QLatin1String("Loaded Private actions:")).constData();
}

ActionList DispatcherPrivate::getContainers(const QString &ns) const
{
    ActionList ret;

    if (ns != QLatin1String("/")) {
        int pos = ns.size();
//        qDebug() << pos << ns.mid(0, pos);
        while (pos > 0) {
//            qDebug() << pos << ns.mid(0, pos);
            ret.append(actionContainer.value(ns.mid(0, pos)));
            pos = ns.lastIndexOf(QLatin1Char('/'), pos - 1);
        }
    }
//    qDebug() << actionContainer.size() << rootActions;
    ret.append(rootActions);

    return ret;
}

Action *DispatcherPrivate::command2Action(Context *c, const QString &command, const QStringList &args) const
{
    auto it = actions.constFind(command);
    if (it != actions.constEnd()) {
        return it.value();
    }

    return invokeAsPath(c, command, args);
}

Action *DispatcherPrivate::invokeAsPath(Context *c, const QString &relativePath, const QStringList &args) const
{
    Q_Q(const Dispatcher);

    Action *ret;
    QString path = DispatcherPrivate::actionRel2Abs(c, relativePath);

    int pos = path.lastIndexOf(QLatin1Char('/'));
    int lastPos = path.size();
    do {
        if (pos == -1) {
            ret = q->getAction(path, QString());
            if (ret) {
                return ret;
            }
        } else {
            const QString name = path.mid(pos + 1, lastPos);
            path = path.mid(0, pos);
            ret = q->getAction(name, path);
            if (ret) {
                return ret;
            }
        }

        lastPos = pos;
        pos = path.indexOf(QLatin1Char('/'), pos - 1);
    } while (pos != -1);

    return 0;
}

QString DispatcherPrivate::actionRel2Abs(Context *c, const QString &path)
{
    QString ret;
    if (path.startsWith(QLatin1Char('/'))) {
        ret = path.mid(1);
        return ret;
    }

    const QString ns = qobject_cast<Action *>(c->stack().constLast())->ns();
    if (ns.isEmpty()) {
        ret = path;
    } else {
        ret = ns + QLatin1Char('/') + path;
    }
    return ret;
}

#include "moc_dispatcher.cpp"
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

+template<typename T>
 +class BinaryTree;
 +
 +template<typename T>
 +std::ostream& operator<<(ostream& ost, BinaryTree<T>& temp);

template <typename T>
struct Node {
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree
{
private:
	Node<T>* root;
	int CountElements = 0;

public:
	BinaryTree();
	~BinaryTree();
	BinaryTree(const std::initializer_list<T>&);
	unsigned int count() const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	Node<T>*root_();
	void deleteNode(Node<T>* temp);
	void writing(const std::string& filename)const;
	void output(std::ostream& ost, const Node<T>* temp);
	friend std::ostream& operator<< <> (std::ostream&, const BinaryTree<T>&);

};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::output(std::ostream& ost, const Node<T>* temp)
{
	if (temp == nullptr)
	{
		throw "error";
		return;
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template <typename T>
std::ostream& show(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	show(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	show(ost, node->left, level + 1);
	return ost;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& bst)
{
	if (!bst.root)
		throw "error";
	show(ost, bst.root, 0);
	return ost;
}
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template<typename T>
class BinaryTree;

template<typename T>
std::ostream& operator<<(ostream& ost, BinaryTree<T>& temp);

template <typename T>
struct Node {
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree
{
private:
	Node<T>* root;
	int CountElements = 0;

public:
	BinaryTree();
	~BinaryTree();
	BinaryTree(const std::initializer_list<T>&);
	unsigned int count() const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	Node<T>*root_();
	void deleteNode(Node<T>* temp);
	void writing(const std::string& filename)const;
	void output(std::ostream& ost, const Node<T>* temp);
	friend std::ostream& operator<< <> (std::ostream&, const BinaryTree<T>&);

};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::output(std::ostream& ost, const Node<T>* temp)
{
	if (temp == nullptr)
	{
		throw "error";
		return;
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template <typename T>
std::ostream& show(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	show(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	show(ost, node->left, level + 1);
	return ost;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& bst)
{
	if (!bst.root)
		throw "error";
	show(ost, bst.root, 0);
	return ost;
}
<|endoftext|>


<commit_before><commit_msg>Fixed Issue in track selection menu<commit_after><|endoftext|>


<commit_before>#include "matrix_multiply_static_improved.hpp"

#include <algorithm>

#include <hpx/include/async.hpp>
#include <hpx/include/components.hpp>
#include <hpx/include/iostreams.hpp>
#include <hpx/include/lcos.hpp>

#include "matrix_multiply_recursive.hpp"
#include "matrix_multiply_multiplier.hpp"

void matrix_multiply_static_improved::print_schedule(
		std::vector<std::vector<matrix_multiply_work>> &all_work) {
	std::cout << "-----work-distribution:-----" << std::endl;
	for (size_t i = 0; i < all_work.size(); i++) {
		std::vector<matrix_multiply_work> &locality_work = all_work[i];
		std::cout << "locality: " << i << " = ";
		for (size_t j = 0; j < locality_work.size(); j++) {
			if (j > 0) {
				std::cout << ", ";
			}
			std::cout << "[" << locality_work[j].N << "]";
		}
		std::cout << std::endl;
	}
}

void matrix_multiply_static_improved::insert_submatrix(
		const std::vector<double> &submatrix, const matrix_multiply_work &w) {
	for (size_t i = 0; i < w.N; i++) {
		for (size_t j = 0; j < w.N; j++) {
			// std::cout << (w.x + i) << ", " << (w.y + j) << " val: " << submatrix[i * w.N + j] << std::endl;
			C[(w.x + i) * N + (w.y + j)] = submatrix[i * w.N + j];
		}
	}
}

bool matrix_multiply_static_improved::fulfills_constraints(
		std::vector<uint64_t> &total_work) {
	uint64_t min_work = total_work[0];
	uint64_t max_work = total_work[0];

	for (size_t i = 1; i < total_work.size(); i++) {
		if (total_work[i] < min_work) {
			min_work = total_work[i];
		}
		if (total_work[i] > max_work) {
			max_work = total_work[i];
		}
	}

	std::cout << "+++ work_difference: " << (max_work - min_work) << std::endl;

	if (max_work - min_work < max_work_difference) {
		return true;
	}
	if (min_work > 0 && max_work > 0) {
		double relative_work_difference = (static_cast<double>(max_work
				- min_work) / static_cast<double>(min_work));
		std::cout << "+++ relative_work_difference: "
				<< relative_work_difference << std::endl;
		if (relative_work_difference < max_relative_work_difference) {
			return true;
		}
	}
	return false;
}

std::vector<std::vector<matrix_multiply_work>> matrix_multiply_static_improved::create_schedule(
		size_t num_localities) {
	// one slot per locality, stores the work to do
	std::vector<std::vector<matrix_multiply_work>> all_work(num_localities);

	// map: locality -> assigned components
	std::vector<uint64_t> total_work(num_localities);

	// initially all work is placed on the first locality
	all_work[0].emplace_back(0, 0, N);
	total_work[0] = N * N;

	while (!this->fulfills_constraints(total_work)) {

		// give some work from the max element to the min element
		uint64_t max_work = total_work[0];
		size_t max_index = 0;
		uint64_t min_work = total_work[0];
		size_t min_index = 0;

		for (size_t i = 1; i < num_localities; i++) {
			if (total_work[i] > max_work) {
				max_work = total_work[i];
				max_index = i;
			}
			if (total_work[i] < min_work) {
				min_work = total_work[i];
				min_index = i;
			}
		}

		// will always succeed, do not have to skip first iteration
		size_t work_to_balance_index = all_work[max_index].size();
		uint64_t smallest_work_difference = max_work - min_work;
		for (size_t j = 0; j < all_work[max_index].size(); j++) {
			matrix_multiply_work &w = all_work[max_index][j];
			if (w.N <= 1) {
				continue;
			}
			// split work package between both locations
			uint64_t split_size = (w.N * w.N) / 2;
			uint64_t work_difference = (max_work - split_size)
					- (min_work + split_size);
			if (work_difference < smallest_work_difference) {
				smallest_work_difference = work_difference;
				work_to_balance_index = j;
			}
		}

		// no work found
		if (work_to_balance_index == all_work[max_index].size()) {
			break;
		}

		matrix_multiply_work w = all_work[max_index][work_to_balance_index];
		all_work[max_index].erase(
				all_work[max_index].begin() + work_to_balance_index);

		size_t n_new = w.N / 2;
		std::vector<std::tuple<size_t, size_t>> offsets = { { 0, 0 }, { 0
				+ n_new, 0 }, { 0, 0 + n_new }, { 0 + n_new, 0 + n_new } };

		all_work[max_index].emplace_back(w.x + std::get<0>(offsets[0]),
				w.y + std::get<1>(offsets[0]), n_new);
		all_work[max_index].emplace_back(w.x + std::get<0>(offsets[1]),
				w.y + std::get<1>(offsets[1]), n_new);

		all_work[min_index].emplace_back(w.x + std::get<0>(offsets[2]),
				w.y + std::get<1>(offsets[2]), n_new);
		all_work[min_index].emplace_back(w.x + std::get<0>(offsets[3]),
				w.y + std::get<1>(offsets[3]), n_new);

		total_work[max_index] -= 2 * n_new * n_new;
		total_work[min_index] += 2 * n_new * n_new;
	}

	return all_work;
}

std::vector<double> matrix_multiply_static_improved::matrix_multiply() {
	hpx::cout << "using pseudodynamic distributed algorithm" << std::endl
			<< hpx::flush;
	size_t num_localities = hpx::get_num_localities().get();
	std::vector<hpx::id_type> all_ids = hpx::find_all_localities();
	hpx::default_distribution_policy policy = hpx::default_layout(all_ids);

// one multiplier per node, to avoid additional copies of A and B
	std::vector<hpx::components::client<matrix_multiply_multiplier>> multipliers =
			hpx::new_<hpx::components::client<matrix_multiply_multiplier>[]>(
					policy, num_localities, N, A, B, verbose).get();

// colocated
	for (hpx::components::client<matrix_multiply_multiplier> &multiplier : multipliers) {
		uint32_t comp_locality = hpx::naming::get_locality_id_from_id(
				multiplier.get_id());
		multiplier.register_as("/multiplier#" + std::to_string(comp_locality));
	}

	std::vector<hpx::future<void>> futures;

	std::vector<hpx::components::client<matrix_multiply_recursive>> recursives;

	std::vector<std::vector<matrix_multiply_work>> test1 =
			this->create_schedule(5);

	std::vector<std::vector<matrix_multiply_work>> all_work =
			this->create_schedule(num_localities);

	if (verbose >= 1) {
		this->print_schedule(all_work);
	}

	for (size_t i = 0; i < all_work.size(); i++) {
		// transmit the work to the processing locality
		for (matrix_multiply_work &w : all_work[i]) {
			hpx::components::client<matrix_multiply_recursive> recursive =
					hpx::new_<hpx::components::client<matrix_multiply_recursive>>(
							hpx::find_here(), small_block_size, verbose);
			hpx::future<std::vector<double>> f = hpx::async<
					matrix_multiply_recursive::distribute_recursively_action>(
					recursive.get_id(), w.x, w.y, w.N);
			hpx::future<void> g = f.then(
					hpx::util::unwrapped([=](std::vector<double> submatrix)
					{
						this->insert_submatrix(submatrix, w);
					}));
			futures.push_back(std::move(g));
			recursives.push_back(std::move(recursive));
		}
	}

	hpx::wait_all(futures);
	return C;
}
<commit_msg>Pseudodynamic algorithm seems to work now<commit_after>#include "matrix_multiply_static_improved.hpp"

#include <algorithm>

#include <hpx/include/async.hpp>
#include <hpx/include/components.hpp>
#include <hpx/include/iostreams.hpp>
#include <hpx/include/lcos.hpp>

#include "matrix_multiply_recursive.hpp"
#include "matrix_multiply_multiplier.hpp"

void matrix_multiply_static_improved::print_schedule(
		std::vector<std::vector<matrix_multiply_work>> &all_work) {
	std::cout << "-----work-distribution:-----" << std::endl;
	for (size_t i = 0; i < all_work.size(); i++) {
		std::vector<matrix_multiply_work> &locality_work = all_work[i];
		std::cout << "locality: " << i << " = ";
		for (size_t j = 0; j < locality_work.size(); j++) {
			if (j > 0) {
				std::cout << ", ";
			}
			std::cout << "[" << locality_work[j].N << "]";
		}
		std::cout << std::endl;
	}
}

void matrix_multiply_static_improved::insert_submatrix(
		const std::vector<double> &submatrix, const matrix_multiply_work &w) {
	for (size_t i = 0; i < w.N; i++) {
		for (size_t j = 0; j < w.N; j++) {
			// std::cout << (w.x + i) << ", " << (w.y + j) << " val: " << submatrix[i * w.N + j] << std::endl;
			C[(w.x + i) * N + (w.y + j)] = submatrix[i * w.N + j];
		}
	}
}

bool matrix_multiply_static_improved::fulfills_constraints(
		std::vector<uint64_t> &total_work) {
	uint64_t min_work = total_work[0];
	uint64_t max_work = total_work[0];

	for (size_t i = 1; i < total_work.size(); i++) {
		if (total_work[i] < min_work) {
			min_work = total_work[i];
		}
		if (total_work[i] > max_work) {
			max_work = total_work[i];
		}
	}

	std::cout << "+++ work_difference: " << (max_work - min_work) << std::endl;

	if (max_work - min_work < max_work_difference) {
		return true;
	}
	if (min_work > 0 && max_work > 0) {
		double relative_work_difference = (static_cast<double>(max_work
				- min_work) / static_cast<double>(min_work));
		std::cout << "+++ relative_work_difference: "
			  << relative_work_difference << " bound: " << max_relative_work_difference << std::endl;
		if (relative_work_difference < max_relative_work_difference) {
			return true;
		}
	}
	return false;
}

std::vector<std::vector<matrix_multiply_work>> matrix_multiply_static_improved::create_schedule(
		size_t num_localities) {
	// one slot per locality, stores the work to do
	std::vector<std::vector<matrix_multiply_work>> all_work(num_localities);

	// map: locality -> assigned components
	std::vector<uint64_t> total_work(num_localities);

	// initially all work is placed on the first locality
	all_work[0].emplace_back(0, 0, N);
	total_work[0] = N * N;

	while (!this->fulfills_constraints(total_work)) {

		// give some work from the max element to the min element
		uint64_t max_work = total_work[0];
		// is a vector, as there could be multiple indices with max work value
		// test every of them, as some might be invalid due to no existing work packages to distribute
		std::vector<size_t> max_indices = {0};
		uint64_t min_work = total_work[0];
		size_t min_index = 0;

		for (size_t i = 1; i < num_localities; i++) {
			if (total_work[i] > max_work) {
				max_work = total_work[i];
				max_indices.clear();
				max_indices.push_back(i);
			} else if (total_work[i] == max_work) {
			  max_indices.push_back(i);
			}

			if (total_work[i] < min_work) {
				min_work = total_work[i];
				min_index = i;
			}
		}

		std::cout << "max_work: " << max_work << std::endl;
		std::cout << "min_work: " << min_work << std::endl;

		bool found = false;
		size_t valid_max_index = 0;
		size_t valid_work_to_balance_index = 0;

		// std::cout << "max_indices: ";
		// for (size_t i = 0; i < max_indices.size(); i++) {
		//   if (i > 0) {
		//     std::cout << ", ";
		//   }
		//   std::cout << max_indices[i];
		// }
		// std::cout << std::endl;

		for (size_t max_index: max_indices) {

		  // will always succeed, do not have to skip first iteration
		  size_t work_to_balance_index = all_work[max_index].size();
		  uint64_t smallest_work_difference = max_work - min_work;
		  for (size_t j = 0; j < all_work[max_index].size(); j++) {
		    matrix_multiply_work &w = all_work[max_index][j];
		    if (w.N <= this->min_work_size) {
		      continue;
		    }
		    // split work package between both locations
		    uint64_t split_size = (w.N * w.N) / 2;
		    // std::cout << "smallest_work_difference: " << smallest_work_difference << std::endl;
		    // std::cout << "split_size: " << split_size << std::endl;
		    int64_t work_difference = std::abs(static_cast<int64_t>(max_work - split_size)
						       - static_cast<int64_t>(min_work + split_size));
		    // std::cout << "work_difference: " << work_difference << std::endl;
		    if (static_cast<uint64_t>(work_difference) <= smallest_work_difference) {
		      smallest_work_difference = work_difference;
		      work_to_balance_index = j;
		    }
		  }

		  // work found -> apply
		  if (work_to_balance_index != all_work[max_index].size()) {
		    found = true;
		    valid_max_index = max_index;
		    valid_work_to_balance_index = work_to_balance_index;
		    break;
		  }
		}

		if (!found) {
		  if (verbose >= 1) {
		    std::cout << "aborted due to no valid work package to distribute found" << std::endl;
		  }
		  break;
		}

		matrix_multiply_work w = all_work[valid_max_index][valid_work_to_balance_index];
		all_work[valid_max_index].erase(
				all_work[valid_max_index].begin() + valid_work_to_balance_index);

		size_t n_new = w.N / 2;
		std::vector<std::tuple<size_t, size_t>> offsets = { { 0, 0 }, { 0
				+ n_new, 0 }, { 0, 0 + n_new }, { 0 + n_new, 0 + n_new } };

		all_work[valid_max_index].emplace_back(w.x + std::get<0>(offsets[0]),
				w.y + std::get<1>(offsets[0]), n_new);
		all_work[valid_max_index].emplace_back(w.x + std::get<0>(offsets[1]),
				w.y + std::get<1>(offsets[1]), n_new);

		all_work[min_index].emplace_back(w.x + std::get<0>(offsets[2]),
				w.y + std::get<1>(offsets[2]), n_new);
		all_work[min_index].emplace_back(w.x + std::get<0>(offsets[3]),
				w.y + std::get<1>(offsets[3]), n_new);

		total_work[valid_max_index] -= 2 * n_new * n_new;
		total_work[min_index] += 2 * n_new * n_new;
	}

	return all_work;
}

std::vector<double> matrix_multiply_static_improved::matrix_multiply() {
	hpx::cout << "using pseudodynamic distributed algorithm" << std::endl
			<< hpx::flush;
	size_t num_localities = hpx::get_num_localities().get();
	std::vector<hpx::id_type> all_ids = hpx::find_all_localities();
	hpx::default_distribution_policy policy = hpx::default_layout(all_ids);

// one multiplier per node, to avoid additional copies of A and B
	std::vector<hpx::components::client<matrix_multiply_multiplier>> multipliers =
			hpx::new_<hpx::components::client<matrix_multiply_multiplier>[]>(
					policy, num_localities, N, A, B, verbose).get();

// colocated
	for (hpx::components::client<matrix_multiply_multiplier> &multiplier : multipliers) {
		uint32_t comp_locality = hpx::naming::get_locality_id_from_id(
				multiplier.get_id());
		multiplier.register_as("/multiplier#" + std::to_string(comp_locality));
	}

	std::vector<hpx::future<void>> futures;

	std::vector<hpx::components::client<matrix_multiply_recursive>> recursives;

	std::vector<std::vector<matrix_multiply_work>> all_work =
			this->create_schedule(num_localities);

	if (verbose >= 1) {
		this->print_schedule(all_work);
	}

	for (size_t i = 0; i < all_work.size(); i++) {
	  // transmit the work to the processing locality
	  for (matrix_multiply_work &w : all_work[i]) {
	    hpx::components::client<matrix_multiply_recursive> recursive =
	      hpx::new_<hpx::components::client<matrix_multiply_recursive>>(
									    all_ids[i], small_block_size, verbose);
	    hpx::future<std::vector<double>> f = hpx::async<
	      matrix_multiply_recursive::distribute_recursively_action>(
									recursive.get_id(), w.x, w.y, w.N);
	    hpx::future<void> g = f.then(
					 hpx::util::unwrapped([=](std::vector<double> submatrix)
							      {
								this->insert_submatrix(submatrix, w);
							      }));
	    futures.push_back(std::move(g));
	    recursives.push_back(std::move(recursive));
	  }
	}

	hpx::wait_all(futures);
	return C;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <class T>
struct Node
{
	T data;
	Node<T>* left;
	Node<T>* right;
};

template <class T>
class BinaryTree
{
private:
	Node<T> *root;
	uint16_t CountElements = 0;
public:
	BinaryTree();
	~BinaryTree();
	void deleteNode(Node<T>* temp);
	void insert_node(const T&);
	void print()const;
	Node<T>*root_();
	Node<T> *find_node(const T&, Node<T>*)const;
	void reading(const std::string&);
	void output(std::ostream&,const Node<T>*);
	void writing(const std::string&)const;
	bool search_result(const T& value)const;
	Node<T>* get_pointer(const T& value, Node<T>* temp)const;
	friend std::ostream& show(std::ostream&, Node<T>*, unsigned int);
	friend std::ostream& operator<<(ostream&, BinaryTree<T>&);

};

template<typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
Node<T> *BinaryTree<T>::get_pointer(const T& value, Node<T>* temp)const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return get_pointer(value, temp->right);
	else return get_pointer(value, temp->left);
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template<typename T>
bool BinaryTree<T>::search_result(const T& value)const
{
	return get_pointer(value, root);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
		return;
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void output(std::ostream& ost,const Node<T>* temp)
{
	if (temp == nullptr)
	{
		return;
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::reading(const std::string& filename)
{
	ifstream fin(filename);
	if (root != nullptr)
		deleteNode(root);

	int k;
	fin >> k;
	T temp;
	for (int i = 0; i < k; ++i)
	{
		fin >> temp;
		insert_node(temp);
	}
	fin.close();
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
std::ostream& show(std::ostream& ost, Node<T>* temp, unsigned int level)
{
	show(ost, temp->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
	ost << "\t";
	ost << temp->data << std::endl;
	show(ost, temp->left, level + 1);
	return ost;
}

template<typename T>
std::ostream& operator<<(ostream& ost, BinaryTree<T>& temp)
{
	show(ost, temp.root, 0);
	return ost;
}
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <class T>
struct Node
{
	T data;
	Node<T>* left;
	Node<T>* right;
};

template <class T>
class BinaryTree
{
private:
	Node<T> *root;
	uint16_t CountElements = 0;
public:
	BinaryTree();
	~BinaryTree();
	void deleteNode(Node<T>* temp);
	void insert_node(const T&);
	void print()const;
	Node<T>*root_();
	Node<T> *find_node(const T&, Node<T>*)const;
	void reading(const std::string&);
	void output(std::ostream&,const Node<T>*);
	void writing(const std::string&)const;
	bool search_result(const T& value)const;
	Node<T>* get_pointer(const T& value, Node<T>* temp)const;
	friend std::ostream& show(std::ostream&, Node<T>*, unsigned int);
	friend std::ostream& operator<< <>(ostream&, BinaryTree<T>&);

};

template<typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
Node<T> *BinaryTree<T>::get_pointer(const T& value, Node<T>* temp)const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return get_pointer(value, temp->right);
	else return get_pointer(value, temp->left);
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template<typename T>
bool BinaryTree<T>::search_result(const T& value)const
{
	return get_pointer(value, root);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
		return;
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void output(std::ostream& ost,const Node<T>* temp)
{
	if (temp == nullptr)
	{
		return;
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::reading(const std::string& filename)
{
	ifstream fin(filename);
	if (root != nullptr)
		deleteNode(root);

	int k;
	fin >> k;
	T temp;
	for (int i = 0; i < k; ++i)
	{
		fin >> temp;
		insert_node(temp);
	}
	fin.close();
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
std::ostream& show(std::ostream& ost, Node<T>* temp, unsigned int level)
{
	show(ost, temp->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
	ost << "\t";
	ost << temp->data << std::endl;
	show(ost, temp->left, level + 1);
	return ost;
}

template<typename T>
std::ostream& operator<<(ostream& ost, BinaryTree<T>& temp)
{
	show(ost, temp.root, 0);
	return ost;
}
<|endoftext|>


<commit_before>#include "AliBaseMCTrackDensity.h"
#include "AliForwardFlowWeights.h"
#include <AliMCEvent.h>
#include <AliTrackReference.h>
#include <AliStack.h>
#include <TMath.h>
#include <AliLog.h>
#include <TH2D.h>
#include <TH1D.h>
#include <TList.h>
#include <TROOT.h>
#include <iostream>
#include "AliCollisionGeometry.h"
#include "AliGenEventHeader.h"
#include "AliForwardUtil.h"
#include <TF1.h>
#include <TGraph.h>

//____________________________________________________________________
AliBaseMCTrackDensity::AliBaseMCTrackDensity()
  : TNamed(),
    fUseOnlyPrimary(false),
    fBinFlow(0),
    fEtaBinFlow(0),
    fPhiBinFlow(0),
    fNRefs(0),
    fWeights(0),
    fTruthWeights(0),
    fVz(0),
    fB(0),
    fPhiR(0),
    fDebug(false),
    fTrackGammaToPi0(false)
{
  // Default constructor
  DGUARD(fDebug, 3,"Default CTOR of AliBasMCTrackDensity");
}

//____________________________________________________________________
AliBaseMCTrackDensity::AliBaseMCTrackDensity(const char* name)
  : TNamed(name,"mcTrackDensity"),
    fUseOnlyPrimary(false),
    fBinFlow(0),
    fEtaBinFlow(0),
    fPhiBinFlow(0),
    fNRefs(0),
    fWeights(0),
    fTruthWeights(0),
    fVz(0),
    fB(0),
    fPhiR(0),
    fDebug(false),
    fTrackGammaToPi0(false)
{
  // Normal constructor constructor
  DGUARD(fDebug, 3,"Named CTOR of AliBasMCTrackDensity: %s", name);
}

//____________________________________________________________________
AliBaseMCTrackDensity::AliBaseMCTrackDensity(const AliBaseMCTrackDensity& o)
  : TNamed(o),
    fUseOnlyPrimary(o.fUseOnlyPrimary),
    fBinFlow(o.fBinFlow),
    fEtaBinFlow(o.fEtaBinFlow),
    fPhiBinFlow(o.fPhiBinFlow),
    fNRefs(o.fNRefs),
    fWeights(o.fWeights),
    fTruthWeights(o.fTruthWeights),
    fVz(o.fVz),
    fB(o.fB),
    fPhiR(o.fPhiR),
    fDebug(o.fDebug),
    fTrackGammaToPi0(o.fTrackGammaToPi0)
{
  // Normal constructor constructor
  DGUARD(fDebug, 3,"Copy CTOR of AliBasMCTrackDensity");
}

//____________________________________________________________________
AliBaseMCTrackDensity&
AliBaseMCTrackDensity::operator=(const AliBaseMCTrackDensity& o)
{
  // Assignment operator
  DGUARD(fDebug,3,"MC track density assignmetn");
  if (&o == this) return *this;
  TNamed::operator=(o);
  fUseOnlyPrimary       = o.fUseOnlyPrimary;
  fBinFlow              = o.fBinFlow;
  fEtaBinFlow           = o.fEtaBinFlow;
  fPhiBinFlow           = o.fPhiBinFlow;
  fNRefs                = o.fNRefs;
  fDebug                = o.fDebug;
  fWeights              = o.fWeights;
  fTruthWeights         = o.fTruthWeights;
  fVz                   = o.fVz;
  fB                    = o.fB;
  fPhiR                 = o.fPhiR;
  fTrackGammaToPi0      = o.fTrackGammaToPi0;
  return *this;
}

//____________________________________________________________________
void
AliBaseMCTrackDensity::SetWeights(AliBaseMCWeights* w)
{
  if (fWeights) {
    delete fWeights;
    fWeights = 0;
  }
  fWeights = w;
}
//____________________________________________________________________
void
AliBaseMCTrackDensity::SetTruthWeights(AliBaseMCWeights* w)
{
  if (fTruthWeights) {
    delete fTruthWeights;
    fTruthWeights = 0;
  }
  fTruthWeights = w;
}
//____________________________________________________________________
void
AliBaseMCTrackDensity::SetUseFlowWeights(Bool_t use)
{
  if (!use) return;

  SetWeights(new AliForwardFlowWeights());
}
//____________________________________________________________________
void
AliBaseMCTrackDensity::CreateOutputObjects(TList* l)
{
  DGUARD(fDebug,1,"MC track defines output");
  TList* ll = new TList;
  ll->SetName(GetTitle());
  ll->SetOwner();
  l->Add(ll);

  fBinFlow = new TH2D("binFlow", "#eta and #varphi bin flow",
		      200, -5, 5, 40, -180, 180);
  fBinFlow->SetXTitle("#Delta#eta");
  fBinFlow->SetYTitle("#Delta#varphi");
  fBinFlow->SetOption("colz");
  fBinFlow->SetDirectory(0);
  ll->Add(fBinFlow);

  fEtaBinFlow = new TH2D("binFlowEta", "#eta bin flow vs #eta",
			 200, -4, 6, 200, -5, 5);
  fEtaBinFlow->SetXTitle("#eta");
  fEtaBinFlow->SetYTitle("#Delta#eta");
  fEtaBinFlow->SetOption("colz");
  fEtaBinFlow->SetDirectory(0);
  ll->Add(fEtaBinFlow);

  fPhiBinFlow = new TH2D("binFlowPhi", "#phi bin flow vs #phi",
			 40, 0, 360, 40, -180, 180);
  fPhiBinFlow->SetXTitle("#varphi");
  fPhiBinFlow->SetYTitle("#Delta#varphi");
  fPhiBinFlow->SetOption("colz");
  fPhiBinFlow->SetDirectory(0);
  ll->Add(fPhiBinFlow);

  fNRefs = new TH1D("nRefs", "# references per track", 21, -.5, 20.5);
  fNRefs->SetXTitle("# references");
  fNRefs->SetFillColor(kMagenta+1);
  fNRefs->SetFillStyle(3001);
  fNRefs->SetDirectory(0);
  ll->Add(fNRefs);

  if(fWeights)  fWeights->Init(ll);
}

//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::StoreParticle(AliMCParticle*       particle,
				     const AliMCParticle* mother,
				     AliTrackReference*   ref) const
{
  // Store this particle
  //
  // Note: If particle refers to a primary, then particle and mother
  // refers to the same particle (the address are the same)
  //
  DGUARD(fDebug,3,"MC track density store particle");
  // Store a particle.
  if (!ref) return 0;

  Double_t weight = 1;
  if (fWeights)
    weight = CalculateWeight(mother, (mother == particle));

  // Get track-reference stuff
  Double_t x      = ref->X();
  Double_t y      = ref->Y();
  Double_t z      = ref->Z()-fVz;
  Double_t rr     = TMath::Sqrt(x*x+y*y);
  Double_t thetaR = TMath::ATan2(rr,z);
  Double_t phiR   = TMath::ATan2(y,x);
  Double_t etaR   = -TMath::Log(TMath::Tan(thetaR/2));

  // Correct angle and convert to degrees
  if (thetaR < 0) thetaR += 2*TMath::Pi();
  thetaR *= 180. / TMath::Pi();
  if (phiR < 0) phiR += 2*TMath::Pi();
  phiR *= 180. / TMath::Pi();

  const AliMCParticle* mp = (mother ? mother : particle);
  Double_t dEta = mp->Eta() - etaR;
  Double_t dPhi = mp->Phi() * 180 / TMath::Pi() - phiR;
  if (dPhi >  180) dPhi -= 360;
  if (dPhi < -180) dPhi += 360;
  fBinFlow->Fill(dEta, dPhi);
  fEtaBinFlow->Fill(etaR, dEta);
  fPhiBinFlow->Fill(phiR, dPhi);
  return weight;
}

//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::GetTrackRefTheta(const AliTrackReference* ref) const
{
  // Get the incidient angle of the track reference.
  Double_t x    = ref->X();
  Double_t y    = ref->Y();
  Double_t z    = ref->Z()-fVz;
  Double_t rr   = TMath::Sqrt(x*x+y*y);
  Double_t theta= TMath::ATan2(rr,z);
  Double_t ang  = TMath::Abs(TMath::Pi()-theta);
  return ang;
}

//____________________________________________________________________
const AliMCParticle*
AliBaseMCTrackDensity::GetMother(Int_t     iTr,
				const AliMCEvent& event) const
{
  //
  // Track down primary mother
  //
  Int_t  i                       = iTr;
  Bool_t               gammaSeen = false;
  const AliMCParticle* candidate = 0;
  do {
    const AliMCParticle* p = static_cast<AliMCParticle*>(event.GetTrack(i));
    if (gammaSeen && TMath::Abs(p->PdgCode()) == 111)
      // If we're looking for a mother pi0 of gamma, and we find it
      // here, we return it - irrespective of whether it's flagged as
      // a primary or not.
      return p;

    if (const_cast<AliMCEvent&>(event).Stack()->IsPhysicalPrimary(i)) {
      if (fTrackGammaToPi0 && TMath::Abs(p->PdgCode()) == 22) {
	// If we want to track gammas back to a possible pi0, we flag
	// the gamma seen, and store it as a candidate in case we do
	// not find a pi0 in the stack
	candidate = p;
	gammaSeen = true;
      }
      else
	return p;
    }

    // We get here if the current track isn't a primary, or it was a
    // primary gamma and we want to track back to a pi0.
    i = p->GetMother();
  } while (i > 0);

  // Return our candidate (gamma) if we find no mother pi0.  Note, we
  // should never get here with a null pointer, so we issue a warning
  // in that case.
  if (!candidate)
    AliWarningF("No mother found for track # %d", iTr);
  return candidate;
}

//____________________________________________________________________
Bool_t
AliBaseMCTrackDensity::GetCollisionParameters(const AliMCEvent& event)
{
  DGUARD(fDebug,3,"MC track density get collision parameters");
  AliCollisionGeometry* hd =
    dynamic_cast<AliCollisionGeometry*>(event.GenEventHeader());
  fPhiR = (hd ? hd->ReactionPlaneAngle() : 0.);
  fB    = (hd ? hd->ImpactParameter() : -1 );
  return hd != 0;
}

//____________________________________________________________________
Bool_t
AliBaseMCTrackDensity::ProcessTrack(AliMCParticle* particle,
				    const AliMCParticle* mother)
{
  // Check the returned particle
  //
  // Note: If particle refers to a primary, then particle and mother
  // refers to the same particle (the address are the same)
  //
  DGUARD(fDebug,3,"MC track density Process a track");
  if (!particle) return false;

  Int_t              nTrRef = particle->GetNumberOfTrackReferences();
  AliTrackReference* store  = 0;

  BeginTrackRefs();

  // Double_t oTheta= 0;
  Int_t nRefs = 0;
  for (Int_t iTrRef = 0; iTrRef < nTrRef; iTrRef++) {
    AliTrackReference* ref = particle->GetTrackReference(iTrRef);

    // Check existence
    if (!ref) continue;

    // Check that we hit an Base element
    if (ref->DetectorId() != GetDetectorId()) continue;
    if (!CheckTrackRef(ref)) continue;

    nRefs++;

    AliTrackReference* test = ProcessRef(particle, mother, ref);
    if (test) store = test;

  } // Loop over track references
  if (!store) return true; // Nothing found

  StoreParticle(particle, mother, store);

  fNRefs->Fill(nRefs);

  EndTrackRefs(nRefs);

  return true;
}

//____________________________________________________________________
Bool_t
AliBaseMCTrackDensity::ProcessTracks(const AliMCEvent& event,
				     Double_t          vz,
				     TH2D*             primary)
{
  //
  // Filter the input kinematics and track references, using
  // some of the ESD information
  //
  // Parameters:
  //    input   Input ESD event
  //    event   Input MC event
  //    vz      Vertex position
  //    output  Output ESD-like object
  //    primary Per-event histogram of primaries
  //
  // Return:
  //    True on succes, false otherwise
  //
  DGUARD(fDebug,3,"MC track density Process a tracks");
  fVz = vz;
  GetCollisionParameters(event);

  AliStack* stack = const_cast<AliMCEvent&>(event).Stack();
  Int_t nTracks   = stack->GetNtrack();//event.GetNumberOfTracks();
  Int_t nPrim     = stack->GetNprimary();//event.GetNumberOfPrimary();
  for (Int_t iTr = 0; iTr < nTracks; iTr++) {
    AliMCParticle* particle =
      static_cast<AliMCParticle*>(event.GetTrack(iTr));

    // Check if this charged and a primary
    if (!particle->Charge() != 0) continue;

    Bool_t isPrimary = stack->IsPhysicalPrimary(iTr) && iTr < nPrim;

    // Fill 'dn/deta' histogram
    if (isPrimary && primary) {
      Double_t w = 1;
      if (fTruthWeights) w = CalculateTruthWeight(particle);
      primary->Fill(particle->Eta(), particle->Phi(), w);
    }

    // Bail out if we're only processing primaries - perhaps we should
    // track back to the original primary?
    if (fUseOnlyPrimary && !isPrimary) continue;

    const AliMCParticle* mother = isPrimary ? particle : GetMother(iTr, event);
    // IF the track corresponds to a primary, pass that as both
    // arguments.
    ProcessTrack(particle, mother);

  } // Loop over tracks
  return kTRUE;
}

//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::CalculateWeight(const AliMCParticle* p,
				       Bool_t isPrimary) const
{
  // Note, it is always the ultimate mother that is passed here.
  if (!p) return 0;
  return fWeights->CalcWeight(p, isPrimary, fPhiR, fB);
}
//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::CalculateTruthWeight(const AliMCParticle* p) const
{
  // Note, it is always the ultimate mother that is passed here.
  return fTruthWeights->CalcWeight(p, true, fPhiR, fB);
}

#define PF(N,V,...)					\
  AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
#define PFB(N,FLAG)				\
  do {									\
    AliForwardUtil::PrintName(N);					\
    std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
  } while(false)
#define PFV(N,VALUE)					\
  do {							\
    AliForwardUtil::PrintName(N);			\
    std::cout << (VALUE) << std::endl; } while(false)

//____________________________________________________________________
void
AliBaseMCTrackDensity::Print(Option_t* option) const
{
  AliForwardUtil::PrintTask(*this);
  gROOT->IncreaseDirLevel();
  PFB("Only primary tracks", fUseOnlyPrimary);
  PFB("Use weights", fWeights);
  if (fWeights) fWeights->Print(option);
  gROOT->DecreaseDirLevel();
}

//____________________________________________________________________
//
// EOF
//
<commit_msg>ALIROOT-6011 Additional protection<commit_after>#include "AliBaseMCTrackDensity.h"
#include "AliForwardFlowWeights.h"
#include <AliMCEvent.h>
#include <AliTrackReference.h>
#include <AliStack.h>
#include <TMath.h>
#include <AliLog.h>
#include <TH2D.h>
#include <TH1D.h>
#include <TList.h>
#include <TROOT.h>
#include <iostream>
#include "AliCollisionGeometry.h"
#include "AliGenEventHeader.h"
#include "AliForwardUtil.h"
#include <TF1.h>
#include <TGraph.h>

//____________________________________________________________________
AliBaseMCTrackDensity::AliBaseMCTrackDensity()
  : TNamed(),
    fUseOnlyPrimary(false),
    fBinFlow(0),
    fEtaBinFlow(0),
    fPhiBinFlow(0),
    fNRefs(0),
    fWeights(0),
    fTruthWeights(0),
    fVz(0),
    fB(0),
    fPhiR(0),
    fDebug(false),
    fTrackGammaToPi0(false)
{
  // Default constructor
  DGUARD(fDebug, 3,"Default CTOR of AliBasMCTrackDensity");
}

//____________________________________________________________________
AliBaseMCTrackDensity::AliBaseMCTrackDensity(const char* name)
  : TNamed(name,"mcTrackDensity"),
    fUseOnlyPrimary(false),
    fBinFlow(0),
    fEtaBinFlow(0),
    fPhiBinFlow(0),
    fNRefs(0),
    fWeights(0),
    fTruthWeights(0),
    fVz(0),
    fB(0),
    fPhiR(0),
    fDebug(false),
    fTrackGammaToPi0(false)
{
  // Normal constructor constructor
  DGUARD(fDebug, 3,"Named CTOR of AliBasMCTrackDensity: %s", name);
}

//____________________________________________________________________
AliBaseMCTrackDensity::AliBaseMCTrackDensity(const AliBaseMCTrackDensity& o)
  : TNamed(o),
    fUseOnlyPrimary(o.fUseOnlyPrimary),
    fBinFlow(o.fBinFlow),
    fEtaBinFlow(o.fEtaBinFlow),
    fPhiBinFlow(o.fPhiBinFlow),
    fNRefs(o.fNRefs),
    fWeights(o.fWeights),
    fTruthWeights(o.fTruthWeights),
    fVz(o.fVz),
    fB(o.fB),
    fPhiR(o.fPhiR),
    fDebug(o.fDebug),
    fTrackGammaToPi0(o.fTrackGammaToPi0)
{
  // Normal constructor constructor
  DGUARD(fDebug, 3,"Copy CTOR of AliBasMCTrackDensity");
}

//____________________________________________________________________
AliBaseMCTrackDensity&
AliBaseMCTrackDensity::operator=(const AliBaseMCTrackDensity& o)
{
  // Assignment operator
  DGUARD(fDebug,3,"MC track density assignmetn");
  if (&o == this) return *this;
  TNamed::operator=(o);
  fUseOnlyPrimary       = o.fUseOnlyPrimary;
  fBinFlow              = o.fBinFlow;
  fEtaBinFlow           = o.fEtaBinFlow;
  fPhiBinFlow           = o.fPhiBinFlow;
  fNRefs                = o.fNRefs;
  fDebug                = o.fDebug;
  fWeights              = o.fWeights;
  fTruthWeights         = o.fTruthWeights;
  fVz                   = o.fVz;
  fB                    = o.fB;
  fPhiR                 = o.fPhiR;
  fTrackGammaToPi0      = o.fTrackGammaToPi0;
  return *this;
}

//____________________________________________________________________
void
AliBaseMCTrackDensity::SetWeights(AliBaseMCWeights* w)
{
  if (fWeights) {
    delete fWeights;
    fWeights = 0;
  }
  fWeights = w;
}
//____________________________________________________________________
void
AliBaseMCTrackDensity::SetTruthWeights(AliBaseMCWeights* w)
{
  if (fTruthWeights) {
    delete fTruthWeights;
    fTruthWeights = 0;
  }
  fTruthWeights = w;
}
//____________________________________________________________________
void
AliBaseMCTrackDensity::SetUseFlowWeights(Bool_t use)
{
  if (!use) return;

  SetWeights(new AliForwardFlowWeights());
}
//____________________________________________________________________
void
AliBaseMCTrackDensity::CreateOutputObjects(TList* l)
{
  DGUARD(fDebug,1,"MC track defines output");
  TList* ll = new TList;
  ll->SetName(GetTitle());
  ll->SetOwner();
  l->Add(ll);

  fBinFlow = new TH2D("binFlow", "#eta and #varphi bin flow",
		      200, -5, 5, 40, -180, 180);
  fBinFlow->SetXTitle("#Delta#eta");
  fBinFlow->SetYTitle("#Delta#varphi");
  fBinFlow->SetOption("colz");
  fBinFlow->SetDirectory(0);
  ll->Add(fBinFlow);

  fEtaBinFlow = new TH2D("binFlowEta", "#eta bin flow vs #eta",
			 200, -4, 6, 200, -5, 5);
  fEtaBinFlow->SetXTitle("#eta");
  fEtaBinFlow->SetYTitle("#Delta#eta");
  fEtaBinFlow->SetOption("colz");
  fEtaBinFlow->SetDirectory(0);
  ll->Add(fEtaBinFlow);

  fPhiBinFlow = new TH2D("binFlowPhi", "#phi bin flow vs #phi",
			 40, 0, 360, 40, -180, 180);
  fPhiBinFlow->SetXTitle("#varphi");
  fPhiBinFlow->SetYTitle("#Delta#varphi");
  fPhiBinFlow->SetOption("colz");
  fPhiBinFlow->SetDirectory(0);
  ll->Add(fPhiBinFlow);

  fNRefs = new TH1D("nRefs", "# references per track", 21, -.5, 20.5);
  fNRefs->SetXTitle("# references");
  fNRefs->SetFillColor(kMagenta+1);
  fNRefs->SetFillStyle(3001);
  fNRefs->SetDirectory(0);
  ll->Add(fNRefs);

  if(fWeights)  fWeights->Init(ll);
}

//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::StoreParticle(AliMCParticle*       particle,
				     const AliMCParticle* mother,
				     AliTrackReference*   ref) const
{
  // Store this particle
  //
  // Note: If particle refers to a primary, then particle and mother
  // refers to the same particle (the address are the same)
  //
  DGUARD(fDebug,3,"MC track density store particle");
  // Store a particle.
  if (!ref) return 0;

  Double_t weight = 1;
  if (fWeights)
    weight = CalculateWeight(mother, (mother == particle));

  // Get track-reference stuff
  Double_t x      = ref->X();
  Double_t y      = ref->Y();
  Double_t z      = ref->Z()-fVz;
  Double_t rr     = TMath::Sqrt(x*x+y*y);
  Double_t thetaR = TMath::ATan2(rr,z);
  Double_t phiR   = TMath::ATan2(y,x);
  Double_t etaR   = -TMath::Log(TMath::Tan(thetaR/2));

  // Correct angle and convert to degrees
  if (thetaR < 0) thetaR += 2*TMath::Pi();
  thetaR *= 180. / TMath::Pi();
  if (phiR < 0) phiR += 2*TMath::Pi();
  phiR *= 180. / TMath::Pi();

  const AliMCParticle* mp = (mother ? mother : particle);
  Double_t dEta = mp->Eta() - etaR;
  Double_t dPhi = mp->Phi() * 180 / TMath::Pi() - phiR;
  if (dPhi >  180) dPhi -= 360;
  if (dPhi < -180) dPhi += 360;
  fBinFlow->Fill(dEta, dPhi);
  fEtaBinFlow->Fill(etaR, dEta);
  fPhiBinFlow->Fill(phiR, dPhi);
  return weight;
}

//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::GetTrackRefTheta(const AliTrackReference* ref) const
{
  // Get the incidient angle of the track reference.
  Double_t x    = ref->X();
  Double_t y    = ref->Y();
  Double_t z    = ref->Z()-fVz;
  Double_t rr   = TMath::Sqrt(x*x+y*y);
  Double_t theta= TMath::ATan2(rr,z);
  Double_t ang  = TMath::Abs(TMath::Pi()-theta);
  return ang;
}

//____________________________________________________________________
const AliMCParticle*
AliBaseMCTrackDensity::GetMother(Int_t     iTr,
				const AliMCEvent& event) const
{
  //
  // Track down primary mother
  //
  Int_t  i                       = iTr;
  Bool_t               gammaSeen = false;
  const AliMCParticle* candidate = 0;
  do {
    const AliMCParticle* p = static_cast<AliMCParticle*>(event.GetTrack(i));
    if (gammaSeen && TMath::Abs(p->PdgCode()) == 111)
      // If we're looking for a mother pi0 of gamma, and we find it
      // here, we return it - irrespective of whether it's flagged as
      // a primary or not.
      return p;

    if (const_cast<AliMCEvent&>(event).Stack()->IsPhysicalPrimary(i)) {
      if (fTrackGammaToPi0 && TMath::Abs(p->PdgCode()) == 22) {
	// If we want to track gammas back to a possible pi0, we flag
	// the gamma seen, and store it as a candidate in case we do
	// not find a pi0 in the stack
	candidate = p;
	gammaSeen = true;
      }
      else
	return p;
    }

    // We get here if the current track isn't a primary, or it was a
    // primary gamma and we want to track back to a pi0.
    i = p->GetMother();
  } while (i > 0);

  // Return our candidate (gamma) if we find no mother pi0.  Note, we
  // should never get here with a null pointer, so we issue a warning
  // in that case.
  if (!candidate)
    AliWarningF("No mother found for track # %d", iTr);
  return candidate;
}

//____________________________________________________________________
Bool_t
AliBaseMCTrackDensity::GetCollisionParameters(const AliMCEvent& event)
{
  DGUARD(fDebug,3,"MC track density get collision parameters");
  AliCollisionGeometry* hd =
    dynamic_cast<AliCollisionGeometry*>(event.GenEventHeader());
  fPhiR = (hd ? hd->ReactionPlaneAngle() : 0.);
  fB    = (hd ? hd->ImpactParameter() : -1 );
  return hd != 0;
}

//____________________________________________________________________
Bool_t
AliBaseMCTrackDensity::ProcessTrack(AliMCParticle* particle,
				    const AliMCParticle* mother)
{
  // Check the returned particle
  //
  // Note: If particle refers to a primary, then particle and mother
  // refers to the same particle (the address are the same)
  //
  DGUARD(fDebug,3,"MC track density Process a track");
  if (!particle) return false;

  Int_t              nTrRef = particle->GetNumberOfTrackReferences();
  AliTrackReference* store  = 0;

  BeginTrackRefs();

  // Double_t oTheta= 0;
  Int_t nRefs = 0;
  for (Int_t iTrRef = 0; iTrRef < nTrRef; iTrRef++) {
    AliTrackReference* ref = particle->GetTrackReference(iTrRef);

    // Check existence
    if (!ref) continue;

    // Check that we hit an Base element
    if (ref->DetectorId() != GetDetectorId()) continue;
    if (!CheckTrackRef(ref)) continue;

    nRefs++;

    AliTrackReference* test = ProcessRef(particle, mother, ref);
    if (test) store = test;

  } // Loop over track references
  if (!store) return true; // Nothing found

  StoreParticle(particle, mother, store);

  fNRefs->Fill(nRefs);

  EndTrackRefs(nRefs);

  return true;
}

//____________________________________________________________________
Bool_t
AliBaseMCTrackDensity::ProcessTracks(const AliMCEvent& event,
				     Double_t          vz,
				     TH2D*             primary)
{
  //
  // Filter the input kinematics and track references, using
  // some of the ESD information
  //
  // Parameters:
  //    input   Input ESD event
  //    event   Input MC event
  //    vz      Vertex position
  //    output  Output ESD-like object
  //    primary Per-event histogram of primaries
  //
  // Return:
  //    True on succes, false otherwise
  //
  DGUARD(fDebug,3,"MC track density Process a tracks");
  fVz = vz;
  GetCollisionParameters(event);

  AliStack* stack = const_cast<AliMCEvent&>(event).Stack();
  if (!stack) return kFALSE;

  Int_t nTracks   = stack->GetNtrack();//event.GetNumberOfTracks();
  Int_t nPrim     = stack->GetNprimary();//event.GetNumberOfPrimary();
  for (Int_t iTr = 0; iTr < nTracks; iTr++) {
    AliMCParticle* particle =
      static_cast<AliMCParticle*>(event.GetTrack(iTr));

    // Check if this charged and a primary
    if (!particle->Charge() != 0) continue;

    Bool_t isPrimary = stack->IsPhysicalPrimary(iTr) && iTr < nPrim;

    // Fill 'dn/deta' histogram
    if (isPrimary && primary) {
      Double_t w = 1;
      if (fTruthWeights) w = CalculateTruthWeight(particle);
      primary->Fill(particle->Eta(), particle->Phi(), w);
    }

    // Bail out if we're only processing primaries - perhaps we should
    // track back to the original primary?
    if (fUseOnlyPrimary && !isPrimary) continue;

    const AliMCParticle* mother = isPrimary ? particle : GetMother(iTr, event);
    // IF the track corresponds to a primary, pass that as both
    // arguments.
    ProcessTrack(particle, mother);

  } // Loop over tracks
  return kTRUE;
}

//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::CalculateWeight(const AliMCParticle* p,
				       Bool_t isPrimary) const
{
  // Note, it is always the ultimate mother that is passed here.
  if (!p) return 0;
  return fWeights->CalcWeight(p, isPrimary, fPhiR, fB);
}
//____________________________________________________________________
Double_t
AliBaseMCTrackDensity::CalculateTruthWeight(const AliMCParticle* p) const
{
  // Note, it is always the ultimate mother that is passed here.
  return fTruthWeights->CalcWeight(p, true, fPhiR, fB);
}

#define PF(N,V,...)					\
  AliForwardUtil::PrintField(N,V, ## __VA_ARGS__)
#define PFB(N,FLAG)				\
  do {									\
    AliForwardUtil::PrintName(N);					\
    std::cout << std::boolalpha << (FLAG) << std::noboolalpha << std::endl; \
  } while(false)
#define PFV(N,VALUE)					\
  do {							\
    AliForwardUtil::PrintName(N);			\
    std::cout << (VALUE) << std::endl; } while(false)

//____________________________________________________________________
void
AliBaseMCTrackDensity::Print(Option_t* option) const
{
  AliForwardUtil::PrintTask(*this);
  gROOT->IncreaseDirLevel();
  PFB("Only primary tracks", fUseOnlyPrimary);
  PFB("Use weights", fWeights);
  if (fWeights) fWeights->Print(option);
  gROOT->DecreaseDirLevel();
}

//____________________________________________________________________
//
// EOF
//
<|endoftext|>