<commit_before>void build(Solution &s)
{
    auto &tess = s.addProject("google.tesseract", "master");
    tess += Git("https://github.com/tesseract-ocr/tesseract", "", "{v}");

    auto &libtesseract = tess.addTarget<LibraryTarget>("libtesseract");
    {
        libtesseract.setChecks("libtesseract");

        libtesseract.ExportAllSymbols = true;
        libtesseract.PackageDefinitions = true;

        libtesseract -= "src/lstm/.*\\.cc"_rr;
        libtesseract -= "src/training/.*"_rr;

        libtesseract -=
            "src/api/tesseractmain.cpp",
            "src/viewer/svpaint.cpp";

        libtesseract.Public += "include"_idir;
        libtesseract.Protected +=
            "src/opencl"_id,
            "src/ccmain"_id,
            "src/api"_id,
            "src/dict"_id,
            "src/viewer"_id,
            "src/wordrec"_id,
            "src/ccstruct"_id,
            "src/cutil"_id,
            "src/textord"_id,
            "src/ccutil"_id,
            "src/lstm"_id,
            "src/classify"_id,
            "src/arch"_id,
            "src/training"_id;

        if (libtesseract.getCompilerType() == CompilerType::MSVC ||
            libtesseract.getCompilerType() == CompilerType::ClangCl)
        {
            libtesseract += "__SSE4_1__"_def;
            libtesseract.CompileOptions.push_back("-arch:AVX2");

            libtesseract -=
                "src/arch/dotproductfma.cpp";
        }

        libtesseract.Public += "HAVE_CONFIG_H"_d;
        libtesseract.Public += "_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1"_d;
        libtesseract.Public += "HAVE_LIBARCHIVE"_d;
        libtesseract.Interface += sw::Shared, "TESS_IMPORTS"_d;
        libtesseract.Private += sw::Shared, "TESS_EXPORTS"_d;

        libtesseract.Public += "org.sw.demo.danbloomberg.leptonica"_dep;
        libtesseract.Public += "org.sw.demo.libarchive.libarchive"_dep;

        if (libtesseract.getBuildSettings().TargetOS.Type == OSType::Windows)
        {
            libtesseract.Public += "ws2_32.lib"_slib;
            libtesseract.Protected += "NOMINMAX"_def;
        }

        libtesseract.Variables["TESSERACT_MAJOR_VERSION"] = libtesseract.Variables["PACKAGE_MAJOR_VERSION"];
        libtesseract.Variables["TESSERACT_MINOR_VERSION"] = libtesseract.Variables["PACKAGE_MINOR_VERSION"];
        libtesseract.Variables["TESSERACT_MICRO_VERSION"] = libtesseract.Variables["PACKAGE_PATCH_VERSION"];
        libtesseract.Variables["TESSERACT_VERSION_STR"] = "master";
        libtesseract.configureFile("include/tesseract/version.h.in", "tesseract/version.h");
    }

    //
    auto &tesseract = tess.addExecutable("tesseract");
    tesseract += "src/api/tesseractmain.cpp";
    tesseract += libtesseract;

    //
    auto &tessopt = tess.addStaticLibrary("tessopt");
    tessopt += "src/training/tessopt.*"_rr;
    tessopt.Public += libtesseract;

    //
    auto &common_training = tess.addStaticLibrary("common_training");
    common_training +=
        "src/training/commandlineflags.cpp",
        "src/training/commandlineflags.h",
        "src/training/commontraining.cpp",
        "src/training/commontraining.h",
        "src/training/ctc.cpp",
        "src/training/ctc.h",
        "src/training/errorcounter.cpp",
        "src/training/errorcounter.h",
        "src/training/intfeaturedist.cpp",
        "src/training/intfeaturedist.h",
        "src/training/intfeaturemap.cpp",
        "src/training/intfeaturemap.h",
        "src/training/mastertrainer.cpp",
        "src/training/mastertrainer.h",
        "src/training/networkbuilder.cpp",
        "src/training/networkbuilder.h",
        "src/training/sampleiterator.cpp",
        "src/training/sampleiterator.h",
        "src/training/trainingsampleset.cpp",
        "src/training/trainingsampleset.h";
    common_training.Public += tessopt;

    //
    auto &unicharset_training = tess.addStaticLibrary("unicharset_training");
    unicharset_training +=
        "src/training/fileio.*"_rr,
        "src/training/icuerrorcode.*"_rr,
        "src/training/icuerrorcode.h",
        "src/training/lang_model_helpers.*"_rr,
        "src/training/lstmtester.*"_rr,
        "src/training/lstmtrainer.*"_rr,
        "src/training/normstrngs.*"_rr,
        "src/training/unicharset_training_utils.*"_rr,
        "src/training/validat.*"_rr;
    unicharset_training.Public += common_training;
    unicharset_training.Public += "org.sw.demo.unicode.icu.i18n"_dep;

    //
#define ADD_EXE(n, ...)               \
    auto &n = tess.addExecutable(#n); \
    n += "src/training/" #n ".*"_rr;  \
    n.Public += __VA_ARGS__;          \
    n

    ADD_EXE(ambiguous_words, libtesseract);
    ADD_EXE(classifier_tester, common_training);
    ADD_EXE(combine_lang_model, unicharset_training);
    ADD_EXE(combine_tessdata, libtesseract);
    ADD_EXE(cntraining, common_training);
    ADD_EXE(dawg2wordlist, libtesseract);
    ADD_EXE(mftraining, common_training) += "src/training/mergenf.*"_rr;
    ADD_EXE(shapeclustering, common_training);
    ADD_EXE(unicharset_extractor, unicharset_training);
    ADD_EXE(wordlist2dawg, libtesseract);
    ADD_EXE(lstmeval, unicharset_training);
    ADD_EXE(lstmtraining, unicharset_training);
    ADD_EXE(set_unicharset_properties, unicharset_training);

    ADD_EXE(text2image, unicharset_training);
    text2image +=
        "src/training/boxchar.cpp",
        "src/training/boxchar.h",
        "src/training/degradeimage.cpp",
        "src/training/degradeimage.h",
        "src/training/icuerrorcode.h",
        "src/training/ligature_table.cpp",
        "src/training/ligature_table.h",
        "src/training/normstrngs.cpp",
        "src/training/normstrngs.h",
        "src/training/pango_font_info.cpp",
        "src/training/pango_font_info.h",
        "src/training/stringrenderer.cpp",
        "src/training/stringrenderer.h",
        "src/training/text2image.cpp",
        "src/training/tlog.cpp",
        "src/training/tlog.h",
        "src/training/util.h";
    text2image.Public += "org.sw.demo.gnome.pango.pangocairo"_dep;
}

void check(Checker &c)
{
    auto &s = c.addSet("libtesseract");
    s.checkFunctionExists("getline");
    s.checkIncludeExists("dlfcn.h");
    s.checkIncludeExists("inttypes.h");
    s.checkIncludeExists("limits.h");
    s.checkIncludeExists("malloc.h");
    s.checkIncludeExists("memory.h");
    s.checkIncludeExists("stdbool.h");
    s.checkIncludeExists("stdint.h");
    s.checkIncludeExists("stdlib.h");
    s.checkIncludeExists("string.h");
    s.checkIncludeExists("sys/ipc.h");
    s.checkIncludeExists("sys/shm.h");
    s.checkIncludeExists("sys/stat.h");
    s.checkIncludeExists("sys/types.h");
    s.checkIncludeExists("sys/wait.h");
    s.checkIncludeExists("tiffio.h");
    s.checkIncludeExists("unistd.h");
    s.checkTypeSize("long long int");
    s.checkTypeSize("mbstate_t");
    s.checkTypeSize("off_t");
    s.checkTypeSize("size_t");
    s.checkTypeSize("void *");
    s.checkTypeSize("wchar_t");
    s.checkTypeSize("_Bool");
    {
        auto &c = s.checkSymbolExists("snprintf");
        c.Parameters.Includes.push_back("stdio.h");
    }
}
<commit_msg>[sw] Fix linux build.<commit_after>void build(Solution &s)
{
    auto &tess = s.addProject("google.tesseract", "master");
    tess += Git("https://github.com/tesseract-ocr/tesseract", "", "{v}");

    auto &libtesseract = tess.addTarget<LibraryTarget>("libtesseract");
    {
        libtesseract.setChecks("libtesseract");

        libtesseract.ExportAllSymbols = true;
        libtesseract.PackageDefinitions = true;

        libtesseract += "src/.*"_rr;
        libtesseract -= "src/lstm/.*\\.cc"_rr;
        libtesseract -= "src/training/.*"_rr;

        libtesseract -=
            "src/api/tesseractmain.cpp",
            "src/viewer/svpaint.cpp";

        libtesseract.Public += "include"_idir;
        libtesseract.Protected +=
            "src/opencl"_id,
            "src/ccmain"_id,
            "src/api"_id,
            "src/dict"_id,
            "src/viewer"_id,
            "src/wordrec"_id,
            "src/ccstruct"_id,
            "src/cutil"_id,
            "src/textord"_id,
            "src/ccutil"_id,
            "src/lstm"_id,
            "src/classify"_id,
            "src/arch"_id,
            "src/training"_id;

        if (libtesseract.getCompilerType() == CompilerType::MSVC ||
            libtesseract.getCompilerType() == CompilerType::ClangCl)
        {
            libtesseract += "__SSE4_1__"_def;
            libtesseract.CompileOptions.push_back("-arch:AVX2");
        }

        // check fma flags
        libtesseract -= "src/arch/dotproductfma.cpp";

        if (libtesseract.getBuildSettings().TargetOS.Type != OSType::Windows)
        {
            libtesseract["src/arch/dotproductavx.cpp"].args.push_back("-mavx");
            libtesseract["src/arch/dotproductsse.cpp"].args.push_back("-msse4.1");
            libtesseract["src/arch/intsimdmatrixsse.cpp"].args.push_back("-msse4.1");
            libtesseract["src/arch/intsimdmatrixavx2.cpp"].args.push_back("-mavx2");

            libtesseract += "pthread"_slib;
        }

        libtesseract.Public += "HAVE_CONFIG_H"_d;
        libtesseract.Public += "_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1"_d;
        libtesseract.Public += "HAVE_LIBARCHIVE"_d;
        libtesseract.Interface += sw::Shared, "TESS_IMPORTS"_d;
        libtesseract.Private += sw::Shared, "TESS_EXPORTS"_d;

        libtesseract.Public += "org.sw.demo.danbloomberg.leptonica"_dep;
        libtesseract.Public += "org.sw.demo.libarchive.libarchive"_dep;

        if (libtesseract.getBuildSettings().TargetOS.Type == OSType::Windows)
        {
            libtesseract.Public += "ws2_32.lib"_slib;
            libtesseract.Protected += "NOMINMAX"_def;
        }

        libtesseract.Variables["TESSERACT_MAJOR_VERSION"] = libtesseract.Variables["PACKAGE_MAJOR_VERSION"];
        libtesseract.Variables["TESSERACT_MINOR_VERSION"] = libtesseract.Variables["PACKAGE_MINOR_VERSION"];
        libtesseract.Variables["TESSERACT_MICRO_VERSION"] = libtesseract.Variables["PACKAGE_PATCH_VERSION"];
        libtesseract.Variables["TESSERACT_VERSION_STR"] = "master";
        libtesseract.configureFile("include/tesseract/version.h.in", "tesseract/version.h");
    }

    //
    auto &tesseract = tess.addExecutable("tesseract");
    tesseract += "src/api/tesseractmain.cpp";
    tesseract += libtesseract;

    //
    auto &tessopt = tess.addStaticLibrary("tessopt");
    tessopt += "src/training/tessopt.*"_rr;
    tessopt.Public += libtesseract;

    //
    auto &common_training = tess.addStaticLibrary("common_training");
    common_training +=
        "src/training/commandlineflags.cpp",
        "src/training/commandlineflags.h",
        "src/training/commontraining.cpp",
        "src/training/commontraining.h",
        "src/training/ctc.cpp",
        "src/training/ctc.h",
        "src/training/errorcounter.cpp",
        "src/training/errorcounter.h",
        "src/training/intfeaturedist.cpp",
        "src/training/intfeaturedist.h",
        "src/training/intfeaturemap.cpp",
        "src/training/intfeaturemap.h",
        "src/training/mastertrainer.cpp",
        "src/training/mastertrainer.h",
        "src/training/networkbuilder.cpp",
        "src/training/networkbuilder.h",
        "src/training/sampleiterator.cpp",
        "src/training/sampleiterator.h",
        "src/training/trainingsampleset.cpp",
        "src/training/trainingsampleset.h";
    common_training.Public += tessopt;

    //
    auto &unicharset_training = tess.addStaticLibrary("unicharset_training");
    unicharset_training +=
        "src/training/fileio.*"_rr,
        "src/training/icuerrorcode.*"_rr,
        "src/training/icuerrorcode.h",
        "src/training/lang_model_helpers.*"_rr,
        "src/training/lstmtester.*"_rr,
        "src/training/lstmtrainer.*"_rr,
        "src/training/normstrngs.*"_rr,
        "src/training/unicharset_training_utils.*"_rr,
        "src/training/validat.*"_rr;
    unicharset_training.Public += common_training;
    unicharset_training.Public += "org.sw.demo.unicode.icu.i18n"_dep;

    //
#define ADD_EXE(n, ...)               \
    auto &n = tess.addExecutable(#n); \
    n += "src/training/" #n ".*"_rr;  \
    n.Public += __VA_ARGS__;          \
    n

    ADD_EXE(ambiguous_words, libtesseract);
    ADD_EXE(classifier_tester, common_training);
    ADD_EXE(combine_lang_model, unicharset_training);
    ADD_EXE(combine_tessdata, libtesseract);
    ADD_EXE(cntraining, common_training);
    ADD_EXE(dawg2wordlist, libtesseract);
    ADD_EXE(mftraining, common_training) += "src/training/mergenf.*"_rr;
    ADD_EXE(shapeclustering, common_training);
    ADD_EXE(unicharset_extractor, unicharset_training);
    ADD_EXE(wordlist2dawg, libtesseract);
    ADD_EXE(lstmeval, unicharset_training);
    ADD_EXE(lstmtraining, unicharset_training);
    ADD_EXE(set_unicharset_properties, unicharset_training);

    ADD_EXE(text2image, unicharset_training);
    text2image +=
        "src/training/boxchar.cpp",
        "src/training/boxchar.h",
        "src/training/degradeimage.cpp",
        "src/training/degradeimage.h",
        "src/training/icuerrorcode.h",
        "src/training/ligature_table.cpp",
        "src/training/ligature_table.h",
        "src/training/normstrngs.cpp",
        "src/training/normstrngs.h",
        "src/training/pango_font_info.cpp",
        "src/training/pango_font_info.h",
        "src/training/stringrenderer.cpp",
        "src/training/stringrenderer.h",
        "src/training/text2image.cpp",
        "src/training/tlog.cpp",
        "src/training/tlog.h",
        "src/training/util.h";
    text2image.Public += "org.sw.demo.gnome.pango.pangocairo"_dep;
}

void check(Checker &c)
{
    auto &s = c.addSet("libtesseract");
    s.checkFunctionExists("getline");
    s.checkIncludeExists("dlfcn.h");
    s.checkIncludeExists("inttypes.h");
    s.checkIncludeExists("limits.h");
    s.checkIncludeExists("malloc.h");
    s.checkIncludeExists("memory.h");
    s.checkIncludeExists("stdbool.h");
    s.checkIncludeExists("stdint.h");
    s.checkIncludeExists("stdlib.h");
    s.checkIncludeExists("string.h");
    s.checkIncludeExists("sys/ipc.h");
    s.checkIncludeExists("sys/shm.h");
    s.checkIncludeExists("sys/stat.h");
    s.checkIncludeExists("sys/types.h");
    s.checkIncludeExists("sys/wait.h");
    s.checkIncludeExists("tiffio.h");
    s.checkIncludeExists("unistd.h");
    s.checkTypeSize("long long int");
    s.checkTypeSize("mbstate_t");
    s.checkTypeSize("off_t");
    s.checkTypeSize("size_t");
    s.checkTypeSize("void *");
    s.checkTypeSize("wchar_t");
    s.checkTypeSize("_Bool");
    {
        auto &c = s.checkSymbolExists("snprintf");
        c.Parameters.Includes.push_back("stdio.h");
    }
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of mcompositor.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
/*!
  \class MCompositeWindowAnimation
  \brief MCompositeWindowAnimation class which provides full control
  of position transformation and opacity animations of composite window objects.

  To create more complex animations, re-implement the virtual functions
  windowShown(), windowClosed(), widowIconified() and windowRestored();
  A QParallelAnimationGroup object is provided which can be a container
  for more complex animations for more flexibility.
*/
// TODO: import icongeometry. export signals when animation done to hook
// to composting on off

#include <QMetaMethod>
#include <QRectF>
#include <QDesktopWidget>
#include <QPropertyAnimation>
#include <mcompositewindow.h>
#include <mcompositewindowanimation.h>
#include <QApplication>
#include <QParallelAnimationGroup>
#include <mcompositemanager.h>
#include <mcompositemanager_p.h>
#include <QVector>

class McParallelAnimation: public QParallelAnimationGroup
{
public:
    McParallelAnimation(MCompositeWindowAnimation* p)
        :QParallelAnimationGroup(p),
         parent(p)
    {}

protected:
    virtual void updateCurrentTime(int currentTime)
    {
        MCompositeWindow::update();
        QParallelAnimationGroup::updateCurrentTime(currentTime);
    }

    virtual void updateState(QAbstractAnimation::State newState,
                             QAbstractAnimation::State oldState)
    {
        if (newState == QAbstractAnimation::Running &&
            oldState == QAbstractAnimation::Stopped) {
            parent->ensureAnimationVisible();
            if (parent->targetWindow())
                parent->targetWindow()->beginAnimation();
            if (parent->targetWindow2())
                parent->targetWindow2()->beginAnimation();
        } else if (newState == QAbstractAnimation::Stopped) {
            if (parent->targetWindow())
                parent->targetWindow()->endAnimation();
            if (parent->targetWindow2())
                parent->targetWindow2()->endAnimation();
        }
        QParallelAnimationGroup::updateState(newState, oldState);
    }
private:
    MCompositeWindowAnimation* parent;
};

class MCompositeWindowAnimationPrivate
{
public:

    MCompositeWindowAnimationPrivate(MCompositeWindowAnimation* animation)
        : crossfade(0),
          pending_animation(MCompositeWindowAnimation::NoAnimation),
          is_replaceable(true),
          animhandler(MCompositeWindowAnimation::AnimationTotal, 0)
    {
        const MCompositeManager *mc = static_cast<MCompositeManager*>(qApp);
        int duration = mc->configInt("startup-anim-duration");

        scale = new QPropertyAnimation(animation);
        scale->setPropertyName("scale");
        scale->setDuration(duration);

        position = new QPropertyAnimation(animation);
        position->setPropertyName("pos");
        position->setDuration(duration);

        opacity = new QPropertyAnimation(animation);
        opacity->setPropertyName("opacity");
        opacity->setDuration(duration);

        scalepos = new McParallelAnimation(animation);
        scalepos->addAnimation(scale);
        scalepos->addAnimation(position);
        scalepos->addAnimation(opacity);

        QObject::connect(scalepos, SIGNAL(finished()), animation,
                         SLOT(finalizeState()));
    }

    void setTargetWindow(MCompositeWindow* window)
    {
        if (scale && position && opacity) {
            scale->setTargetObject(window);
            position->setTargetObject(window);
            opacity->setTargetObject(window);
        }
    }

    bool handledByInvoker(MCompositeWindowAnimation::AnimationType type)
    {
        if (animhandler[type]) {
            switch (type) {
            case MCompositeWindowAnimation::Showing:
                animhandler[type]->windowShown();
                return true;
            case MCompositeWindowAnimation::Closing:
                animhandler[type]->windowClosed();
                return true;
            case MCompositeWindowAnimation::Iconify:
                animhandler[type]->windowIconified();
                return true;
            case MCompositeWindowAnimation::Restore:
                animhandler[type]->windowRestored();
                return true;
            default:
                break;
            }
        }

        return false;
    }

    QPointer<MCompositeWindow> target_window, target_window2;
    QPointer<QPropertyAnimation> scale;
    QPointer<QPropertyAnimation> position;
    QPointer<QPropertyAnimation> opacity;
    McParallelAnimation* scalepos, *crossfade;
    MCompositeWindowAnimation::AnimationType pending_animation;
    bool is_replaceable;
    QVector< MAbstractAnimationHandler* > animhandler;
};

MCompositeWindowAnimation::MCompositeWindowAnimation(QObject* parent)
    :QObject(parent),
     d_ptr(new MCompositeWindowAnimationPrivate(this))
{
}

MCompositeWindowAnimation::~MCompositeWindowAnimation()
{
}

void MCompositeWindowAnimation::setTargetWindow(MCompositeWindow* window)
{
    Q_D(MCompositeWindowAnimation);

    // never override a non-replaceable animation
    if (window->animator && !window->animator->isReplaceable()) {
        deleteLater();
        return;
    }

    // replace the old animator if there is one
    if (window->animator && (window->animator != this))
        delete window->animator;

    d->target_window = window;
    d->target_window->animator = this;
    disconnect(SIGNAL(q_finalizeState()));
    connect(this, SIGNAL(q_finalizeState()), window, SLOT(finalizeState()));

    d->setTargetWindow(window);
}

void MCompositeWindowAnimation::finalizeState()
{
    emit q_finalizeState();
}

// returns a group animation for this animator
QParallelAnimationGroup* MCompositeWindowAnimation::animationGroup() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->scalepos;
}

MCompositeWindow* MCompositeWindowAnimation::targetWindow() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->target_window;
}

MCompositeWindow* MCompositeWindowAnimation::targetWindow2() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->target_window2;
}

// Exposed animation properties
QPropertyAnimation* MCompositeWindowAnimation::scaleAnimation() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->scale;
}

QPropertyAnimation* MCompositeWindowAnimation::positionAnimation() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->position;
}

QPropertyAnimation* MCompositeWindowAnimation::opacityAnimation() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->opacity;
}

// Default effect
void MCompositeWindowAnimation::windowShown()
{
#define OPAQUE 1.0
#define DIMMED 0.1
    Q_D(MCompositeWindowAnimation);
    if (!d->target_window)
        return;

    if (d->handledByInvoker(Showing))
        return;

    const qreal scaleStart = 0.2;
    const QRectF &iconGeometry = d->target_window->propertyCache()->iconGeometry();
    QPointF topLeft = iconGeometry.topLeft();

    if (iconGeometry.isEmpty()) {
        const QRectF d = QApplication::desktop()->availableGeometry();
        topLeft.setX(d.width()/2.0f * (1.0f-scaleStart));
        topLeft.setY(d.height()/2.0f * (1.0f-scaleStart));
    }

    d->target_window->setPos(topLeft);
    positionAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    positionAnimation()->setStartValue(topLeft);
    positionAnimation()->setEndValue(
        QPointF(d->target_window->propertyCache()->realGeometry().x(),
                d->target_window->propertyCache()->realGeometry().y()));
    scaleAnimation()->setEasingCurve(QEasingCurve::OutQuad);

    // TODO: use icon geometry signal
    scaleAnimation()->setStartValue(scaleStart);
    scaleAnimation()->setEndValue(1.0);
    opacityAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    opacityAnimation()->setStartValue(DIMMED);
    opacityAnimation()->setEndValue(OPAQUE);

    animationGroup()->setDirection(QAbstractAnimation::Forward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::windowClosed()
{
    Q_D(MCompositeWindowAnimation);
    if (d->handledByInvoker(Closing))
        return;

    positionAnimation()->setEasingCurve(QEasingCurve::InQuad);
    scaleAnimation()->setEasingCurve(QEasingCurve::InQuad);
    opacityAnimation()->setEasingCurve(QEasingCurve::InQuad);
    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::deferAnimation(MCompositeWindowAnimation::AnimationType type)
{
    Q_D(MCompositeWindowAnimation);
    d->pending_animation = type;
}

void MCompositeWindowAnimation::windowIconified()
{
    Q_D(MCompositeWindowAnimation);

    if (d->handledByInvoker(Iconify))
        return;
    positionAnimation()->setEasingCurve(QEasingCurve::InQuad);
    scaleAnimation()->setEasingCurve(QEasingCurve::InQuad);
    opacityAnimation()->setEasingCurve(QEasingCurve::InQuad);
    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::windowRestored()
{
    Q_D(MCompositeWindowAnimation);

    if (d->handledByInvoker(Restore))
        return;
    positionAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    scaleAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    opacityAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    animationGroup()->setDirection(QAbstractAnimation::Forward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::crossFadeTo(MCompositeWindow *cw)
{
    Q_D(MCompositeWindowAnimation);
    const MCompositeManager *mc = static_cast<MCompositeManager*>(qApp);

    if (d->crossfade)
        delete d->crossfade;
    d->crossfade = new McParallelAnimation(this);

    QPropertyAnimation *op = new QPropertyAnimation(this);
    op->setTargetObject(cw);
    op->setEasingCurve(QEasingCurve::Linear);
    op->setPropertyName("opacity");
    op->setDuration(mc->configInt("crossfade-duration"));
    op->setStartValue(0);
    op->setEndValue(1);
    d->crossfade->addAnimation(op);

    d->target_window2 = cw;

    d->crossfade->setDirection(QAbstractAnimation::Forward);
}

void MCompositeWindowAnimation::startTransition()
{
    Q_D(MCompositeWindowAnimation);

    switch (d->pending_animation) {
    case Showing:
        windowShown();
        d->pending_animation = NoAnimation;
        break;
    case Closing:
        windowClosed();
        d->pending_animation = NoAnimation;
        break;
    case Iconify:
        windowIconified();
        d->pending_animation = NoAnimation;
        break;
    case Restore:
        windowRestored();
        d->pending_animation = NoAnimation;
        break;
    case CrossFade:
        if (targetWindow2())
            targetWindow2()->show();
        d->crossfade->start();
        d->pending_animation = NoAnimation;
        break;
    default:  break;
    }
}

void MCompositeWindowAnimation::ensureAnimationVisible()
{
    // Always ensure the animation is REALLY visible. Z-values get corrected
    // later at checkStacking if needed
    if (targetWindow() &&
        targetWindow()->propertyCache()->windowState() != IconicState)
        targetWindow()->setZValue(
              ((MCompositeManager*)qApp)->d->stacking_list.size() + 1);
    if (targetWindow2())
        targetWindow2()->setZValue(
              ((MCompositeManager*)qApp)->d->stacking_list.size() + 2);
}

// plays the animation group;
void MCompositeWindowAnimation::start()
{
    animationGroup()->start();
}

// pauses the animation group;
void MCompositeWindowAnimation::pause()
{
    animationGroup()->pause();
}

void MCompositeWindowAnimation::finish()
{
    animationGroup()->setCurrentTime(animationGroup()->duration());
    animationGroup()->stop();
}

bool MCompositeWindowAnimation::isActive()
{
    return (animationGroup()->state() != QAbstractAnimation::Stopped);
}

MCompositeWindowAnimation::AnimationType MCompositeWindowAnimation::pendingAnimation() const
{
    Q_D(const MCompositeWindowAnimation);

    return d->pending_animation;
}

/*!
  Enabled or disables this animation. Re-implement this function to customize
  how a custom animation can be disabled or disabled
 */
void MCompositeWindowAnimation::setEnabled(bool enabled)
{
    if (enabled) {
        if (animationGroup()->indexOfAnimation(positionAnimation()) == -1)
            animationGroup()->addAnimation(positionAnimation());
        if (animationGroup()->indexOfAnimation(scaleAnimation()) == -1)
            animationGroup()->addAnimation(scaleAnimation());
        if (animationGroup()->indexOfAnimation(opacityAnimation()) == -1)
            animationGroup()->addAnimation(opacityAnimation());
    } else if (!enabled) {
        animationGroup()->stop();
        animationGroup()->removeAnimation(positionAnimation());
        animationGroup()->removeAnimation(scaleAnimation());
        animationGroup()->removeAnimation(opacityAnimation());
    }
}

/*!
  \return Whether this animation can be replaced or not. By default, window
  animations can be replaced with a custom animation
 */
bool MCompositeWindowAnimation::isReplaceable() const
{
    Q_D(const MCompositeWindowAnimation);

    return d->is_replaceable;
}

/*!
   If \a replaceable is true, this animation can be replaced with another custom
   animation object. If \a replaceable is false, the animation may not be
   replaced with another animation and will be set for the lifetime of the
   window that is initially associated with it.
 */
void MCompositeWindowAnimation::setReplaceable(bool replaceable)
{
    Q_D(MCompositeWindowAnimation);

    d->is_replaceable = replaceable;
}

/*!
   Sets a custom external animation handler for animation \a type. If an
   external handler is set it will use the virtual functions of that animation
   \a handler instead of this object's handlers.
   To create an external handler, inherit from MAbstractAnimationHandler class
   and reimplement the required animation functions as needed.
 */
void MCompositeWindowAnimation::setAnimationHandler(AnimationType type,
                                                    MAbstractAnimationHandler* handler)
{
    Q_D(MCompositeWindowAnimation);

    handler->target_window = targetWindow();
    d->animhandler[type] = handler;
}

void MCompositeWindowAnimation::disconnectHandler(MAbstractAnimationHandler* handler)
{
    Q_D(MCompositeWindowAnimation);
    int type = d->animhandler.indexOf(handler);
    if (type > -1)
        d->animhandler[type] = 0;
}

void MAbstractAnimationHandler::windowShown()
{// NOOP
}

void MAbstractAnimationHandler::windowClosed()
{// NOOP
}

void MAbstractAnimationHandler::windowIconified()
{// NOOP
}

void MAbstractAnimationHandler::windowRestored()
{// NOOP
}

MCompositeWindow* MAbstractAnimationHandler::targetWindow() const
{
    return target_window;
}

MAbstractAnimationHandler::~MAbstractAnimationHandler()
{
    if (main_animator)
        main_animator->disconnectHandler(this);
}
<commit_msg>Changes: Fix the forgotten assignment to the main_operator of the external animation handler<commit_after>/***************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of mcompositor.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
/*!
  \class MCompositeWindowAnimation
  \brief MCompositeWindowAnimation class which provides full control
  of position transformation and opacity animations of composite window objects.

  To create more complex animations, re-implement the virtual functions
  windowShown(), windowClosed(), widowIconified() and windowRestored();
  A QParallelAnimationGroup object is provided which can be a container
  for more complex animations for more flexibility.
*/
// TODO: import icongeometry. export signals when animation done to hook
// to composting on off

#include <QMetaMethod>
#include <QRectF>
#include <QDesktopWidget>
#include <QPropertyAnimation>
#include <mcompositewindow.h>
#include <mcompositewindowanimation.h>
#include <QApplication>
#include <QParallelAnimationGroup>
#include <mcompositemanager.h>
#include <mcompositemanager_p.h>
#include <QVector>

class McParallelAnimation: public QParallelAnimationGroup
{
public:
    McParallelAnimation(MCompositeWindowAnimation* p)
        :QParallelAnimationGroup(p),
         parent(p)
    {}

protected:
    virtual void updateCurrentTime(int currentTime)
    {
        MCompositeWindow::update();
        QParallelAnimationGroup::updateCurrentTime(currentTime);
    }

    virtual void updateState(QAbstractAnimation::State newState,
                             QAbstractAnimation::State oldState)
    {
        if (newState == QAbstractAnimation::Running &&
            oldState == QAbstractAnimation::Stopped) {
            parent->ensureAnimationVisible();
            if (parent->targetWindow())
                parent->targetWindow()->beginAnimation();
            if (parent->targetWindow2())
                parent->targetWindow2()->beginAnimation();
        } else if (newState == QAbstractAnimation::Stopped) {
            if (parent->targetWindow())
                parent->targetWindow()->endAnimation();
            if (parent->targetWindow2())
                parent->targetWindow2()->endAnimation();
        }
        QParallelAnimationGroup::updateState(newState, oldState);
    }
private:
    MCompositeWindowAnimation* parent;
};

class MCompositeWindowAnimationPrivate
{
public:

    MCompositeWindowAnimationPrivate(MCompositeWindowAnimation* animation)
        : crossfade(0),
          pending_animation(MCompositeWindowAnimation::NoAnimation),
          is_replaceable(true),
          animhandler(MCompositeWindowAnimation::AnimationTotal, 0)
    {
        const MCompositeManager *mc = static_cast<MCompositeManager*>(qApp);
        int duration = mc->configInt("startup-anim-duration");

        scale = new QPropertyAnimation(animation);
        scale->setPropertyName("scale");
        scale->setDuration(duration);

        position = new QPropertyAnimation(animation);
        position->setPropertyName("pos");
        position->setDuration(duration);

        opacity = new QPropertyAnimation(animation);
        opacity->setPropertyName("opacity");
        opacity->setDuration(duration);

        scalepos = new McParallelAnimation(animation);
        scalepos->addAnimation(scale);
        scalepos->addAnimation(position);
        scalepos->addAnimation(opacity);

        QObject::connect(scalepos, SIGNAL(finished()), animation,
                         SLOT(finalizeState()));
    }

    void setTargetWindow(MCompositeWindow* window)
    {
        if (scale && position && opacity) {
            scale->setTargetObject(window);
            position->setTargetObject(window);
            opacity->setTargetObject(window);
        }
    }

    bool handledByInvoker(MCompositeWindowAnimation::AnimationType type)
    {
        if (animhandler[type]) {
            switch (type) {
            case MCompositeWindowAnimation::Showing:
                animhandler[type]->windowShown();
                return true;
            case MCompositeWindowAnimation::Closing:
                animhandler[type]->windowClosed();
                return true;
            case MCompositeWindowAnimation::Iconify:
                animhandler[type]->windowIconified();
                return true;
            case MCompositeWindowAnimation::Restore:
                animhandler[type]->windowRestored();
                return true;
            default:
                break;
            }
        }

        return false;
    }

    QPointer<MCompositeWindow> target_window, target_window2;
    QPointer<QPropertyAnimation> scale;
    QPointer<QPropertyAnimation> position;
    QPointer<QPropertyAnimation> opacity;
    McParallelAnimation* scalepos, *crossfade;
    MCompositeWindowAnimation::AnimationType pending_animation;
    bool is_replaceable;
    QVector< MAbstractAnimationHandler* > animhandler;
};

MCompositeWindowAnimation::MCompositeWindowAnimation(QObject* parent)
    :QObject(parent),
     d_ptr(new MCompositeWindowAnimationPrivate(this))
{
}

MCompositeWindowAnimation::~MCompositeWindowAnimation()
{
}

void MCompositeWindowAnimation::setTargetWindow(MCompositeWindow* window)
{
    Q_D(MCompositeWindowAnimation);

    // never override a non-replaceable animation
    if (window->animator && !window->animator->isReplaceable()) {
        deleteLater();
        return;
    }

    // replace the old animator if there is one
    if (window->animator && (window->animator != this))
        delete window->animator;

    d->target_window = window;
    d->target_window->animator = this;
    disconnect(SIGNAL(q_finalizeState()));
    connect(this, SIGNAL(q_finalizeState()), window, SLOT(finalizeState()));

    d->setTargetWindow(window);
}

void MCompositeWindowAnimation::finalizeState()
{
    emit q_finalizeState();
}

// returns a group animation for this animator
QParallelAnimationGroup* MCompositeWindowAnimation::animationGroup() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->scalepos;
}

MCompositeWindow* MCompositeWindowAnimation::targetWindow() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->target_window;
}

MCompositeWindow* MCompositeWindowAnimation::targetWindow2() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->target_window2;
}

// Exposed animation properties
QPropertyAnimation* MCompositeWindowAnimation::scaleAnimation() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->scale;
}

QPropertyAnimation* MCompositeWindowAnimation::positionAnimation() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->position;
}

QPropertyAnimation* MCompositeWindowAnimation::opacityAnimation() const
{
    Q_D(const MCompositeWindowAnimation);
    return d->opacity;
}

// Default effect
void MCompositeWindowAnimation::windowShown()
{
#define OPAQUE 1.0
#define DIMMED 0.1
    Q_D(MCompositeWindowAnimation);
    if (!d->target_window)
        return;

    if (d->handledByInvoker(Showing))
        return;

    const qreal scaleStart = 0.2;
    const QRectF &iconGeometry = d->target_window->propertyCache()->iconGeometry();
    QPointF topLeft = iconGeometry.topLeft();

    if (iconGeometry.isEmpty()) {
        const QRectF d = QApplication::desktop()->availableGeometry();
        topLeft.setX(d.width()/2.0f * (1.0f-scaleStart));
        topLeft.setY(d.height()/2.0f * (1.0f-scaleStart));
    }

    d->target_window->setPos(topLeft);
    positionAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    positionAnimation()->setStartValue(topLeft);
    positionAnimation()->setEndValue(
        QPointF(d->target_window->propertyCache()->realGeometry().x(),
                d->target_window->propertyCache()->realGeometry().y()));
    scaleAnimation()->setEasingCurve(QEasingCurve::OutQuad);

    // TODO: use icon geometry signal
    scaleAnimation()->setStartValue(scaleStart);
    scaleAnimation()->setEndValue(1.0);
    opacityAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    opacityAnimation()->setStartValue(DIMMED);
    opacityAnimation()->setEndValue(OPAQUE);

    animationGroup()->setDirection(QAbstractAnimation::Forward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::windowClosed()
{
    Q_D(MCompositeWindowAnimation);
    if (d->handledByInvoker(Closing))
        return;

    positionAnimation()->setEasingCurve(QEasingCurve::InQuad);
    scaleAnimation()->setEasingCurve(QEasingCurve::InQuad);
    opacityAnimation()->setEasingCurve(QEasingCurve::InQuad);
    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::deferAnimation(MCompositeWindowAnimation::AnimationType type)
{
    Q_D(MCompositeWindowAnimation);
    d->pending_animation = type;
}

void MCompositeWindowAnimation::windowIconified()
{
    Q_D(MCompositeWindowAnimation);

    if (d->handledByInvoker(Iconify))
        return;
    positionAnimation()->setEasingCurve(QEasingCurve::InQuad);
    scaleAnimation()->setEasingCurve(QEasingCurve::InQuad);
    opacityAnimation()->setEasingCurve(QEasingCurve::InQuad);
    animationGroup()->setDirection(QAbstractAnimation::Backward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::windowRestored()
{
    Q_D(MCompositeWindowAnimation);

    if (d->handledByInvoker(Restore))
        return;
    positionAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    scaleAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    opacityAnimation()->setEasingCurve(QEasingCurve::OutQuad);
    animationGroup()->setDirection(QAbstractAnimation::Forward);
    animationGroup()->start();
}

void MCompositeWindowAnimation::crossFadeTo(MCompositeWindow *cw)
{
    Q_D(MCompositeWindowAnimation);
    const MCompositeManager *mc = static_cast<MCompositeManager*>(qApp);

    if (d->crossfade)
        delete d->crossfade;
    d->crossfade = new McParallelAnimation(this);

    QPropertyAnimation *op = new QPropertyAnimation(this);
    op->setTargetObject(cw);
    op->setEasingCurve(QEasingCurve::Linear);
    op->setPropertyName("opacity");
    op->setDuration(mc->configInt("crossfade-duration"));
    op->setStartValue(0);
    op->setEndValue(1);
    d->crossfade->addAnimation(op);

    d->target_window2 = cw;

    d->crossfade->setDirection(QAbstractAnimation::Forward);
}

void MCompositeWindowAnimation::startTransition()
{
    Q_D(MCompositeWindowAnimation);

    switch (d->pending_animation) {
    case Showing:
        windowShown();
        d->pending_animation = NoAnimation;
        break;
    case Closing:
        windowClosed();
        d->pending_animation = NoAnimation;
        break;
    case Iconify:
        windowIconified();
        d->pending_animation = NoAnimation;
        break;
    case Restore:
        windowRestored();
        d->pending_animation = NoAnimation;
        break;
    case CrossFade:
        if (targetWindow2())
            targetWindow2()->show();
        d->crossfade->start();
        d->pending_animation = NoAnimation;
        break;
    default:  break;
    }
}

void MCompositeWindowAnimation::ensureAnimationVisible()
{
    // Always ensure the animation is REALLY visible. Z-values get corrected
    // later at checkStacking if needed
    if (targetWindow() &&
        targetWindow()->propertyCache()->windowState() != IconicState)
        targetWindow()->setZValue(
              ((MCompositeManager*)qApp)->d->stacking_list.size() + 1);
    if (targetWindow2())
        targetWindow2()->setZValue(
              ((MCompositeManager*)qApp)->d->stacking_list.size() + 2);
}

// plays the animation group;
void MCompositeWindowAnimation::start()
{
    animationGroup()->start();
}

// pauses the animation group;
void MCompositeWindowAnimation::pause()
{
    animationGroup()->pause();
}

void MCompositeWindowAnimation::finish()
{
    animationGroup()->setCurrentTime(animationGroup()->duration());
    animationGroup()->stop();
}

bool MCompositeWindowAnimation::isActive()
{
    return (animationGroup()->state() != QAbstractAnimation::Stopped);
}

MCompositeWindowAnimation::AnimationType MCompositeWindowAnimation::pendingAnimation() const
{
    Q_D(const MCompositeWindowAnimation);

    return d->pending_animation;
}

/*!
  Enabled or disables this animation. Re-implement this function to customize
  how a custom animation can be disabled or disabled
 */
void MCompositeWindowAnimation::setEnabled(bool enabled)
{
    if (enabled) {
        if (animationGroup()->indexOfAnimation(positionAnimation()) == -1)
            animationGroup()->addAnimation(positionAnimation());
        if (animationGroup()->indexOfAnimation(scaleAnimation()) == -1)
            animationGroup()->addAnimation(scaleAnimation());
        if (animationGroup()->indexOfAnimation(opacityAnimation()) == -1)
            animationGroup()->addAnimation(opacityAnimation());
    } else if (!enabled) {
        animationGroup()->stop();
        animationGroup()->removeAnimation(positionAnimation());
        animationGroup()->removeAnimation(scaleAnimation());
        animationGroup()->removeAnimation(opacityAnimation());
    }
}

/*!
  \return Whether this animation can be replaced or not. By default, window
  animations can be replaced with a custom animation
 */
bool MCompositeWindowAnimation::isReplaceable() const
{
    Q_D(const MCompositeWindowAnimation);

    return d->is_replaceable;
}

/*!
   If \a replaceable is true, this animation can be replaced with another custom
   animation object. If \a replaceable is false, the animation may not be
   replaced with another animation and will be set for the lifetime of the
   window that is initially associated with it.
 */
void MCompositeWindowAnimation::setReplaceable(bool replaceable)
{
    Q_D(MCompositeWindowAnimation);

    d->is_replaceable = replaceable;
}

/*!
   Sets a custom external animation handler for animation \a type. If an
   external handler is set it will use the virtual functions of that animation
   \a handler instead of this object's handlers.
   To create an external handler, inherit from MAbstractAnimationHandler class
   and reimplement the required animation functions as needed.
 */
void MCompositeWindowAnimation::setAnimationHandler(AnimationType type,
                                                    MAbstractAnimationHandler* handler)
{
    Q_D(MCompositeWindowAnimation);

    handler->target_window = targetWindow();
    handler->main_animator = this;
    d->animhandler[type] = handler;
}

void MCompositeWindowAnimation::disconnectHandler(MAbstractAnimationHandler* handler)
{
    Q_D(MCompositeWindowAnimation);
    int type = d->animhandler.indexOf(handler);
    if (type > -1)
        d->animhandler[type] = 0;
}

void MAbstractAnimationHandler::windowShown()
{// NOOP
}

void MAbstractAnimationHandler::windowClosed()
{// NOOP
}

void MAbstractAnimationHandler::windowIconified()
{// NOOP
}

void MAbstractAnimationHandler::windowRestored()
{// NOOP
}

MCompositeWindow* MAbstractAnimationHandler::targetWindow() const
{
    return target_window;
}

MAbstractAnimationHandler::~MAbstractAnimationHandler()
{
    if (main_animator)
        main_animator->disconnectHandler(this);
}
<|endoftext|>


<commit_before>#pragma once

#include <algorithm>
#include <vector>

#include "nano_function.hpp"
#include "nano_mutex.hpp"

namespace Nano
{

template <typename MT_Policy = ST_Policy>
class Observer : private MT_Policy
{
    // Only Nano::Signal is allowed private access
    template <typename, typename> friend class Signal;

    struct Connection
    {
        Delegate_Key delegate;
        typename MT_Policy::Weak_Ptr observer;

        Connection() noexcept = default;
        Connection(Delegate_Key const& key) : delegate(key), observer() {}
        Connection(Delegate_Key const& key, Observer* obs) : delegate(key), observer(obs->weak_ptr()) {}
    };

    struct Z_Order
    {
        inline bool operator()(Delegate_Key const& lhs, Delegate_Key const& rhs) const
        {
            std::size_t x = lhs[0] ^ rhs[0];
            std::size_t y = lhs[1] ^ rhs[1];
            auto k = (x < y) && x < (x ^ y);
            return lhs[k] < rhs[k];
        }

        inline bool operator()(Connection const& lhs, Connection const& rhs) const
        {
            return operator()(lhs.delegate, rhs.delegate);
        }
    };

    std::vector<Connection> connections;

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

    void insert(Delegate_Key const& key, Observer* obs)
    {
        [[maybe_unused]] auto lock = MT_Policy::lock_guard();

        auto begin = std::begin(connections);
        auto end = std::end(connections);

        connections.emplace(std::upper_bound(begin, end, key, Z_Order()), key, obs);
    }

    void remove(Delegate_Key const& key) noexcept
    {
        [[maybe_unused]] auto lock = MT_Policy::lock_guard();

        auto begin = std::begin(connections);
        auto end = std::end(connections);

        auto slots = std::equal_range(begin, end, key, Z_Order());
        connections.erase(slots.first, slots.second);
    }

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

    template <typename Function, typename... Uref>
    void for_each(Uref&&... args)
    {
        auto lock = MT_Policy::lock_guard();

        for (auto const& slot : MT_Policy::copy_or_ref(connections, lock))
        {
            if (auto observer = MT_Policy::observed(slot.observer))
            {
                Function::bind(slot.delegate)(args...);
            }
        }
    }

    template <typename Function, typename Accumulate, typename... Uref>
    void for_each_accumulate(Accumulate&& accumulate, Uref&&... args)
    {
        auto lock = MT_Policy::lock_guard();

        for (auto const& slot : MT_Policy::copy_or_ref(connections, lock))
        {
            if (auto observer = MT_Policy::observed(slot.observer))
            {
                accumulate(Function::bind(slot.delegate)(args...));
            }
        }
    }

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

    public:

    void disconnect_all() noexcept
    {
        [[maybe_unused]] auto lock = MT_Policy::lock_guard();

        for (auto const& slot : connections)
        {
            if (auto observer = MT_Policy::visiting(slot.observer))
            {
                static_cast<Observer*>(MT_Policy::unmask(observer))->remove(slot.delegate);
            }
        }
        connections.clear();
    }

    bool is_empty() const noexcept
    {
        auto lock = MT_Policy::lock_guard();

        return connections.empty();
    }

    protected:

    // Guideline #4: A base class destructor should be
    // either public and virtual, or protected and non-virtual.
    ~Observer()
    {
        MT_Policy::before_disconnect_all();

        disconnect_all();
    }

    Observer() noexcept = default;

    // Observer may be movable depending on policy, but should never be copied
    Observer(Observer const&) noexcept = delete;
    Observer& operator= (Observer const&) noexcept = delete;

    Observer(Observer&&) noexcept = default;
    Observer& operator=(Observer&&) noexcept = default;
};

} // namespace Nano ------------------------------------------------------------
<commit_msg>Move connections when moving an observer<commit_after>#pragma once

#include <algorithm>
#include <vector>

#include "nano_function.hpp"
#include "nano_mutex.hpp"

namespace Nano
{

template <typename MT_Policy = ST_Policy>
class Observer : private MT_Policy
{
    // Only Nano::Signal is allowed private access
    template <typename, typename> friend class Signal;

    struct Connection
    {
        Delegate_Key delegate;
        typename MT_Policy::Weak_Ptr observer;

        Connection() noexcept = default;
        Connection(Delegate_Key const& key) : delegate(key), observer() {}
        Connection(Delegate_Key const& key, Observer* obs) : delegate(key), observer(obs->weak_ptr()) {}
    };

    struct Z_Order
    {
        inline bool operator()(Delegate_Key const& lhs, Delegate_Key const& rhs) const
        {
            std::size_t x = lhs[0] ^ rhs[0];
            std::size_t y = lhs[1] ^ rhs[1];
            auto k = (x < y) && x < (x ^ y);
            return lhs[k] < rhs[k];
        }

        inline bool operator()(Connection const& lhs, Connection const& rhs) const
        {
            return operator()(lhs.delegate, rhs.delegate);
        }
    };

    std::vector<Connection> connections;
    bool movedFrom = false;

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

    void insert(Delegate_Key const& key, Observer* obs)
    {
        [[maybe_unused]] auto lock = MT_Policy::lock_guard();

        auto begin = std::begin(connections);
        auto end = std::end(connections);

        connections.emplace(std::upper_bound(begin, end, key, Z_Order()), key, obs);
    }

    void remove(Delegate_Key const& key) noexcept
    {
        [[maybe_unused]] auto lock = MT_Policy::lock_guard();

        auto begin = std::begin(connections);
        auto end = std::end(connections);

        auto slots = std::equal_range(begin, end, key, Z_Order());
        connections.erase(slots.first, slots.second);
    }

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

    template <typename Function, typename... Uref>
    void for_each(Uref&&... args)
    {
        auto lock = MT_Policy::lock_guard();

        for (auto const& slot : MT_Policy::copy_or_ref(connections, lock))
        {
            if (auto observer = MT_Policy::observed(slot.observer))
            {
                Function::bind(slot.delegate)(args...);
            }
        }
    }

    template <typename Function, typename Accumulate, typename... Uref>
    void for_each_accumulate(Accumulate&& accumulate, Uref&&... args)
    {
        auto lock = MT_Policy::lock_guard();

        for (auto const& slot : MT_Policy::copy_or_ref(connections, lock))
        {
            if (auto observer = MT_Policy::observed(slot.observer))
            {
                accumulate(Function::bind(slot.delegate)(args...));
            }
        }
    }

    void move_connections_from(Observer* other) noexcept
    {
        [[maybe_unused]] auto lock = MT_Policy::lock_guard();
        [[maybe_unused]] auto otherLock = other->lock_guard();

        connections.clear();

        // Disconnect other from everyone else, and connect them to us instead
        for (auto const& slot : other->connections)
        {
            if (auto observer = MT_Policy::visiting(slot.observer))
            {
                auto obsPtr = static_cast<Observer*>(MT_Policy::unmask(observer));
                obsPtr->remove(slot.delegate);
                obsPtr->insert(slot.delegate, this);

                insert(slot.delegate, obsPtr);
            }
        }

        other->connections.clear();
    }

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

    public:

    void disconnect_all() noexcept
    {
        [[maybe_unused]] auto lock = MT_Policy::lock_guard();

        for (auto const& slot : connections)
        {
            if (auto observer = MT_Policy::visiting(slot.observer))
            {
                static_cast<Observer*>(MT_Policy::unmask(observer))->remove(slot.delegate);
            }
        }
        connections.clear();
    }

    bool is_empty() const noexcept
    {
        auto lock = MT_Policy::lock_guard();

        return connections.empty();
    }

    protected:

    // Guideline #4: A base class destructor should be
    // either public and virtual, or protected and non-virtual.
    ~Observer()
    {
        MT_Policy::before_disconnect_all();

        if (!movedFrom)
            disconnect_all();
    }

    Observer() noexcept = default;

    // Observer may be movable depending on policy, but should never be copied
    Observer(Observer const&) noexcept = delete;
    Observer& operator= (Observer const&) noexcept = delete;

    // When moving an observer, make sure everyone it's connected to knows about it
    Observer(Observer&& other) noexcept
    {
        move_connections_from(&other);
        other.movedFrom = true;
    }

    Observer& operator=(Observer&& other) noexcept
    {
        move_connections_from(&other);
        other.movedFrom = true;
        return *this;
    }
};

} // namespace Nano ------------------------------------------------------------
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2012-2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file load_mon.cpp
 *
 * @author Jonathan Challinger <jonathan@3drobotics.com>
 * @author Julian Oes <julian@oes.ch
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <px4_config.h>
#include <px4_workqueue.h>

#include <drivers/drv_hrt.h>

#include <systemlib/systemlib.h>
#include <systemlib/err.h>
#include <systemlib/cpuload.h>

#include <uORB/uORB.h>
#include <uORB/topics/cpuload.h>

extern struct system_load_s system_load;

namespace load_mon
{

extern "C" __EXPORT int load_mon_main(int argc, char *argv[]);

// Run it at 1 Hz.
const unsigned LOAD_MON_INTERVAL_US = 1000000;

class LoadMon
{
public:
	LoadMon();
	~LoadMon();

	/* Start the load monitoring
	 *
	 * @return 0 if successfull, -1 on error. */
	int start();

	/* Stop the load monitoring */
	void stop();

	/* Trampoline for the work queue. */
	static void cycle_trampoline(void *arg);

	bool isRunning() { return _taskIsRunning; }

private:
	/* Do a compute and schedule the next cycle. */
	void _cycle();

	/* Do a calculation of the CPU load and publish it. */
	void _compute();

	bool _taskShouldExit;
	bool _taskIsRunning;
	struct work_s _work;

	struct cpuload_s _cpuload;
	orb_advert_t _cpuload_pub;
	hrt_abstime _last_idle_time;
};

LoadMon::LoadMon() :
	_taskShouldExit(false),
	_taskIsRunning(false),
	_work{},
	_cpuload{},
	_cpuload_pub(nullptr),
	_last_idle_time(0)
{}

LoadMon::~LoadMon()
{
	work_cancel(HPWORK, &_work);
	_taskIsRunning = false;
}

int LoadMon::start()
{
	/* Schedule a cycle to start things. */
	return work_queue(HPWORK, &_work, (worker_t)&LoadMon::cycle_trampoline, this, 0);
}

void LoadMon::stop()
{
	_taskShouldExit = true;
}

void
LoadMon::cycle_trampoline(void *arg)
{
	LoadMon *dev = reinterpret_cast<LoadMon *>(arg);

	dev->_cycle();
}

void LoadMon::_cycle()
{
	_taskIsRunning = true;

	_compute();

	if (!_taskShouldExit) {
		work_queue(HPWORK, &_work, (worker_t)&LoadMon::cycle_trampoline, this,
			   USEC2TICK(LOAD_MON_INTERVAL_US));
	}
}

void LoadMon::_compute()
{
	if (_last_idle_time == 0) {
		/* Just get the time in the first iteration */
		_last_idle_time = system_load.tasks[0].total_runtime;
		return;
	}

	/* compute system load */
	const hrt_abstime interval_idletime = system_load.tasks[0].total_runtime - _last_idle_time;
	_last_idle_time = system_load.tasks[0].total_runtime;

	_cpuload.timestamp = hrt_absolute_time();
	_cpuload.load = 1.0f - (float)interval_idletime / (float)LOAD_MON_INTERVAL_US;

	if (_cpuload_pub == nullptr) {
		_cpuload_pub = orb_advertise(ORB_ID(cpuload), &_cpuload);

	} else {
		orb_publish(ORB_ID(cpuload), _cpuload_pub, &_cpuload);
	}
}

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_INFO("usage: load_mon {start|stop|status}");
}

static LoadMon *load_mon = nullptr;

/**
 * The daemon app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int load_mon_main(int argc, char *argv[])
{
	if (argc < 2) {
		usage("missing command");
		return 1;
	}

	if (!strcmp(argv[1], "start")) {

		if (load_mon != nullptr && load_mon->isRunning()) {
			PX4_WARN("already running");
			/* this is not an error */
			return 0;
		}

		load_mon = new LoadMon();

		// Check if alloc worked.
		if (load_mon == nullptr) {
			PX4_ERR("alloc failed");
			return -1;
		}

		int ret = load_mon->start();

		if (ret != 0) {
			PX4_ERR("start failed");
		}

		return 0;
	}

	if (!strcmp(argv[1], "stop")) {

		if (load_mon == nullptr || load_mon->isRunning()) {
			PX4_WARN("not running");
			/* this is not an error */
			return 0;
		}

		load_mon->stop();

		// Wait for task to die
		int i = 0;

		do {
			/* wait up to 3s */
			usleep(100000);

		} while (load_mon->isRunning() && ++i < 30);

		delete load_mon;
		load_mon = nullptr;

		return 0;
	}

	if (!strcmp(argv[1], "status")) {
		if (load_mon != nullptr && load_mon->isRunning()) {
			PX4_INFO("running");

		} else {
			PX4_INFO("not running\n");
		}

		return 0;
	}

	usage("unrecognized command");
	return 1;
}

} // namespace load_mon
<commit_msg>load_mon: added missing include<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2012-2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file load_mon.cpp
 *
 * @author Jonathan Challinger <jonathan@3drobotics.com>
 * @author Julian Oes <julian@oes.ch
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <px4_config.h>
#include <px4_workqueue.h>
#include <px4_defines.h>

#include <drivers/drv_hrt.h>

#include <systemlib/systemlib.h>
#include <systemlib/err.h>
#include <systemlib/cpuload.h>

#include <uORB/uORB.h>
#include <uORB/topics/cpuload.h>

extern struct system_load_s system_load;

namespace load_mon
{

extern "C" __EXPORT int load_mon_main(int argc, char *argv[]);

// Run it at 1 Hz.
const unsigned LOAD_MON_INTERVAL_US = 1000000;

class LoadMon
{
public:
	LoadMon();
	~LoadMon();

	/* Start the load monitoring
	 *
	 * @return 0 if successfull, -1 on error. */
	int start();

	/* Stop the load monitoring */
	void stop();

	/* Trampoline for the work queue. */
	static void cycle_trampoline(void *arg);

	bool isRunning() { return _taskIsRunning; }

private:
	/* Do a compute and schedule the next cycle. */
	void _cycle();

	/* Do a calculation of the CPU load and publish it. */
	void _compute();

	bool _taskShouldExit;
	bool _taskIsRunning;
	struct work_s _work;

	struct cpuload_s _cpuload;
	orb_advert_t _cpuload_pub;
	hrt_abstime _last_idle_time;
};

LoadMon::LoadMon() :
	_taskShouldExit(false),
	_taskIsRunning(false),
	_work{},
	_cpuload{},
	_cpuload_pub(nullptr),
	_last_idle_time(0)
{}

LoadMon::~LoadMon()
{
	work_cancel(HPWORK, &_work);
	_taskIsRunning = false;
}

int LoadMon::start()
{
	/* Schedule a cycle to start things. */
	return work_queue(HPWORK, &_work, (worker_t)&LoadMon::cycle_trampoline, this, 0);
}

void LoadMon::stop()
{
	_taskShouldExit = true;
}

void
LoadMon::cycle_trampoline(void *arg)
{
	LoadMon *dev = reinterpret_cast<LoadMon *>(arg);

	dev->_cycle();
}

void LoadMon::_cycle()
{
	_taskIsRunning = true;

	_compute();

	if (!_taskShouldExit) {
		work_queue(HPWORK, &_work, (worker_t)&LoadMon::cycle_trampoline, this,
			   USEC2TICK(LOAD_MON_INTERVAL_US));
	}
}

void LoadMon::_compute()
{
	if (_last_idle_time == 0) {
		/* Just get the time in the first iteration */
		_last_idle_time = system_load.tasks[0].total_runtime;
		return;
	}

	/* compute system load */
	const hrt_abstime interval_idletime = system_load.tasks[0].total_runtime - _last_idle_time;
	_last_idle_time = system_load.tasks[0].total_runtime;

	_cpuload.timestamp = hrt_absolute_time();
	_cpuload.load = 1.0f - (float)interval_idletime / (float)LOAD_MON_INTERVAL_US;

	if (_cpuload_pub == nullptr) {
		_cpuload_pub = orb_advertise(ORB_ID(cpuload), &_cpuload);

	} else {
		orb_publish(ORB_ID(cpuload), _cpuload_pub, &_cpuload);
	}
}

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_INFO("usage: load_mon {start|stop|status}");
}

static LoadMon *load_mon = nullptr;

/**
 * The daemon app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int load_mon_main(int argc, char *argv[])
{
	if (argc < 2) {
		usage("missing command");
		return 1;
	}

	if (!strcmp(argv[1], "start")) {

		if (load_mon != nullptr && load_mon->isRunning()) {
			PX4_WARN("already running");
			/* this is not an error */
			return 0;
		}

		load_mon = new LoadMon();

		// Check if alloc worked.
		if (load_mon == nullptr) {
			PX4_ERR("alloc failed");
			return -1;
		}

		int ret = load_mon->start();

		if (ret != 0) {
			PX4_ERR("start failed");
		}

		return 0;
	}

	if (!strcmp(argv[1], "stop")) {

		if (load_mon == nullptr || load_mon->isRunning()) {
			PX4_WARN("not running");
			/* this is not an error */
			return 0;
		}

		load_mon->stop();

		// Wait for task to die
		int i = 0;

		do {
			/* wait up to 3s */
			usleep(100000);

		} while (load_mon->isRunning() && ++i < 30);

		delete load_mon;
		load_mon = nullptr;

		return 0;
	}

	if (!strcmp(argv[1], "status")) {
		if (load_mon != nullptr && load_mon->isRunning()) {
			PX4_INFO("running");

		} else {
			PX4_INFO("not running\n");
		}

		return 0;
	}

	usage("unrecognized command");
	return 1;
}

} // namespace load_mon
<|endoftext|>


<commit_before>/*
** Copyright 2009-2013,2015 Centreon
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
**
** For more information : contact@centreon.com
*/

#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/events.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/neb/events.hh"
#include "com/centreon/broker/neb/internal.hh"
#include "com/centreon/broker/neb/node_events_factory.hh"
#include "com/centreon/broker/io/protocols.hh"

using namespace com::centreon::broker;

static unsigned int neb_instances(0);

extern "C" {
  /**
   *  Module version symbol. Used to check for version mismatch.
   */
  char const* broker_module_version = CENTREON_BROKER_VERSION;

  /**
   *  Module deinitialization routine.
   */
  void broker_module_deinit() {
    if (!--neb_instances) {
      // Remove factory.
      io::protocols::instance().unreg("node_events");

      // Remove events.
      io::events::instance().unregister_category(io::events::neb);
    }
    return ;
  }

  /**
   *  Module initialization routine.
   *
   *  @param[in] arg Configuration object.
   */
  void broker_module_init(void const* arg) {
    (void)arg;
    if (!neb_instances++) {
      logging::info(logging::high)
        << "NEB: module for Centreon Broker "
        << CENTREON_BROKER_VERSION;
      io::events& e(io::events::instance());

      // Register category.
      int neb_category(e.register_category("neb", io::events::neb));
      if (neb_category != io::events::neb) {
        e.unregister_category(neb_category);
        --neb_instances;
        throw (exceptions::msg() << "NEB: category " << io::events::neb
               << " is already registered whereas it should be "
               << "reserved for the NEB module");
      }

      // Register events.
      {
        e.register_event(
            io::events::neb,
            neb::de_acknowledgement,
            io::event_info(
                  "acknowledgement",
                  &neb::acknowledgement::operations,
                  neb::acknowledgement::entries,
                  "rt_acknowledgements",
                  "acknowledgements"));
        e.register_event(
            io::events::neb,
            neb::de_comment,
            io::event_info(
                  "comment",
                  &neb::comment::operations,
                  neb::comment::entries,
                  "",
                  "comments"));
        e.register_event(
            io::events::neb,
            neb::de_custom_variable,
            io::event_info(
                  "custom_variable",
                  &neb::custom_variable::operations,
                  neb::custom_variable::entries,
                  "rt_customvariables",
                  "customvariables"));
        e.register_event(
            io::events::neb,
            neb::de_custom_variable_status,
            io::event_info(
                  "custom_variable_status",
                  &neb::custom_variable_status::operations,
                  neb::custom_variable_status::entries,
                  "rt_customvariables",
                  "customvariables"));
        e.register_event(
            io::events::neb,
            neb::de_downtime,
            io::event_info(
                  "downtime",
                  &neb::downtime::operations,
                  neb::downtime::entries,
                  "rt_downtimes",
                  "downtimes"));
        e.register_event(
            io::events::neb,
            neb::de_event_handler,
            io::event_info(
                  "event_handler",
                  &neb::event_handler::operations,
                  neb::event_handler::entries,
                  "rt_eventhandlers",
                  "eventhandlers"));
        e.register_event(
            io::events::neb,
            neb::de_flapping_status,
            io::event_info(
                  "flapping_status",
                  &neb::flapping_status::operations,
                  neb::flapping_status::entries,
                  "rt_flappingstatuses",
                  "flappingstatuses"));
        e.register_event(
            io::events::neb,
            neb::de_host_check,
            io::event_info(
                  "host_check",
                  &neb::host_check::operations,
                  neb::host_check::entries,
                  "rt_hosts",
                  "hosts"));
        e.register_event(
            io::events::neb,
            neb::de_host_dependency,
            io::event_info(
                  "host_dependency",
                  &neb::host_dependency::operations,
                  neb::host_dependency::entries,
                  "rt_hosts_hosts_dependencies",
                  "hosts_hosts_dependencies"));
        e.register_event(
            io::events::neb,
            neb::de_host,
            io::event_info(
                  "host",
                  &neb::host::operations,
                  neb::host::entries,
                  "rt_hosts",
                  "hosts"));
        e.register_event(
            io::events::neb,
            neb::de_host_group,
            io::event_info(
                  "host_group",
                  &neb::host_group::operations,
                  neb::host_group::entries,
                  "",
                  "hostgroups"));
        e.register_event(
            io::events::neb,
            neb::de_host_group_member,
            io::event_info(
                  "host_group_member",
                  &neb::host_group_member::operations,
                  neb::host_group_member::entries,
                  "",
                  "hosts_hostgroups"));
        e.register_event(
            io::events::neb,
            neb::de_host_parent,
            io::event_info(
                  "host_parent",
                  &neb::host_parent::operations,
                  neb::host_parent::entries,
                  "rt_hosts_hosts_parents",
                  "hosts_hosts_parents"));
        e.register_event(
            io::events::neb,
            neb::de_host_status,
            io::event_info(
                  "host_status",
                  &neb::host_status::operations,
                  neb::host_status::entries,
                  "rt_hosts",
                  "hosts"));
        e.register_event(
            io::events::neb,
            neb::de_instance,
            io::event_info(
                  "instance",
                  &neb::instance::operations,
                  neb::instance::entries,
                  "rt_instances",
                  "instances"));
        e.register_event(
            io::events::neb,
            neb::de_instance_status,
            io::event_info(
                  "instance_status",
                  &neb::instance_status::operations,
                  neb::instance_status::entries,
                  "rt_instances",
                  "instances"));
        e.register_event(
            io::events::neb,
            neb::de_log_entry,
            io::event_info(
                  "log_entry",
                  &neb::log_entry::operations,
                  neb::log_entry::entries,
                  "log_logs",
                  "logs"));
        e.register_event(
            io::events::neb,
            neb::de_module,
            io::event_info(
                  "module",
                  &neb::module::operations,
                  neb::module::entries,
                  "rt_modules",
                  "modules"));
        e.register_event(
            io::events::neb,
            neb::de_service_check,
            io::event_info(
                  "service_check",
                  &neb::service_check::operations,
                  neb::service_check::entries,
                  "rt_services",
                  "services"));
        e.register_event(
            io::events::neb,
            neb::de_service_dependency,
            io::event_info(
                  "service_dependency",
                  &neb::service_dependency::operations,
                  neb::service_dependency::entries,
                  "rt_services_services_dependencies",
                  "services_services_dependencies"));
        e.register_event(
            io::events::neb,
            neb::de_service,
            io::event_info(
                  "service",
                  &neb::service::operations,
                  neb::service::entries,
                  "rt_services",
                  "services"));
        e.register_event(
            io::events::neb,
            neb::de_service_group,
            io::event_info(
                  "service_group",
                  &neb::service_group::operations,
                  neb::service_group::entries,
                  "",
                  "servicegroups"));
        e.register_event(
            io::events::neb,
            neb::de_service_group_member,
            io::event_info(
                  "service_group_member",
                  &neb::service_group_member::operations,
                  neb::service_group_member::entries,
                  "",
                  "services_servicegroups"));
        e.register_event(
            io::events::neb,
            neb::de_service_status,
            io::event_info(
                  "service_status",
                  &neb::service_status::operations,
                  neb::service_status::entries,
                  "rt_services",
                  "services"));
        e.register_event(
            io::events::neb,
            neb::de_service_status,
            io::event_info(
                  "instance_configuration",
                  &neb::instance_configuration::operations,
                  neb::instance_configuration::entries));
      }

      // Register neb layer.
      io::protocols::instance().reg(
                                  "node_events",
                                  neb::node_events_factory(),
                                  1,
                                  7);
    }

    return ;
  }
}
<commit_msg>Neb: fix instance configuration registering.<commit_after>/*
** Copyright 2009-2013,2015 Centreon
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
**
** For more information : contact@centreon.com
*/

#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/events.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/neb/events.hh"
#include "com/centreon/broker/neb/internal.hh"
#include "com/centreon/broker/neb/node_events_factory.hh"
#include "com/centreon/broker/io/protocols.hh"

using namespace com::centreon::broker;

static unsigned int neb_instances(0);

extern "C" {
  /**
   *  Module version symbol. Used to check for version mismatch.
   */
  char const* broker_module_version = CENTREON_BROKER_VERSION;

  /**
   *  Module deinitialization routine.
   */
  void broker_module_deinit() {
    if (!--neb_instances) {
      // Remove factory.
      io::protocols::instance().unreg("node_events");

      // Remove events.
      io::events::instance().unregister_category(io::events::neb);
    }
    return ;
  }

  /**
   *  Module initialization routine.
   *
   *  @param[in] arg Configuration object.
   */
  void broker_module_init(void const* arg) {
    (void)arg;
    if (!neb_instances++) {
      logging::info(logging::high)
        << "NEB: module for Centreon Broker "
        << CENTREON_BROKER_VERSION;
      io::events& e(io::events::instance());

      // Register category.
      int neb_category(e.register_category("neb", io::events::neb));
      if (neb_category != io::events::neb) {
        e.unregister_category(neb_category);
        --neb_instances;
        throw (exceptions::msg() << "NEB: category " << io::events::neb
               << " is already registered whereas it should be "
               << "reserved for the NEB module");
      }

      // Register events.
      {
        e.register_event(
            io::events::neb,
            neb::de_acknowledgement,
            io::event_info(
                  "acknowledgement",
                  &neb::acknowledgement::operations,
                  neb::acknowledgement::entries,
                  "rt_acknowledgements",
                  "acknowledgements"));
        e.register_event(
            io::events::neb,
            neb::de_comment,
            io::event_info(
                  "comment",
                  &neb::comment::operations,
                  neb::comment::entries,
                  "",
                  "comments"));
        e.register_event(
            io::events::neb,
            neb::de_custom_variable,
            io::event_info(
                  "custom_variable",
                  &neb::custom_variable::operations,
                  neb::custom_variable::entries,
                  "rt_customvariables",
                  "customvariables"));
        e.register_event(
            io::events::neb,
            neb::de_custom_variable_status,
            io::event_info(
                  "custom_variable_status",
                  &neb::custom_variable_status::operations,
                  neb::custom_variable_status::entries,
                  "rt_customvariables",
                  "customvariables"));
        e.register_event(
            io::events::neb,
            neb::de_downtime,
            io::event_info(
                  "downtime",
                  &neb::downtime::operations,
                  neb::downtime::entries,
                  "rt_downtimes",
                  "downtimes"));
        e.register_event(
            io::events::neb,
            neb::de_event_handler,
            io::event_info(
                  "event_handler",
                  &neb::event_handler::operations,
                  neb::event_handler::entries,
                  "rt_eventhandlers",
                  "eventhandlers"));
        e.register_event(
            io::events::neb,
            neb::de_flapping_status,
            io::event_info(
                  "flapping_status",
                  &neb::flapping_status::operations,
                  neb::flapping_status::entries,
                  "rt_flappingstatuses",
                  "flappingstatuses"));
        e.register_event(
            io::events::neb,
            neb::de_host_check,
            io::event_info(
                  "host_check",
                  &neb::host_check::operations,
                  neb::host_check::entries,
                  "rt_hosts",
                  "hosts"));
        e.register_event(
            io::events::neb,
            neb::de_host_dependency,
            io::event_info(
                  "host_dependency",
                  &neb::host_dependency::operations,
                  neb::host_dependency::entries,
                  "rt_hosts_hosts_dependencies",
                  "hosts_hosts_dependencies"));
        e.register_event(
            io::events::neb,
            neb::de_host,
            io::event_info(
                  "host",
                  &neb::host::operations,
                  neb::host::entries,
                  "rt_hosts",
                  "hosts"));
        e.register_event(
            io::events::neb,
            neb::de_host_group,
            io::event_info(
                  "host_group",
                  &neb::host_group::operations,
                  neb::host_group::entries,
                  "",
                  "hostgroups"));
        e.register_event(
            io::events::neb,
            neb::de_host_group_member,
            io::event_info(
                  "host_group_member",
                  &neb::host_group_member::operations,
                  neb::host_group_member::entries,
                  "",
                  "hosts_hostgroups"));
        e.register_event(
            io::events::neb,
            neb::de_host_parent,
            io::event_info(
                  "host_parent",
                  &neb::host_parent::operations,
                  neb::host_parent::entries,
                  "rt_hosts_hosts_parents",
                  "hosts_hosts_parents"));
        e.register_event(
            io::events::neb,
            neb::de_host_status,
            io::event_info(
                  "host_status",
                  &neb::host_status::operations,
                  neb::host_status::entries,
                  "rt_hosts",
                  "hosts"));
        e.register_event(
            io::events::neb,
            neb::de_instance,
            io::event_info(
                  "instance",
                  &neb::instance::operations,
                  neb::instance::entries,
                  "rt_instances",
                  "instances"));
        e.register_event(
            io::events::neb,
            neb::de_instance_status,
            io::event_info(
                  "instance_status",
                  &neb::instance_status::operations,
                  neb::instance_status::entries,
                  "rt_instances",
                  "instances"));
        e.register_event(
            io::events::neb,
            neb::de_log_entry,
            io::event_info(
                  "log_entry",
                  &neb::log_entry::operations,
                  neb::log_entry::entries,
                  "log_logs",
                  "logs"));
        e.register_event(
            io::events::neb,
            neb::de_module,
            io::event_info(
                  "module",
                  &neb::module::operations,
                  neb::module::entries,
                  "rt_modules",
                  "modules"));
        e.register_event(
            io::events::neb,
            neb::de_service_check,
            io::event_info(
                  "service_check",
                  &neb::service_check::operations,
                  neb::service_check::entries,
                  "rt_services",
                  "services"));
        e.register_event(
            io::events::neb,
            neb::de_service_dependency,
            io::event_info(
                  "service_dependency",
                  &neb::service_dependency::operations,
                  neb::service_dependency::entries,
                  "rt_services_services_dependencies",
                  "services_services_dependencies"));
        e.register_event(
            io::events::neb,
            neb::de_service,
            io::event_info(
                  "service",
                  &neb::service::operations,
                  neb::service::entries,
                  "rt_services",
                  "services"));
        e.register_event(
            io::events::neb,
            neb::de_service_group,
            io::event_info(
                  "service_group",
                  &neb::service_group::operations,
                  neb::service_group::entries,
                  "",
                  "servicegroups"));
        e.register_event(
            io::events::neb,
            neb::de_service_group_member,
            io::event_info(
                  "service_group_member",
                  &neb::service_group_member::operations,
                  neb::service_group_member::entries,
                  "",
                  "services_servicegroups"));
        e.register_event(
            io::events::neb,
            neb::de_service_status,
            io::event_info(
                  "service_status",
                  &neb::service_status::operations,
                  neb::service_status::entries,
                  "rt_services",
                  "services"));
        e.register_event(
            io::events::neb,
            neb::de_instance_configuration,
            io::event_info(
                  "instance_configuration",
                  &neb::instance_configuration::operations,
                  neb::instance_configuration::entries));
      }

      // Register neb layer.
      io::protocols::instance().reg(
                                  "node_events",
                                  neb::node_events_factory(),
                                  1,
                                  7);
    }

    return ;
  }
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*! @file
    @brief  ネット・メイン @n
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/ip_adrs.hpp"
#include "common/dhcp_client.hpp"
#include "net2/ethernet.hpp"
#include "net2/net_st.hpp"

#define NET_MAIN_DEBUG

namespace net {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  net_main テンプレート・クラス
		@param[in]	ETHD	イーサーネット・ドライバー
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class ETHD>
	class net_main {
	public:
		typedef ethernet<ETHD> ETHERNET;

	private:
#ifndef NET_MAIN_DEBUG
		typedef utils::null_format debug_format;
#else
		typedef utils::format debug_format;
#endif

		enum class task : uint8_t {
			wait_link,	// リンクアップを待つ
			wait_dhcp,	// DHCP IP アドレスの取得を待つ
			main_init,	// メイン初期化
			main_loop,	// メインループ
			stall,		// ストール
		};

		ETHD&		ethd_;

		typedef dhcp_client<ETHD> DHCP;
		DHCP		dhcp_;

		ETHERNET	ethernet_;

		task		task_;

		uint8_t		link_interval_;
		uint8_t		stall_loop_;

		void set_tcpudp_env_()
		{
			const DHCP_INFO& info = dhcp_.get_info();
			info.list();
			ethernet_.at_info().ip.set(info.ipaddr);
			ethernet_.at_info().mask.set(info.maskaddr);
			ethernet_.at_info().gw.set(info.gwaddr);
			ethernet_.at_info().dns.set(info.dnsaddr);
			ethernet_.at_info().dns2.set(info.dnsaddr2);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	ETHD	イーサーネット・ドライバー・クラス
		*/
		//-----------------------------------------------------------------//
		net_main(ETHD& ethd) : ethd_(ethd), dhcp_(ethd), ethernet_(ethd),
			task_(task::wait_link), link_interval_(0), stall_loop_(0)
			{
				ethernet_.at_info().ip.set(192, 168, 3, 20);
				ethernet_.at_info().mask.set(255, 255, 255, 0);
				ethernet_.at_info().gw.set(192, 168, 3, 1);
				ethernet_.at_info().dns.set(192, 168, 3, 1);
			}

		//-----------------------------------------------------------------//
		/*!
			@brief  ネット情報を参照
			@return ネット情報
		*/
		//-----------------------------------------------------------------//
		const net_info& get_info() const { return ethernet_.get_info(); }

		//-----------------------------------------------------------------//
		/*!
			@brief  イーサーネットの参照
			@return	インサーネット
		*/
		//-----------------------------------------------------------------//
		ETHERNET& at_ethernet() { return ethernet_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  開始
			@param[in]	mac	インサーネット・コントローラー MAC アドレス
		*/
		//-----------------------------------------------------------------//
		bool start(const uint8_t* mac)
		{
			bool ret = ethd_.open(mac);
			if(ret) {
				debug_format("net_main: start OK\n");
				link_interval_ = 0;
				std::memcpy(ethernet_.at_info().mac, ethd_.get_mac(), 6);
				task_ = task::wait_link;
			} else {
				debug_format("net_main: start NG\n");
				task_ = task::stall;
			}
			return ret;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  プロセス（割り込みタスク）
		*/
		//-----------------------------------------------------------------//
		void process()
		{
			if(task_ == task::main_loop) {
				ethernet_.process();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  サービス（10ミリ秒毎に呼び出す）
		*/
		//-----------------------------------------------------------------//
		void service()
		{
			ethernet_.service();

			switch(task_) {

			case task::wait_link:
				{
					if(link_interval_ >= 100) {
						ethd_.polling_link_status();
						link_interval_ = 0;
						debug_format("net_main: PHY wait link loop\n");
					}
					++link_interval_;

					bool link = ethd_.service_link();
					if(link) {
						dhcp_.start();
						task_ = task::wait_dhcp;
					}
				}
				break;

			case task::wait_dhcp:
				dhcp_.service();
				if(dhcp_.get_info().state == DHCP_INFO::state_t::collect) {
					debug_format("net_main: DHCP Collect\n");
					set_tcpudp_env_();
					task_ = task::main_init;
				} else if(dhcp_.get_info().state == DHCP_INFO::state_t::timeout) {
					debug_format("net_main: DHCP Timeout (setup for fixed IP)\n");
					task_ = task::main_init;
				} else if(dhcp_.get_info().state == DHCP_INFO::state_t::error) {
					debug_format("net_main: DHCP Error\n");
					task_ = task::stall;
				}
				break;

			case task::main_init:
				ethd_.service_link();

				// test code
				{

				}

				task_ = task::main_loop;
				break;

			case task::main_loop:
				ethd_.service_link();

				if(link_interval_ >= 100) {
					ethd_.polling_link_status();
					link_interval_ = 0;
				}
				++link_interval_;

				if(!ethd_.get_stat().link_) {
					task_ = task::wait_link;
				}

				break;

			case task::stall:
				if(stall_loop_ >= 250) {
					debug_format("net_main: stall\n");
					stall_loop_ = 0;
				}
				++stall_loop_;
				break;

			default:
				break;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  メインを確認する
			@return 「true」なら、リンク
		*/
		//-----------------------------------------------------------------//
		bool check_main() const { return task_ == task::main_loop; }
	};
}
<commit_msg>add UDP test code<commit_after>#pragma once
//=====================================================================//
/*! @file
    @brief  ネット・メイン @n
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/ip_adrs.hpp"
#include "common/dhcp_client.hpp"
#include "net2/ethernet.hpp"
#include "net2/net_st.hpp"

#define NET_MAIN_DEBUG

namespace net {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  net_main テンプレート・クラス
		@param[in]	ETHD	イーサーネット・ドライバー
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class ETHD>
	class net_main {
	public:
		typedef ethernet<ETHD> ETHERNET;

	private:
#ifndef NET_MAIN_DEBUG
		typedef utils::null_format debug_format;
#else
		typedef utils::format debug_format;
#endif

		enum class task : uint8_t {
			wait_link,	// リンクアップを待つ
			wait_dhcp,	// DHCP IP アドレスの取得を待つ
			main_init,	// メイン初期化
			main_loop,	// メインループ
			stall,		// ストール
		};

		ETHD&		ethd_;

		typedef dhcp_client<ETHD> DHCP;
		DHCP		dhcp_;

		ETHERNET	ethernet_;

		task		task_;

		uint8_t		link_interval_;
		uint8_t		stall_loop_;

		int			udp_dsc_;

		void set_tcpudp_env_()
		{
			const DHCP_INFO& info = dhcp_.get_info();
			info.list();
			ethernet_.at_info().ip.set(info.ipaddr);
			ethernet_.at_info().mask.set(info.maskaddr);
			ethernet_.at_info().gw.set(info.gwaddr);
			ethernet_.at_info().dns.set(info.dnsaddr);
			ethernet_.at_info().dns2.set(info.dnsaddr2);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	ETHD	イーサーネット・ドライバー・クラス
		*/
		//-----------------------------------------------------------------//
		net_main(ETHD& ethd) : ethd_(ethd), dhcp_(ethd), ethernet_(ethd),
			task_(task::wait_link), link_interval_(0), stall_loop_(0),
			udp_dsc_(-1)
			{
				ethernet_.at_info().ip.set(192, 168, 3, 20);
				ethernet_.at_info().mask.set(255, 255, 255, 0);
				ethernet_.at_info().gw.set(192, 168, 3, 1);
				ethernet_.at_info().dns.set(192, 168, 3, 1);
			}

		//-----------------------------------------------------------------//
		/*!
			@brief  ネット情報を参照
			@return ネット情報
		*/
		//-----------------------------------------------------------------//
		const net_info& get_info() const { return ethernet_.get_info(); }

		//-----------------------------------------------------------------//
		/*!
			@brief  イーサーネットの参照
			@return	インサーネット
		*/
		//-----------------------------------------------------------------//
		ETHERNET& at_ethernet() { return ethernet_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  開始
			@param[in]	mac	インサーネット・コントローラー MAC アドレス
		*/
		//-----------------------------------------------------------------//
		bool start(const uint8_t* mac)
		{
			bool ret = ethd_.open(mac);
			if(ret) {
				debug_format("net_main: start OK\n");
				link_interval_ = 0;
				std::memcpy(ethernet_.at_info().mac, ethd_.get_mac(), 6);
				task_ = task::wait_link;
			} else {
				debug_format("net_main: start NG\n");
				task_ = task::stall;
			}
			return ret;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  プロセス（割り込みタスク）
		*/
		//-----------------------------------------------------------------//
		void process()
		{
			if(task_ == task::main_loop) {
				ethernet_.process();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  サービス（10ミリ秒毎に呼び出す）
		*/
		//-----------------------------------------------------------------//
		void service()
		{
			ethernet_.service();

			switch(task_) {

			case task::wait_link:
				{
					if(link_interval_ >= 100) {
						ethd_.polling_link_status();
						link_interval_ = 0;
						debug_format("net_main: PHY wait link loop\n");
					}
					++link_interval_;

					bool link = ethd_.service_link();
					if(link) {
						dhcp_.start();
						task_ = task::wait_dhcp;
					}
				}
				break;

			case task::wait_dhcp:
				dhcp_.service();
				if(dhcp_.get_info().state == DHCP_INFO::state_t::collect) {
					debug_format("net_main: DHCP Collect\n");
					set_tcpudp_env_();
					task_ = task::main_init;
				} else if(dhcp_.get_info().state == DHCP_INFO::state_t::timeout) {
					debug_format("net_main: DHCP Timeout (setup for fixed IP)\n");
					task_ = task::main_init;
				} else if(dhcp_.get_info().state == DHCP_INFO::state_t::error) {
					debug_format("net_main: DHCP Error\n");
					task_ = task::stall;
				}
				break;

			case task::main_init:
				ethd_.service_link();

				// test code
				{
					auto& ipv4 = ethernet_.at_ipv4();
					auto& udp  = ipv4.at_udp();

					udp_dsc_ = udp.open(ip_adrs(), 3000, 3000);

				}

				task_ = task::main_loop;
				break;

			case task::main_loop:
				ethd_.service_link();

				if(link_interval_ >= 100) {
					ethd_.polling_link_status();
					link_interval_ = 0;
				}
				++link_interval_;

				if(!ethd_.get_stat().link_) {
					task_ = task::wait_link;
				}

				break;

			case task::stall:
				if(stall_loop_ >= 250) {
					debug_format("net_main: stall\n");
					stall_loop_ = 0;
				}
				++stall_loop_;
				break;

			default:
				break;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  メインを確認する
			@return 「true」なら、リンク
		*/
		//-----------------------------------------------------------------//
		bool check_main() const { return task_ == task::main_loop; }
	};
}
<|endoftext|>