<commit_before>/*
    This file is part of KAddressBook.
    Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QtCore/QTimer>
#include <QtGui/QGridLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QPushButton>
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>

#include <kabc/resource.h>
#include <kabc/resourceabc.h>
#include <kdialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kresources/configdialog.h>

#include "core.h"
#include "resourceselection.h"

class AddressBookWrapper : public KABC::AddressBook
{
  public:
    AddressBookWrapper( KABC::AddressBook* );

    KRES::Manager<KABC::Resource>* getResourceManager()
    {
      return resourceManager();
    }
};

class KABCResourceItem : public QTreeWidgetItem
{
  public:
    KABCResourceItem( QTreeWidget *parent, KABC::Resource *resource )
      : QTreeWidgetItem( parent, QStringList( resource->resourceName() ) ),
        mResource( resource ),
        mIsSubresource( false ), mSubItemsCreated( false ),
        mResourceIdentifier()
    {
      setFlags( flags() | Qt::ItemIsUserCheckable );
      setCheckState( 0, resource->isActive() ? Qt::Checked : Qt::Unchecked );
      setIcon( 0, KIcon( "x-office-address-book" ) );
    }

    KABCResourceItem( KABC::ResourceABC *resourceABC, KABCResourceItem* parent,
                  const QString& resourceIdent )
      : QTreeWidgetItem( parent, QStringList( resourceABC->subresourceLabel( resourceIdent ) ) ),
        mResource( resourceABC ),
        mIsSubresource( true ), mSubItemsCreated( false ),
        mResourceIdentifier( resourceIdent )
    {
      setFlags( flags() | Qt::ItemIsUserCheckable );
      KABC::ResourceABC* res = static_cast<KABC::ResourceABC *>( mResource );
      setCheckState( 0, res->subresourceActive( mResourceIdentifier ) ? Qt::Checked : Qt::Unchecked );
      setIcon( 0, KIcon( "x-office-address-book" ) );

      treeWidget()->setRootIsDecorated( true );
    }

    ~KABCResourceItem()
    {
        qDebug( ) << "Deleting Item";
    }

    void createSubresourceItems();
    KABC::Resource *resource() const { return mResource; }
    QString resourceIdentifier() const { return mResourceIdentifier; }
    bool isSubResource() const { return mIsSubresource; }

  private:
    KABC::Resource * const mResource;
    const bool mIsSubresource;
    bool mSubItemsCreated;
    const QString mResourceIdentifier;
};

// Comes from korganizer/resourceview.cpp
void KABCResourceItem::createSubresourceItems()
{
  if ( !mIsSubresource && !mSubItemsCreated ) {
    KABC::ResourceABC* res = dynamic_cast<KABC::ResourceABC *>( mResource );
    QStringList subresources;
    if ( res )
      subresources = res->subresources();
    if ( !subresources.isEmpty() ) {
      setExpanded( true );

      // This resource has subresources
      QStringList::ConstIterator it;
      for ( it = subresources.begin(); it != subresources.end(); ++it ) {
        (void)new KABCResourceItem( res, this, *it );
      }
    }
    mSubItemsCreated = true;

    setExpanded( childCount() > 0 );
  }
}

////

ResourceSelection::ResourceSelection( KAB::Core *core, QWidget *parent )
  : KAB::ExtensionWidget( core, parent ), mManager( 0 )
{
  initGUI();

  AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( core->addressBook() );
  mManager = wrapper->getResourceManager();

  connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) );
  connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) );
  connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) );

  connect( mListView, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ),
           SLOT( currentChanged( QTreeWidgetItem * ) ) );

  QTimer::singleShot( 0, this, SLOT( updateView() ) );
}

ResourceSelection::~ResourceSelection()
{
}

QString ResourceSelection::title() const
{
  return i18n( "Address Books" );
}

QString ResourceSelection::identifier() const
{
  return "resourceselection";
}

void ResourceSelection::add()
{
  QStringList types = mManager->resourceTypeNames();
  QStringList descs = mManager->resourceTypeDescriptions();

  bool ok = false;
  QString desc = KInputDialog::getItem( i18n( "Add Address Book" ),
                                        i18n( "Please select type of the new address book:" ),
                                        descs, 0, false, &ok, this );
  if ( !ok )
    return;

  QString type = types[ descs.indexOf( desc ) ];

  // Create new resource
  KABC::Resource *resource = mManager->createResource( type );
  if ( !resource ) {
    KMessageBox::error( this, i18n("<qt>Unable to create an address book of type %1.</qt>",
                                type ) );
    return;
  }

  resource->setResourceName( i18n( "%1 address book", type ) );
  resource->setAddressBook( core()->addressBook() );

  KRES::ConfigDialog dlg( this, QString( "contact" ), resource );

  if ( dlg.exec() ) {
    core()->addressBook()->addResource( resource );
    resource->asyncLoad();

    mLastResource = resource->identifier();
    updateView();
  } else {
    delete resource;
    resource = 0;
  }
}

void ResourceSelection::edit()
{
  KABCResourceItem *item = selectedItem();
  if ( !item )
    return;

  KRES::ConfigDialog dlg( this, QString( "contact" ), item->resource() );

  if ( dlg.exec() ) {
    mManager->change( item->resource() );
    item->resource()->asyncLoad();

    mLastResource = item->resource()->identifier();
    updateView();
  }
}

void ResourceSelection::remove()
{
  KABCResourceItem *item = selectedItem();
  if ( !item )
    return;

  int result = KMessageBox::warningContinueCancel( this,
        i18n( "<qt>Do you really want to remove the address book %1?</qt>" ,
          item->resource()->resourceName() ), "",
        KGuiItem( i18n( "&Remove" ), "edit-delete" ) );
  if ( result == KMessageBox::Cancel )
    return;

  mLastResource = item->resource()->identifier();

  core()->addressBook()->removeResource( item->resource() );
  core()->addressBook()->emitAddressBookChanged();

  updateView();
}

void ResourceSelection::currentChanged( QTreeWidgetItem *item )
{
  KABCResourceItem *resItem = static_cast<KABCResourceItem*>( item );
  bool state = (resItem && !resItem->isSubResource() );

  mEditButton->setEnabled( state );
  mRemoveButton->setEnabled( state );

  if ( !resItem )
    return;

  KABC::Resource *resource = resItem->resource();

  resItem->createSubresourceItems();

  if ( resItem->isSubResource() ) {
    KABC::ResourceABC *res = static_cast<KABC::ResourceABC *>( resource );
    res->setSubresourceActive( resItem->resourceIdentifier(), resItem->checkState( 0 ) == Qt::Checked );
    mManager->change( resource );
  } else {
    resource->setActive( resItem->checkState( 0 ) == Qt::Checked );
    mManager->change( resource );

    if ( resItem->checkState( 0 ) == Qt::Checked ) {
      if ( !resource->addressBook() )
        resource->setAddressBook( core()->addressBook() );

      if ( !resource->isOpen() )
        resource->open();

      resource->asyncLoad();
    } else {
      resource->close();
    }
  }

  mLastResource = resource->identifier();
  core()->addressBook()->emitAddressBookChanged();
  //updateView();
}

void ResourceSelection::updateView()
{
  if ( !mManager )
    return;

  mListView->clear();

  KRES::Manager<KABC::Resource>::Iterator it;
  for ( it = mManager->begin(); it != mManager->end(); ++it ) {

    new KABCResourceItem( mListView, *it );
    KABC::ResourceABC* resource = dynamic_cast<KABC::ResourceABC *>( *it );
    if ( resource ) {
      disconnect( resource, 0, this, 0 );
      connect( resource, SIGNAL( signalSubresourceAdded( KABC::ResourceABC *,
                                                         const QString &, const QString & ) ),
               SLOT( slotSubresourceAdded( KABC::ResourceABC *,
                                           const QString &, const QString & ) ) );

      connect( resource, SIGNAL( signalSubresourceRemoved( KABC::ResourceABC *,
                                                           const QString &, const QString & ) ),
               SLOT( slotSubresourceRemoved( KABC::ResourceABC *,
                                             const QString &, const QString & ) ) );
      connect( resource, SIGNAL( signalSubresourceChanged( KABC::ResourceABC *,
                                                           const QString &, const QString & ) ),
               SLOT( slotSubresourceChanged( KABC::ResourceABC *,
                                             const QString &, const QString & ) ) );
      //connect( resource, SIGNAL( resourceSaved( KABC::ResourceABC * ) ),
      //         SLOT( closeResource( KABC::ResourceABC * ) ) );
    }
  }

  QTreeWidgetItemIterator iterator( mListView );
  while ( *iterator ) {
    KABCResourceItem *item = static_cast< KABCResourceItem * >( *iterator );
    if ( item->resource()->identifier() == mLastResource ) {
      item->setSelected( true );
      break;
    }
    ++iterator;
  }

  core()->addressBook()->emitAddressBookChanged();
}

// Add a new entry
void ResourceSelection::slotSubresourceAdded( KABC::ResourceABC *resource,
                                              const QString& /*type*/,
                                              const QString& subResource )
{
  kDebug(5720) << resource->resourceName() << subResource;

  QList< QTreeWidgetItem * > foundItems =
      mListView->findItems( resource->resourceName(), Qt::MatchExactly );

  if ( foundItems.size() == 0 )
    // Not found
    return;

  KABCResourceItem *item = static_cast<KABCResourceItem *>( foundItems[0] );

  // make sure all other sub items have already been created
  item->createSubresourceItems();

  // check if we already have an item for it
  if ( !findSubResourceItem( resource, subResource ) )
    (void)new KABCResourceItem( resource, item, subResource );
}

// Remove an entry
void ResourceSelection::slotSubresourceRemoved( KABC::ResourceABC* resource,
                                                const QString& /*type*/,
                                                const QString& subResource )
{
  kDebug(5720) << resource->resourceName() << subResource;

  KABCResourceItem *item = findSubResourceItem( resource, subResource );
  delete item;
  // TODO
  //emitResourcesChanged();
}

// change an entry
void ResourceSelection::slotSubresourceChanged( KABC::ResourceABC* resource,
                                                const QString& type,
                                                const QString& subResource )
{
  kDebug(5720) << resource->resourceName() << subResource;

  KABCResourceItem *item = findSubResourceItem( resource, subResource );
  if ( item == 0 ) {
    kWarning(5720) << "Changed before it was added?";
    slotSubresourceAdded( resource, type, subResource );
    return;
  }

  item->setText( 0, resource->subresourceLabel( subResource ) );
  item->setCheckState( 0, resource->subresourceActive( subResource )
                            ? Qt::Checked : Qt::Unchecked );
  // TODO
  //emitResourcesChanged();
}

KABCResourceItem* ResourceSelection::selectedItem() const
{
  return static_cast<KABCResourceItem*>( mListView->currentItem() );
}

KABCResourceItem* ResourceSelection::findSubResourceItem( KABC::ResourceABC *resource,
                                                          const QString &subResource )
{
  QTreeWidgetItemIterator parentIt( mListView );
  for ( ; *parentIt; ++parentIt ) {
    if ( static_cast<KABCResourceItem*>(*parentIt)->resource() != resource )
      continue;

    QTreeWidgetItemIterator childIt( *parentIt );
    for ( ; *childIt; ++childIt ) {
      KABCResourceItem *item = static_cast<KABCResourceItem*>(*childIt);
      if ( item->resourceIdentifier() == subResource )
        return item;
    }
  }

  return 0;
}

void ResourceSelection::initGUI()
{
  QBoxLayout *topLayout = new QVBoxLayout( this );
  topLayout->setSpacing( KDialog::spacingHint() );
  QBoxLayout *buttonLayout = new QHBoxLayout();
  buttonLayout->setSpacing( KDialog::spacingHint() );
  topLayout->addLayout( buttonLayout );

  QLabel *abLabel = new QLabel( i18n( "Address Books" ), this );
  buttonLayout->addWidget( abLabel );
  buttonLayout->addStretch( 1 );

  mAddButton = new QToolButton( this );
  mAddButton->setIcon( KIcon( "list-add" ) );
  mAddButton->setToolTip( i18n( "Add addressbook" ) );
  buttonLayout->addWidget( mAddButton );
  mEditButton = new QToolButton( this );
  mEditButton->setIcon( KIcon( "document-properties" ) );
  mEditButton->setEnabled( false );
  mEditButton->setToolTip( i18n( "Edit addressbook settings" ) );
  buttonLayout->addWidget( mEditButton );
  mRemoveButton = new QToolButton( this );
  mRemoveButton->setIcon( KIcon( "edit-delete" ) );
  mRemoveButton->setEnabled( false );
  mRemoveButton->setToolTip( i18n( "Remove addressbook" ) );
  buttonLayout->addWidget( mRemoveButton );

  mListView = new QTreeWidget( this );
  mListView->setRootIsDecorated( false );
  mListView->setHeaderLabel( i18n( "Address Books" ) );
  mListView->header()->hide();
  topLayout->addWidget( mListView );
}

class ResourceSelectionFactory : public KAB::ExtensionFactory
{
  public:
    KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent )
    {
      return new ResourceSelection( core, parent );
    }

    QString identifier() const
    {
      return "resourceselection";
    }
};

K_EXPORT_PLUGIN(ResourceSelectionFactory)

#include "resourceselection.moc"
<commit_msg>SVN_SILENT no debug<commit_after>/*
    This file is part of KAddressBook.
    Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QtCore/QTimer>
#include <QtGui/QGridLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QPushButton>
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>

#include <kabc/resource.h>
#include <kabc/resourceabc.h>
#include <kdialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kresources/configdialog.h>

#include "core.h"
#include "resourceselection.h"

class AddressBookWrapper : public KABC::AddressBook
{
  public:
    AddressBookWrapper( KABC::AddressBook* );

    KRES::Manager<KABC::Resource>* getResourceManager()
    {
      return resourceManager();
    }
};

class KABCResourceItem : public QTreeWidgetItem
{
  public:
    KABCResourceItem( QTreeWidget *parent, KABC::Resource *resource )
      : QTreeWidgetItem( parent, QStringList( resource->resourceName() ) ),
        mResource( resource ),
        mIsSubresource( false ), mSubItemsCreated( false ),
        mResourceIdentifier()
    {
      setFlags( flags() | Qt::ItemIsUserCheckable );
      setCheckState( 0, resource->isActive() ? Qt::Checked : Qt::Unchecked );
      setIcon( 0, KIcon( "x-office-address-book" ) );
    }

    KABCResourceItem( KABC::ResourceABC *resourceABC, KABCResourceItem* parent,
                  const QString& resourceIdent )
      : QTreeWidgetItem( parent, QStringList( resourceABC->subresourceLabel( resourceIdent ) ) ),
        mResource( resourceABC ),
        mIsSubresource( true ), mSubItemsCreated( false ),
        mResourceIdentifier( resourceIdent )
    {
      setFlags( flags() | Qt::ItemIsUserCheckable );
      KABC::ResourceABC* res = static_cast<KABC::ResourceABC *>( mResource );
      setCheckState( 0, res->subresourceActive( mResourceIdentifier ) ? Qt::Checked : Qt::Unchecked );
      setIcon( 0, KIcon( "x-office-address-book" ) );

      treeWidget()->setRootIsDecorated( true );
    }

    ~KABCResourceItem()
    {
    }

    void createSubresourceItems();
    KABC::Resource *resource() const { return mResource; }
    QString resourceIdentifier() const { return mResourceIdentifier; }
    bool isSubResource() const { return mIsSubresource; }

  private:
    KABC::Resource * const mResource;
    const bool mIsSubresource;
    bool mSubItemsCreated;
    const QString mResourceIdentifier;
};

// Comes from korganizer/resourceview.cpp
void KABCResourceItem::createSubresourceItems()
{
  if ( !mIsSubresource && !mSubItemsCreated ) {
    KABC::ResourceABC* res = dynamic_cast<KABC::ResourceABC *>( mResource );
    QStringList subresources;
    if ( res )
      subresources = res->subresources();
    if ( !subresources.isEmpty() ) {
      setExpanded( true );

      // This resource has subresources
      QStringList::ConstIterator it;
      for ( it = subresources.begin(); it != subresources.end(); ++it ) {
        (void)new KABCResourceItem( res, this, *it );
      }
    }
    mSubItemsCreated = true;

    setExpanded( childCount() > 0 );
  }
}

////

ResourceSelection::ResourceSelection( KAB::Core *core, QWidget *parent )
  : KAB::ExtensionWidget( core, parent ), mManager( 0 )
{
  initGUI();

  AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( core->addressBook() );
  mManager = wrapper->getResourceManager();

  connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) );
  connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) );
  connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) );

  connect( mListView, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ),
           SLOT( currentChanged( QTreeWidgetItem * ) ) );

  QTimer::singleShot( 0, this, SLOT( updateView() ) );
}

ResourceSelection::~ResourceSelection()
{
}

QString ResourceSelection::title() const
{
  return i18n( "Address Books" );
}

QString ResourceSelection::identifier() const
{
  return "resourceselection";
}

void ResourceSelection::add()
{
  QStringList types = mManager->resourceTypeNames();
  QStringList descs = mManager->resourceTypeDescriptions();

  bool ok = false;
  QString desc = KInputDialog::getItem( i18n( "Add Address Book" ),
                                        i18n( "Please select type of the new address book:" ),
                                        descs, 0, false, &ok, this );
  if ( !ok )
    return;

  QString type = types[ descs.indexOf( desc ) ];

  // Create new resource
  KABC::Resource *resource = mManager->createResource( type );
  if ( !resource ) {
    KMessageBox::error( this, i18n("<qt>Unable to create an address book of type %1.</qt>",
                                type ) );
    return;
  }

  resource->setResourceName( i18n( "%1 address book", type ) );
  resource->setAddressBook( core()->addressBook() );

  KRES::ConfigDialog dlg( this, QString( "contact" ), resource );

  if ( dlg.exec() ) {
    core()->addressBook()->addResource( resource );
    resource->asyncLoad();

    mLastResource = resource->identifier();
    updateView();
  } else {
    delete resource;
    resource = 0;
  }
}

void ResourceSelection::edit()
{
  KABCResourceItem *item = selectedItem();
  if ( !item )
    return;

  KRES::ConfigDialog dlg( this, QString( "contact" ), item->resource() );

  if ( dlg.exec() ) {
    mManager->change( item->resource() );
    item->resource()->asyncLoad();

    mLastResource = item->resource()->identifier();
    updateView();
  }
}

void ResourceSelection::remove()
{
  KABCResourceItem *item = selectedItem();
  if ( !item )
    return;

  int result = KMessageBox::warningContinueCancel( this,
        i18n( "<qt>Do you really want to remove the address book %1?</qt>" ,
          item->resource()->resourceName() ), "",
        KGuiItem( i18n( "&Remove" ), "edit-delete" ) );
  if ( result == KMessageBox::Cancel )
    return;

  mLastResource = item->resource()->identifier();

  core()->addressBook()->removeResource( item->resource() );
  core()->addressBook()->emitAddressBookChanged();

  updateView();
}

void ResourceSelection::currentChanged( QTreeWidgetItem *item )
{
  KABCResourceItem *resItem = static_cast<KABCResourceItem*>( item );
  bool state = (resItem && !resItem->isSubResource() );

  mEditButton->setEnabled( state );
  mRemoveButton->setEnabled( state );

  if ( !resItem )
    return;

  KABC::Resource *resource = resItem->resource();

  resItem->createSubresourceItems();

  if ( resItem->isSubResource() ) {
    KABC::ResourceABC *res = static_cast<KABC::ResourceABC *>( resource );
    res->setSubresourceActive( resItem->resourceIdentifier(), resItem->checkState( 0 ) == Qt::Checked );
    mManager->change( resource );
  } else {
    resource->setActive( resItem->checkState( 0 ) == Qt::Checked );
    mManager->change( resource );

    if ( resItem->checkState( 0 ) == Qt::Checked ) {
      if ( !resource->addressBook() )
        resource->setAddressBook( core()->addressBook() );

      if ( !resource->isOpen() )
        resource->open();

      resource->asyncLoad();
    } else {
      resource->close();
    }
  }

  mLastResource = resource->identifier();
  core()->addressBook()->emitAddressBookChanged();
  //updateView();
}

void ResourceSelection::updateView()
{
  if ( !mManager )
    return;

  mListView->clear();

  KRES::Manager<KABC::Resource>::Iterator it;
  for ( it = mManager->begin(); it != mManager->end(); ++it ) {

    new KABCResourceItem( mListView, *it );
    KABC::ResourceABC* resource = dynamic_cast<KABC::ResourceABC *>( *it );
    if ( resource ) {
      disconnect( resource, 0, this, 0 );
      connect( resource, SIGNAL( signalSubresourceAdded( KABC::ResourceABC *,
                                                         const QString &, const QString & ) ),
               SLOT( slotSubresourceAdded( KABC::ResourceABC *,
                                           const QString &, const QString & ) ) );

      connect( resource, SIGNAL( signalSubresourceRemoved( KABC::ResourceABC *,
                                                           const QString &, const QString & ) ),
               SLOT( slotSubresourceRemoved( KABC::ResourceABC *,
                                             const QString &, const QString & ) ) );
      connect( resource, SIGNAL( signalSubresourceChanged( KABC::ResourceABC *,
                                                           const QString &, const QString & ) ),
               SLOT( slotSubresourceChanged( KABC::ResourceABC *,
                                             const QString &, const QString & ) ) );
      //connect( resource, SIGNAL( resourceSaved( KABC::ResourceABC * ) ),
      //         SLOT( closeResource( KABC::ResourceABC * ) ) );
    }
  }

  QTreeWidgetItemIterator iterator( mListView );
  while ( *iterator ) {
    KABCResourceItem *item = static_cast< KABCResourceItem * >( *iterator );
    if ( item->resource()->identifier() == mLastResource ) {
      item->setSelected( true );
      break;
    }
    ++iterator;
  }

  core()->addressBook()->emitAddressBookChanged();
}

// Add a new entry
void ResourceSelection::slotSubresourceAdded( KABC::ResourceABC *resource,
                                              const QString& /*type*/,
                                              const QString& subResource )
{
  kDebug(5720) << resource->resourceName() << subResource;

  QList< QTreeWidgetItem * > foundItems =
      mListView->findItems( resource->resourceName(), Qt::MatchExactly );

  if ( foundItems.size() == 0 )
    // Not found
    return;

  KABCResourceItem *item = static_cast<KABCResourceItem *>( foundItems[0] );

  // make sure all other sub items have already been created
  item->createSubresourceItems();

  // check if we already have an item for it
  if ( !findSubResourceItem( resource, subResource ) )
    (void)new KABCResourceItem( resource, item, subResource );
}

// Remove an entry
void ResourceSelection::slotSubresourceRemoved( KABC::ResourceABC* resource,
                                                const QString& /*type*/,
                                                const QString& subResource )
{
  kDebug(5720) << resource->resourceName() << subResource;

  KABCResourceItem *item = findSubResourceItem( resource, subResource );
  delete item;
  // TODO
  //emitResourcesChanged();
}

// change an entry
void ResourceSelection::slotSubresourceChanged( KABC::ResourceABC* resource,
                                                const QString& type,
                                                const QString& subResource )
{
  kDebug(5720) << resource->resourceName() << subResource;

  KABCResourceItem *item = findSubResourceItem( resource, subResource );
  if ( item == 0 ) {
    kWarning(5720) << "Changed before it was added?";
    slotSubresourceAdded( resource, type, subResource );
    return;
  }

  item->setText( 0, resource->subresourceLabel( subResource ) );
  item->setCheckState( 0, resource->subresourceActive( subResource )
                            ? Qt::Checked : Qt::Unchecked );
  // TODO
  //emitResourcesChanged();
}

KABCResourceItem* ResourceSelection::selectedItem() const
{
  return static_cast<KABCResourceItem*>( mListView->currentItem() );
}

KABCResourceItem* ResourceSelection::findSubResourceItem( KABC::ResourceABC *resource,
                                                          const QString &subResource )
{
  QTreeWidgetItemIterator parentIt( mListView );
  for ( ; *parentIt; ++parentIt ) {
    if ( static_cast<KABCResourceItem*>(*parentIt)->resource() != resource )
      continue;

    QTreeWidgetItemIterator childIt( *parentIt );
    for ( ; *childIt; ++childIt ) {
      KABCResourceItem *item = static_cast<KABCResourceItem*>(*childIt);
      if ( item->resourceIdentifier() == subResource )
        return item;
    }
  }

  return 0;
}

void ResourceSelection::initGUI()
{
  QBoxLayout *topLayout = new QVBoxLayout( this );
  topLayout->setSpacing( KDialog::spacingHint() );
  QBoxLayout *buttonLayout = new QHBoxLayout();
  buttonLayout->setSpacing( KDialog::spacingHint() );
  topLayout->addLayout( buttonLayout );

  QLabel *abLabel = new QLabel( i18n( "Address Books" ), this );
  buttonLayout->addWidget( abLabel );
  buttonLayout->addStretch( 1 );

  mAddButton = new QToolButton( this );
  mAddButton->setIcon( KIcon( "list-add" ) );
  mAddButton->setToolTip( i18n( "Add addressbook" ) );
  buttonLayout->addWidget( mAddButton );
  mEditButton = new QToolButton( this );
  mEditButton->setIcon( KIcon( "document-properties" ) );
  mEditButton->setEnabled( false );
  mEditButton->setToolTip( i18n( "Edit addressbook settings" ) );
  buttonLayout->addWidget( mEditButton );
  mRemoveButton = new QToolButton( this );
  mRemoveButton->setIcon( KIcon( "edit-delete" ) );
  mRemoveButton->setEnabled( false );
  mRemoveButton->setToolTip( i18n( "Remove addressbook" ) );
  buttonLayout->addWidget( mRemoveButton );

  mListView = new QTreeWidget( this );
  mListView->setRootIsDecorated( false );
  mListView->setHeaderLabel( i18n( "Address Books" ) );
  mListView->header()->hide();
  topLayout->addWidget( mListView );
}

class ResourceSelectionFactory : public KAB::ExtensionFactory
{
  public:
    KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent )
    {
      return new ResourceSelection( core, parent );
    }

    QString identifier() const
    {
      return "resourceselection";
    }
};

K_EXPORT_PLUGIN(ResourceSelectionFactory)

#include "resourceselection.moc"
<|endoftext|>


<commit_before>/**
 * @file   llcapabilitylistener_test.cpp
 * @author Nat Goodspeed
 * @date   2008-12-31
 * @brief  Test for llcapabilitylistener.cpp.
 *
 * $LicenseInfo:firstyear=2008&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

// Precompiled header
#include "../llviewerprecompiledheaders.h"
// Own header
#include "../llcapabilitylistener.h"
// STL headers
#include <stdexcept>
#include <map>
#include <vector>
// std headers
// external library headers
#include "boost/bind.hpp"
// other Linden headers
#include "../test/lltut.h"
#include "../llcapabilityprovider.h"
#include "lluuid.h"
#include "tests/networkio.h"
#include "tests/commtest.h"
#include "tests/wrapllerrs.h"
#include "message.h"
#include "stringize.h"

#if defined(LL_WINDOWS)
#pragma warning(disable: 4355)      // using 'this' in base-class ctor initializer expr
#endif

/*****************************************************************************
*   TestCapabilityProvider
*****************************************************************************/
struct TestCapabilityProvider: public LLCapabilityProvider
{
    TestCapabilityProvider(const LLHost& host):
        mHost(host)
    {}

    std::string getCapability(const std::string& cap) const
    {
        CapMap::const_iterator found = mCaps.find(cap);
        if (found != mCaps.end())
            return found->second;
        // normal LLViewerRegion lookup failure mode
        return "";
    }
    void setCapability(const std::string& cap, const std::string& url)
    {
        mCaps[cap] = url;
    }
    LLHost getHost() const { return mHost; }
    std::string getDescription() const { return "TestCapabilityProvider"; }

    LLHost mHost;
    typedef std::map<std::string, std::string> CapMap;
    CapMap mCaps;
};

/*****************************************************************************
*   Dummy LLMessageSystem methods
*****************************************************************************/
/*==========================================================================*|
// This doesn't work because we're already linking in llmessage.a, and we get
// duplicate-symbol errors from the linker. Perhaps if I wanted to go through
// the exercise of providing dummy versions of every single symbol defined in
// message.o -- maybe some day.
typedef std::vector< std::pair<std::string, std::string> > StringPairVector;
StringPairVector call_history;

S32 LLMessageSystem::sendReliable(const LLHost& host)
{
    call_history.push_back(StringPairVector::value_type("sendReliable", stringize(host)));
    return 0;
}
|*==========================================================================*/

/*****************************************************************************
*   TUT
*****************************************************************************/
namespace tut
{
    struct llcapears_data: public commtest_data
    {
        TestCapabilityProvider provider;
        LLCapabilityListener regionListener;
        LLEventPump& regionPump;

        llcapears_data():
            provider(host),
            regionListener("testCapabilityListener", NULL, provider, LLUUID(), LLUUID()),
            regionPump(regionListener.getCapAPI())
        {
            provider.setCapability("good", server + "capability-test");
            provider.setCapability("fail", server + "fail");
        }
    };
    typedef test_group<llcapears_data> llcapears_group;
    typedef llcapears_group::object llcapears_object;
    llcapears_group llsdmgr("llcapabilitylistener");

    template<> template<>
    void llcapears_object::test<1>()
    {
        LLSD request, body;
        body["data"] = "yes";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        std::string threw;
        try
        {
            WrapLL_ERRS capture;
            regionPump.post(request);
        }
        catch (const WrapLL_ERRS::FatalException& e)
        {
            threw = e.what();
        }
        ensure_contains("missing capability name", threw, "without 'message' key");
    }

    template<> template<>
    void llcapears_object::test<2>()
    {
        LLSD request, body;
        body["data"] = "yes";
        request["message"] = "good";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        regionPump.post(request);
        ensure("got response", netio.pump());
        ensure("success response", success);
        ensure_equals(result.asString(), "success");

        body["status"] = 499;
        body["reason"] = "custom error message";
        request["message"] = "fail";
        request["payload"] = body;
        regionPump.post(request);
        ensure("got response", netio.pump());
        ensure("failure response", ! success);
        ensure_equals(result["status"].asInteger(), body["status"].asInteger());
        ensure_equals(result["reason"].asString(),  body["reason"].asString());
    }

    template<> template<>
    void llcapears_object::test<3>()
    {
        LLSD request, body;
        body["data"] = "yes";
        request["message"] = "unknown";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        std::string threw;
        try
        {
            WrapLL_ERRS capture;
            regionPump.post(request);
        }
        catch (const WrapLL_ERRS::FatalException& e)
        {
            threw = e.what();
        }
        ensure_contains("bad capability name", threw, "unsupported capability");
    }

    struct TestMapper: public LLCapabilityListener::CapabilityMapper
    {
        // Instantiator gets to specify whether mapper expects a reply.
        // I'd really like to be able to test CapabilityMapper::buildMessage()
        // functionality, too, but -- even though LLCapabilityListener accepts
        // the LLMessageSystem* that it passes to CapabilityMapper --
        // LLMessageSystem::sendReliable(const LLHost&) isn't virtual, so it's
        // not helpful to pass a subclass instance. I suspect that making any
        // LLMessageSystem methods virtual would provoke howls of outrage,
        // given how heavily it's used. Nor can I just provide a local
        // definition of LLMessageSystem::sendReliable(const LLHost&) because
        // we're already linking in the rest of message.o via llmessage.a, and
        // that produces duplicate-symbol link errors.
        TestMapper(const std::string& replyMessage = std::string()):
            LLCapabilityListener::CapabilityMapper("test", replyMessage)
        {}
        virtual void buildMessage(LLMessageSystem* msg,
                                  const LLUUID& agentID,
                                  const LLUUID& sessionID,
                                  const std::string& capabilityName,
                                  const LLSD& payload) const
        {
            msg->newMessageFast(_PREHASH_SetStartLocationRequest);
            msg->nextBlockFast( _PREHASH_AgentData);
            msg->addUUIDFast(_PREHASH_AgentID, agentID);
            msg->addUUIDFast(_PREHASH_SessionID, sessionID);
            msg->nextBlockFast( _PREHASH_StartLocationData);
            // corrected by sim
            msg->addStringFast(_PREHASH_SimName, "");
            msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger());
/*==========================================================================*|
            msg->addVector3Fast(_PREHASH_LocationPos,
                                ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"]));
            msg->addVector3Fast(_PREHASH_LocationLookAt,
                                ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"]));
|*==========================================================================*/
        }
    };

    template<> template<>
    void llcapears_object::test<4>()
    {
        TestMapper testMapper("WantReply");
        LLSD request, body;
        body["data"] = "yes";
        request["message"] = "test";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        std::string threw;
        try
        {
            WrapLL_ERRS capture;
            regionPump.post(request);
        }
        catch (const WrapLL_ERRS::FatalException& e)
        {
            threw = e.what();
        }
        ensure_contains("capability mapper wants reply", threw, "unimplemented support for reply message");
    }

    template<> template<>
    void llcapears_object::test<5>()
    {
        TestMapper testMapper;
        std::string threw;
        try
        {
            TestMapper testMapper2;
        }
        catch (const std::runtime_error& e)
        {
            threw = e.what();
        }
        ensure_contains("no dup cap mapper", threw, "DupCapMapper");
    }
}
<commit_msg>correct build error<commit_after>/**
 * @file   llcapabilitylistener_test.cpp
 * @author Nat Goodspeed
 * @date   2008-12-31
 * @brief  Test for llcapabilitylistener.cpp.
 *
 * $LicenseInfo:firstyear=2008&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

// Precompiled header
#include "../llviewerprecompiledheaders.h"
// Own header
#include "../llcapabilitylistener.h"
// STL headers
#include <stdexcept>
#include <map>
#include <vector>
// std headers
// external library headers
#include "boost/bind.hpp"
// other Linden headers
#include "../test/lltut.h"
#include "../llcapabilityprovider.h"
#include "lluuid.h"
#include "tests/networkio.h"
#include "tests/commtest.h"
#include "tests/wrapllerrs.h"
#include "message.h"
#include "stringize.h"

#if defined(LL_WINDOWS)
#pragma warning(disable: 4355)      // using 'this' in base-class ctor initializer expr
#endif

/*****************************************************************************
*   TestCapabilityProvider
*****************************************************************************/
struct TestCapabilityProvider: public LLCapabilityProvider
{
    TestCapabilityProvider(const LLHost& host):
        mHost(host)
    {}

    std::string getCapability(const std::string& cap) const
    {
        CapMap::const_iterator found = mCaps.find(cap);
        if (found != mCaps.end())
            return found->second;
        // normal LLViewerRegion lookup failure mode
        return "";
    }
    void setCapability(const std::string& cap, const std::string& url)
    {
        mCaps[cap] = url;
    }
    const LLHost& getHost() const { return mHost; }
    std::string getDescription() const { return "TestCapabilityProvider"; }

    LLHost mHost;
    typedef std::map<std::string, std::string> CapMap;
    CapMap mCaps;
};

/*****************************************************************************
*   Dummy LLMessageSystem methods
*****************************************************************************/
/*==========================================================================*|
// This doesn't work because we're already linking in llmessage.a, and we get
// duplicate-symbol errors from the linker. Perhaps if I wanted to go through
// the exercise of providing dummy versions of every single symbol defined in
// message.o -- maybe some day.
typedef std::vector< std::pair<std::string, std::string> > StringPairVector;
StringPairVector call_history;

S32 LLMessageSystem::sendReliable(const LLHost& host)
{
    call_history.push_back(StringPairVector::value_type("sendReliable", stringize(host)));
    return 0;
}
|*==========================================================================*/

/*****************************************************************************
*   TUT
*****************************************************************************/
namespace tut
{
    struct llcapears_data: public commtest_data
    {
        TestCapabilityProvider provider;
        LLCapabilityListener regionListener;
        LLEventPump& regionPump;

        llcapears_data():
            provider(host),
            regionListener("testCapabilityListener", NULL, provider, LLUUID(), LLUUID()),
            regionPump(regionListener.getCapAPI())
        {
            provider.setCapability("good", server + "capability-test");
            provider.setCapability("fail", server + "fail");
        }
    };
    typedef test_group<llcapears_data> llcapears_group;
    typedef llcapears_group::object llcapears_object;
    llcapears_group llsdmgr("llcapabilitylistener");

    template<> template<>
    void llcapears_object::test<1>()
    {
        LLSD request, body;
        body["data"] = "yes";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        std::string threw;
        try
        {
            WrapLL_ERRS capture;
            regionPump.post(request);
        }
        catch (const WrapLL_ERRS::FatalException& e)
        {
            threw = e.what();
        }
        ensure_contains("missing capability name", threw, "without 'message' key");
    }

    template<> template<>
    void llcapears_object::test<2>()
    {
        LLSD request, body;
        body["data"] = "yes";
        request["message"] = "good";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        regionPump.post(request);
        ensure("got response", netio.pump());
        ensure("success response", success);
        ensure_equals(result.asString(), "success");

        body["status"] = 499;
        body["reason"] = "custom error message";
        request["message"] = "fail";
        request["payload"] = body;
        regionPump.post(request);
        ensure("got response", netio.pump());
        ensure("failure response", ! success);
        ensure_equals(result["status"].asInteger(), body["status"].asInteger());
        ensure_equals(result["reason"].asString(),  body["reason"].asString());
    }

    template<> template<>
    void llcapears_object::test<3>()
    {
        LLSD request, body;
        body["data"] = "yes";
        request["message"] = "unknown";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        std::string threw;
        try
        {
            WrapLL_ERRS capture;
            regionPump.post(request);
        }
        catch (const WrapLL_ERRS::FatalException& e)
        {
            threw = e.what();
        }
        ensure_contains("bad capability name", threw, "unsupported capability");
    }

    struct TestMapper: public LLCapabilityListener::CapabilityMapper
    {
        // Instantiator gets to specify whether mapper expects a reply.
        // I'd really like to be able to test CapabilityMapper::buildMessage()
        // functionality, too, but -- even though LLCapabilityListener accepts
        // the LLMessageSystem* that it passes to CapabilityMapper --
        // LLMessageSystem::sendReliable(const LLHost&) isn't virtual, so it's
        // not helpful to pass a subclass instance. I suspect that making any
        // LLMessageSystem methods virtual would provoke howls of outrage,
        // given how heavily it's used. Nor can I just provide a local
        // definition of LLMessageSystem::sendReliable(const LLHost&) because
        // we're already linking in the rest of message.o via llmessage.a, and
        // that produces duplicate-symbol link errors.
        TestMapper(const std::string& replyMessage = std::string()):
            LLCapabilityListener::CapabilityMapper("test", replyMessage)
        {}
        virtual void buildMessage(LLMessageSystem* msg,
                                  const LLUUID& agentID,
                                  const LLUUID& sessionID,
                                  const std::string& capabilityName,
                                  const LLSD& payload) const
        {
            msg->newMessageFast(_PREHASH_SetStartLocationRequest);
            msg->nextBlockFast( _PREHASH_AgentData);
            msg->addUUIDFast(_PREHASH_AgentID, agentID);
            msg->addUUIDFast(_PREHASH_SessionID, sessionID);
            msg->nextBlockFast( _PREHASH_StartLocationData);
            // corrected by sim
            msg->addStringFast(_PREHASH_SimName, "");
            msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger());
/*==========================================================================*|
            msg->addVector3Fast(_PREHASH_LocationPos,
                                ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"]));
            msg->addVector3Fast(_PREHASH_LocationLookAt,
                                ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"]));
|*==========================================================================*/
        }
    };

    template<> template<>
    void llcapears_object::test<4>()
    {
        TestMapper testMapper("WantReply");
        LLSD request, body;
        body["data"] = "yes";
        request["message"] = "test";
        request["payload"] = body;
        request["reply"] = replyPump.getName();
        request["error"] = errorPump.getName();
        std::string threw;
        try
        {
            WrapLL_ERRS capture;
            regionPump.post(request);
        }
        catch (const WrapLL_ERRS::FatalException& e)
        {
            threw = e.what();
        }
        ensure_contains("capability mapper wants reply", threw, "unimplemented support for reply message");
    }

    template<> template<>
    void llcapears_object::test<5>()
    {
        TestMapper testMapper;
        std::string threw;
        try
        {
            TestMapper testMapper2;
        }
        catch (const std::runtime_error& e)
        {
            threw = e.what();
        }
        ensure_contains("no dup cap mapper", threw, "DupCapMapper");
    }
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <vector>

#define NXP_HW_SELF_TEST
#include "linux_nfc_factory_api.h"
#include "linux_nfc_api.h"

static int keepPolling = 1;
static std::vector <nfc_tag_info_t*> tags;
static pthread_mutex_t mutex;

void tagArrived(nfc_tag_info_t *p_taginfo)
{
    pthread_mutex_lock(&mutex);

    nfc_tag_info_t *temp = (nfc_tag_info_t *) malloc(sizeof(nfc_tag_info_t));
    memcpy(temp, p_taginfo, sizeof(nfc_tag_info_t));
    tags.push_back(temp);

    pthread_mutex_unlock(&mutex);
}

void tagDeparted()
{
}

int main(int argc, char ** argv)
{
    pthread_mutex_init(&mutex, NULL);

    // initialize nfcManager
    int result = nfcManager_doInitialize();
    if(result != 0)
    {
        printf("nfcManager_doInitialize failed with error code %d", result);
        exit(result);
    }

    // try to get versions
#ifdef NXP_HW_SELF_TEST
    printf("nfcFactory_GetMwVersion:\t%x\n", nfcFactory_GetMwVersion());
#endif
    printf("nfcManager_getFwVersion:\t%x\n", nfcManager_getFwVersion());

    // set up tag-callback
    nfcTagCallback_t cb_tag;
    cb_tag.onTagArrival = tagArrived;
    cb_tag.onTagDeparture = tagDeparted;
    nfcManager_registerTagCallback(&cb_tag);

    nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 0x00, 0x00, 0);

    while(keepPolling)
    {
        nfc_tag_info_t *tag = NULL;

        pthread_mutex_lock(&mutex);

        int tagcount = tags.size();

        if(tagcount)
        {
            tag = tags.front();
            tags.erase(tags.begin());
        }

        pthread_mutex_unlock(&mutex);

        if(tag)
        {
            char uid[97];
            int len = tag->uid_length;
            if(len > 32)
                len = 32;
            for(int i = 0; i < len; i++) {
                sprintf(uid + (i*3), "%02x ", tag->uid[i]);
            }
            uid[len*3] = '\0';
            printf("UID: %s\n", uid);

            free(tag);
        }

        usleep(10000);
    }

    pthread_mutex_destroy(&mutex);

    printf("\nExiting...\n");
    return 0;
}
<commit_msg>some cleanup and signal handling<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <vector>

#define NXP_HW_SELF_TEST
#include "linux_nfc_factory_api.h"
#include "linux_nfc_api.h"

#define MAX_UID_LENGTH 32
#define MAIN_SLEEP 10000

static int do_poll = 1;
static std::vector <nfc_tag_info_t*> v_tags;
static pthread_mutex_t mutex;

static void interrupted(int signal)
{
    do_poll = 0;
}

void tagArrived(nfc_tag_info_t *p_taginfo)
{
    pthread_mutex_lock(&mutex);

    nfc_tag_info_t *temp = (nfc_tag_info_t *) malloc(sizeof(nfc_tag_info_t));
    memcpy(temp, p_taginfo, sizeof(nfc_tag_info_t));
    v_tags.push_back(temp);

    pthread_mutex_unlock(&mutex);
}

void tagDeparted() { }

void printTagUID(nfc_tag_info_t *p_tag)
{
    char uid[3*MAX_UID_LENGTH+1];
    int len = p_tag->uid_length;
    if(len > MAX_UID_LENGTH)
        len = MAX_UID_LENGTH;

    for(int i = 0; i < len; i++) {
        sprintf(uid + (i*3), "%02x ", p_tag->uid[i]);
    }
    uid[len*3] = '\0';

    printf("UID: %s\n", uid);
}

int main(int argc, char ** argv)
{
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_handler = &interrupted;

    if (sigaction(SIGINT, &act, NULL) < 0 || sigaction(SIGTERM, &act, NULL)) {
        perror("sigaction");
        exit(1);
    }

    pthread_mutex_init(&mutex, NULL);

    // initialize nfcManager
    int result = nfcManager_doInitialize();
    if(result != 0)
    {
        printf("nfcManager_doInitialize failed with error code %d", result);
        exit(result);
    }

    // try to get versions
    #ifdef NXP_HW_SELF_TEST
    printf("nfcFactory_GetMwVersion:\t0x%x\n", nfcFactory_GetMwVersion());
    #endif
    printf("nfcManager_getFwVersion:\t0x%x\n\n", nfcManager_getFwVersion());

    // set up tag-callback
    nfcTagCallback_t cb_tag;
    cb_tag.onTagArrival = tagArrived;
    cb_tag.onTagDeparture = tagDeparted;
    nfcManager_registerTagCallback(&cb_tag);

    // start tag-discovery
    nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 0x00, 0x00, 0);

    // main loop, performs handling of read tags
    while(do_poll)
    {
        nfc_tag_info_t *tag = NULL;

        pthread_mutex_lock(&mutex);

        int tagcount = v_tags.size();
        if(tagcount)
        {
            tag = v_tags.front();
            v_tags.erase(v_tags.begin());
        }

        pthread_mutex_unlock(&mutex);

        if(tag)
        {
            printTagUID(tag);
            free(tag);
        }

        usleep(MAIN_SLEEP);
    }

    pthread_mutex_destroy(&mutex);

    printf("\n\nExiting...\n");
    return 0;
}
<|endoftext|>


<commit_before>/* dtkComposerNodeLoopDataComposite.cpp ---
 *
 * Author: Thibaud Kloczko
 * Copyright (C) 2011 - Thibaud Kloczko, Inria.
 * Created: Wed Oct 12 16:02:18 2011 (+0200)
 * Version: $Id$
 * Last-Updated: Thu Oct 13 17:40:52 2011 (+0200)
 *           By: Thibaud Kloczko
 *     Update #: 130
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerNodeLoopDataComposite.h"

#include <dtkComposer/dtkComposerEdge>
#include <dtkComposer/dtkComposerNode>
#include <dtkComposer/dtkComposerNodeControlBlock>
#include <dtkComposer/dtkComposerNodeNumber>
#include <dtkComposer/dtkComposerNodeProperty>

#include <dtkCore/dtkAbstractData>
#include <dtkCore/dtkAbstractDataComposite>
#include <dtkCore/dtkAbstractProcess>
#include <dtkCore/dtkGlobal>
#include <dtkCore/dtkLog>

#define DTK_DEBUG_COMPOSER_INTERACTION 1
#define DTK_DEBUG_COMPOSER_EVALUATION 1

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeLoopDataCompositePrivate declaration
// /////////////////////////////////////////////////////////////////

class dtkComposerNodeLoopDataCompositePrivate
{
public:
    dtkComposerNodeControlBlock *block_loop;

public:
    dtkxarch_int from_default;
    dtkxarch_int to_default;
    dtkxarch_int step_default;

    dtkxarch_int from;
    dtkxarch_int to;
    dtkxarch_int step;
    dtkxarch_int index;

    dtkAbstractData *item;

    dtkAbstractDataComposite *composite;

    bool valid_input_composite;
};

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeLoopDataComposite implementation
// /////////////////////////////////////////////////////////////////

dtkComposerNodeLoopDataComposite::dtkComposerNodeLoopDataComposite(dtkComposerNode *parent) : dtkComposerNodeLoop(parent), d(new dtkComposerNodeLoopDataCompositePrivate)
{
    d->block_loop = this->addBlock("loop");
    d->block_loop->setInteractive(false);
    d->block_loop->setHeightRatio(1);
    this->addInputProperty(d->block_loop->addInputProperty("from", dtkComposerNodeProperty::Input, dtkComposerNodeProperty::Single, dtkComposerNodeProperty::None, this));
    this->addInputProperty(d->block_loop->addInputProperty("to", dtkComposerNodeProperty::Input, dtkComposerNodeProperty::Single, dtkComposerNodeProperty::None, this));
    this->addInputProperty(d->block_loop->addInputProperty("step", dtkComposerNodeProperty::Input, dtkComposerNodeProperty::Single, dtkComposerNodeProperty::None, this));
    this->addInputProperty(d->block_loop->addInputProperty("item", dtkComposerNodeProperty::Output, dtkComposerNodeProperty::Multiple, dtkComposerNodeProperty::AsLoopInput, this));

    this->setColor(QColor("#2ABFFF"));
    this->setInputPropertyName("composite");
    this->setTitle("Composite Data Loop");
    this->setType("dtkComposerLoopDataComposite");

    d->from_default = 0;
    d->to_default = 0;
    d->step_default = 1;

    d->from = -1;
    d->to = -1;
    d->step = -1;

    d->index = 0;

    d->item = NULL;
    d->composite = NULL;

    d->valid_input_composite = false;
}

dtkComposerNodeLoopDataComposite::~dtkComposerNodeLoopDataComposite(void)
{
    delete d;

    d = NULL;
}

void dtkComposerNodeLoopDataComposite::layout(void)
{
    dtkComposerNodeControl::layout();

    QRectF  node_rect = this->boundingRect();
    qreal node_radius = this->nodeRadius();

    int j;
    qreal offset = 23;

    dtkComposerNodeControlBlock *block = this->blocks().at(0);

    block->setRect(QRectF(node_rect.x(),
                          node_rect.y() + offset,
                          node_rect.width(),
                          block->height()));

    j = 0;
    foreach(dtkComposerNodeProperty *property, block->inputProperties()) {

        property->setRect(QRectF(block->mapRectToParent(block->rect()).left() + node_radius,
                                 block->mapRectToParent(block->rect()).top()  + node_radius * (4*j + 1),
                                 2 * node_radius,
                                 2 * node_radius ));

        if (property->name() == "item") {
            property->mirror();
            j++;
        }

        j++;
    }
    j = 5;
    foreach(dtkComposerNodeProperty *property, block->outputProperties()) {

        property->setRect(QRectF(block->mapRectToParent(block->rect()).right() - node_radius * 3,
                                 block->mapRectToParent(block->rect()).top()   + node_radius * (4*j + 1),
                                 2 * node_radius,
                                 2 * node_radius ));

        j++;
    }
}

void dtkComposerNodeLoopDataComposite::update(void)
{

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
    qDebug() << DTK_PRETTY_FUNCTION << this;
#endif

    if (this->isRunning()) {

        return;

    } else {

        if (!this->dirty())
            return;

        // -- Check dirty input value

        if (this->dirtyInputValue())
            return;

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_GREEN << DTK_PRETTY_FUNCTION << "Dirty input value OK" << DTK_NO_COLOR;
#endif

        // -- Check dirty inputs

        if (this->dtkComposerNode::dirtyUpstreamNodes())
            return;

        // -- Mark dirty outputs

        this->dtkComposerNode::markDirtyDownstreamNodes();

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_GREEN << DTK_PRETTY_FUNCTION << "All output nodes are set to dirty" << DTK_NO_COLOR;
#endif

        // -- Clean active input routes

        this->cleanInputActiveRoutes();

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Input active routes cleaned" << DTK_NO_COLOR;
#endif

        // -- Pull

        foreach(dtkComposerEdge *i_route, this->inputRoutes())
            this->pull(i_route, i_route->destination());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Pull done" << DTK_NO_COLOR;
#endif

        // -- Set input composite and loop options

        foreach(dtkComposerEdge *i_route, this->inputActiveRoutes()) {
            if (i_route->destination() == this->inputProperty()) {

                dtkAbstractData *data = NULL;

                if(dtkAbstractData *dt = qobject_cast<dtkAbstractData *>(i_route->source()->node()->object())) {

                    data = dt;

                } else if(dtkAbstractProcess *process = qobject_cast<dtkAbstractProcess *>(i_route->source()->node()->object())) {

                    if(i_route->source()->node()->outputProperties().count() >= 1)
                        data = process->output(i_route->source()->node()->number(i_route->source()));
                    else
                        data = process->output();

                }

                if (data) {

                    d->composite = qobject_cast<dtkAbstractDataComposite *>(data);
                    if (!d->composite) {
                        dtkDebug() << DTK_PRETTY_FUNCTION << "input data is not of dtkAbstractDataComposite* type.";
                        return;
                    }
                    if (d->composite->count())
                        this->setObject((*d->composite)[0]);

                    d->to_default = d->composite->count()-1;

                    d->valid_input_composite = true;

                } else {

                    dtkDebug() << DTK_PRETTY_FUNCTION << "input data is not defined";
                    return;

                }

            } else if (i_route->destination()->name() == "from") {

                d->from = (dtkxarch_int)(i_route->source()->node()->value(i_route->source()).toLongLong());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
                qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "from value =" << d->from << DTK_NO_COLOR;
#endif

            } else if (i_route->destination()->name() == "to") {

                d->to = (dtkxarch_int)(i_route->source()->node()->value(i_route->source()).toLongLong());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
                qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "to value =" << d->to << DTK_NO_COLOR;
#endif

            } else if (i_route->destination()->name() == "step") {

                d->step = (dtkxarch_int)(i_route->source()->node()->value(i_route->source()).toLongLong());
#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
                qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "step value =" << d->step << DTK_NO_COLOR;
#endif

            }

            qDebug() << i_route;

        }

        if (!d->valid_input_composite) {
            dtkDebug() << DTK_PRETTY_FUNCTION << " input composite property is not connected.";
            return;
        }

        if ((d->from > d->to) && (d->from > d->to_default))
            d->from = d->to_default;
        else if (d->from < 0)
            d->from = d->from_default;
        else if (d->to < d->from && d->to < 0)
            d->to = d->from_default;
        else if (d->to > d->to_default)
            d->to = d->to_default;

        if (d->step < 0 && (d->from < d->to))
            d->step = d->step_default;

        d->index = d->from;

        // -- Running logics of conditional block

        this->setRunning(true);

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_RED  << "Loop initialization done" << DTK_NO_COLOR;
#endif

        while(d->index <= d->to) {

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
            qDebug() << DTK_COLOR_BG_RED  << "Loop is running, index = " << d->index << DTK_NO_COLOR;
#endif

            d->item = (*d->composite)[d->index];
            this->run();
            d->index += d->step;

        }

        // -- Clean active output routes

        this->cleanOutputActiveRoutes();

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Output active routes cleaned" << DTK_NO_COLOR;
#endif

        // -- Push

        foreach(dtkComposerEdge *o_route, this->outputRoutes())
            this->push(o_route, o_route->source());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Push done" << DTK_NO_COLOR;
#endif

        // -- Forward

        this->setDirty(false);
        this->setRunning(false);

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_BLUE << DTK_PRETTY_FUNCTION << "Forward done" << DTK_NO_COLOR;
#endif

        foreach(dtkComposerEdge *o_route, this->outputRoutes())
            o_route->destination()->node()->update();

    }
}

void dtkComposerNodeLoopDataComposite::pull(dtkComposerEdge *i_route, dtkComposerNodeProperty *property)
{
    if (property->name() == "from" || property->name() == "to" || property->name() == "step")
        this->addInputActiveRoute(i_route);

    dtkComposerNodeLoop::pull(i_route, property);
}

QVariant dtkComposerNodeLoopDataComposite::value(dtkComposerNodeProperty *property)
{
    QVariant value;
    // if (property == this->inputProperty())
    //     value = d->loop_variable;
    // else
    //     value = dtkComposerNodeLoop::value(property);

    return value;
}
<commit_msg>Adding update of loop variables.<commit_after>/* dtkComposerNodeLoopDataComposite.cpp ---
 *
 * Author: Thibaud Kloczko
 * Copyright (C) 2011 - Thibaud Kloczko, Inria.
 * Created: Wed Oct 12 16:02:18 2011 (+0200)
 * Version: $Id$
 * Last-Updated: Fri Oct 14 12:11:33 2011 (+0200)
 *           By: Thibaud Kloczko
 *     Update #: 131
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerNodeLoopDataComposite.h"

#include <dtkComposer/dtkComposerEdge>
#include <dtkComposer/dtkComposerNode>
#include <dtkComposer/dtkComposerNodeControlBlock>
#include <dtkComposer/dtkComposerNodeNumber>
#include <dtkComposer/dtkComposerNodeProperty>

#include <dtkCore/dtkAbstractData>
#include <dtkCore/dtkAbstractDataComposite>
#include <dtkCore/dtkAbstractProcess>
#include <dtkCore/dtkGlobal>
#include <dtkCore/dtkLog>

#define DTK_DEBUG_COMPOSER_INTERACTION 1
#define DTK_DEBUG_COMPOSER_EVALUATION 1

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeLoopDataCompositePrivate declaration
// /////////////////////////////////////////////////////////////////

class dtkComposerNodeLoopDataCompositePrivate
{
public:
    dtkComposerNodeControlBlock *block_loop;

public:
    dtkxarch_int from_default;
    dtkxarch_int to_default;
    dtkxarch_int step_default;

    dtkxarch_int from;
    dtkxarch_int to;
    dtkxarch_int step;
    dtkxarch_int index;

    dtkAbstractData *item;

    dtkAbstractDataComposite *composite;

    bool valid_input_composite;
};

// /////////////////////////////////////////////////////////////////
// dtkComposerNodeLoopDataComposite implementation
// /////////////////////////////////////////////////////////////////

dtkComposerNodeLoopDataComposite::dtkComposerNodeLoopDataComposite(dtkComposerNode *parent) : dtkComposerNodeLoop(parent), d(new dtkComposerNodeLoopDataCompositePrivate)
{
    d->block_loop = this->addBlock("loop");
    d->block_loop->setInteractive(false);
    d->block_loop->setHeightRatio(1);
    this->addInputProperty(d->block_loop->addInputProperty("from", dtkComposerNodeProperty::Input, dtkComposerNodeProperty::Single, dtkComposerNodeProperty::None, this));
    this->addInputProperty(d->block_loop->addInputProperty("to", dtkComposerNodeProperty::Input, dtkComposerNodeProperty::Single, dtkComposerNodeProperty::None, this));
    this->addInputProperty(d->block_loop->addInputProperty("step", dtkComposerNodeProperty::Input, dtkComposerNodeProperty::Single, dtkComposerNodeProperty::None, this));
    this->addInputProperty(d->block_loop->addInputProperty("item", dtkComposerNodeProperty::Output, dtkComposerNodeProperty::Multiple, dtkComposerNodeProperty::AsLoopInput, this));

    this->setColor(QColor("#2ABFFF"));
    this->setInputPropertyName("composite");
    this->setTitle("Composite Data Loop");
    this->setType("dtkComposerLoopDataComposite");

    d->from_default = 0;
    d->to_default = 0;
    d->step_default = 1;

    d->from = -1;
    d->to = -1;
    d->step = -1;

    d->index = 0;

    d->item = NULL;
    d->composite = NULL;

    d->valid_input_composite = false;
}

dtkComposerNodeLoopDataComposite::~dtkComposerNodeLoopDataComposite(void)
{
    delete d;

    d = NULL;
}

void dtkComposerNodeLoopDataComposite::layout(void)
{
    dtkComposerNodeControl::layout();

    QRectF  node_rect = this->boundingRect();
    qreal node_radius = this->nodeRadius();

    int j;
    qreal offset = 23;

    dtkComposerNodeControlBlock *block = this->blocks().at(0);

    block->setRect(QRectF(node_rect.x(),
                          node_rect.y() + offset,
                          node_rect.width(),
                          block->height()));

    j = 0;
    foreach(dtkComposerNodeProperty *property, block->inputProperties()) {

        property->setRect(QRectF(block->mapRectToParent(block->rect()).left() + node_radius,
                                 block->mapRectToParent(block->rect()).top()  + node_radius * (4*j + 1),
                                 2 * node_radius,
                                 2 * node_radius ));

        if (property->name() == "item") {
            property->mirror();
            j++;
        }

        j++;
    }
    j = 5;
    foreach(dtkComposerNodeProperty *property, block->outputProperties()) {

        property->setRect(QRectF(block->mapRectToParent(block->rect()).right() - node_radius * 3,
                                 block->mapRectToParent(block->rect()).top()   + node_radius * (4*j + 1),
                                 2 * node_radius,
                                 2 * node_radius ));

        j++;
    }
}

void dtkComposerNodeLoopDataComposite::update(void)
{

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
    qDebug() << DTK_PRETTY_FUNCTION << this;
#endif

    if (this->isRunning()) {

        return;

    } else {

        if (!this->dirty())
            return;

        // -- Check dirty input value

        if (this->dirtyInputValue())
            return;

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_GREEN << DTK_PRETTY_FUNCTION << "Dirty input value OK" << DTK_NO_COLOR;
#endif

        // -- Check dirty inputs

        if (this->dtkComposerNode::dirtyUpstreamNodes())
            return;

        // -- Mark dirty outputs

        this->dtkComposerNode::markDirtyDownstreamNodes();

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_GREEN << DTK_PRETTY_FUNCTION << "All output nodes are set to dirty" << DTK_NO_COLOR;
#endif

        // -- Clean active input routes

        this->cleanInputActiveRoutes();

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Input active routes cleaned" << DTK_NO_COLOR;
#endif

        // -- Pull

        foreach(dtkComposerEdge *i_route, this->inputRoutes())
            this->pull(i_route, i_route->destination());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Pull done" << DTK_NO_COLOR;
#endif

        // -- Set input composite and loop options

        foreach(dtkComposerEdge *i_route, this->inputActiveRoutes()) {
            if (i_route->destination() == this->inputProperty()) {

                dtkAbstractData *data = NULL;

                if(dtkAbstractData *dt = qobject_cast<dtkAbstractData *>(i_route->source()->node()->object())) {

                    data = dt;

                } else if(dtkAbstractProcess *process = qobject_cast<dtkAbstractProcess *>(i_route->source()->node()->object())) {

                    if(i_route->source()->node()->outputProperties().count() >= 1)
                        data = process->output(i_route->source()->node()->number(i_route->source()));
                    else
                        data = process->output();

                }

                if (data) {

                    d->composite = qobject_cast<dtkAbstractDataComposite *>(data);
                    if (!d->composite) {
                        dtkDebug() << DTK_PRETTY_FUNCTION << "input data is not of dtkAbstractDataComposite* type.";
                        return;
                    }
                    if (d->composite->count())
                        this->setObject((*d->composite)[0]);

                    d->to_default = d->composite->count()-1;

                    d->valid_input_composite = true;

                } else {

                    dtkDebug() << DTK_PRETTY_FUNCTION << "input data is not defined";
                    return;

                }

            } else if (i_route->destination()->name() == "from") {

                d->from = (dtkxarch_int)(i_route->source()->node()->value(i_route->source()).toLongLong());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
                qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "from value =" << d->from << DTK_NO_COLOR;
#endif

            } else if (i_route->destination()->name() == "to") {

                d->to = (dtkxarch_int)(i_route->source()->node()->value(i_route->source()).toLongLong());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
                qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "to value =" << d->to << DTK_NO_COLOR;
#endif

            } else if (i_route->destination()->name() == "step") {

                d->step = (dtkxarch_int)(i_route->source()->node()->value(i_route->source()).toLongLong());
#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
                qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "step value =" << d->step << DTK_NO_COLOR;
#endif

            }

            qDebug() << i_route;

        }

        if (!d->valid_input_composite) {
            dtkDebug() << DTK_PRETTY_FUNCTION << " input composite property is not connected.";
            return;
        }

        if ((d->from > d->to) && (d->from > d->to_default))
            d->from = d->to_default;
        else if (d->from < 0)
            d->from = d->from_default;
        else if (d->to < d->from && d->to < 0)
            d->to = d->from_default;
        else if (d->to > d->to_default)
            d->to = d->to_default;

        if (d->step < 0 && (d->from < d->to))
            d->step = d->step_default;

        d->index = d->from;

        // -- Running logics of conditional block

        this->setRunning(true);

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_RED  << "Loop initialization done" << DTK_NO_COLOR;
#endif

        while(d->index <= d->to) {

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
            qDebug() << DTK_COLOR_BG_RED  << "Loop is running, index = " << d->index << DTK_NO_COLOR;
#endif

            d->item = (*d->composite)[d->index];
            this->run();
            this->updatePassThroughVariables();
            d->index += d->step;

        }

        // -- Clean active output routes

        this->cleanOutputActiveRoutes();

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Output active routes cleaned" << DTK_NO_COLOR;
#endif

        // -- Push

        foreach(dtkComposerEdge *o_route, this->outputRoutes())
            this->push(o_route, o_route->source());

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_YELLOW << DTK_PRETTY_FUNCTION << "Push done" << DTK_NO_COLOR;
#endif

        // -- Forward

        this->setDirty(false);
        this->setRunning(false);

#if defined(DTK_DEBUG_COMPOSER_EVALUATION)
        qDebug() << DTK_COLOR_BG_BLUE << DTK_PRETTY_FUNCTION << "Forward done" << DTK_NO_COLOR;
#endif

        foreach(dtkComposerEdge *o_route, this->outputRoutes())
            o_route->destination()->node()->update();

    }
}

void dtkComposerNodeLoopDataComposite::pull(dtkComposerEdge *i_route, dtkComposerNodeProperty *property)
{
    if (property->name() == "from" || property->name() == "to" || property->name() == "step")
        this->addInputActiveRoute(i_route);

    dtkComposerNodeLoop::pull(i_route, property);
}

QVariant dtkComposerNodeLoopDataComposite::value(dtkComposerNodeProperty *property)
{
    QVariant value;
    // if (property == this->inputProperty())
    //     value = d->loop_variable;
    // else
    //     value = dtkComposerNodeLoop::value(property);

    return value;
}
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */
#include "SerialBase.h"
#include "wait_api.h"
#include "minar/minar.h"

#if DEVICE_SERIAL

namespace mbed {

SerialBase::SerialBase(PinName tx, PinName rx) :
#if DEVICE_SERIAL_ASYNCH
                                                 _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
                                                 _rx_usage(DMA_USAGE_NEVER),
#endif
                                                _serial(), _baud(9600) {
    serial_init(&_serial, tx, rx);
    serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this);
}

void SerialBase::baud(int baudrate) {
    serial_baud(&_serial, baudrate);
    _baud = baudrate;
}

void SerialBase::format(int bits, Parity parity, int stop_bits) {
    serial_format(&_serial, bits, (SerialParity)parity, stop_bits);
}

int SerialBase::readable() {
    return serial_readable(&_serial);
}

int SerialBase::writeable() {
    return serial_writable(&_serial);
}

void SerialBase::attach(void (*fptr)(void), IrqType type) {
    if (fptr) {
        _irq[type].attach(fptr);
        serial_irq_set(&_serial, (SerialIrq)type, 1);
    } else {
        serial_irq_set(&_serial, (SerialIrq)type, 0);
    }
}

void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) {
    SerialBase *handler = (SerialBase*)id;
    handler->_irq[irq_type].call();
}

int SerialBase::_base_getc() {
    return serial_getc(&_serial);
}

int SerialBase::_base_putc(int c) {
    serial_putc(&_serial, c);
    return c;
}

void SerialBase::send_break() {
  // Wait for 1.5 frames before clearing the break condition
  // This will have different effects on our platforms, but should
  // ensure that we keep the break active for at least one frame.
  // We consider a full frame (1 start bit + 8 data bits bits +
  // 1 parity bit + 2 stop bits = 12 bits) for computation.
  // One bit time (in us) = 1000000/_baud
  // Twelve bits: 12000000/baud delay
  // 1.5 frames: 18000000/baud delay
  serial_break_set(&_serial);
  wait_us(18000000/_baud);
  serial_break_clear(&_serial);
}

#if DEVICE_SERIAL_FC
void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) {
    FlowControl flow_type = (FlowControl)type;
    switch(type) {
        case RTS:
            serial_set_flow_control(&_serial, flow_type, flow1, NC);
            break;

        case CTS:
            serial_set_flow_control(&_serial, flow_type, NC, flow1);
            break;

        case RTSCTS:
        case Disabled:
            serial_set_flow_control(&_serial, flow_type, flow1, flow2);
            break;

        default:
            break;
    }
}
#endif

#if DEVICE_SERIAL_ASYNCH

int SerialBase::write(void *buffer, int length, const event_callback_t& callback, int event) {
    return write(Buffer(buffer, length), callback, event);
}

int SerialBase::write(const Buffer& buffer, const event_callback_t& callback, int event) {
    if (serial_tx_active(&_serial)) {
        return -1; // transaction ongoing
    }
    start_write(buffer, 8, callback, event);
    return 0;
}

void SerialBase::start_write(const Buffer& buffer, char buffer_width, const event_callback_t& callback, int event)
{
    _current_tx_transaction.callback = callback;
    _current_tx_transaction.buffer = buffer;
    _thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
    serial_tx_asynch(&_serial, buffer.buf, buffer.length, buffer_width, _thunk_irq.entry(), event, _tx_usage);
}

void SerialBase::abort_write(void)
{
    serial_tx_abort_asynch(&_serial);
}

void SerialBase::abort_read(void)
{
    serial_rx_abort_asynch(&_serial);
}

int SerialBase::set_dma_usage_tx(DMAUsage usage)
{
    if (serial_tx_active(&_serial)) {
        return -1;
    }
    _tx_usage = usage;
    return 0;
}

int SerialBase::set_dma_usage_rx(DMAUsage usage)
{
    if (serial_tx_active(&_serial)) {
        return -1;
    }
    _rx_usage = usage;
    return 0;
}

int SerialBase::read(void *buffer, int length, const event_callback_t& callback, int event, unsigned char char_match) {
    return read(Buffer(buffer, length), callback, event, char_match);
}

int SerialBase::read(const Buffer& buffer, const event_callback_t& callback, int event, unsigned char char_match)
{
    if (serial_rx_active(&_serial)) {
        return -1; // transaction ongoing
    }
    start_read(buffer, 8, callback, event, char_match);
    return 0;
}

void SerialBase::start_read(const Buffer& buffer, char buffer_width, const event_callback_t& callback, int event, unsigned char char_match)
{
    _current_rx_transaction.callback = callback;
    _current_tx_transaction.buffer = buffer;
    _thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
    serial_rx_asynch(&_serial, buffer.buf, buffer.length, buffer_width, _thunk_irq.entry(), event, char_match, _rx_usage);
}

void SerialBase::interrupt_handler_asynch(void)
{
    int event = serial_irq_handler_asynch(&_serial);
    int rx_event = event & SERIAL_EVENT_RX_MASK;
    if (_current_rx_transaction.callback && rx_event) {
        minar::Scheduler::postCallback(_current_rx_transaction.callback.bind(_current_rx_transaction.buffer, rx_event));
    }

    int tx_event = event & SERIAL_EVENT_TX_MASK;
    if (_current_tx_transaction.callback && tx_event) {
        minar::Scheduler::postCallback(_current_tx_transaction.callback.bind(_current_tx_transaction.buffer, tx_event));
    }
}

#endif

} // namespace mbed

#endif
<commit_msg>Serial - bit width is deprecated, set to 0<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */
#include "SerialBase.h"
#include "wait_api.h"
#include "minar/minar.h"

#if DEVICE_SERIAL

namespace mbed {

SerialBase::SerialBase(PinName tx, PinName rx) :
#if DEVICE_SERIAL_ASYNCH
                                                 _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
                                                 _rx_usage(DMA_USAGE_NEVER),
#endif
                                                _serial(), _baud(9600) {
    serial_init(&_serial, tx, rx);
    serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this);
}

void SerialBase::baud(int baudrate) {
    serial_baud(&_serial, baudrate);
    _baud = baudrate;
}

void SerialBase::format(int bits, Parity parity, int stop_bits) {
    serial_format(&_serial, bits, (SerialParity)parity, stop_bits);
}

int SerialBase::readable() {
    return serial_readable(&_serial);
}

int SerialBase::writeable() {
    return serial_writable(&_serial);
}

void SerialBase::attach(void (*fptr)(void), IrqType type) {
    if (fptr) {
        _irq[type].attach(fptr);
        serial_irq_set(&_serial, (SerialIrq)type, 1);
    } else {
        serial_irq_set(&_serial, (SerialIrq)type, 0);
    }
}

void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) {
    SerialBase *handler = (SerialBase*)id;
    handler->_irq[irq_type].call();
}

int SerialBase::_base_getc() {
    return serial_getc(&_serial);
}

int SerialBase::_base_putc(int c) {
    serial_putc(&_serial, c);
    return c;
}

void SerialBase::send_break() {
  // Wait for 1.5 frames before clearing the break condition
  // This will have different effects on our platforms, but should
  // ensure that we keep the break active for at least one frame.
  // We consider a full frame (1 start bit + 8 data bits bits +
  // 1 parity bit + 2 stop bits = 12 bits) for computation.
  // One bit time (in us) = 1000000/_baud
  // Twelve bits: 12000000/baud delay
  // 1.5 frames: 18000000/baud delay
  serial_break_set(&_serial);
  wait_us(18000000/_baud);
  serial_break_clear(&_serial);
}

#if DEVICE_SERIAL_FC
void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) {
    FlowControl flow_type = (FlowControl)type;
    switch(type) {
        case RTS:
            serial_set_flow_control(&_serial, flow_type, flow1, NC);
            break;

        case CTS:
            serial_set_flow_control(&_serial, flow_type, NC, flow1);
            break;

        case RTSCTS:
        case Disabled:
            serial_set_flow_control(&_serial, flow_type, flow1, flow2);
            break;

        default:
            break;
    }
}
#endif

#if DEVICE_SERIAL_ASYNCH

int SerialBase::write(void *buffer, int length, const event_callback_t& callback, int event) {
    return write(Buffer(buffer, length), callback, event);
}

int SerialBase::write(const Buffer& buffer, const event_callback_t& callback, int event) {
    if (serial_tx_active(&_serial)) {
        return -1; // transaction ongoing
    }
    start_write(buffer, 0, callback, event);
    return 0;
}

void SerialBase::start_write(const Buffer& buffer, char buffer_width, const event_callback_t& callback, int event)
{
    (void)buffer_width; // deprecated
    _current_tx_transaction.callback = callback;
    _current_tx_transaction.buffer = buffer;
    _thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
    serial_tx_asynch(&_serial, buffer.buf, buffer.length, 0, _thunk_irq.entry(), event, _tx_usage);
}

void SerialBase::abort_write(void)
{
    serial_tx_abort_asynch(&_serial);
}

void SerialBase::abort_read(void)
{
    serial_rx_abort_asynch(&_serial);
}

int SerialBase::set_dma_usage_tx(DMAUsage usage)
{
    if (serial_tx_active(&_serial)) {
        return -1;
    }
    _tx_usage = usage;
    return 0;
}

int SerialBase::set_dma_usage_rx(DMAUsage usage)
{
    if (serial_tx_active(&_serial)) {
        return -1;
    }
    _rx_usage = usage;
    return 0;
}

int SerialBase::read(void *buffer, int length, const event_callback_t& callback, int event, unsigned char char_match) {
    return read(Buffer(buffer, length), callback, event, char_match);
}

int SerialBase::read(const Buffer& buffer, const event_callback_t& callback, int event, unsigned char char_match)
{
    if (serial_rx_active(&_serial)) {
        return -1; // transaction ongoing
    }
    start_read(buffer, 0, callback, event, char_match);
    return 0;
}

void SerialBase::start_read(const Buffer& buffer, char buffer_width, const event_callback_t& callback, int event, unsigned char char_match)
{
    (void)buffer_width; // deprecated
    _current_rx_transaction.callback = callback;
    _current_tx_transaction.buffer = buffer;
    _thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
    serial_rx_asynch(&_serial, buffer.buf, buffer.length, 0, _thunk_irq.entry(), event, char_match, _rx_usage);
}

void SerialBase::interrupt_handler_asynch(void)
{
    int event = serial_irq_handler_asynch(&_serial);
    int rx_event = event & SERIAL_EVENT_RX_MASK;
    if (_current_rx_transaction.callback && rx_event) {
        minar::Scheduler::postCallback(_current_rx_transaction.callback.bind(_current_rx_transaction.buffer, rx_event));
    }

    int tx_event = event & SERIAL_EVENT_TX_MASK;
    if (_current_tx_transaction.callback && tx_event) {
        minar::Scheduler::postCallback(_current_tx_transaction.callback.bind(_current_tx_transaction.buffer, tx_event));
    }
}

#endif

} // namespace mbed

#endif
<|endoftext|>


<commit_before>#include "common.h"
#include "SoftXMT.hpp"
#include "ForkJoin.hpp"
#include "Cache.hpp"
#include "Delegate.hpp"
#include "PerformanceTools.hpp"
#include "GlobalAllocator.hpp"
#include "timer.h"
#include "GlobalTaskJoiner.hpp"
#include "AsyncParallelFor.hpp"

GRAPPA_DEFINE_EVENT_GROUP(bfs);

#define read      SoftXMT_delegate_read_word
#define write     SoftXMT_delegate_write_word
#define cmp_swap  SoftXMT_delegate_compare_and_swap_word
#define fetch_add SoftXMT_delegate_fetch_and_add_word

#define BUF_LEN 16384
static int64_t buf[BUF_LEN];
static int64_t kbuf;
static GlobalAddress<int64_t> vlist;
static GlobalAddress<int64_t> xoff;
static GlobalAddress<int64_t> xadj;
static GlobalAddress<int64_t> bfs_tree;
static GlobalAddress<int64_t> k2;
static int64_t nadj;

#define XOFF(k) (xoff+2*(k))
#define XENDOFF(k) (xoff+2*(k)+1)

#define GA64(name) ((GlobalAddress<int64_t>,name))

void bfs_visit_neighbor(int64_t estart, int64_t eiters, GlobalAddress<void*> packed) {
  int64_t v = (int64_t)packed.pointer();

  //const int64_t j = read(xadj+vo);
  //VLOG(1) << "estart: " << estart << ", eiters: " << eiters;

  int64_t cbuf[eiters];
  Incoherent<int64_t>::RO cadj(xadj+estart, eiters, cbuf);

  for (int64_t i = 0; i < eiters; i++) {
    const int64_t j = cadj[i];
    //VLOG(1) << "v = " << v << ", j = " << j << ", i = " << i << ", eiters = " << eiters;

    if (cmp_swap(bfs_tree+j, -1, v)) {
      while (kbuf == -1) { SoftXMT_yield(); }
      if (kbuf < BUF_LEN) {
        buf[kbuf] = j;
        (kbuf)++;
      } else {
        // TODO: swap buffer!
        kbuf = -1; // lock other threads out temporarily
        int64_t voff = fetch_add(k2, BUF_LEN);
        Incoherent<int64_t>::RW cvlist(vlist+voff, BUF_LEN);
        for (int64_t vk=0; vk < BUF_LEN; vk++) {
          cvlist[vk] = buf[vk];
        }
        buf[0] = j;
        kbuf = 1;
      }
    }
  }
}

void bfs_visit_vertex(int64_t kstart, int64_t kiters) {
  //VLOG(1) << "bfs_visit_vertex(" << kstart << ", " << kiters << ")";

  int64_t buf[kiters];
  Incoherent<int64_t>::RO cvlist(vlist+kstart, kiters, buf);

  for (int64_t i=0; i<kiters; i++) {
    const int64_t v = cvlist[i];

    int64_t buf[2];
    Incoherent<int64_t>::RO cxoff(xoff+2*v, 2, buf);
    const int64_t vstart = cxoff[0], vend = cxoff[1];

    GlobalAddress<void*> packed = make_global( (void**)(v) );
    //VLOG(1) << "apfor<bfs_visit_neighbor>(" << vstart << ", " << vend << ")";
    async_parallel_for<void*, bfs_visit_neighbor, joinerSpawn_hack<void*,bfs_visit_neighbor> >(vstart, vend-vstart, packed);
    //for (int64_t vo = vstart; vo < vend; vo++) {
      //uint64_t packed = (((uint64_t)v) << 32) | vo;
      //global_joiner.registerTask(); // register these new tasks on *this task*'s joiner
      //SoftXMT_publicTask(&bfs_visit_neighbor, packed, global_joiner.addr());
    //}
  }
}

static unsigned marker = -1;

void bfs_level(Node nid, int64_t start, int64_t end) {
  range_t r = blockDist(start, end, nid, SoftXMT_nodes());

  kbuf = 0;

#ifdef VTRACE
  VT_TRACER("bfs_level");
#endif

  global_joiner.reset();
#ifdef VTRACE
  if (SoftXMT_mynode() == 0) {
    char s[256];
    sprintf(s, "<%ld>", end-start);
    VT_MARKER(marker, s);
  }
#endif
  VLOG(2) << "phase start <" << end-start << "> (" << r.start << ", " << r.end << ")";
  async_parallel_for< bfs_visit_vertex, joinerSpawn<bfs_visit_vertex> >(r.start, r.end-r.start);
  //for (int64_t i = r.start; i < r.end; i++) {
    //global_joiner.registerTask();
    //SoftXMT_publicTask(&bfs_visit_vertex, i, global_joiner.addr());
  //}
  global_joiner.wait();
  VLOG(2) << "phase complete";
}

void clear_buffers() {
  if (kbuf) {
    int64_t voff = fetch_add(k2, kbuf);
    VLOG(2) << "flushing vlist buffer (kbuf=" << kbuf << ", k2=" << voff << ")";
    Incoherent<int64_t>::RW cvlist(vlist+voff, kbuf);
    for (int64_t vk=0; vk < kbuf; vk++) {
      cvlist[vk] = buf[vk];
    }
    kbuf = 0;
  }
}

LOOP_FUNCTOR(bfs_node, nid, GA64(_vlist)GA64(_xoff)GA64(_xadj)GA64(_bfs_tree)GA64(_k2)((int64_t,_nadj))) {
  // setup globals
  kbuf = 0;
  vlist = _vlist;
  xoff = _xoff;
  xadj = _xadj;
  bfs_tree = _bfs_tree;
  k2 = _k2;
  nadj = _nadj;

  int64_t k1 = 0, _k2 = 1;

  while (k1 != _k2) {
    VLOG(2) << "k1=" << k1 << ", k2=" << _k2;
    const int64_t oldk2 = _k2;

    bfs_level(SoftXMT_mynode(), k1, oldk2);

    SoftXMT_barrier_suspending();

    clear_buffers();

    SoftXMT_barrier_suspending();

    k1 = oldk2;
    _k2 = read(k2);
  }
}

double make_bfs_tree(csr_graph * g, GlobalAddress<int64_t> bfs_tree, int64_t root) {
  int64_t NV = g->nv;
  GlobalAddress<int64_t> vlist = SoftXMT_typed_malloc<int64_t>(NV);

#ifdef VTRACE
  if (marker == -1) marker = VT_MARKER_DEF("bfs_level", VT_MARKER_TYPE_HINT);
#endif

  double t;
  t = timer();

  // start with root as only thing in vlist
  write(vlist, root);

  int64_t k1 = 0, k2 = 1;
  GlobalAddress<int64_t> k2addr = make_global(&k2);

  // initialize bfs_tree to -1
  SoftXMT_memset(bfs_tree, (int64_t)-1,  NV);

  write(bfs_tree+root, root); // parent of root is self

  { bfs_node f(vlist, g->xoff, g->xadj, bfs_tree, k2addr, g->nadj); fork_join_custom(&f); }

  t = timer() - t;

  SoftXMT_free(vlist);

  return t;
}

<commit_msg>Use WO cache for buffer write-back.<commit_after>#include "common.h"
#include "SoftXMT.hpp"
#include "ForkJoin.hpp"
#include "Cache.hpp"
#include "Delegate.hpp"
#include "PerformanceTools.hpp"
#include "GlobalAllocator.hpp"
#include "timer.h"
#include "GlobalTaskJoiner.hpp"
#include "AsyncParallelFor.hpp"

GRAPPA_DEFINE_EVENT_GROUP(bfs);

#define read      SoftXMT_delegate_read_word
#define write     SoftXMT_delegate_write_word
#define cmp_swap  SoftXMT_delegate_compare_and_swap_word
#define fetch_add SoftXMT_delegate_fetch_and_add_word

#define BUF_LEN 16384
static int64_t buf[BUF_LEN];
static int64_t kbuf;
static GlobalAddress<int64_t> vlist;
static GlobalAddress<int64_t> xoff;
static GlobalAddress<int64_t> xadj;
static GlobalAddress<int64_t> bfs_tree;
static GlobalAddress<int64_t> k2;
static int64_t nadj;

#define XOFF(k) (xoff+2*(k))
#define XENDOFF(k) (xoff+2*(k)+1)

#define GA64(name) ((GlobalAddress<int64_t>,name))

void bfs_visit_neighbor(int64_t estart, int64_t eiters, GlobalAddress<void*> packed) {
  int64_t v = (int64_t)packed.pointer();

  //const int64_t j = read(xadj+vo);
  //VLOG(1) << "estart: " << estart << ", eiters: " << eiters;

  int64_t cbuf[eiters];
  Incoherent<int64_t>::RO cadj(xadj+estart, eiters, cbuf);

  for (int64_t i = 0; i < eiters; i++) {
    const int64_t j = cadj[i];
    //VLOG(1) << "v = " << v << ", j = " << j << ", i = " << i << ", eiters = " << eiters;

    if (cmp_swap(bfs_tree+j, -1, v)) {
      while (kbuf == -1) { SoftXMT_yield(); }
      if (kbuf < BUF_LEN) {
        buf[kbuf] = j;
        (kbuf)++;
      } else {
        // TODO: swap buffer!
        kbuf = -1; // lock other threads out temporarily
        int64_t voff = fetch_add(k2, BUF_LEN);
        Incoherent<int64_t>::WO cvlist(vlist+voff, BUF_LEN);
        for (int64_t vk=0; vk < BUF_LEN; vk++) {
          cvlist[vk] = buf[vk];
        }
        buf[0] = j;
        kbuf = 1;
      }
    }
  }
}

void bfs_visit_vertex(int64_t kstart, int64_t kiters) {
  //VLOG(1) << "bfs_visit_vertex(" << kstart << ", " << kiters << ")";

  int64_t buf[kiters];
  Incoherent<int64_t>::RO cvlist(vlist+kstart, kiters, buf);

  for (int64_t i=0; i<kiters; i++) {
    const int64_t v = cvlist[i];

    int64_t buf[2];
    Incoherent<int64_t>::RO cxoff(xoff+2*v, 2, buf);
    const int64_t vstart = cxoff[0], vend = cxoff[1];

    GlobalAddress<void*> packed = make_global( (void**)(v) );
    //VLOG(1) << "apfor<bfs_visit_neighbor>(" << vstart << ", " << vend << ")";
    async_parallel_for<void*, bfs_visit_neighbor, joinerSpawn_hack<void*,bfs_visit_neighbor> >(vstart, vend-vstart, packed);
    //for (int64_t vo = vstart; vo < vend; vo++) {
      //uint64_t packed = (((uint64_t)v) << 32) | vo;
      //global_joiner.registerTask(); // register these new tasks on *this task*'s joiner
      //SoftXMT_publicTask(&bfs_visit_neighbor, packed, global_joiner.addr());
    //}
  }
}

static unsigned marker = -1;

void bfs_level(Node nid, int64_t start, int64_t end) {
  range_t r = blockDist(start, end, nid, SoftXMT_nodes());

  kbuf = 0;

#ifdef VTRACE
  VT_TRACER("bfs_level");
#endif

  global_joiner.reset();
#ifdef VTRACE
  if (SoftXMT_mynode() == 0) {
    char s[256];
    sprintf(s, "<%ld>", end-start);
    VT_MARKER(marker, s);
  }
#endif
  VLOG(2) << "phase start <" << end-start << "> (" << r.start << ", " << r.end << ")";
  async_parallel_for< bfs_visit_vertex, joinerSpawn<bfs_visit_vertex> >(r.start, r.end-r.start);
  //for (int64_t i = r.start; i < r.end; i++) {
    //global_joiner.registerTask();
    //SoftXMT_publicTask(&bfs_visit_vertex, i, global_joiner.addr());
  //}
  global_joiner.wait();
  VLOG(2) << "phase complete";
}

void clear_buffers() {
  if (kbuf) {
    int64_t voff = fetch_add(k2, kbuf);
    VLOG(2) << "flushing vlist buffer (kbuf=" << kbuf << ", k2=" << voff << ")";
    Incoherent<int64_t>::WO cvlist(vlist+voff, kbuf);
    for (int64_t vk=0; vk < kbuf; vk++) {
      cvlist[vk] = buf[vk];
    }
    kbuf = 0;
  }
}

LOOP_FUNCTOR(bfs_node, nid, GA64(_vlist)GA64(_xoff)GA64(_xadj)GA64(_bfs_tree)GA64(_k2)((int64_t,_nadj))) {
  // setup globals
  kbuf = 0;
  vlist = _vlist;
  xoff = _xoff;
  xadj = _xadj;
  bfs_tree = _bfs_tree;
  k2 = _k2;
  nadj = _nadj;

  int64_t k1 = 0, _k2 = 1;

  while (k1 != _k2) {
    VLOG(2) << "k1=" << k1 << ", k2=" << _k2;
    const int64_t oldk2 = _k2;

    bfs_level(SoftXMT_mynode(), k1, oldk2);

    SoftXMT_barrier_suspending();

    clear_buffers();

    SoftXMT_barrier_suspending();

    k1 = oldk2;
    _k2 = read(k2);
  }
}

double make_bfs_tree(csr_graph * g, GlobalAddress<int64_t> bfs_tree, int64_t root) {
  int64_t NV = g->nv;
  GlobalAddress<int64_t> vlist = SoftXMT_typed_malloc<int64_t>(NV);

#ifdef VTRACE
  if (marker == -1) marker = VT_MARKER_DEF("bfs_level", VT_MARKER_TYPE_HINT);
#endif

  double t;
  t = timer();

  // start with root as only thing in vlist
  write(vlist, root);

  int64_t k1 = 0, k2 = 1;
  GlobalAddress<int64_t> k2addr = make_global(&k2);

  // initialize bfs_tree to -1
  SoftXMT_memset(bfs_tree, (int64_t)-1,  NV);

  write(bfs_tree+root, root); // parent of root is self

  { bfs_node f(vlist, g->xoff, g->xadj, bfs_tree, k2addr, g->nadj); fork_join_custom(&f); }

  t = timer() - t;

  SoftXMT_free(vlist);

  return t;
}

<|endoftext|>