<commit_before>//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   src/Transfer_Evaluator.hh
 * \author Stuart Slattery
 * \date   Wed Oct 05 11:02:59 2011
 * \brief  Transfer_Evaluator class definition.
 */
//---------------------------------------------------------------------------//
// $Id: template.hh,v 1.4 2008/01/02 17:18:47 9te Exp $
//---------------------------------------------------------------------------//

#ifndef dtransfer_Transfer_Evaluator_hh
#define dtransfer_Transfer_Evaluator_hh

#include "comm/global.hh"
#include <vector>
#include <string>

namespace dtransfer
{

//===========================================================================//
/*!
 * \class Transfer_Evaluator
 * \brief Base class definition of the transfer evaluator interface.
 */
//===========================================================================//
template<class FieldType_T>
class Transfer_Evaluator
{
  public:

    //@{
    //! Useful typedefs.
    typedef FieldType_T                                   FieldType;
    typedef typename FieldType::value_type                ValueType;
    typedef typename ValueType::iterator                  Iterator;
    typedef typename ValueType::const_iterator            Const_Iterator;
    typedef nemesis::Communicator_t                       Communicator_t;
    //@}

    //! Constructor.
    Transfer_Evaluator()
    { /* ... */ }

    //! Destructor.
    virtual ~Transfer_Evaluator()
    { /* ... */ }

    //! Register communicator object.
    virtual void register_comm(Communicator_t &comm) = 0;

    //! Register a field associated with the entities. Return false if this
    //! field is not supported.
    virtual bool register_field(std::string field_name) = 0;

    //! Register entities with a field.
    virtual void register_xyz(std::string field_name,
			      std::vector<double> &points) = 0;

    //! Register the domain of a field. Return false if domain not supported
    //! for the field.
    virtual void register_domain(std::string field_name,
	                         Const_Iterator &begin,
				 Const_Iterator &end) = 0;

    //! Register the range of a field. Return false if range not supported for
    //! the field.
    virtual void register_range(std::string field_name,
				Iterator &begin,
				Iterator &end) = 0;

    //! Given (x,y,z) coordinates, return the local process rank in which that
    //! point exists and the iterator into the local data vector that will be
    //! applied at that point. Return true if point is in the local domain,
    //! false if not.
    virtual bool find_xyz(double x,
			  double y,
			  double z,
			  int &rank,
			  Const_Iterator &value_iterator) = 0;

    //! Pull data from a field.
    virtual void pull_data(std::string field_name,
			   Data_Vector &data) = 0;

    //! Push data onto a field.
    virtual void push_data(std::string field_name,
			   Data_Vector data) = 0;
};

} // end namespace dtransfer

#endif // dtransfer_Transfer_Evaluator_hh

//---------------------------------------------------------------------------//
//              end of src/Transfer_Evaluator.hh
//---------------------------------------------------------------------------//
<commit_msg>Added a field integration and field rebalance method to the interface.<commit_after>//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   src/Transfer_Evaluator.hh
 * \author Stuart Slattery
 * \date   Wed Oct 05 11:02:59 2011
 * \brief  Transfer_Evaluator class definition.
 */
//---------------------------------------------------------------------------//
// $Id: template.hh,v 1.4 2008/01/02 17:18:47 9te Exp $
//---------------------------------------------------------------------------//

#ifndef dtransfer_Transfer_Evaluator_hh
#define dtransfer_Transfer_Evaluator_hh

#include "comm/global.hh"
#include <vector>
#include <string>

namespace dtransfer
{

//===========================================================================//
/*!
 * \class Transfer_Evaluator
 * \brief Base class definition of the transfer evaluator interface.
 */
//===========================================================================//
template<class FieldType_T>
class Transfer_Evaluator
{
  public:

    //@{
    //! Useful typedefs.
    typedef FieldType_T                                   FieldType;
    typedef typename FieldType::value_type                ValueType;
    typedef typename ValueType::iterator                  Iterator;
    typedef typename ValueType::const_iterator            Const_Iterator;
    typedef nemesis::Communicator_t                       Communicator_t;
    //@}

    //! Constructor.
    Transfer_Evaluator()
    { /* ... */ }

    //! Destructor.
    virtual ~Transfer_Evaluator()
    { /* ... */ }

    //! Register communicator object.
    virtual void register_comm(Communicator_t &comm) = 0;

    //! Register a field associated with the entities. Return false if this
    //! field is not supported.
    virtual bool register_field(std::string field_name) = 0;

    //! Register entities with a field.
    virtual void register_xyz(std::string field_name,
			      std::vector<double> &points) = 0;

    //! Register the domain of a field. Return false if domain not supported
    //! for the field.
    virtual void register_domain(std::string field_name,
	                         Const_Iterator &begin,
				 Const_Iterator &end) = 0;

    //! Register the range of a field. Return false if range not supported for
    //! the field.
    virtual void register_range(std::string field_name,
				Iterator &begin,
				Iterator &end) = 0;

    //! Given (x,y,z) coordinates, return the local process rank in which that
    //! point exists and the iterator into the local data vector that will be
    //! applied at that point. Return true if point is in the local domain,
    //! false if not.
    virtual bool find_xyz(double x,
			  double y,
			  double z,
			  int &rank,
			  Const_Iterator &value_iterator) = 0;

    //! Perfom a global integration on a field for rebalance.
    virtual void integrate_field(std::string field_name,
				 ValueType &field_norm) = 0;

    //! Perform a rebalance on a field for global/local conservation.
    virtual void rebalance(std::string field_name,
			   ValueType field_norm) = 0;
};

} // end namespace dtransfer

#endif // dtransfer_Transfer_Evaluator_hh

//---------------------------------------------------------------------------//
//              end of src/Transfer_Evaluator.hh
//---------------------------------------------------------------------------//
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */

#if MBED_CONF_NSAPI_PRESENT

#include "ONBOARD_QUECTEL_BG96.h"

#include "gpio_api.h"
#include "platform/mbed_thread.h"
#include "PinNames.h"
#include "drivers/BufferedSerial.h"

#define WAIT_AFTER_POWR_CHANGED (1000)  // [msec.]

using namespace mbed;

ONBOARD_QUECTEL_BG96::ONBOARD_QUECTEL_BG96(FileHandle *fh) : QUECTEL_BG96(fh)
{
    onboard_modem_init();
}

nsapi_error_t ONBOARD_QUECTEL_BG96::hard_power_on()
{
    onboard_modem_init();
    return NSAPI_ERROR_OK;
}

nsapi_error_t ONBOARD_QUECTEL_BG96::hard_power_off()
{
    onboard_modem_deinit();
    return NSAPI_ERROR_OK;
}

nsapi_error_t ONBOARD_QUECTEL_BG96::soft_power_on()
{
    onboard_modem_power_up();
    return NSAPI_ERROR_OK;
}

nsapi_error_t ONBOARD_QUECTEL_BG96::soft_power_off()
{
    onboard_modem_power_down();
    return NSAPI_ERROR_OK;
}

void ONBOARD_QUECTEL_BG96::press_power_button(int time_ms)
{
    gpio_t gpio;

    gpio_init_out_ex(&gpio, PWRKEY, 1);
    thread_sleep_for(time_ms);
    gpio_write(&gpio, 0);
}

void ONBOARD_QUECTEL_BG96::onboard_modem_init()
{
    gpio_t gpio;

    // Power Supply
    gpio_init_out_ex(&gpio, M_POWR, 0);
    // Turn On/Off
    gpio_init_out_ex(&gpio, PWRKEY, 0);
    gpio_init_out_ex(&gpio, RESET_MODULE, 0);
    // Status Indication
    gpio_init_in_ex(&gpio, MDMSTAT, PullUp);
    // Main UART Interface
    gpio_init_out_ex(&gpio, MDMDTR, 0);

    thread_sleep_for(WAIT_AFTER_POWR_CHANGED);
}

void ONBOARD_QUECTEL_BG96::onboard_modem_deinit()
{
    onboard_modem_power_down();
}

void ONBOARD_QUECTEL_BG96::onboard_modem_power_up()
{
    gpio_t gpio;

    // Power supply ON
    gpio_init_out_ex(&gpio, M_POWR, 1);
    thread_sleep_for(WAIT_AFTER_POWR_CHANGED);

    // Turn on
    thread_sleep_for(100);
    press_power_button(200);
}

void ONBOARD_QUECTEL_BG96::onboard_modem_power_down()
{
    gpio_t gpio;

    // Power supply OFF
    gpio_init_out_ex(&gpio, M_POWR, 0);
    thread_sleep_for(WAIT_AFTER_POWR_CHANGED);
}

CellularDevice *CellularDevice::get_target_default_instance()
{
    static BufferedSerial serial(MDMTXD, MDMRXD, 115200);
    static ONBOARD_QUECTEL_BG96 device(&serial);
    return &device;
}

#endif // MBED_CONF_NSAPI_PRESENT
<commit_msg>WIO_BG96: fix macro exclusion - use cellular<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */

#if MBED_CONF_CELLULAR_PRESENT

#include "ONBOARD_QUECTEL_BG96.h"

#include "gpio_api.h"
#include "platform/mbed_thread.h"
#include "PinNames.h"
#include "drivers/BufferedSerial.h"

#define WAIT_AFTER_POWR_CHANGED (1000)  // [msec.]

using namespace mbed;

ONBOARD_QUECTEL_BG96::ONBOARD_QUECTEL_BG96(FileHandle *fh) : QUECTEL_BG96(fh)
{
    onboard_modem_init();
}

nsapi_error_t ONBOARD_QUECTEL_BG96::hard_power_on()
{
    onboard_modem_init();
    return NSAPI_ERROR_OK;
}

nsapi_error_t ONBOARD_QUECTEL_BG96::hard_power_off()
{
    onboard_modem_deinit();
    return NSAPI_ERROR_OK;
}

nsapi_error_t ONBOARD_QUECTEL_BG96::soft_power_on()
{
    onboard_modem_power_up();
    return NSAPI_ERROR_OK;
}

nsapi_error_t ONBOARD_QUECTEL_BG96::soft_power_off()
{
    onboard_modem_power_down();
    return NSAPI_ERROR_OK;
}

void ONBOARD_QUECTEL_BG96::press_power_button(int time_ms)
{
    gpio_t gpio;

    gpio_init_out_ex(&gpio, PWRKEY, 1);
    thread_sleep_for(time_ms);
    gpio_write(&gpio, 0);
}

void ONBOARD_QUECTEL_BG96::onboard_modem_init()
{
    gpio_t gpio;

    // Power Supply
    gpio_init_out_ex(&gpio, M_POWR, 0);
    // Turn On/Off
    gpio_init_out_ex(&gpio, PWRKEY, 0);
    gpio_init_out_ex(&gpio, RESET_MODULE, 0);
    // Status Indication
    gpio_init_in_ex(&gpio, MDMSTAT, PullUp);
    // Main UART Interface
    gpio_init_out_ex(&gpio, MDMDTR, 0);

    thread_sleep_for(WAIT_AFTER_POWR_CHANGED);
}

void ONBOARD_QUECTEL_BG96::onboard_modem_deinit()
{
    onboard_modem_power_down();
}

void ONBOARD_QUECTEL_BG96::onboard_modem_power_up()
{
    gpio_t gpio;

    // Power supply ON
    gpio_init_out_ex(&gpio, M_POWR, 1);
    thread_sleep_for(WAIT_AFTER_POWR_CHANGED);

    // Turn on
    thread_sleep_for(100);
    press_power_button(200);
}

void ONBOARD_QUECTEL_BG96::onboard_modem_power_down()
{
    gpio_t gpio;

    // Power supply OFF
    gpio_init_out_ex(&gpio, M_POWR, 0);
    thread_sleep_for(WAIT_AFTER_POWR_CHANGED);
}

CellularDevice *CellularDevice::get_target_default_instance()
{
    static BufferedSerial serial(MDMTXD, MDMRXD, 115200);
    static ONBOARD_QUECTEL_BG96 device(&serial);
    return &device;
}

#endif // MBED_CONF_CELLULAR_PRESENT
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** 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.
**
****************************************************************************/

#include "mlayout.h"
#include "mlayout_p.h"

#include "mapplication.h"
#include "mabstractlayoutpolicy.h"
#include "mabstractlayoutpolicy_p.h"
#include "mbasiclayoutanimation.h"
#include "morientationchangeevent.h"

#include <QGraphicsItem>
#include <QApplication>
#include <MDebug>

MLayout::MLayout(QGraphicsLayoutItem *parent) :
    QGraphicsLayout(parent),
    d_ptr(new MLayoutPrivate(this))
{
    Q_ASSERT(0 != d_ptr);
    d_ptr->recheckOrientation(false);
    // Disabling layout animations by default
    // new MBasicLayoutAnimation(this);
}

MLayout::~MLayout()
{
    Q_D(MLayout);
    d->current_policy = NULL;  //Make sure we have no policy before

    qDeleteAll(d->policies);
    delete d->animation;
    //Remove all the items from the layout and delete any layouts
    //(which are ownedByLayout) inside this layout
    //Because we don't have any policies, this should be pretty fast
    for (int i = count() - 1; i >= 0; --i) {
        const MLayoutPrivate::LayoutItem &item = d->items.at(i);
        if (item.item) {
            item.item->setParentLayoutItem(0);
            if (item.item->ownedByLayout() || item.toBeDeleted)
                delete item.item;
        }
    }
    delete d_ptr;
}

// Reimplemented from QGraphicsLayout
void MLayout::invalidate()
{
    Q_D(MLayout);
    //We need to check if the orientation has changed.  This can cause the current policy to change
    //Unfortunately, this is the only function called when widget->setLayout(layout)  is called.
    d->recheckOrientation();

    if (d->current_policy)
        d->current_policy->invalidate();
    QGraphicsLayout::invalidate();
    //This following warning is useful, but too many false negatives :-/
//    if(!parentLayoutItem())
//        mWarning("MLayout") << "MLayout does not have a parent - layouting will not be correct.  Add the layout to a QGraphicsWidget";
}

void MLayout::invalidateLayoutOnly()
{
    QGraphicsLayout::invalidate();
}

int MLayout::count() const
{
    Q_D(const MLayout);
    return d->items.count();
}
bool MLayout::isEmpty() const
{
    Q_D(const MLayout);
    return d->items.isEmpty();
}
QGraphicsLayoutItem *MLayout::itemAt(int index) const
{
    Q_D(const MLayout);
    if (0 > index || count() <= index) {
        mWarning("MLayout") << Q_FUNC_INFO << "Attempting to access item at index" << index << "when there are" << count() << "items";
        return NULL;
    }
    return d->items.at(index).item;
}

void MLayout::removeAt(int index)
{
    (void)takeAt(index);
}

QGraphicsLayoutItem *MLayout::takeAt(int index)
{
    Q_D(MLayout);
    if (0 > index || count() <= index) {
        if (index != 0) //It's common to just try deleting the first item until there are none left, so suppress this warning for index=0
            mWarning("MLayout") << Q_FUNC_INFO << "Attempting to remove item at index" << index << "when there are" << count() << "items";
        return NULL;
    }
    bool toBeDeleted = d->items.at(index).toBeDeleted;
    QGraphicsLayoutItem *item = d->items.at(index).item;
    Q_ASSERT(item);
    //First remove the item from all the policies, then update the indexes using aboutToBeRemovedFromLayout
    //We cannot do this in once pass since removeAt() is virtual and can do pretty much anything
    foreach(MAbstractLayoutPolicy * policy, d->policies) {
        Q_ASSERT(policy);
        int policyIndex = policy->indexOf(item);
        if (policyIndex >= 0 ) {
            policy->d_ptr->removingFromLayout = true;  //Indicate to the policy to remove the item but not to hide it
            policy->removeAt(policyIndex);
            policy->d_ptr->removingFromLayout = false;
        }
    }
    foreach(MAbstractLayoutPolicy * policy, d->policies) {
        policy->d_ptr->aboutToBeRemovedFromLayout(index);
    }
    if (d->animation)
        d->animation->itemRemovedFromLayout(index);

    d->items.removeAt(index);
    item->setParentLayoutItem(NULL);
    invalidate();
    if (toBeDeleted) {
        delete item;
        return NULL;
    }
    /* We cannot actually show the item as it might be in the process of being deleted */
    d->removeHiddenFlag(item->graphicsItem());
    return item;
}

void MLayout::animatedDeleteItem(const QGraphicsLayoutItem * item)
{
    animatedDeleteAt(indexOf(item));
}

void MLayout::animatedDeleteAt(int index)
{
    Q_D(MLayout);
    if (0 > index || count() <= index) {
        if (index != 0)
            mWarning("MLayout") << Q_FUNC_INFO << "Attempting to remove item at index" << index << "when there are" << count() << "items";
        return;
    }

    const MLayoutPrivate::LayoutItem &item = d->items.at(index);
    // Abort if already scheduled for deletion
    // (this can happen because a graphics layout item removes itself from its
    //  layout upon destruction and would lead to an infinite recursion here)
    if (item.toBeDeleted)
        return;

    if (d->animation && item.item->graphicsItem() && item.item->graphicsItem()->isWidget()) {
        if (item.toBeDeleted)
            return; //Already set
        d->items[index].toBeDeleted = true;
        d->animation->animatedDeleteItem(index);
    } else {
        delete takeAt(index); //Delete immediately if we can't animate it
    }
}

// QGraphicsLayoutItem:

QSizeF MLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    Q_D(const MLayout);
    if (d->current_policy) {
        return d->current_policy->sizeHint(which, constraint);
    }
    return QSizeF(-1, -1);
}

void MLayout::setGeometry(const QRectF &rect)
{
    Q_D(MLayout);
    QRectF previousGeometry = geometry();
    //setGeometry is also called when the layout is activated after being invalidated
    //so we should always setGeometry even if the rect has not changed

    //Note that setGeometry first adjusts rect to obey the sizehints, so our actual geometry
    //afterwards is not necessarily equal to the parameter 'rect'.
    QGraphicsLayout::setGeometry(rect);

    if (d->current_policy) {
        d->current_policy->relayout();
        //If the width really has changed and our height depends on the width, we need to recalculate
        //the width.
        if (d->current_policy->hasHeightForWidth() && previousGeometry.width() != geometry().width())
            updateGeometry(); //Since the height sizeHint has changed, we need to invalidate the current size hint
    }

}

int MLayout::addItem(QGraphicsLayoutItem *item)
{
    Q_D(MLayout);
    // do we know this item already?
    if (!item)
        return -1; //error
    int index = indexOf(item);
    if (index < 0) {
        // If the item is a layout, we need to add all of its items
        addChildLayoutItem(item);
        // Add item
        index = d->items.size();

        MLayoutPrivate::LayoutItem layoutItem;
        layoutItem.item = item;
        layoutItem.toBeDeleted = false;
        layoutItem.geometry = item->geometry();
        d->items.append(layoutItem);
        // Hide item for now since we do not know where to place it
        if(item->graphicsItem())
            d->hideItemNow(item->graphicsItem());
        if(d->animation)
            d->animation->itemAddedToLayout(index);
    }
    return index;
}

void MLayout::removeItem(const QGraphicsLayoutItem *const item)
{
    if (0 == item) {
        return;
    }

    int index = indexOf(item);
    if (index == -1)
        return; //Should we display a warning?
    removeAt(index);
}

int MLayout::indexOf(const QGraphicsItem *item) const
{
    Q_D(const MLayout);
    if (0 == item) {
        return -1;
    }

    const int theCount = count();
    for (int i = 0; i < theCount; ++i) {
        if (d->items.at(i).item->graphicsItem() == item) {
            return i;
        }
    }

    return -1;
}

int MLayout::indexOf(const QGraphicsLayoutItem *item) const
{
    Q_D(const MLayout);
    if (0 == item) {
        return -1;
    }

    const int theCount = count();
    for (int i = 0; i < theCount; ++i) {
        if (d->items.at(i).item == item) {
            return i;
        }
    }

    return -1;
}

void MLayout::setPolicy(MAbstractLayoutPolicy *policy)
{
    Q_D(MLayout);
    if (d->current_policy == policy)
        return;

    d->current_policy = policy;

    QSizePolicy newSizePolicy(sizePolicy());
    newSizePolicy.setHeightForWidth(d->current_policy?d->current_policy->hasHeightForWidth():false);
    setSizePolicy(newSizePolicy);

    if (d->current_policy) {
        Q_ASSERT(d->policies.contains(policy));
        policy->activated();
    }
    invalidate();
    //Note that the policy might not be fully constructed yet, since we might still be in the
    //MAbstractLayoutPolicy constructor.  So we cannot immediately do a re-layout - we have to
    //invalidate, waiting until the next event loop to activate()
}
void MLayout::setLandscapePolicy(MAbstractLayoutPolicy *policy)
{
    Q_D(MLayout);
    if (d->landscapePolicy == policy)
        return;
    d->landscapePolicy = policy;
    Q_ASSERT(!policy || policy->layout() == this);
    d->recheckOrientation();
    if (d->landscapePolicy && d->m_orientation == M::Landscape) {
        policy->activate();
    }
}
MAbstractLayoutPolicy *MLayout::landscapePolicy() const
{
    Q_D(const MLayout);
    return d->landscapePolicy;
}

void MLayout::setPortraitPolicy(MAbstractLayoutPolicy *policy)
{
    Q_D(MLayout);
    if (d->portraitPolicy == policy)
        return;
    d->portraitPolicy = policy;
    Q_ASSERT(!policy || policy->layout() == this);
    d->recheckOrientation();
    if (d->portraitPolicy && d->m_orientation == M::Portrait) {
        policy->activate();
    }
}
MAbstractLayoutPolicy *MLayout::portraitPolicy() const
{
    Q_D(const MLayout);
    return d->portraitPolicy;
}

MAbstractLayoutPolicy *MLayout::policy() const
{
    Q_D(const MLayout);
    return d->current_policy;
}

QList<MAbstractLayoutPolicy *> MLayout::registeredPolicies() const
{
    Q_D(const MLayout);
    return d->policies;
}

void MLayout::setAnimation(MLayoutAnimation *animation)
{
    Q_D(MLayout);
    delete d->animation;
    d->animation = animation;
}

MLayoutAnimation *MLayout::animation() const
{
    Q_D(const MLayout);
    return d->animation;
}

void MLayout::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
{
    QGraphicsLayout::setContentsMargins(left, top, right, bottom);
}

void MLayout::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
{
    Q_D(const MLayout);
    //If there is a current policy, give it a chance to override current margins
    if (d->current_policy)
        d->current_policy->getContentsMargins(left, top, right, bottom);

    //if the policy returned negative values, use the QGraphicsLayout margins, otherwise do not change.
    if (left && *left >= 0)
        left = NULL;
    if (top && *top >= 0)
        top = NULL;
    if (right && *right >= 0)
        right = NULL;
    if (bottom && *bottom >= 0)
        bottom = NULL;

    QGraphicsLayout::getContentsMargins(left, top, right, bottom);
}

/* This function was copied from Qt 4.5's qgraphicslayout_p.cpp's visualDirection*/
Qt::LayoutDirection MLayout::layoutDirection() const
{
    Q_D(const MLayout);
    if (QGraphicsItem *maybeWidget = d->parentItem()) {
        if (maybeWidget->isWidget())
            return static_cast<QGraphicsWidget *>(maybeWidget)->layoutDirection();
    }
    return QApplication::layoutDirection();
}
void MLayout::widgetEvent ( QEvent * event )
{
    Q_D(MLayout);
    if(event->type() == QEvent::ParentChange || event->type() == QEvent::PolishRequest) {
        d->recheckOrientation();
    } else if(event->type() == MOrientationChangeEvent::eventNumber()) {
        MOrientationChangeEvent *oce = static_cast<MOrientationChangeEvent *>(event);
        d->setOrientation(oce->orientation());
        activate();
    }

    QGraphicsLayout::widgetEvent(event);
}
<commit_msg>Changes: Improve performance for orientation changes<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** 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.
**
****************************************************************************/

#include "mlayout.h"
#include "mlayout_p.h"

#include "mapplication.h"
#include "mabstractlayoutpolicy.h"
#include "mabstractlayoutpolicy_p.h"
#include "mbasiclayoutanimation.h"
#include "morientationchangeevent.h"

#include <QGraphicsItem>
#include <QApplication>
#include <MDebug>

MLayout::MLayout(QGraphicsLayoutItem *parent) :
    QGraphicsLayout(parent),
    d_ptr(new MLayoutPrivate(this))
{
    Q_ASSERT(0 != d_ptr);
    d_ptr->recheckOrientation(false);
    // Disabling layout animations by default
    // new MBasicLayoutAnimation(this);
}

MLayout::~MLayout()
{
    Q_D(MLayout);
    d->current_policy = NULL;  //Make sure we have no policy before

    qDeleteAll(d->policies);
    delete d->animation;
    //Remove all the items from the layout and delete any layouts
    //(which are ownedByLayout) inside this layout
    //Because we don't have any policies, this should be pretty fast
    for (int i = count() - 1; i >= 0; --i) {
        const MLayoutPrivate::LayoutItem &item = d->items.at(i);
        if (item.item) {
            item.item->setParentLayoutItem(0);
            if (item.item->ownedByLayout() || item.toBeDeleted)
                delete item.item;
        }
    }
    delete d_ptr;
}

// Reimplemented from QGraphicsLayout
void MLayout::invalidate()
{
    Q_D(MLayout);
    //We need to check if the orientation has changed.  This can cause the current policy to change
    //Unfortunately, this is the only function called when widget->setLayout(layout)  is called.
    d->recheckOrientation();

    if (d->current_policy)
        d->current_policy->invalidate();
    QGraphicsLayout::invalidate();
    //This following warning is useful, but too many false negatives :-/
//    if(!parentLayoutItem())
//        mWarning("MLayout") << "MLayout does not have a parent - layouting will not be correct.  Add the layout to a QGraphicsWidget";
}

void MLayout::invalidateLayoutOnly()
{
    QGraphicsLayout::invalidate();
}

int MLayout::count() const
{
    Q_D(const MLayout);
    return d->items.count();
}
bool MLayout::isEmpty() const
{
    Q_D(const MLayout);
    return d->items.isEmpty();
}
QGraphicsLayoutItem *MLayout::itemAt(int index) const
{
    Q_D(const MLayout);
    if (0 > index || count() <= index) {
        mWarning("MLayout") << Q_FUNC_INFO << "Attempting to access item at index" << index << "when there are" << count() << "items";
        return NULL;
    }
    return d->items.at(index).item;
}

void MLayout::removeAt(int index)
{
    (void)takeAt(index);
}

QGraphicsLayoutItem *MLayout::takeAt(int index)
{
    Q_D(MLayout);
    if (0 > index || count() <= index) {
        if (index != 0) //It's common to just try deleting the first item until there are none left, so suppress this warning for index=0
            mWarning("MLayout") << Q_FUNC_INFO << "Attempting to remove item at index" << index << "when there are" << count() << "items";
        return NULL;
    }
    bool toBeDeleted = d->items.at(index).toBeDeleted;
    QGraphicsLayoutItem *item = d->items.at(index).item;
    Q_ASSERT(item);
    //First remove the item from all the policies, then update the indexes using aboutToBeRemovedFromLayout
    //We cannot do this in once pass since removeAt() is virtual and can do pretty much anything
    foreach(MAbstractLayoutPolicy * policy, d->policies) {
        Q_ASSERT(policy);
        int policyIndex = policy->indexOf(item);
        if (policyIndex >= 0 ) {
            policy->d_ptr->removingFromLayout = true;  //Indicate to the policy to remove the item but not to hide it
            policy->removeAt(policyIndex);
            policy->d_ptr->removingFromLayout = false;
        }
    }
    foreach(MAbstractLayoutPolicy * policy, d->policies) {
        policy->d_ptr->aboutToBeRemovedFromLayout(index);
    }
    if (d->animation)
        d->animation->itemRemovedFromLayout(index);

    d->items.removeAt(index);
    item->setParentLayoutItem(NULL);
    invalidate();
    if (toBeDeleted) {
        delete item;
        return NULL;
    }
    /* We cannot actually show the item as it might be in the process of being deleted */
    d->removeHiddenFlag(item->graphicsItem());
    return item;
}

void MLayout::animatedDeleteItem(const QGraphicsLayoutItem * item)
{
    animatedDeleteAt(indexOf(item));
}

void MLayout::animatedDeleteAt(int index)
{
    Q_D(MLayout);
    if (0 > index || count() <= index) {
        if (index != 0)
            mWarning("MLayout") << Q_FUNC_INFO << "Attempting to remove item at index" << index << "when there are" << count() << "items";
        return;
    }

    const MLayoutPrivate::LayoutItem &item = d->items.at(index);
    // Abort if already scheduled for deletion
    // (this can happen because a graphics layout item removes itself from its
    //  layout upon destruction and would lead to an infinite recursion here)
    if (item.toBeDeleted)
        return;

    if (d->animation && item.item->graphicsItem() && item.item->graphicsItem()->isWidget()) {
        if (item.toBeDeleted)
            return; //Already set
        d->items[index].toBeDeleted = true;
        d->animation->animatedDeleteItem(index);
    } else {
        delete takeAt(index); //Delete immediately if we can't animate it
    }
}

// QGraphicsLayoutItem:

QSizeF MLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    Q_D(const MLayout);
    if (d->current_policy) {
        return d->current_policy->sizeHint(which, constraint);
    }
    return QSizeF(-1, -1);
}

void MLayout::setGeometry(const QRectF &rect)
{
    Q_D(MLayout);
    QRectF previousGeometry = geometry();
    //setGeometry is also called when the layout is activated after being invalidated
    //so we should always setGeometry even if the rect has not changed

    //Note that setGeometry first adjusts rect to obey the sizehints, so our actual geometry
    //afterwards is not necessarily equal to the parameter 'rect'.
    QGraphicsLayout::setGeometry(rect);

    if (d->current_policy) {
        d->current_policy->relayout();
        //If the width really has changed and our height depends on the width, we need to recalculate
        //the width.
        if (d->current_policy->hasHeightForWidth() && previousGeometry.width() != geometry().width())
            updateGeometry(); //Since the height sizeHint has changed, we need to invalidate the current size hint
    }

}

int MLayout::addItem(QGraphicsLayoutItem *item)
{
    Q_D(MLayout);
    // do we know this item already?
    if (!item)
        return -1; //error
    int index = indexOf(item);
    if (index < 0) {
        // If the item is a layout, we need to add all of its items
        addChildLayoutItem(item);
        // Add item
        index = d->items.size();

        MLayoutPrivate::LayoutItem layoutItem;
        layoutItem.item = item;
        layoutItem.toBeDeleted = false;
        layoutItem.geometry = item->geometry();
        d->items.append(layoutItem);
        // Hide item for now since we do not know where to place it
        if(item->graphicsItem())
            d->hideItemNow(item->graphicsItem());
        if(d->animation)
            d->animation->itemAddedToLayout(index);
    }
    return index;
}

void MLayout::removeItem(const QGraphicsLayoutItem *const item)
{
    if (0 == item) {
        return;
    }

    int index = indexOf(item);
    if (index == -1)
        return; //Should we display a warning?
    removeAt(index);
}

int MLayout::indexOf(const QGraphicsItem *item) const
{
    Q_D(const MLayout);
    if (0 == item) {
        return -1;
    }

    const int theCount = count();
    for (int i = 0; i < theCount; ++i) {
        if (d->items.at(i).item->graphicsItem() == item) {
            return i;
        }
    }

    return -1;
}

int MLayout::indexOf(const QGraphicsLayoutItem *item) const
{
    Q_D(const MLayout);
    if (0 == item) {
        return -1;
    }

    const int theCount = count();
    for (int i = 0; i < theCount; ++i) {
        if (d->items.at(i).item == item) {
            return i;
        }
    }

    return -1;
}

void MLayout::setPolicy(MAbstractLayoutPolicy *policy)
{
    Q_D(MLayout);
    if (d->current_policy == policy)
        return;

    d->current_policy = policy;

    QSizePolicy newSizePolicy(sizePolicy());
    newSizePolicy.setHeightForWidth(d->current_policy?d->current_policy->hasHeightForWidth():false);
    setSizePolicy(newSizePolicy);

    if (d->current_policy) {
        Q_ASSERT(d->policies.contains(policy));
        policy->activated();
    }
    invalidate();
    //Note that the policy might not be fully constructed yet, since we might still be in the
    //MAbstractLayoutPolicy constructor.  So we cannot immediately do a re-layout - we have to
    //invalidate, waiting until the next event loop to activate()
}
void MLayout::setLandscapePolicy(MAbstractLayoutPolicy *policy)
{
    Q_D(MLayout);
    if (d->landscapePolicy == policy)
        return;
    d->landscapePolicy = policy;
    Q_ASSERT(!policy || policy->layout() == this);
    d->recheckOrientation();
    if (d->landscapePolicy && d->m_orientation == M::Landscape) {
        policy->activate();
    }
}
MAbstractLayoutPolicy *MLayout::landscapePolicy() const
{
    Q_D(const MLayout);
    return d->landscapePolicy;
}

void MLayout::setPortraitPolicy(MAbstractLayoutPolicy *policy)
{
    Q_D(MLayout);
    if (d->portraitPolicy == policy)
        return;
    d->portraitPolicy = policy;
    Q_ASSERT(!policy || policy->layout() == this);
    d->recheckOrientation();
    if (d->portraitPolicy && d->m_orientation == M::Portrait) {
        policy->activate();
    }
}
MAbstractLayoutPolicy *MLayout::portraitPolicy() const
{
    Q_D(const MLayout);
    return d->portraitPolicy;
}

MAbstractLayoutPolicy *MLayout::policy() const
{
    Q_D(const MLayout);
    return d->current_policy;
}

QList<MAbstractLayoutPolicy *> MLayout::registeredPolicies() const
{
    Q_D(const MLayout);
    return d->policies;
}

void MLayout::setAnimation(MLayoutAnimation *animation)
{
    Q_D(MLayout);
    delete d->animation;
    d->animation = animation;
}

MLayoutAnimation *MLayout::animation() const
{
    Q_D(const MLayout);
    return d->animation;
}

void MLayout::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
{
    QGraphicsLayout::setContentsMargins(left, top, right, bottom);
}

void MLayout::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
{
    Q_D(const MLayout);
    //If there is a current policy, give it a chance to override current margins
    if (d->current_policy)
        d->current_policy->getContentsMargins(left, top, right, bottom);

    //if the policy returned negative values, use the QGraphicsLayout margins, otherwise do not change.
    if (left && *left >= 0)
        left = NULL;
    if (top && *top >= 0)
        top = NULL;
    if (right && *right >= 0)
        right = NULL;
    if (bottom && *bottom >= 0)
        bottom = NULL;

    QGraphicsLayout::getContentsMargins(left, top, right, bottom);
}

/* This function was copied from Qt 4.5's qgraphicslayout_p.cpp's visualDirection*/
Qt::LayoutDirection MLayout::layoutDirection() const
{
    Q_D(const MLayout);
    if (QGraphicsItem *maybeWidget = d->parentItem()) {
        if (maybeWidget->isWidget())
            return static_cast<QGraphicsWidget *>(maybeWidget)->layoutDirection();
    }
    return QApplication::layoutDirection();
}
void MLayout::widgetEvent ( QEvent * event )
{
    Q_D(MLayout);
    if(event->type() == QEvent::ParentChange || event->type() == QEvent::PolishRequest) {
        d->recheckOrientation();
    } else if(event->type() == MOrientationChangeEvent::eventNumber()) {
        MOrientationChangeEvent *oce = static_cast<MOrientationChangeEvent *>(event);
        d->setOrientation(oce->orientation());
        QGraphicsLayout::invalidate();
    }

    QGraphicsLayout::widgetEvent(event);
}
<|endoftext|>


<commit_before>#include "XXX/pubsub_man.h"

#include "XXX/topic.h"
#include "XXX/event_loop.h"
#include "XXX/log_macros.h"
#include "XXX/wamp_session.h"
#include "XXX/kernel.h"
#include "XXX/utils.h"

#include <list>
#include <iostream>
#include <algorithm>

namespace XXX {

static bool session_equals(const session_handle& p1, const session_handle& p2)
{
  return ( !p1.owner_before(p2) && !p2.owner_before(p1) );
}

/*
Thread safety for pubsub.

Currently the public methods:

  - inbound_publish

  - subscribe

... are both called on the event loop thead, so presently no need for any
synchronization around the managed topics.  Additionally for the addition of a
new subscriber, the synchronization of the initially snapshot followed by
updates is also acheived through the single threaded approach.
*/
struct managed_topic
{
  std::vector< std::weak_ptr<wamp_session> > m_subscribers;

  // current upto date image of the value
  jalson::json_value image;

  t_subscription_id subscription_id() const { return m_subscription_id; }

  managed_topic(size_t __subscription_id)
  :  m_subscription_id(__subscription_id)
  {
  }

  uint64_t next_publication_id() { return m_id_gen.next(); }

  /** Add a subscriber to this topic. */
  void add(std::weak_ptr<wamp_session> wp)
  {
    auto it = std::find_if(std::begin(m_subscribers),
                           std::end(m_subscribers),
                           [wp](std::weak_ptr<wamp_session>& rhs)
                           {
                             return session_equals(wp,rhs);
                           });

    /* In WAMP it is not an error for a session to subscribe multiple times. So
     * we dont throw an exception here if the session is already subscribed. */
    if (it == std::end(m_subscribers))
      m_subscribers.push_back(wp);
  }

  /** Remove a subscriber from this topic. */
  void remove(std::weak_ptr<wamp_session> wp)
  {
    auto it = std::find_if(std::begin(m_subscribers),
                           std::end(m_subscribers),
                           [wp](std::weak_ptr<wamp_session>& rhs)
                           {
                             return session_equals(wp,rhs);
                           });

    /* In WAMP it is not an error for a session to subscribe multiple times. So
     * we dont throw an exception here if the session is not found. */
    if (it != std::end(m_subscribers))
      m_subscribers.erase(it);
  }

private:
  global_scope_id_generator m_id_gen;

  // Note, we are tieing the subscription ID direct to the topic.  WAMP does
  // allow this, and it has the benefit that we can perform a single message
  // serialisation for all subscribers.  Might have to change later if more
  // complex subscription features are supported.
  size_t m_subscription_id;
};

/* Constructor */
pubsub_man::pubsub_man(kernel& k)
  : __logger(k.get_logger()),
    m_next_subscription_id(1)  /* zero used for initial snapshot */
{
}

pubsub_man::~pubsub_man()
{
  // destructor needed here so that unique_ptr can see the definition of
  // managed_topic
}

managed_topic* pubsub_man::find_topic(const std::string& topic,
                                      const std::string& realm,
                                      bool allow_create)
{
  // first find the realm
  auto realm_iter = m_topics.find( realm );
  if (realm_iter == m_topics.end())
  {
    if (allow_create)
    {
      auto result = m_topics.insert(std::make_pair(realm, topic_registry()));
      realm_iter = result.first;
    }
    else
      return nullptr;
  }

  // now find the topic
  auto topic_iter = realm_iter->second.find( topic );
  if (topic_iter ==  realm_iter->second.end())
  {
    if (allow_create)
    {
      std::unique_ptr<managed_topic> ptr(new managed_topic(m_next_subscription_id++));
      m_subscription_registry[ptr->subscription_id()] = ptr.get();
      auto result = realm_iter->second.insert(std::make_pair(topic, std::move( ptr )));
      topic_iter = result.first;
    }
    else return nullptr;
  }

  return topic_iter->second.get();
}

void pubsub_man::update_topic(const std::string& topic,
                              const std::string& realm,
                              jalson::json_object options,
                              wamp_args args)
{
  /* EVENT thread */

  managed_topic* mt = find_topic(topic, realm, true);

  if (!mt)
  {
    LOG_WARN("Discarding update to non existing topic '" << topic << "'");
    return;
  }

  if (options.find(KEY_PATCH) != options.end() && args.args_list.is_array())
  {
    // apply the patch
    //std::cout << "@" << topic << ", patch\n";
    //std::cout << "BEFORE: " << mt->image << "\n";
    //std::cout << "PATCH : " << args.args_list << "\n";
    jalson::json_array & change = args.args_list.as_array();
    mt->image.patch(change[0].as_array());
    //std::cout << "AFTER : "  << mt->image << "\n";
    //std::cout << "-------\n";
  }

  // broadcast event to subscribers

  jalson::json_array msg;
  msg.reserve(6);
  msg.push_back( EVENT );
  msg.push_back( mt->subscription_id() );
  msg.push_back( mt->next_publication_id() );
  msg.push_back( std::move(options) );
  if (!args.args_list.is_null())
  {
    msg.push_back( args.args_list );
    if (!args.args_dict.is_null()) msg.push_back( args.args_dict );
  }

  size_t num_active = 0;
  for (auto & item : mt->m_subscribers)
  {
    if (auto sp = item.lock())
    {
      sp->send_msg(msg);
      num_active++;
    }
  }

  // remove any expired sessions

  if (num_active != mt->m_subscribers.size())
  {
    std::vector< std::weak_ptr<wamp_session> > temp;
    temp.resize(num_active);
    for (auto item : mt->m_subscribers)
    {
      if (!item.expired())
        temp.push_back( std::move(item) );
    }
    mt->m_subscribers.swap( temp );
  }

}

/* Handle arrival of the a PUBLISH event, targeted at a topic. This will write
 * to a managed topic. */
void pubsub_man::inbound_publish(std::string realm,
                                 std::string topic,
                                 jalson::json_object options,
                                 wamp_args args)
{
  /* EV thread */

  update_topic(topic, realm, std::move(options), args);
}

/* Add a subscription to a managed topic.  Need to sync the addition of the
  subscriber, with the series of images and updates it sees. This is done via
  single threaded access to this class.
 */
uint64_t pubsub_man::subscribe(wamp_session* sptr,
                               t_request_id request_id,
                               std::string uri,
                               jalson::json_object & options)
{
  /* EV thread */

  /* We have received an external request to subscribe to a top */

  // validate the URI
  // TODO: implement Strict URIs

  if (uri.empty())
    throw wamp_error(WAMP_ERROR_INVALID_URI, "URI zero length");

  // find or create a topic
  managed_topic* mt = find_topic(uri, sptr->realm(), true);

  if (!mt) throw wamp_error(WAMP_ERROR_INVALID_URI);

  LOG_INFO("session " << sptr->unique_id() << " subscribed to '"<< uri<< "'");

  jalson::json_array msg({SUBSCRIBED,request_id,mt->subscription_id()});
  sptr->send_msg(msg);

  /* for stateful topic must send initial snapshot */
  if (options.find(KEY_PATCH) != options.end())
  {
    XXX::wamp_args pub_args;
    pub_args.args_list = jalson::json_array();

    jalson::json_array patch;
    jalson::json_object& operation = jalson::append_object(patch);
    operation["op"]    = "replace";
    operation["path"]  = "";  /* replace whole document */
    operation["value"] = mt->image;

    pub_args.args_list.as_array().push_back(std::move(patch));
    pub_args.args_list.as_array().push_back(jalson::json_array()); // empty event

    jalson::json_object event_options;
    event_options[KEY_PATCH] = options[KEY_PATCH];
    event_options[KEY_SNAPSHOT] = 1;
    jalson::json_array snapshot_msg;
    snapshot_msg.reserve(5);
    snapshot_msg.push_back( EVENT );
    snapshot_msg.push_back( mt->subscription_id() );
    snapshot_msg.push_back( 0 ); // publication id
    snapshot_msg.push_back( std::move(event_options) );
    snapshot_msg.push_back( pub_args.args_list );
    sptr->send_msg(snapshot_msg);
  }

  mt->add(sptr->handle());

  return mt->subscription_id();
}

void pubsub_man::unsubscribe(wamp_session* sptr,
                             t_request_id request_id,
                             t_subscription_id sub_id)
{
  /* EV thread */

  auto it = m_subscription_registry.find(sub_id);

  if (it != m_subscription_registry.end())
  {
    it->second->remove(sptr->handle());

    jalson::json_array msg({ UNSUBSCRIBED, request_id });
    sptr->send_msg(msg);
  }
  else
  {
    throw wamp_error(WAMP_ERROR_NO_SUCH_SUBSCRIPTION);
  }
}

void pubsub_man::session_closed(session_handle /*sh*/)
{
  /* EV loop */

  // // design of this can be improved, ie, we should track what topics a session
  // // has subscribed too, rather than searching every topic.
  // for (auto & realm_iter : m_topics)
  //   for (auto & item : realm_iter.second)
  //   {

  //     for (auto it = item.second->m_subscribers.begin();
  //          it != item.second->m_subscribers.end(); it++)
  //     {
  //       if (compare_session( *it, sh))
  //       {
  //         item.second->m_subscribers.erase( it );
  //         break;
  //       }
  //     }
  //   }
}

} // namespace XXX
<commit_msg>minor refactor<commit_after>#include "XXX/pubsub_man.h"

#include "XXX/topic.h"
#include "XXX/event_loop.h"
#include "XXX/log_macros.h"
#include "XXX/wamp_session.h"
#include "XXX/kernel.h"
#include "XXX/utils.h"

#include <list>
#include <iostream>
#include <algorithm>

namespace XXX {

static bool session_equals(const session_handle& p1, const session_handle& p2)
{
  return ( !p1.owner_before(p2) && !p2.owner_before(p1) );
}

/*
Thread safety for pubsub.

Currently the public methods:

  - inbound_publish

  - subscribe

... are both called on the event loop thead, so presently no need for any
synchronization around the managed topics.  Additionally for the addition of a
new subscriber, the synchronization of the initially snapshot followed by
updates is also acheived through the single threaded approach.
*/
class managed_topic
{
public:

  managed_topic(size_t __subscription_id)
  :  m_subscription_id(__subscription_id)
  {
  }

  t_subscription_id subscription_id() const { return m_subscription_id; }

  uint64_t next_publication_id() { return m_id_gen.next(); }

  /** Add a subscriber to this topic. */
  void add(std::weak_ptr<wamp_session> wp)
  {
    auto it = std::find_if(std::begin(m_subscribers),
                           std::end(m_subscribers),
                           [wp](std::weak_ptr<wamp_session>& rhs)
                           {
                             return session_equals(wp,rhs);
                           });

    /* In WAMP it is not an error for a session to subscribe multiple times. So
     * we dont throw an exception here if the session is already subscribed. */
    if (it == std::end(m_subscribers))
      m_subscribers.push_back(wp);
  }

  /** Remove a subscriber from this topic. */
  void remove(std::weak_ptr<wamp_session> wp)
  {
    auto it = std::find_if(std::begin(m_subscribers),
                           std::end(m_subscribers),
                           [wp](std::weak_ptr<wamp_session>& rhs)
                           {
                             return session_equals(wp,rhs);
                           });

    /* In WAMP it is not an error for a session to subscribe multiple times. So
     * we dont throw an exception here if the session is not found. */
    if (it != std::end(m_subscribers))
      m_subscribers.erase(it);
  }

  jalson::json_value& image() { return m_image; }
  const jalson::json_value& image() const { return m_image; }

  std::vector< std::weak_ptr<wamp_session> > &  subscribers()  {return m_subscribers;}
  const std::vector< std::weak_ptr<wamp_session> > &  subscribers() const {return m_subscribers;}

private:

  std::vector< std::weak_ptr<wamp_session> > m_subscribers;

  // current upto date image of the value
  jalson::json_value m_image;

  global_scope_id_generator m_id_gen;

  // Note, we are tieing the subscription ID direct to the topic.  WAMP does
  // allow this, and it has the benefit that we can perform a single message
  // serialisation for all subscribers.  Might have to change later if more
  // complex subscription features are supported.
  size_t m_subscription_id;
};

/* Constructor */
pubsub_man::pubsub_man(kernel& k)
  : __logger(k.get_logger()),
    m_next_subscription_id(1)  /* zero used for initial snapshot */
{
}

pubsub_man::~pubsub_man()
{
  // destructor needed here so that unique_ptr can see the definition of
  // managed_topic
}

managed_topic* pubsub_man::find_topic(const std::string& topic,
                                      const std::string& realm,
                                      bool allow_create)
{
  // first find the realm
  auto realm_iter = m_topics.find( realm );
  if (realm_iter == m_topics.end())
  {
    if (allow_create)
    {
      auto result = m_topics.insert(std::make_pair(realm, topic_registry()));
      realm_iter = result.first;
    }
    else
      return nullptr;
  }

  // now find the topic
  auto topic_iter = realm_iter->second.find( topic );
  if (topic_iter ==  realm_iter->second.end())
  {
    if (allow_create)
    {
      std::unique_ptr<managed_topic> ptr(new managed_topic(m_next_subscription_id++));
      m_subscription_registry[ptr->subscription_id()] = ptr.get();
      auto result = realm_iter->second.insert(std::make_pair(topic, std::move( ptr )));
      topic_iter = result.first;
    }
    else return nullptr;
  }

  return topic_iter->second.get();
}

void pubsub_man::update_topic(const std::string& topic,
                              const std::string& realm,
                              jalson::json_object options,
                              wamp_args args)
{
  /* EVENT thread */

  managed_topic* mt = find_topic(topic, realm, true);

  if (!mt)
  {
    LOG_WARN("Discarding update to non existing topic '" << topic << "'");
    return;
  }

  if (options.find(KEY_PATCH) != options.end() && args.args_list.is_array())
  {
    // apply the patch
    //std::cout << "@" << topic << ", patch\n";
    //std::cout << "BEFORE: " << mt->image << "\n";
    //std::cout << "PATCH : " << args.args_list << "\n";
    jalson::json_array & change = args.args_list.as_array();
    mt->image().patch(change[0].as_array());
    //std::cout << "AFTER : "  << mt->image << "\n";
    //std::cout << "-------\n";
  }

  // broadcast event to subscribers

  jalson::json_array msg;
  msg.reserve(6);
  msg.push_back( EVENT );
  msg.push_back( mt->subscription_id() );
  msg.push_back( mt->next_publication_id() );
  msg.push_back( std::move(options) );
  if (!args.args_list.is_null())
  {
    msg.push_back( args.args_list );
    if (!args.args_dict.is_null()) msg.push_back( args.args_dict );
  }

  size_t num_active = 0;
  for (auto & item : mt->subscribers())
  {
    if (auto sp = item.lock())
    {
      sp->send_msg(msg);
      num_active++;
    }
  }

  // remove any expired sessions

  if (num_active != mt->subscribers().size())
  {
    std::vector< std::weak_ptr<wamp_session> > temp;
    temp.resize(num_active);
    for (auto item : mt->subscribers())
    {
      if (!item.expired())
        temp.push_back( std::move(item) );
    }
    mt->subscribers().swap( temp );
  }

}

/* Handle arrival of the a PUBLISH event, targeted at a topic. This will write
 * to a managed topic. */
void pubsub_man::inbound_publish(std::string realm,
                                 std::string topic,
                                 jalson::json_object options,
                                 wamp_args args)
{
  /* EV thread */

  update_topic(topic, realm, std::move(options), args);
}

/* Add a subscription to a managed topic.  Need to sync the addition of the
  subscriber, with the series of images and updates it sees. This is done via
  single threaded access to this class.
 */
uint64_t pubsub_man::subscribe(wamp_session* sptr,
                               t_request_id request_id,
                               std::string uri,
                               jalson::json_object & options)
{
  /* EV thread */

  /* We have received an external request to subscribe to a top */

  // validate the URI
  // TODO: implement Strict URIs

  if (uri.empty())
    throw wamp_error(WAMP_ERROR_INVALID_URI, "URI zero length");

  // find or create a topic
  managed_topic* mt = find_topic(uri, sptr->realm(), true);

  if (!mt) throw wamp_error(WAMP_ERROR_INVALID_URI);

  LOG_INFO("session " << sptr->unique_id() << " subscribed to '"<< uri<< "'");

  jalson::json_array msg({SUBSCRIBED,request_id,mt->subscription_id()});
  sptr->send_msg(msg);

  /* for stateful topic must send initial snapshot */
  if (options.find(KEY_PATCH) != options.end())
  {
    XXX::wamp_args pub_args;
    pub_args.args_list = jalson::json_array();

    jalson::json_array patch;
    jalson::json_object& operation = jalson::append_object(patch);
    operation["op"]    = "replace";
    operation["path"]  = "";  /* replace whole document */
    operation["value"] = mt->image();

    pub_args.args_list.as_array().push_back(std::move(patch));
    pub_args.args_list.as_array().push_back(jalson::json_array()); // empty event

    jalson::json_object event_options;
    event_options[KEY_PATCH] = options[KEY_PATCH];
    event_options[KEY_SNAPSHOT] = 1;
    jalson::json_array snapshot_msg;
    snapshot_msg.reserve(5);
    snapshot_msg.push_back( EVENT );
    snapshot_msg.push_back( mt->subscription_id() );
    snapshot_msg.push_back( 0 ); // publication id
    snapshot_msg.push_back( std::move(event_options) );
    snapshot_msg.push_back( pub_args.args_list );
    sptr->send_msg(snapshot_msg);
  }

  mt->add(sptr->handle());

  return mt->subscription_id();
}

void pubsub_man::unsubscribe(wamp_session* sptr,
                             t_request_id request_id,
                             t_subscription_id sub_id)
{
  /* EV thread */

  auto it = m_subscription_registry.find(sub_id);

  if (it != m_subscription_registry.end())
  {
    it->second->remove(sptr->handle());

    jalson::json_array msg({ UNSUBSCRIBED, request_id });
    sptr->send_msg(msg);
  }
  else
  {
    throw wamp_error(WAMP_ERROR_NO_SUCH_SUBSCRIPTION);
  }
}

void pubsub_man::session_closed(session_handle /*sh*/)
{
  /* EV loop */

  // // design of this can be improved, ie, we should track what topics a session
  // // has subscribed too, rather than searching every topic.
  // for (auto & realm_iter : m_topics)
  //   for (auto & item : realm_iter.second)
  //   {

  //     for (auto it = item.second->m_subscribers.begin();
  //          it != item.second->m_subscribers.end(); it++)
  //     {
  //       if (compare_session( *it, sh))
  //       {
  //         item.second->m_subscribers.erase( it );
  //         break;
  //       }
  //     }
  //   }
}

} // namespace XXX
<|endoftext|>


<commit_before>#include <vector>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fstream>
#include "overlapgraph.h"

#define VERTEX_INACTIVE 0
#define VERTEX_ACTIVE 1
#define VERTEX_ELIMINATED -1
#define FUZZ 10

using namespace std;

/*
Constructor for OverlapGraph class.
*/
OverlapGraph::OverlapGraph(std::vector<std::string> readvector, std::vector<overlap> overlapvector)
{
	reads = readvector;
	overlaps = overlapvector;
}

void OverlapGraph::initialize()
{
	graph.resize(reads.size());
	completeGraph.resize(reads.size());
	reducedGraph.resize(reads.size());

	nonContainedReads.resize(reads.size());
	nonContainedReads.assign(reads.size(), 1);

	overlapFlags = (bool *)malloc(sizeof(bool)*reads.size());
	memset(overlapFlags, 0, sizeof(bool)*reads.size());

	for(int i=0;i<overlaps.size();i++)
	{
		overlap o = overlaps[i];

		//removing contained reads
		if(o.ahg > 0 & o.bhg > 0)
			graph[o.read1].push_back(o);
		else if (o.ahg < 0 & o.bhg < 0)
			graph[o.read2].push_back(o);
		else if (o.ahg >= 0 & o.bhg <= 0)
			nonContainedReads[o.read2] = 0;
		else if (o.ahg <= 0 & o.bhg>=0)
			nonContainedReads[o.read1] = 0;

		completeGraph[o.read1].push_back(o);
		overlapFlags[o.read1] = true;
		overlapFlags[o.read2] = true;
	}

	int *indegree = (int *)malloc(reads.size()*sizeof(int));
	memset(indegree, 0, reads.size()*sizeof(int));
	for (int i = 0; i < graph.size(); i++)
	{
		for (int j = 0; j < graph[i].size(); j++)
		{
			indegree[graph[i][j].read2]++;
		}
	}

	for (int i = 0; i < reads.size(); i++)
	{
		if (indegree[i] == 0 & graph[i].size() == 0)
			nonContainedReads[i] = 0;
	}

	free(indegree);
}

/*
Method that runs untigging after contained reads are eliminated. (Contained reads are marked as eliminated
while graph was being initialized.
)
*/
void OverlapGraph::runUnitigging()
{
	int N = reads.size();

	initialize();

	int *vertexstatus = (int *)malloc(N*sizeof(int));
	memset(vertexstatus, VERTEX_INACTIVE, N*sizeof(int));
	vector< vector<bool> > reduceflags(N);

	for (int i = 0; i < N; i++)
		for (int j = 0; j < graph[i].size(); j++)
			reduceflags[i].push_back(false);

	for (int I = 0; I < N; I++)
	{
		if (graph[I].size() == 0)
			continue;

		for (int j = 0; j < graph[I].size(); j++)
			vertexstatus[graph[I][j].read2] = VERTEX_ACTIVE;

		int longest = 0;
		for (int j = 0; j < graph[I].size(); j++)
		{
			if (graph[I][j].bhg > longest)
				longest = graph[I][j].bhg;
		}

		longest += FUZZ;
		//cout << longest << endl;

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ACTIVE)
			{
				int x = graph[I][j].read2;
				for (int k = 0; k < graph[x].size(); k++)
				{
					if (graph[I][j].bhg + graph[x][k].bhg <= longest)
					{
						if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
							vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
					}
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			int x = graph[I][j].read2;
			for (int k = 0; k < graph[x].size(); k++)
			{
				if (graph[x][k].bhg < FUZZ)
				{
					if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
						vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ELIMINATED)
			{
				reduceflags[I][j] = true;
			}
			vertexstatus[graph[I][j].read2] == VERTEX_INACTIVE;
		}
	}

	for(int i=0;i<graph.size();i++)
    {
        for(int j=0;j<graph[i].size();j++)
        {
			if (!reduceflags[i][j] & nonContainedReads[graph[i][j].read1] & nonContainedReads[graph[i][j].read2]){
				// Add edge to the reduced graph
				reducedGraph[i].push_back(graph[i][j]);
				cout << graph[i][j].read1 + 1<< " -> " << graph[i][j].read2 + 1<< endl;
			}
        }
    }

	uniqueJoinCollapsing();

	free(vertexstatus);
	return;
}

void OverlapGraph::unitigsPrinting()
{
	ofstream output("unitigsPrinting.afg");

	int counter = 1;

	output << "{unitigs" << endl;

	for (Chunk c : collapsedReducedGraph)
	{
		output << "{" << "unitig" << endl;
		output << "id: " << counter << endl;
		output << "members: ";
		for (int a : c.members)
		{
			output << a << ",";
		}

		output << endl;
		output << "}" << endl;
	}

	output << "}" << endl;
}

void OverlapGraph::printLayouts()
{
	ofstream output("layouts.afg");
	ofstream pretty("pretty.afg");

	int *offsets = (int *)malloc(reads.size()*sizeof(int));
	memset(offsets, 0, reads.size()*sizeof(int));

	int *mapping = (int *)malloc(reads.size()*sizeof(int));
	int *bhglen = (int *)malloc(reads.size()*sizeof(int));
	memset(mapping, -1, reads.size() * sizeof(int));

	for (int i = 0; i < reads.size(); i++)
	{
		for (int j = 0; j < completeGraph[i].size(); j++)
		{
			overlap o = completeGraph[i][j];
			if (nonContainedReads[o.read1] & nonContainedReads[o.read2]) {
				offsets[o.read2] = offsets[o.read1] + o.ahg;
			}
			else if (nonContainedReads[o.read1] & !nonContainedReads[o.read2])
			{
				if (mapping[o.read2] == -1 || abs(o.bhg) < bhglen[o.read2])
				{
					mapping[o.read2] = o.read1;
					bhglen[o.read2] = abs(o.bhg);
				}
			}
		}
	}

	for (int i = 0; i < reads.size(); i++)
	{
		if (!nonContainedReads[i] && overlapFlags[i])
		{
			int m = mapping[i];

			overlap *o = NULL;
			for (int j = 0; j < completeGraph[m].size(); j++)
				if (completeGraph[m][j].read2 == i)
					o = &completeGraph[m][j];

			offsets[i] = offsets[m] + o->ahg;
		}
	}

	output << "{LAY" << endl;
	for (int i = 0; i < reads.size(); i++)
	{
		if (overlapFlags[i]){
			output << "{TLE" << endl;
			output << "clr:0," << reads[i].length() << endl;
			output << "off:" << offsets[i] << endl;
			output << "src:" << i + 1 << endl;
			output << "}" << endl;
		}

			//pretty << string(offsets[i], ' ') + reads[i] << endl;
			//pretty <<reads[i] << endl;
	}

	output << "}" << endl;
	output.close();

	free(offsets);
}

void OverlapGraph::uniqueJoinCollapsing(){

	reducedGraphVertexReferenceCounter.assign(reducedGraph.size(), 0);

	// Calculate references to vertexes
	for (int i = 0; i < reducedGraph.size(); i++){
		for (int j = 0; j < reducedGraph[i].size(); j++){
			reducedGraphVertexReferenceCounter[reducedGraph[i][j].read2]++;
		}
	}

	// Find first "juncture" vertex
	int startingVertex = 0;
	bool startingVertexFound = false;
	while (startingVertex < reducedGraph.size()){
		if (reducedGraph[startingVertex].size() > 0){
			startingVertexFound = true;
			break;
		}
		startingVertex++;
	}
	if (startingVertexFound){
		calculateChunks(startingVertex);
	}
}

void OverlapGraph::calculateChunks(int chunkStartingVertexId){

	int currentVertexId = chunkStartingVertexId;

	if (vertexAlreadyInChunk(currentVertexId)){
		return;
	}

	// create new chunk
	Chunk chunk;

	while (true){
		if (reducedGraphVertexReferenceCounter[currentVertexId] > 1 && currentVertexId != chunkStartingVertexId){
			// special case: juncture vertex (not part of our chunk)
			calculateChunks(currentVertexId);
			break;
		}

		chunk.members.push_back(currentVertexId);

		if (reducedGraph[currentVertexId].size() < 1){
			// dead end
			break;
		}

		if (reducedGraph[currentVertexId].size() > 1){
			// juncture point - each path vertex represents a new chunk start
			for (int i = 0; i < reducedGraph[currentVertexId].size(); i++){
				calculateChunks(reducedGraph[currentVertexId][i].read2);
			}
			break;
		}

		currentVertexId = reducedGraph[currentVertexId][0].read2;
	}
	collapsedReducedGraph.push_back(chunk);

	return;
}

bool OverlapGraph::vertexAlreadyInChunk(int vertexId){
	for (int i = 0; i < collapsedReducedGraph.size(); ++i){
		for (int j = 0; j < collapsedReducedGraph[i].members.size(); ++j){
			if (vertexId == collapsedReducedGraph[i].members[j]){
				return true;
			}
		}
	}
	return false;
}<commit_msg>Fixed bug in layout offset calculation.<commit_after>#include <vector>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fstream>
#include "overlapgraph.h"

#define VERTEX_INACTIVE 0
#define VERTEX_ACTIVE 1
#define VERTEX_ELIMINATED -1
#define FUZZ 10

using namespace std;

/*
Constructor for OverlapGraph class.
*/
OverlapGraph::OverlapGraph(std::vector<std::string> readvector, std::vector<overlap> overlapvector)
{
	reads = readvector;
	overlaps = overlapvector;
}

void OverlapGraph::initialize()
{
	graph.resize(reads.size());
	completeGraph.resize(reads.size());
	reducedGraph.resize(reads.size());

	nonContainedReads.resize(reads.size());
	nonContainedReads.assign(reads.size(), 1);

	overlapFlags = (bool *)malloc(sizeof(bool)*reads.size());
	memset(overlapFlags, 0, sizeof(bool)*reads.size());

	for(int i=0;i<overlaps.size();i++)
	{
		overlap o = overlaps[i];

		//removing contained reads
		if(o.ahg > 0 & o.bhg > 0)
			graph[o.read1].push_back(o);
		else if (o.ahg < 0 & o.bhg < 0)
			graph[o.read2].push_back(o);
		else if (o.ahg >= 0 & o.bhg <= 0)
			nonContainedReads[o.read2] = 0;
		else if (o.ahg <= 0 & o.bhg>=0)
			nonContainedReads[o.read1] = 0;

		completeGraph[o.read1].push_back(o);
		overlapFlags[o.read1] = true;
		overlapFlags[o.read2] = true;
	}

	int *indegree = (int *)malloc(reads.size()*sizeof(int));
	memset(indegree, 0, reads.size()*sizeof(int));
	for (int i = 0; i < graph.size(); i++)
	{
		for (int j = 0; j < graph[i].size(); j++)
		{
			indegree[graph[i][j].read2]++;
		}
	}

	for (int i = 0; i < reads.size(); i++)
	{
		if (indegree[i] == 0 & graph[i].size() == 0)
			nonContainedReads[i] = 0;
	}

	free(indegree);
}

/*
Method that runs untigging after contained reads are eliminated. (Contained reads are marked as eliminated
while graph was being initialized.
)
*/
void OverlapGraph::runUnitigging()
{
	int N = reads.size();

	initialize();

	int *vertexstatus = (int *)malloc(N*sizeof(int));
	memset(vertexstatus, VERTEX_INACTIVE, N*sizeof(int));
	vector< vector<bool> > reduceflags(N);

	for (int i = 0; i < N; i++)
		for (int j = 0; j < graph[i].size(); j++)
			reduceflags[i].push_back(false);

	for (int I = 0; I < N; I++)
	{
		if (graph[I].size() == 0)
			continue;

		for (int j = 0; j < graph[I].size(); j++)
			vertexstatus[graph[I][j].read2] = VERTEX_ACTIVE;

		int longest = 0;
		for (int j = 0; j < graph[I].size(); j++)
		{
			if (graph[I][j].bhg > longest)
				longest = graph[I][j].bhg;
		}

		longest += FUZZ;
		//cout << longest << endl;

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ACTIVE)
			{
				int x = graph[I][j].read2;
				for (int k = 0; k < graph[x].size(); k++)
				{
					if (graph[I][j].bhg + graph[x][k].bhg <= longest)
					{
						if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
							vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
					}
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			int x = graph[I][j].read2;
			for (int k = 0; k < graph[x].size(); k++)
			{
				if (graph[x][k].bhg < FUZZ)
				{
					if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
						vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ELIMINATED)
			{
				reduceflags[I][j] = true;
			}
			vertexstatus[graph[I][j].read2] == VERTEX_INACTIVE;
		}
	}

	for(int i=0;i<graph.size();i++)
    {
        for(int j=0;j<graph[i].size();j++)
        {
			if (!reduceflags[i][j] & nonContainedReads[graph[i][j].read1] & nonContainedReads[graph[i][j].read2]){
				// Add edge to the reduced graph
				reducedGraph[i].push_back(graph[i][j]);
				cout << graph[i][j].read1 + 1<< " -> " << graph[i][j].read2 + 1<< endl;
			}
        }
    }

	uniqueJoinCollapsing();

	free(vertexstatus);
	return;
}

void OverlapGraph::unitigsPrinting()
{
	ofstream output("unitigsPrinting.afg");

	int counter = 1;

	output << "{unitigs" << endl;

	for (Chunk c : collapsedReducedGraph)
	{
		output << "{" << "unitig" << endl;
		output << "id: " << counter << endl;
		output << "members: ";
		for (int a : c.members)
		{
			output << a << ",";
		}

		output << endl;
		output << "}" << endl;
	}

	output << "}" << endl;
}

void OverlapGraph::printLayouts()
{
	ofstream output("layouts.afg");

	int *offsets = (int *)malloc(reads.size()*sizeof(int));
	memset(offsets, 0, reads.size()*sizeof(int));

	int *mapping = (int *)malloc(reads.size()*sizeof(int));
	//int mapping[200];
	int *bhglen = (int *)malloc(reads.size()*sizeof(int));
	memset(mapping, -1, reads.size() * sizeof(int));

	for (int i = 0; i < reads.size(); i++)
	{
		for (int j = 0; j < completeGraph[i].size(); j++)
		{
			overlap o = completeGraph[i][j];
			if (nonContainedReads[o.read1] & nonContainedReads[o.read2]) {
				offsets[o.read2] = offsets[o.read1] + o.ahg;
			}
			else if (nonContainedReads[o.read1] & !nonContainedReads[o.read2])
			{
				if ((mapping[o.read2] == -1 || abs(o.bhg) < bhglen[o.read2]) && o.bhg <= 0)
				{
					mapping[o.read2] = o.read1;
					bhglen[o.read2] = abs(o.bhg);
				}
			}
		}
	}

	for (int i = 0; i < reads.size(); i++)
	{
		if (!nonContainedReads[i] && overlapFlags[i])
		{
			int m = mapping[i];

			overlap *o = NULL;
			for (int j = 0; j < completeGraph[m].size(); j++)
				if (completeGraph[m][j].read2 == i)
					o = &completeGraph[m][j];

			offsets[i] = offsets[m] + o->ahg;
		}
	}

	output << "{LAY" << endl;
	for (int i = 0; i < reads.size(); i++)
	{
		if (overlapFlags[i]){
			output << "{TLE" << endl;
			output << "clr:0," << reads[i].length() << endl;
			output << "off:" << offsets[i] << endl;
			output << "src:" << i + 1 << endl;
			output << "}" << endl;
		}
	}

	output << "}" << endl;
	output.close();

	free(offsets);
}

void OverlapGraph::uniqueJoinCollapsing(){

	reducedGraphVertexReferenceCounter.assign(reducedGraph.size(), 0);

	// Calculate references to vertexes
	for (int i = 0; i < reducedGraph.size(); i++){
		for (int j = 0; j < reducedGraph[i].size(); j++){
			reducedGraphVertexReferenceCounter[reducedGraph[i][j].read2]++;
		}
	}

	// Find first "juncture" vertex
	int startingVertex = 0;
	bool startingVertexFound = false;
	while (startingVertex < reducedGraph.size()){
		if (reducedGraph[startingVertex].size() > 0){
			startingVertexFound = true;
			break;
		}
		startingVertex++;
	}
	if (startingVertexFound){
		calculateChunks(startingVertex);
	}
}

void OverlapGraph::calculateChunks(int chunkStartingVertexId){

	int currentVertexId = chunkStartingVertexId;

	if (vertexAlreadyInChunk(currentVertexId)){
		return;
	}

	// create new chunk
	Chunk chunk;

	while (true){
		if (reducedGraphVertexReferenceCounter[currentVertexId] > 1 && currentVertexId != chunkStartingVertexId){
			// special case: juncture vertex (not part of our chunk)
			calculateChunks(currentVertexId);
			break;
		}

		chunk.members.push_back(currentVertexId);

		if (reducedGraph[currentVertexId].size() < 1){
			// dead end
			break;
		}

		if (reducedGraph[currentVertexId].size() > 1){
			// juncture point - each path vertex represents a new chunk start
			for (int i = 0; i < reducedGraph[currentVertexId].size(); i++){
				calculateChunks(reducedGraph[currentVertexId][i].read2);
			}
			break;
		}

		currentVertexId = reducedGraph[currentVertexId][0].read2;
	}
	collapsedReducedGraph.push_back(chunk);

	return;
}

bool OverlapGraph::vertexAlreadyInChunk(int vertexId){
	for (int i = 0; i < collapsedReducedGraph.size(); ++i){
		for (int j = 0; j < collapsedReducedGraph[i].members.size(); ++j){
			if (vertexId == collapsedReducedGraph[i].members[j]){
				return true;
			}
		}
	}
	return false;
}<|endoftext|>


<commit_before>//
// detail/visitor_from_js.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_DETAIL_VISITOR_FROM_JS_HPP
#define EIGENJS_DETAIL_VISITOR_FROM_JS_HPP

#include <v8.h>
#include <node.h>
#include <nan.h>

#include <eigen3/Eigen/Dense>

#include <complex>

#include "../Complex.hpp"

namespace EigenJS {
namespace detail {

template <typename T>
struct visitor_from_js {
  typedef typename T::value_type::Index Index;
  typedef typename T::scalar_type scalar_type;

  visitor_from_js(
    _NAN_METHOD_ARGS_TYPE args
  , v8::Handle<v8::Function> func
  ) : args_(args), func_(func)
  {}

  ~visitor_from_js() {}

  inline void init(const scalar_type& value, Index i, Index j) const {
    this->operator()(value, i, j);
  }

  inline void init(const std::complex<scalar_type>& value, Index i, Index j)
  const {
    this->operator()(value, i, j);
  }

  void operator()(const scalar_type& value, Index i, Index j) const {
    v8::Local<v8::Value> argv[] = {
      NanNew<v8::Number>(value)
    , NanNew<v8::Integer>(i)
    , NanNew<v8::Integer>(j)
    };

    NanMakeCallback(
        args_.This()
      , func_
      , sizeof(argv) / sizeof(v8::Local<v8::Value>)
      , argv
      );
  }

  void operator()(
    const std::complex<scalar_type>& value, Index i, Index j
  ) const {
    v8::Local<v8::Value> value_argv[] = {
      NanNew<v8::Number>(value.real())
    , NanNew<v8::Number>(value.imag())
    };

    v8::Local<v8::Value> argv[] = {
      NanNew(
        Complex<scalar_type>::new_instance(
          args_
        , sizeof(value_argv) / sizeof(v8::Local<v8::Value>)
        , value_argv
        )
      )
    , NanNew<v8::Integer>(i)
    , NanNew<v8::Integer>(j)
    };

    NanMakeCallback(
        args_.This()
      , func_
      , sizeof(argv) / sizeof(v8::Local<v8::Value>)
      , argv
      );
  }

 private:
  _NAN_METHOD_ARGS_TYPE args_;
  v8::Handle<v8::Function> func_;
};

}  // namespace detail
}  // namespace EigenJS

#endif  // EIGENJS_DETAIL_VISITOR_FROM_JS_HPP
<commit_msg>src: modify code for linting pass<commit_after>//
// detail/visitor_from_js.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_DETAIL_VISITOR_FROM_JS_HPP
#define EIGENJS_DETAIL_VISITOR_FROM_JS_HPP

#include <v8.h>
#include <node.h>
#include <nan.h>

#include <eigen3/Eigen/Dense>

#include <complex>

#include "../Complex.hpp"

namespace EigenJS {
namespace detail {

template <typename T>
struct visitor_from_js {
  typedef typename T::value_type::Index Index;
  typedef typename T::scalar_type scalar_type;

  visitor_from_js(
    _NAN_METHOD_ARGS_TYPE args
  , v8::Handle<v8::Function> func
  ) : args_(args), func_(func)
  {}

  ~visitor_from_js() {}

  inline void init(const scalar_type& value, Index i, Index j) const {
    this->operator()(value, i, j);
  }

  inline void init(const std::complex<scalar_type>& value, Index i, Index j)
  const {
    this->operator()(value, i, j);
  }

  void operator()(const scalar_type& value, Index i, Index j) const {
    v8::Local<v8::Value> argv[] = {
      NanNew<v8::Number>(value)
    , NanNew<v8::Integer>(i)
    , NanNew<v8::Integer>(j)
    };

    NanMakeCallback(
        args_.This()
      , func_
      , sizeof(argv) / sizeof(v8::Local<v8::Value>)
      , argv
      );
  }

  void operator()(
    const std::complex<scalar_type>& value, Index i, Index j
  ) const {
    v8::Local<v8::Value> value_argv[] = {
      NanNew<v8::Number>(value.real())
    , NanNew<v8::Number>(value.imag())
    };

    v8::Local<v8::Value> argv[] = {
      NanNew(
        Complex<scalar_type>::new_instance(
          args_
        , sizeof(value_argv) / sizeof(v8::Local<v8::Value>)
        , value_argv
        )
      )
    , NanNew<v8::Integer>(i)
    , NanNew<v8::Integer>(j)
    };

    NanMakeCallback(
        args_.This()
      , func_
      , sizeof(argv) / sizeof(v8::Local<v8::Value>)
      , argv
      );
  }

 private:
  _NAN_METHOD_ARGS_TYPE args_;
  v8::Handle<v8::Function> func_;
};

}  // namespace detail
}  // namespace EigenJS

#endif  // EIGENJS_DETAIL_VISITOR_FROM_JS_HPP
<|endoftext|>


<commit_before>// Driver for the diagnostics module. Provides an start point for the OS.
// This driver's only job is to instantiate the Diagnostics class, handle ROS initialization,
// allow ROS to handle events (spin), and determine the name to publish under (command line
// argument or, if none, the hostname).
//

#include "Diagnostics.h"
#include <string>
#include <signal.h>
#include <gazebo/gazebo.hh>

using namespace std;

// OS Signal Handler
void sigintEventHandler(int signal);

int main(int argc, char** argv) {

  // For processing gazebo messages from the world stats topic.
  // Used to gather information for simulated rovers
  gazebo::setupClient(argc, argv);

  char host[128];
  gethostname(host, sizeof (host));
  std::string hostname(host);

  std::string publishedName;
  if (argc >= 2) {
    publishedName = argv[1];
    cout << "Welcome to the world of tomorrow " << publishedName << "!  Diagnostic module started." << endl;
  } else {
    publishedName = hostname;
    cout << "No Name Selected. Default is: " << publishedName << endl;
  }

  // NoSignalHandler so we can catch SIGINT ourselves and shutdown the node
  ros::init(argc, argv, (publishedName + "_DIAGNOSTICS"), ros::init_options::NoSigintHandler);

  Diagnostics diags(publishedName);

  signal(SIGINT, sigintEventHandler); // Register the SIGINT event handler so the node can shutdown properly

  ros::spin(); // Process ROS events

  return EXIT_SUCCESS;
}

void sigintEventHandler(int sig) {
  // All the default sigint handler does is call shutdown()
  ros::shutdown();
}
<commit_msg>Removed gazebo client start in diagnostics and replaced with a 10 sec sleep This is to allow the other nodes time to start up before diagnostics starts monitoring their output. The gazebo client start was moved to Diagnostics and only occurs if there is a simulated rover to monitor.<commit_after>// Driver for the diagnostics module. Provides an start point for the OS.
// This driver's only job is to instantiate the Diagnostics class, handle ROS initialization,
// allow ROS to handle events (spin), and determine the name to publish under (command line
// argument or, if none, the hostname).
//

#include "Diagnostics.h"
#include <string>
#include <signal.h>
#include <gazebo/gazebo.hh>

using namespace std;

// OS Signal Handler
void sigintEventHandler(int signal);

int main(int argc, char** argv) {

  sleep(10);
  char host[128];
  gethostname(host, sizeof (host));
  std::string hostname(host);

  std::string publishedName;
  if (argc >= 2) {
    publishedName = argv[1];
    cout << "Welcome to the world of tomorrow " << publishedName << "!  Diagnostic module started." << endl;
  } else {
    publishedName = hostname;
    cout << "No Name Selected. Default is: " << publishedName << endl;
  }

  // NoSignalHandler so we can catch SIGINT ourselves and shutdown the node
  ros::init(argc, argv, (publishedName + "_DIAGNOSTICS"), ros::init_options::NoSigintHandler);

  Diagnostics diags(publishedName);

  signal(SIGINT, sigintEventHandler); // Register the SIGINT event handler so the node can shutdown properly

  ros::spin(); // Process ROS events

  return EXIT_SUCCESS;
}

void sigintEventHandler(int sig) {
  // All the default sigint handler does is call shutdown()
  ros::shutdown();
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "SoundDataVorbis.h"
#include "StreamVorbis.h"
#include "core/Engine.h"
#include "files/FileSystem.h"
#include "utils/Log.h"
#include "utils/Utils.h"
#include "stb_vorbis.c"

namespace ouzel
{
    namespace audio
    {
        static const uint32_t DECODE_BUFFER_SIZE = 32 * 4096;

        SoundDataVorbis::SoundDataVorbis()
        {
        }

        bool SoundDataVorbis::init(const std::string& newFilename)
        {
            filename = newFilename;

            std::vector<uint8_t> newData;
            if (!sharedEngine->getFileSystem()->readFile(newFilename, newData))
            {
                return false;
            }

            return init(newData);
        }

        bool SoundDataVorbis::init(const std::vector<uint8_t>& newData)
        {
            data = newData;

            stb_vorbis* vorbisStream = stb_vorbis_open_memory(data.data(), static_cast<int>(data.size()), nullptr, nullptr);
            stb_vorbis_info info = stb_vorbis_get_info(vorbisStream);

            channels = static_cast<uint16_t>(info.channels);
            samplesPerSecond = info.sample_rate;

            stb_vorbis_close(vorbisStream);

            return true;
        }

        std::unique_ptr<Stream> SoundDataVorbis::createStream()
        {
            std::unique_ptr<Stream> stream(new StreamVorbis(data));

            return stream;
        }

        std::vector<uint8_t> SoundDataVorbis::getData(Stream* stream, uint32_t size)
        {
            StreamVorbis* streamVorbis = static_cast<StreamVorbis*>(stream);

            std::vector<uint8_t> result(size);

            int n = stb_vorbis_get_samples_short_interleaved(streamVorbis->getVorbisStream(), channels, reinterpret_cast<short*>(result.data()), size / 2);

            result.resize(n * 2 * channels);

            return result;
        }
    } // namespace audio
} // namespace ouzel
<commit_msg>Remove unneeded constant<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "SoundDataVorbis.h"
#include "StreamVorbis.h"
#include "core/Engine.h"
#include "files/FileSystem.h"
#include "utils/Log.h"
#include "utils/Utils.h"
#include "stb_vorbis.c"

namespace ouzel
{
    namespace audio
    {
        SoundDataVorbis::SoundDataVorbis()
        {
        }

        bool SoundDataVorbis::init(const std::string& newFilename)
        {
            filename = newFilename;

            std::vector<uint8_t> newData;
            if (!sharedEngine->getFileSystem()->readFile(newFilename, newData))
            {
                return false;
            }

            return init(newData);
        }

        bool SoundDataVorbis::init(const std::vector<uint8_t>& newData)
        {
            data = newData;

            stb_vorbis* vorbisStream = stb_vorbis_open_memory(data.data(), static_cast<int>(data.size()), nullptr, nullptr);
            stb_vorbis_info info = stb_vorbis_get_info(vorbisStream);

            channels = static_cast<uint16_t>(info.channels);
            samplesPerSecond = info.sample_rate;

            stb_vorbis_close(vorbisStream);

            return true;
        }

        std::unique_ptr<Stream> SoundDataVorbis::createStream()
        {
            std::unique_ptr<Stream> stream(new StreamVorbis(data));

            return stream;
        }

        std::vector<uint8_t> SoundDataVorbis::getData(Stream* stream, uint32_t size)
        {
            StreamVorbis* streamVorbis = static_cast<StreamVorbis*>(stream);

            std::vector<uint8_t> result(size);

            int n = stb_vorbis_get_samples_short_interleaved(streamVorbis->getVorbisStream(), channels, reinterpret_cast<short*>(result.data()), size / 2);

            result.resize(n * 2 * channels);

            return result;
        }
    } // namespace audio
} // namespace ouzel
<|endoftext|>


<commit_before>#include "stupid_queue.hpp"

#include "board.hpp"

bool boards_are_equal(const Board &one, const Board &two) {
	for (Board_Position position = 0; position < board_size; ++position)
		if (get_normalized(one[position]) != get_normalized(two[position]))
			return false;
	return true;
}

void reset_board_state(Board_State &state) {
	for (Board_Position position = 0; position < board_size; ++position)
		state.filled[position] = false;
	state.solved = false;
}

void update_board_state(const Board &board, Board_State &state) {
	reset_board_state(state);
	bool closed[board_size] = {};
	Stupid_Queue<Board_Position, board_size> open;
	for (Board_Position position = 0; position < board_size; ++position) {
		if (is_start(board[position])) {
			closed[position] = true;
			open.push(position);
			break;
		}
	}
	while (!open.empty()) {
		Board_Position current = open.pop();
		state.filled[current] = true;
		if (is_end(board[current])) state.solved = true;
		if (has_up(current)) {
			Board_Position up = get_up(current);
			if (!closed[up] && connects_up(board[current], board[up])) {
				closed[up] = true;
				open.push(up);
			}
		}
		if (has_right(current)) {
			Board_Position right = get_right(current);
			if (!closed[right] && connects_right(board[current], board[right])) {
				closed[right] = true;
				open.push(right);
			}
		}
		if (has_down(current)) {
			Board_Position down = get_down(current);
			if (!closed[down] && connects_down(board[current], board[down])) {
				closed[down] = true;
				open.push(down);
			}
		}
		if (has_left(current)) {
			Board_Position left = get_left(current);
			if (!closed[left] && connects_left(board[current], board[left])) {
				closed[left] = true;
				open.push(left);
			}
		}
	}
}<commit_msg>Improve board state algorithm.<commit_after>#include "stupid_queue.hpp"

#include "board.hpp"

bool boards_are_equal(const Board &one, const Board &two) {
	for (Board_Position position = 0; position < board_size; ++position)
		if (get_normalized(one[position]) != get_normalized(two[position]))
			return false;
	return true;
}

void reset_board_state(Board_State &state) {
	for (Board_Position position = 0; position < board_size; ++position)
		state.filled[position] = false;
	state.solved = false;
}

void update_board_state(const Board &board, Board_State &state) {
	reset_board_state(state);
	Stupid_Queue<Board_Position, board_size> open;
	for (Board_Position position = 0; position < board_size; ++position) {
		if (is_start(board[position])) {
			state.filled[position] = true;
			open.push(position);
			break;
		}
	}
	while (!open.empty()) {
		Board_Position current = open.pop();
		if (is_end(board[current])) state.solved = true;
		if (has_up(current)) {
			Board_Position up = get_up(current);
			if (!state.filled[up] && connects_up(board[current], board[up])) {
				state.filled[up] = true;
				open.push(up);
			}
		}
		if (has_right(current)) {
			Board_Position right = get_right(current);
			if (!state.filled[right] && connects_right(board[current], board[right])) {
				state.filled[right] = true;
				open.push(right);
			}
		}
		if (has_down(current)) {
			Board_Position down = get_down(current);
			if (!state.filled[down] && connects_down(board[current], board[down])) {
				state.filled[down] = true;
				open.push(down);
			}
		}
		if (has_left(current)) {
			Board_Position left = get_left(current);
			if (!state.filled[left] && connects_left(board[current], board[left])) {
				state.filled[left] = true;
				open.push(left);
			}
		}
	}
}<|endoftext|>