<commit_before>#include "ghost/timing.h"
#include "ghost/util.h"

#include <map>
#include <vector>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <numeric>
#include <algorithm>

using namespace std;

/**
 * @brief Region timing accumulator
 */
typedef struct
{
    /**
     * @brief The runtimes of this region.
     */
    vector<double> times;
    /**
     * @brief The last start time of this region.
     */
    double start;
}
ghost_timing_region_accu_t;

static map<string,ghost_timing_region_accu_t> timings;

void ghost_timing_tick(char *tag)
{
    double start;
    ghost_timing_wc(&start);
    timings[tag].start = start;
}

void ghost_timing_tock(char *tag)
{
    double end;
    ghost_timing_wc(&end);
    ghost_timing_region_accu_t *ti = &timings[string(tag)];
    ti->times.push_back(end-ti->start);
}

ghost_error_t ghost_timing_region_create(ghost_timing_region_t ** ri, char *tag)
{
    ghost_timing_region_accu_t ti;
    if (!timings.count(string(tag))) {
        ERROR_LOG("The region %s does not exist!",tag);
        return GHOST_ERR_INVALID_ARG;
    }
    ti = timings[string(tag)];

    ghost_error_t ret = GHOST_SUCCESS;
    GHOST_CALL_GOTO(ghost_malloc((void **)ri,sizeof(ghost_timing_region_t)),err,ret);
    (*ri)->nCalls =  ti.times.size();
    (*ri)->minTime = *min_element(ti.times.begin(),ti.times.end());
    (*ri)->maxTime = *max_element(ti.times.begin(),ti.times.end());
    (*ri)->avgTime = accumulate(ti.times.begin(),ti.times.end(),0.)/(*ri)->nCalls;

    GHOST_CALL_GOTO(ghost_malloc((void **)(&((*ri)->times)),sizeof(double)*(*ri)->nCalls),err,ret);
    memcpy((*ri)->times,&ti.times[0],(*ri)->nCalls*sizeof(double));

    goto out;

err:
    ERROR_LOG("Freeing region info");
    if (*ri) {
        free((*ri)->times); (*ri)->times = NULL;
    }
    free(*ri); (*ri) = NULL;
out:

    return ret;
}

void ghost_timing_region_destroy(ghost_timing_region_t * ri)
{
    if (ri) {
        free(ri->times); ri->times = NULL;
    }
    free(ri);
}

ghost_error_t ghost_timing_summarystring(char **str)
{
    stringstream buffer;
    map<string,ghost_timing_region_accu_t>::iterator iter;

    size_t maxRegionLen = 0;
    size_t maxCallsLen = 0;

    stringstream tmp;
    for (iter = timings.begin(); iter != timings.end(); ++iter) {
        tmp << iter->first.length();
        maxRegionLen = max(iter->first.length(),maxRegionLen);
        tmp.str("");

        tmp << iter->second.times.size();
        maxCallsLen = max(maxCallsLen,tmp.str().length());
        tmp.str("");
    }
    if (maxCallsLen < 5) {
        maxCallsLen = 5;
    }

    buffer << left << setw(maxRegionLen) << "Region" << right << " | ";
    buffer << setw(maxCallsLen+3) << "Calls | ";
    buffer << "   t_min | ";
    buffer << "   t_max | ";
    buffer << "   t_avg" << endl;
    buffer << string(maxRegionLen+maxCallsLen+3+3*11,'-') << endl;

    buffer.precision(2);
    for (iter = timings.begin(); iter != timings.end(); ++iter) {
        buffer << scientific << left << setw(maxRegionLen) << iter->first << " | " <<
            right << setw(maxCallsLen) << iter->second.times.size() << " | " <<
            *min_element(iter->second.times.begin(),iter->second.times.end()) << " | " <<
            *max_element(iter->second.times.begin(),iter->second.times.end()) << " | " <<
            accumulate(iter->second.times.begin(),iter->second.times.end(),0.)/iter->second.times.size() << endl;
    }

    GHOST_CALL_RETURN(ghost_malloc((void **)str,buffer.str().length()+1));
    strcpy(*str,buffer.str().c_str());

    return GHOST_SUCCESS;
}
<commit_msg>print total time in timing summary<commit_after>#include "ghost/timing.h"
#include "ghost/util.h"

#include <map>
#include <vector>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <numeric>
#include <algorithm>

using namespace std;

/**
 * @brief Region timing accumulator
 */
typedef struct
{
    /**
     * @brief The runtimes of this region.
     */
    vector<double> times;
    /**
     * @brief The last start time of this region.
     */
    double start;
}
ghost_timing_region_accu_t;

static map<string,ghost_timing_region_accu_t> timings;

void ghost_timing_tick(char *tag)
{
    double start;
    ghost_timing_wc(&start);
    timings[tag].start = start;
}

void ghost_timing_tock(char *tag)
{
    double end;
    ghost_timing_wc(&end);
    ghost_timing_region_accu_t *ti = &timings[string(tag)];
    ti->times.push_back(end-ti->start);
}

ghost_error_t ghost_timing_region_create(ghost_timing_region_t ** ri, char *tag)
{
    ghost_timing_region_accu_t ti;
    if (!timings.count(string(tag))) {
        ERROR_LOG("The region %s does not exist!",tag);
        return GHOST_ERR_INVALID_ARG;
    }
    ti = timings[string(tag)];

    ghost_error_t ret = GHOST_SUCCESS;
    GHOST_CALL_GOTO(ghost_malloc((void **)ri,sizeof(ghost_timing_region_t)),err,ret);
    (*ri)->nCalls =  ti.times.size();
    (*ri)->minTime = *min_element(ti.times.begin(),ti.times.end());
    (*ri)->maxTime = *max_element(ti.times.begin(),ti.times.end());
    (*ri)->avgTime = accumulate(ti.times.begin(),ti.times.end(),0.)/(*ri)->nCalls;

    GHOST_CALL_GOTO(ghost_malloc((void **)(&((*ri)->times)),sizeof(double)*(*ri)->nCalls),err,ret);
    memcpy((*ri)->times,&ti.times[0],(*ri)->nCalls*sizeof(double));

    goto out;

err:
    ERROR_LOG("Freeing region info");
    if (*ri) {
        free((*ri)->times); (*ri)->times = NULL;
    }
    free(*ri); (*ri) = NULL;
out:

    return ret;
}

void ghost_timing_region_destroy(ghost_timing_region_t * ri)
{
    if (ri) {
        free(ri->times); ri->times = NULL;
    }
    free(ri);
}

ghost_error_t ghost_timing_summarystring(char **str)
{
    stringstream buffer;
    map<string,ghost_timing_region_accu_t>::iterator iter;

    size_t maxRegionLen = 0;
    size_t maxCallsLen = 0;

    stringstream tmp;
    for (iter = timings.begin(); iter != timings.end(); ++iter) {
        tmp << iter->first.length();
        maxRegionLen = max(iter->first.length(),maxRegionLen);
        tmp.str("");

        tmp << iter->second.times.size();
        maxCallsLen = max(maxCallsLen,tmp.str().length());
        tmp.str("");
    }
    if (maxCallsLen < 5) {
        maxCallsLen = 5;
    }

    buffer << left << setw(maxRegionLen) << "Region" << right << " | ";
    buffer << setw(maxCallsLen+3) << "Calls | ";
    buffer << "   t_min | ";
    buffer << "   t_max | ";
    buffer << "   t_avg | ";
    buffer << "   t_tot" << endl;
    buffer << string(maxRegionLen+maxCallsLen+3+4*11,'-') << endl;

    buffer.precision(2);
    for (iter = timings.begin(); iter != timings.end(); ++iter) {
        buffer << scientific << left << setw(maxRegionLen) << iter->first << " | " <<
            right << setw(maxCallsLen) << iter->second.times.size() << " | " <<
            *min_element(iter->second.times.begin(),iter->second.times.end()) << " | " <<
            *max_element(iter->second.times.begin(),iter->second.times.end()) << " | " <<
            accumulate(iter->second.times.begin(),iter->second.times.end(),0.)/iter->second.times.size()  << " | " <<
            accumulate(iter->second.times.begin(),iter->second.times.end(),0.) << endl;
    }

    GHOST_CALL_RETURN(ghost_malloc((void **)str,buffer.str().length()+1));
    strcpy(*str,buffer.str().c_str());

    return GHOST_SUCCESS;
}
<|endoftext|>


<commit_before>#include "musicvideotablewidget.h"
#include "musicdatadownloadthread.h"
#include "musicmessagebox.h"

#include <time.h>

MusicVideoTableWidget::MusicVideoTableWidget(QWidget *parent)
    : MusicQueryTableWidget(parent)
{
    setColumnCount(8);
    QHeaderView *headerview = horizontalHeader();
    headerview->resizeSection(0,30);
    headerview->resizeSection(1,175);
    headerview->resizeSection(2,151);
    headerview->resizeSection(3,30);
    headerview->resizeSection(4,55);
    headerview->resizeSection(5,24);
    headerview->resizeSection(6,24);
    headerview->resizeSection(7,24);
    setTransparent(255);
    qsrand(time(NULL));
}

MusicVideoTableWidget::~MusicVideoTableWidget()
{
    clearAllItems();
}

void MusicVideoTableWidget::startSearchQuery(const QString &text)
{
    m_downLoadManager->startSearchSong(MVQuery, text);
}

void MusicVideoTableWidget::clearAllItems()
{
    MusicAbstractTableWidget::clear();
    setColumnCount(8);
}

QString MusicVideoTableWidget::randToGetStrength() const
{
    switch(qrand()%5)
    {
        case 0: return QString::fromUtf8(":/video/video_1");
        case 1: return QString::fromUtf8(":/video/video_2");
        case 2: return QString::fromUtf8(":/video/video_3");
        case 3: return QString::fromUtf8(":/video/video_4");
        case 4: return QString::fromUtf8(":/video/video_5");
    }
    return QString::fromUtf8(":/video/video_5");
}

void MusicVideoTableWidget::creatSearchedItems(const QString &songname,
                                               const QString &artistname,
                                               const QString &time)
{
    int count;
    setRowCount(count = m_downLoadManager->getSongIdIndex());
    setStyleSheet(MusicUIObject::MTableWidgetStyle01 + \
                  MusicUIObject::MScrollBarStyle01);

    QTableWidgetItem *item = new QTableWidgetItem;
    item->setData(Qt::DisplayRole, false);
    setItem(count - 1, 0, item);

                      item = new QTableWidgetItem(songname);
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    item->setToolTip(songname);
    setItem(count - 1, 1, item);

                      item = new QTableWidgetItem(artistname);
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    item->setToolTip(artistname);
    setItem(count - 1, 2, item);

                      item = new QTableWidgetItem(QIcon( randToGetStrength() ),"");
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 3, item);

                      item = new QTableWidgetItem(time);
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 4, item);

                      item = new QTableWidgetItem(QIcon(QString::fromUtf8(":/share/showMV")),"");
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 5, item);

                      item = new QTableWidgetItem(QIcon(QString::fromUtf8(":/share/autionplay")),"");
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 6, item);

                      item = new QTableWidgetItem(QIcon(QString::fromUtf8(":/share/musicdownload")),"");
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 7, item);
}

void MusicVideoTableWidget::listCellClicked(int row,int col)
{
    MusicQueryTableWidget::listCellClicked(row, col);
    switch(col)
    {
        case 5:
        case 6:
            itemDoubleClicked(row, -1);break;
        case 7:
            musicDownloadLocal(row);break;
        default:break;
    }
}

void MusicVideoTableWidget::musicDownloadLocal(int row)
{
    if(row < 0)
    {
        MusicMessageBox message;
        message.setText(tr("Please Select One Item First!"));
        message.exec();
        return;
    }
    MStringLists musicSongInfo(m_downLoadManager->getMusicSongInfo());

    MusicDataDownloadThread* download = new MusicDataDownloadThread(musicSongInfo[row][2], QString("%1 - %2.%3")
        .arg(musicSongInfo[row][0]).arg(musicSongInfo[row][1]).arg(musicSongInfo[row][3]), Download_Video, this);
    download->startToDownload();
}

void MusicVideoTableWidget::itemDoubleClicked(int row, int column)
{
    if(column <= 0 || row < 0)
    {
        return;
    }
    MStringLists musicSongInfo(m_downLoadManager->getMusicSongInfo());
    emit mvURLChanged(musicSongInfo[row][2]);
}

void MusicVideoTableWidget::contextMenuEvent(QContextMenuEvent *event)
{
    MusicQueryTableWidget::contextMenuEvent(event);
    QMenu rightClickMenu(this);
    createContextMenu(rightClickMenu);

    rightClickMenu.exec(QCursor::pos());
}
<commit_msg>fix column index incorrect when insert into -1, now set to 999[015452]<commit_after>#include "musicvideotablewidget.h"
#include "musicdatadownloadthread.h"
#include "musicmessagebox.h"

#include <time.h>

MusicVideoTableWidget::MusicVideoTableWidget(QWidget *parent)
    : MusicQueryTableWidget(parent)
{
    setColumnCount(8);
    QHeaderView *headerview = horizontalHeader();
    headerview->resizeSection(0,30);
    headerview->resizeSection(1,175);
    headerview->resizeSection(2,151);
    headerview->resizeSection(3,30);
    headerview->resizeSection(4,55);
    headerview->resizeSection(5,24);
    headerview->resizeSection(6,24);
    headerview->resizeSection(7,24);
    setTransparent(255);
    qsrand(time(NULL));
}

MusicVideoTableWidget::~MusicVideoTableWidget()
{
    clearAllItems();
}

void MusicVideoTableWidget::startSearchQuery(const QString &text)
{
    m_downLoadManager->startSearchSong(MVQuery, text);
}

void MusicVideoTableWidget::clearAllItems()
{
    MusicAbstractTableWidget::clear();
    setColumnCount(8);
}

QString MusicVideoTableWidget::randToGetStrength() const
{
    switch(qrand()%5)
    {
        case 0: return QString::fromUtf8(":/video/video_1");
        case 1: return QString::fromUtf8(":/video/video_2");
        case 2: return QString::fromUtf8(":/video/video_3");
        case 3: return QString::fromUtf8(":/video/video_4");
        case 4: return QString::fromUtf8(":/video/video_5");
    }
    return QString::fromUtf8(":/video/video_5");
}

void MusicVideoTableWidget::creatSearchedItems(const QString &songname,
                                               const QString &artistname,
                                               const QString &time)
{
    int count;
    setRowCount(count = m_downLoadManager->getSongIdIndex());
    setStyleSheet(MusicUIObject::MTableWidgetStyle01 + \
                  MusicUIObject::MScrollBarStyle01);

    QTableWidgetItem *item = new QTableWidgetItem;
    item->setData(Qt::DisplayRole, false);
    setItem(count - 1, 0, item);

                      item = new QTableWidgetItem(songname);
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    item->setToolTip(songname);
    setItem(count - 1, 1, item);

                      item = new QTableWidgetItem(artistname);
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    item->setToolTip(artistname);
    setItem(count - 1, 2, item);

                      item = new QTableWidgetItem(QIcon( randToGetStrength() ),"");
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 3, item);

                      item = new QTableWidgetItem(time);
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 4, item);

                      item = new QTableWidgetItem(QIcon(QString::fromUtf8(":/share/showMV")),"");
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 5, item);

                      item = new QTableWidgetItem(QIcon(QString::fromUtf8(":/share/autionplay")),"");
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 6, item);

                      item = new QTableWidgetItem(QIcon(QString::fromUtf8(":/share/musicdownload")),"");
    item->setTextColor(QColor(50,50,50));
    item->setTextAlignment(Qt::AlignCenter);
    setItem(count - 1, 7, item);
}

void MusicVideoTableWidget::listCellClicked(int row,int col)
{
    MusicQueryTableWidget::listCellClicked(row, col);
    switch(col)
    {
        case 5:
        case 6:
            itemDoubleClicked(row, 999);break;
        case 7:
            musicDownloadLocal(row);break;
        default:break;
    }
}

void MusicVideoTableWidget::musicDownloadLocal(int row)
{
    if(row < 0)
    {
        MusicMessageBox message;
        message.setText(tr("Please Select One Item First!"));
        message.exec();
        return;
    }
    MStringLists musicSongInfo(m_downLoadManager->getMusicSongInfo());

    MusicDataDownloadThread* download = new MusicDataDownloadThread(musicSongInfo[row][2], QString("%1 - %2.%3")
        .arg(musicSongInfo[row][0]).arg(musicSongInfo[row][1]).arg(musicSongInfo[row][3]), Download_Video, this);
    download->startToDownload();
}

void MusicVideoTableWidget::itemDoubleClicked(int row, int column)
{
    if(column <= 0 || row < 0)
    {
        return;
    }
    MStringLists musicSongInfo(m_downLoadManager->getMusicSongInfo());
    emit mvURLChanged(musicSongInfo[row][2]);
}

void MusicVideoTableWidget::contextMenuEvent(QContextMenuEvent *event)
{
    MusicQueryTableWidget::contextMenuEvent(event);
    QMenu rightClickMenu(this);
    createContextMenu(rightClickMenu);

    rightClickMenu.exec(QCursor::pos());
}
<|endoftext|>


<commit_before>// BotRobot, ATaco
// PPCG: http://codegolf.stackexchange.com/a/104910/11933

// BotRobot
// ONE HUNDRED THOUSAND GENERATIONS TO MAKE THE ULTIMATE LIFEFORM!

#ifndef __BOT_ROBOT_PLAYER_HPP__
#define __BOT_ROBOT_PLAYER_HPP__

#include "Player.hpp"

class BotRobotPlayer final : public Player
{
public:
	BotRobotPlayer(size_t opponent = -1) : Player(opponent) {}

public:
	virtual Action fight()
	{
		std::string action = "";
		action += std::to_string(getAmmo());
		action += ":";
		action += std::to_string(getAmmoOpponent());

		int toDo = 3;

		for (int i = 0; i < sizeof(options); i++) {
			if (options[i].compare(action) == 0) {
				toDo = outputs[i];
				break;
			}
		}

		switch (toDo) {
		case 0:
			return load();
		case 1:
			return bullet();
		case 2:
			return plasma();
		case 3:
			return metal();
		default:
			return thermal();
		}
	}

private:
	std::string options[29] =
	{
		"0:9",
		"1:12",
		"1:10",
		"0:10",
		"1:11",
		"0:11",
		"0:6",
		"2:2",
		"0:2",
		"2:6",
		"3:6",
		"0:7",
		"1:3",
		"2:3",
		"0:3",
		"2:0",
		"1:0",
		"0:4",
		"1:4",
		"2:4",
		"0:0",
		"3:0",
		"1:1",
		"2:1",
		"2:9",
		"0:5",
		"0:8",
		"3:1",
		"0:1"
	};

	int outputs[29] =
	{
		0,
		1,
		1,
		4,
		1,
		0,
		0,
		4,
		4,
		0,
		0,
		3,
		0,
		1,
		3,
		0,
		1,
		4,
		0,
		1,
		0,
		1,
		0,
		3,
		4,
		3,
		0,
		1,
		0
	};
};

#endif // !__BOT_ROBOT_PLAYER_HPP__<commit_msg>Get correct array length.<commit_after>// BotRobot, ATaco
// PPCG: http://codegolf.stackexchange.com/a/104910/11933

// BotRobot
// ONE HUNDRED THOUSAND GENERATIONS TO MAKE THE ULTIMATE LIFEFORM!

#ifndef __BOT_ROBOT_PLAYER_HPP__
#define __BOT_ROBOT_PLAYER_HPP__

#include "Player.hpp"

class BotRobotPlayer final : public Player
{
public:
	BotRobotPlayer(size_t opponent = -1) : Player(opponent) {}

public:
	virtual Action fight()
	{
		std::string action = "";
		action += std::to_string(getAmmo());
		action += ":";
		action += std::to_string(getAmmoOpponent());

		int toDo = 3;

		for (int i = 0; i < sizeof(options)/sizeof(std::string); i++) {
			if (options[i].compare(action) == 0) {
				toDo = outputs[i];
				break;
			}
		}

		switch (toDo) {
		case 0:
			return load();
		case 1:
			return bullet();
		case 2:
			return plasma();
		case 3:
			return metal();
		default:
			return thermal();
		}
	}

private:
	std::string options[29] =
	{
		"0:9",
		"1:12",
		"1:10",
		"0:10",
		"1:11",
		"0:11",
		"0:6",
		"2:2",
		"0:2",
		"2:6",
		"3:6",
		"0:7",
		"1:3",
		"2:3",
		"0:3",
		"2:0",
		"1:0",
		"0:4",
		"1:4",
		"2:4",
		"0:0",
		"3:0",
		"1:1",
		"2:1",
		"2:9",
		"0:5",
		"0:8",
		"3:1",
		"0:1"
	};

	int outputs[29] =
	{
		0,
		1,
		1,
		4,
		1,
		0,
		0,
		4,
		4,
		0,
		0,
		3,
		0,
		1,
		3,
		0,
		1,
		4,
		0,
		1,
		0,
		1,
		0,
		3,
		4,
		3,
		0,
		1,
		0
	};
};

#endif // !__BOT_ROBOT_PLAYER_HPP__<|endoftext|>


<commit_before>#ifndef ALEPH_PERSISTENCE_DIAGRAM_HH__
#define ALEPH_PERSISTENCE_DIAGRAM_HH__

#include <algorithm>
#include <iosfwd>
#include <limits>
#include <utility>
#include <vector>

namespace aleph
{

template <class T> class PersistenceDiagram
{
public:

  // Exporting the data type of the underlying persistence diagrams
  // makes it easier for client code to specify the desired type in
  // advanced. Else, I would require `decltype` or related concepts
  // that make the code harder to read.
  using DataType = T;

  class Point
  {
  public:

    explicit Point( DataType x )
      : _x( x )
      , _y( std::numeric_limits<DataType>::max() )
    {
      if( std::numeric_limits<DataType>::has_infinity )
        _y = std::numeric_limits<DataType>::infinity();
    }

    Point( DataType x, DataType y )
      : _x( x )
      , _y( y )
    {
    }

    DataType x() const { return _x; }
    DataType y() const { return _y; }

    DataType persistence() const
    {
      return _y - _x;
    }

    bool operator==( const Point& other ) const
    {
      return _x == other._x && _y == other._y;
    }

    bool isUnpaired() const
    {
      return    (  std::numeric_limits<DataType>::has_infinity && _y == std::numeric_limits<DataType>::infinity() )
             || ( !std::numeric_limits<DataType>::has_infinity && _y == std::numeric_limits<DataType>::max() );
    }

  private:
    DataType _x;
    DataType _y;
  };

  // Typedefs & aliases ------------------------------------------------

  using ValueType     = Point;
  using ContainerType = std::vector<ValueType>;

  using ConstIterator = typename ContainerType::const_iterator;
  using Iterator      = typename ContainerType::iterator;

  using value_type    = ValueType;

  // Iterators ---------------------------------------------------------

  ConstIterator begin() const { return _points.begin(); }
  Iterator      begin()       { return _points.begin(); }

  ConstIterator end() const   { return _points.end(); }
  Iterator      end()         { return _points.end(); }

  // Modification ------------------------------------------------------

  void add( DataType x )
  {
    _points.push_back( Point( x ) );
  }

  void add( DataType x, DataType y )
  {
    _points.push_back( Point( x, y ) );
  }

  Iterator erase( Iterator position )
  {
    return _points.erase( position );
  }

  Iterator erase( Iterator begin, Iterator end )
  {
    return _points.erase( begin, end );
  }

  /** Removes all points that appear on the diagonal of a persistence diagram */
  void removeDiagonal() noexcept
  {
    _points.erase(
      std::remove_if( _points.begin(), _points.end(),
                      [] ( const Point& p )
                      {
                        return p.x() == p.y();
                      } ),
      _points.end()
    );
  }

  /** Removes all unpaired points, i.e. points with infinite persistence */
  void removeUnpaired() noexcept
  {
    _points.erase(
      std::remove_if( _points.begin(), _points.end(),
                      [] ( const Point& p )
                      {
                        return p.isUnpaired();
                      } ),
      _points.end()
    );
  }

  // Attributes --------------------------------------------------------

  void setDimension( std::size_t dimension )
  {
    _dimension = dimension;
  }

  std::size_t dimension() const
  {
    return _dimension;
  }

  // Comparison operators ----------------------------------------------

  bool operator==( const PersistenceDiagram<DataType>& other ) const
  {
    return _points == other._points;
  }

  bool operator!=( const PersistenceDiagram<DataType>& other ) const
  {
    return !( this->operator==( other ) );
  }

  // Queries -----------------------------------------------------------

  /** @returns Betti number of the persistence diagram, i.e. the number of unpaired points */
  std::size_t betti() const
  {
    auto numUnpairedPoints
      = std::count_if( _points.begin(), _points.end(),
                       [] ( const Point& p )
                       {
                         return p.isUnpaired();
                       } );

    return static_cast<std::size_t>( numUnpairedPoints );
  }

  std::size_t size() const
  {
    return _points.size();
  }

  bool empty() const
  {
    return _points.empty();
  }

private:

  /** Dimension of the persistence pairs stored in the diagram */
  std::size_t _dimension = 0;

  /** Container of persistence pairs */
  ContainerType _points;
};

template <class DataType> std::ostream& operator<<( std::ostream& o, const PersistenceDiagram<DataType>& D )
{
  for( auto&& p : D )
    o << p.x() << "\t" << p.y() << "\n";

  return o;
}

}

#endif
<commit_msg>Extended interface of subordinate `Point` class<commit_after>#ifndef ALEPH_PERSISTENCE_DIAGRAM_HH__
#define ALEPH_PERSISTENCE_DIAGRAM_HH__

#include <algorithm>
#include <iosfwd>
#include <limits>
#include <utility>
#include <vector>

namespace aleph
{

template <class T> class PersistenceDiagram
{
public:

  // Exporting the data type of the underlying persistence diagrams
  // makes it easier for client code to specify the desired type in
  // advanced. Else, I would require `decltype` or related concepts
  // that make the code harder to read.
  using DataType = T;

  class Point
  {
  public:

    explicit Point( DataType x )
      : _x( x )
      , _y( std::numeric_limits<DataType>::max() )
    {
      if( std::numeric_limits<DataType>::has_infinity )
        _y = std::numeric_limits<DataType>::infinity();
    }

    Point( DataType x, DataType y )
      : _x( x )
      , _y( y )
    {
    }

    DataType x() const noexcept { return _x; }
    DataType y() const noexcept { return _y; }

    DataType persistence() const noexcept
    {
      return _y - _x;
    }

    bool operator==( const Point& other ) const noexcept
    {
      return _x == other._x && _y == other._y;
    }

    bool operator!=( const Point& other ) const noexcept
    {
      return !this->operator==( other );
    }

    bool isUnpaired() const noexcept
    {
      return    (  std::numeric_limits<DataType>::has_infinity && _y == std::numeric_limits<DataType>::infinity() )
             || ( !std::numeric_limits<DataType>::has_infinity && _y == std::numeric_limits<DataType>::max() );
    }

  private:
    DataType _x;
    DataType _y;
  };

  // Typedefs & aliases ------------------------------------------------

  using ValueType     = Point;
  using ContainerType = std::vector<ValueType>;

  using ConstIterator = typename ContainerType::const_iterator;
  using Iterator      = typename ContainerType::iterator;

  using value_type    = ValueType;

  // Iterators ---------------------------------------------------------

  ConstIterator begin() const { return _points.begin(); }
  Iterator      begin()       { return _points.begin(); }

  ConstIterator end() const   { return _points.end(); }
  Iterator      end()         { return _points.end(); }

  // Modification ------------------------------------------------------

  void add( DataType x )
  {
    _points.push_back( Point( x ) );
  }

  void add( DataType x, DataType y )
  {
    _points.push_back( Point( x, y ) );
  }

  Iterator erase( Iterator position )
  {
    return _points.erase( position );
  }

  Iterator erase( Iterator begin, Iterator end )
  {
    return _points.erase( begin, end );
  }

  /** Removes all points that appear on the diagonal of a persistence diagram */
  void removeDiagonal() noexcept
  {
    _points.erase(
      std::remove_if( _points.begin(), _points.end(),
                      [] ( const Point& p )
                      {
                        return p.x() == p.y();
                      } ),
      _points.end()
    );
  }

  /** Removes all unpaired points, i.e. points with infinite persistence */
  void removeUnpaired() noexcept
  {
    _points.erase(
      std::remove_if( _points.begin(), _points.end(),
                      [] ( const Point& p )
                      {
                        return p.isUnpaired();
                      } ),
      _points.end()
    );
  }

  // Attributes --------------------------------------------------------

  void setDimension( std::size_t dimension )
  {
    _dimension = dimension;
  }

  std::size_t dimension() const
  {
    return _dimension;
  }

  // Comparison operators ----------------------------------------------

  bool operator==( const PersistenceDiagram<DataType>& other ) const
  {
    return _points == other._points;
  }

  bool operator!=( const PersistenceDiagram<DataType>& other ) const
  {
    return !( this->operator==( other ) );
  }

  // Queries -----------------------------------------------------------

  /** @returns Betti number of the persistence diagram, i.e. the number of unpaired points */
  std::size_t betti() const
  {
    auto numUnpairedPoints
      = std::count_if( _points.begin(), _points.end(),
                       [] ( const Point& p )
                       {
                         return p.isUnpaired();
                       } );

    return static_cast<std::size_t>( numUnpairedPoints );
  }

  std::size_t size() const
  {
    return _points.size();
  }

  bool empty() const
  {
    return _points.empty();
  }

private:

  /** Dimension of the persistence pairs stored in the diagram */
  std::size_t _dimension = 0;

  /** Container of persistence pairs */
  ContainerType _points;
};

template <class DataType> std::ostream& operator<<( std::ostream& o, const PersistenceDiagram<DataType>& D )
{
  for( auto&& p : D )
    o << p.x() << "\t" << p.y() << "\n";

  return o;
}

}

#endif
<|endoftext|>


<commit_before>#include "visualization.h"
#include <opencv2/highgui.hpp>
using namespace std;

namespace mo {

//-----------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, const Color& col){
    return os << "{r,g,b}={" << static_cast<unsigned>(col.red) << ',' <<
                 static_cast<unsigned>(col.green) << ',' <<
                 static_cast<unsigned>(col.blue) << "}";
}

//-----------------------------------------------------------------
void show(const std::string& winname, const Image& img, const int waitms){
    cv::imshow(winname, img);
    cv::waitKey(waitms);
}

//-----------------------------------------------------------------
void line(const Point& pt_sta, const Point& pt_end, Image& img, const Color& color){
    cv::line(img, pt_sta, pt_end, color.pixval());
}

//-----------------------------------------------------------------
void arrow(const Point& pt_sta, const Point& pt_end, Image& img, const Color& color){
    cv::arrowedLine(img, pt_sta, pt_end, color.pixval());
}

//-----------------------------------------------------------------
void point(const Point& pt, Image& img, const Color& color, const int radius){
    cv::circle(img, pt, radius, color.pixval(), -1); //-1 means filled color.
}

//-----------------------------------------------------------------
void text(const std::string& text, Image& img, const Point& org, const double& scale, const Color& color){
    cv::putText(img, text, org, cv::FONT_HERSHEY_SIMPLEX, scale, color.pixval());
}

//-----------------------------------------------------------------
void colorbar(Image& img, const ColormapTypes colormaptype){
    for(int u=0; u<img.rows; ++u){
        unsigned char* Mu = img.ptr(u);
        for(int v=0; v<img.cols*3; v+=3){
            for(int c=0; c<3; ++c){ //color channel
                Mu[v+c] = u*255/img.rows;
            }
        }
    }

    cv::applyColorMap(img, img, cv::COLORMAP_HOT);
}

} //namespace mo
<commit_msg>change colorbar<commit_after>#include "visualization.h"
#include <opencv2/highgui.hpp>
using namespace std;

namespace mo {

//-----------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, const Color& col){
    return os << "{r,g,b}={" << static_cast<unsigned>(col.red) << ',' <<
                 static_cast<unsigned>(col.green) << ',' <<
                 static_cast<unsigned>(col.blue) << "}";
}

//-----------------------------------------------------------------
void show(const std::string& winname, const Image& img, const int waitms){
    cv::imshow(winname, img);
    cv::waitKey(waitms);
}

//-----------------------------------------------------------------
void line(const Point& pt_sta, const Point& pt_end, Image& img, const Color& color){
    cv::line(img, pt_sta, pt_end, color.pixval());
}

//-----------------------------------------------------------------
void arrow(const Point& pt_sta, const Point& pt_end, Image& img, const Color& color){
    cv::arrowedLine(img, pt_sta, pt_end, color.pixval());
}

//-----------------------------------------------------------------
void point(const Point& pt, Image& img, const Color& color, const int radius){
    cv::circle(img, pt, radius, color.pixval(), -1); //-1 means filled color.
}

//-----------------------------------------------------------------
void text(const std::string& text, Image& img, const Point& org, const double& scale, const Color& color){
    cv::putText(img, text, org, cv::FONT_HERSHEY_SIMPLEX, scale, color.pixval());
}

//-----------------------------------------------------------------
void colorbar(Image& img, const ColormapTypes colormaptype){
    for(int u=0; u<img.rows; ++u){
        unsigned char* Mu = img.ptr(u);
        for(int v=0; v<img.cols*3; v+=3){
            for(int c=0; c<3; ++c){ //color channel
                Mu[v+c] = 255 - u*255/img.rows;
            }
        }
    }

    cv::applyColorMap(img, img, cv::COLORMAP_HOT);
}

} //namespace mo
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef INCLUDED_OOX_DRAWINGML_CHART_SERIESCONTEXT_HXX
#define INCLUDED_OOX_DRAWINGML_CHART_SERIESCONTEXT_HXX

#include <drawingml/chart/chartcontextbase.hxx>

namespace oox {
namespace drawingml {
namespace chart {

struct DataLabelModel;

/** Handler for a chart data point label context (c:dLbl element).
 */
class DataLabelContext : public ContextBase< DataLabelModel >
{
public:
    explicit            DataLabelContext( ::oox::core::ContextHandler2Helper& rParent, DataLabelModel& rModel );
    virtual             ~DataLabelContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
    virtual void        onCharacters( const OUString& rChars ) SAL_OVERRIDE;
};

struct DataLabelsModel;

/** Handler for a chart data point label context (c:dLbl element).
 */
class DataLabelsContext : public ContextBase< DataLabelsModel >
{
public:
    explicit            DataLabelsContext( ::oox::core::ContextHandler2Helper& rParent, DataLabelsModel& rModel );
    virtual             ~DataLabelsContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
    virtual void        onCharacters( const OUString& rChars ) SAL_OVERRIDE;
};

struct PictureOptionsModel;

/** Handler for fill bitmap settings (c:pictureOptions element).
 */
class PictureOptionsContext : public ContextBase< PictureOptionsModel >
{
public:
    explicit            PictureOptionsContext( ::oox::core::ContextHandler2Helper& rParent, PictureOptionsModel& rModel );
    virtual             ~PictureOptionsContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct ErrorBarModel;

/** Handler for a series error bar context (c:errBars element).
 */
class ErrorBarContext : public ContextBase< ErrorBarModel >
{
public:
    explicit            ErrorBarContext( ::oox::core::ContextHandler2Helper& rParent, ErrorBarModel& rModel );
    virtual             ~ErrorBarContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct TrendlineLabelModel;

/** Handler for a series trendline label context (c:trendlineLbl element).
 */
class TrendlineLabelContext : public ContextBase< TrendlineLabelModel >
{
public:
    explicit            TrendlineLabelContext( ::oox::core::ContextHandler2Helper& rParent, TrendlineLabelModel& rModel );
    virtual             ~TrendlineLabelContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct TrendlineModel;

/** Handler for a series trendline context (c:trendline element).
 */
class TrendlineContext : public ContextBase< TrendlineModel >
{
public:
    explicit            TrendlineContext( ::oox::core::ContextHandler2Helper& rParent, TrendlineModel& rModel );
    virtual             ~TrendlineContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
    virtual void        onCharacters( const OUString& rChars ) SAL_OVERRIDE;
};

struct DataPointModel;

/** Handler for a chart data point context (c:dPt element).
 */
class DataPointContext : public ContextBase< DataPointModel >
{
public:
    explicit            DataPointContext( ::oox::core::ContextHandler2Helper& rParent, DataPointModel& rModel );
    virtual             ~DataPointContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct SeriesModel;

/** Handler base class for chart data series contexts (c:ser element).
 */
class SeriesContextBase : public ContextBase< SeriesModel >
{
public:
    explicit            SeriesContextBase( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~SeriesContextBase();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for area chart types (c:ser element).
 */
class AreaSeriesContext : public SeriesContextBase
{
public:
    explicit            AreaSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~AreaSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for bar chart types (c:ser element).
 */
class BarSeriesContext : public SeriesContextBase
{
public:
    explicit            BarSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~BarSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for bubble chart types (c:ser element).
 */
class BubbleSeriesContext : public SeriesContextBase
{
public:
    explicit            BubbleSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~BubbleSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for line and stock chart types (c:ser
    element).
 */
class LineSeriesContext : public SeriesContextBase
{
public:
    explicit            LineSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~LineSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for pie and doughnut chart types (c:ser
    element).
 */
class PieSeriesContext : public SeriesContextBase
{
public:
    explicit            PieSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~PieSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for radar chart types (c:ser element).
 */
class RadarSeriesContext : public SeriesContextBase
{
public:
    explicit            RadarSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~RadarSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for scatter chart types (c:ser element).
 */
class ScatterSeriesContext : public SeriesContextBase
{
public:
    explicit            ScatterSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~ScatterSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for scatter chart types (c:ser element).
 */
class SurfaceSeriesContext : public SeriesContextBase
{
public:
    explicit            SurfaceSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~SurfaceSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

} // namespace chart
} // namespace drawingml
} // namespace oox

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Most certainly meant to be plural.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef INCLUDED_OOX_DRAWINGML_CHART_SERIESCONTEXT_HXX
#define INCLUDED_OOX_DRAWINGML_CHART_SERIESCONTEXT_HXX

#include <drawingml/chart/chartcontextbase.hxx>

namespace oox {
namespace drawingml {
namespace chart {

struct DataLabelModel;

/** Handler for a chart data point label context (c:dLbl element).
 */
class DataLabelContext : public ContextBase< DataLabelModel >
{
public:
    explicit            DataLabelContext( ::oox::core::ContextHandler2Helper& rParent, DataLabelModel& rModel );
    virtual             ~DataLabelContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
    virtual void        onCharacters( const OUString& rChars ) SAL_OVERRIDE;
};

struct DataLabelsModel;

/** Handler for a chart data point label context (c:dLbls element).
 */
class DataLabelsContext : public ContextBase< DataLabelsModel >
{
public:
    explicit            DataLabelsContext( ::oox::core::ContextHandler2Helper& rParent, DataLabelsModel& rModel );
    virtual             ~DataLabelsContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
    virtual void        onCharacters( const OUString& rChars ) SAL_OVERRIDE;
};

struct PictureOptionsModel;

/** Handler for fill bitmap settings (c:pictureOptions element).
 */
class PictureOptionsContext : public ContextBase< PictureOptionsModel >
{
public:
    explicit            PictureOptionsContext( ::oox::core::ContextHandler2Helper& rParent, PictureOptionsModel& rModel );
    virtual             ~PictureOptionsContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct ErrorBarModel;

/** Handler for a series error bar context (c:errBars element).
 */
class ErrorBarContext : public ContextBase< ErrorBarModel >
{
public:
    explicit            ErrorBarContext( ::oox::core::ContextHandler2Helper& rParent, ErrorBarModel& rModel );
    virtual             ~ErrorBarContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct TrendlineLabelModel;

/** Handler for a series trendline label context (c:trendlineLbl element).
 */
class TrendlineLabelContext : public ContextBase< TrendlineLabelModel >
{
public:
    explicit            TrendlineLabelContext( ::oox::core::ContextHandler2Helper& rParent, TrendlineLabelModel& rModel );
    virtual             ~TrendlineLabelContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct TrendlineModel;

/** Handler for a series trendline context (c:trendline element).
 */
class TrendlineContext : public ContextBase< TrendlineModel >
{
public:
    explicit            TrendlineContext( ::oox::core::ContextHandler2Helper& rParent, TrendlineModel& rModel );
    virtual             ~TrendlineContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
    virtual void        onCharacters( const OUString& rChars ) SAL_OVERRIDE;
};

struct DataPointModel;

/** Handler for a chart data point context (c:dPt element).
 */
class DataPointContext : public ContextBase< DataPointModel >
{
public:
    explicit            DataPointContext( ::oox::core::ContextHandler2Helper& rParent, DataPointModel& rModel );
    virtual             ~DataPointContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

struct SeriesModel;

/** Handler base class for chart data series contexts (c:ser element).
 */
class SeriesContextBase : public ContextBase< SeriesModel >
{
public:
    explicit            SeriesContextBase( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~SeriesContextBase();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for area chart types (c:ser element).
 */
class AreaSeriesContext : public SeriesContextBase
{
public:
    explicit            AreaSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~AreaSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for bar chart types (c:ser element).
 */
class BarSeriesContext : public SeriesContextBase
{
public:
    explicit            BarSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~BarSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for bubble chart types (c:ser element).
 */
class BubbleSeriesContext : public SeriesContextBase
{
public:
    explicit            BubbleSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~BubbleSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for line and stock chart types (c:ser
    element).
 */
class LineSeriesContext : public SeriesContextBase
{
public:
    explicit            LineSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~LineSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for pie and doughnut chart types (c:ser
    element).
 */
class PieSeriesContext : public SeriesContextBase
{
public:
    explicit            PieSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~PieSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for radar chart types (c:ser element).
 */
class RadarSeriesContext : public SeriesContextBase
{
public:
    explicit            RadarSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~RadarSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for scatter chart types (c:ser element).
 */
class ScatterSeriesContext : public SeriesContextBase
{
public:
    explicit            ScatterSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~ScatterSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

/** Handler for a data series context for scatter chart types (c:ser element).
 */
class SurfaceSeriesContext : public SeriesContextBase
{
public:
    explicit            SurfaceSeriesContext( ::oox::core::ContextHandler2Helper& rParent, SeriesModel& rModel );
    virtual             ~SurfaceSeriesContext();

    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
};

} // namespace chart
} // namespace drawingml
} // namespace oox

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * reactor.cc
 *
 *  Created on: Aug 1, 2014
 *      Author: avi
 */

#include "reactor.hh"
#include <cassert>
#include <unistd.h>
#include <fcntl.h>
#include <sys/eventfd.h>

timespec to_timespec(clock_type::time_point t) {
    using ns = std::chrono::nanoseconds;
    auto n = std::chrono::duration_cast<ns>(t.time_since_epoch()).count();
    return { n / 1'000'000'000, n % 1'000'000'000 };
}

template <typename T>
struct syscall_result {
    T result;
    int error;
    void throw_if_error() {
        if (long(result) == -1) {
            throw std::system_error(error, std::system_category());
        }
    }
};

template <typename T>
syscall_result<T>
wrap_syscall(T result) {
    syscall_result<T> sr;
    sr.result = result;
    sr.error = errno;
    return sr;
}

reactor::reactor()
    : _epollfd(file_desc::epoll_create(EPOLL_CLOEXEC))
    , _io_eventfd()
    , _io_context(0)
    , _io_context_available(max_aio) {
    auto r = ::io_setup(max_aio, &_io_context);
    assert(r >= 0);
    _io_eventfd.wait().then([this] (size_t count) {
        process_io(count);
    });
}

future<> reactor::get_epoll_future(pollable_fd_state& pfd,
        promise<> pollable_fd_state::*pr, int event) {
    if (pfd.events_known & event) {
        pfd.events_known &= ~event;
        return make_ready_future();
    }
    pfd.events_requested |= event;
    if (!(pfd.events_epoll & event)) {
        auto ctl = pfd.events_epoll ? EPOLL_CTL_MOD : EPOLL_CTL_ADD;
        pfd.events_epoll |= event;
        ::epoll_event eevt;
        eevt.events = pfd.events_epoll;
        eevt.data.ptr = &pfd;
        int r = ::epoll_ctl(_epollfd.get(), ctl, pfd.fd.get(), &eevt);
        assert(r == 0);
    }
    pfd.*pr = promise<>();
    return (pfd.*pr).get_future();
}

future<> reactor::readable(pollable_fd_state& fd) {
    return get_epoll_future(fd, &pollable_fd_state::pollin, EPOLLIN);
}

future<> reactor::writeable(pollable_fd_state& fd) {
    return get_epoll_future(fd, &pollable_fd_state::pollout, EPOLLOUT);
}

void reactor::forget(pollable_fd_state& fd) {
    if (fd.events_epoll) {
        ::epoll_ctl(_epollfd.get(), EPOLL_CTL_DEL, fd.fd.get(), nullptr);
    }
}

pollable_fd
reactor::listen(socket_address sa, listen_options opts) {
    file_desc fd = file_desc::socket(sa.u.sa.sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    if (opts.reuse_address) {
        int opt = 1;
        fd.setsockopt(SOL_SOCKET, SO_REUSEADDR, opt);
    }

    fd.bind(sa.u.sa, sizeof(sa.u.sas));
    fd.listen(100);
    return pollable_fd(std::move(fd));
}

void reactor::complete_epoll_event(pollable_fd_state& pfd, promise<> pollable_fd_state::*pr,
        int events, int event) {
    if (pfd.events_requested & events & event) {
        pfd.events_requested &= ~EPOLLIN;
        pfd.events_known &= ~EPOLLIN;
        (pfd.*pr).set_value();
        pfd.*pr = promise<>();
    }
}

template <typename Func>
future<io_event>
reactor::submit_io(Func prepare_io) {
    return _io_context_available.wait(1).then([this, prepare_io = std::move(prepare_io)] () mutable {
        auto pr = std::make_unique<promise<io_event>>();
        iocb io;
        prepare_io(io);
        io.data = pr.get();
        io_set_eventfd(&io, _io_eventfd.get_write_fd());
        iocb* p = &io;
        auto r = ::io_submit(_io_context, 1, &p);
        throw_kernel_error(r);
        return pr.release()->get_future();
    });
}

void reactor::process_io(size_t count)
{
    io_event ev[max_aio];
    auto n = ::io_getevents(_io_context, count, count, ev, NULL);
    assert(n >= 0 && size_t(n) == count);
    for (size_t i = 0; i < size_t(n); ++i) {
        auto pr = reinterpret_cast<promise<io_event>*>(ev[i].data);
        pr->set_value(ev[i]);
        delete pr;
    }
    _io_context_available.signal(n);
    _io_eventfd.wait().then([this] (size_t count) {
        process_io(count);
    });
}

future<size_t>
reactor::write_dma(file& f, uint64_t pos, const void* buffer, size_t len) {
    return submit_io([&f, pos, buffer, len] (iocb& io) {
        io_prep_pwrite(&io, f._fd, const_cast<void*>(buffer), len, pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<size_t>
reactor::write_dma(file& f, uint64_t pos, std::vector<iovec> iov) {
    return submit_io([&f, pos, iov = std::move(iov)] (iocb& io) {
        io_prep_pwritev(&io, f._fd, iov.data(), iov.size(), pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<size_t>
reactor::read_dma(file& f, uint64_t pos, void* buffer, size_t len) {
    return submit_io([&f, pos, buffer, len] (iocb& io) {
        io_prep_pread(&io, f._fd, buffer, len, pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<size_t>
reactor::read_dma(file& f, uint64_t pos, std::vector<iovec> iov) {
    return submit_io([&f, pos, iov = std::move(iov)] (iocb& io) {
        io_prep_preadv(&io, f._fd, iov.data(), iov.size(), pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<file>
reactor::open_file_dma(sstring name) {
    return _thread_pool.submit<syscall_result<int>>([name] {
        return wrap_syscall<int>(::open(name.c_str(), O_DIRECT | O_CLOEXEC | O_CREAT | O_RDWR, S_IRWXU));
    }).then([] (syscall_result<int> sr) {
        sr.throw_if_error();
        return make_ready_future<file>(file(sr.result));
    });
}

future<>
reactor::flush(file& f) {
    return _thread_pool.submit<syscall_result<int>>([&f] {
        return wrap_syscall<int>(::fsync(f._fd));
    }).then([] (syscall_result<int> sr) {
        sr.throw_if_error();
        return make_ready_future<>();
    });
}

void reactor::add_timer(timer* tmr) {
    if (_timers.insert(*tmr) && tmr->get_timeout() < _next_timeout) {
        itimerspec its;
        its.it_interval = {};
        its.it_value = to_timespec(_timers.get_next_timeout());
        _timerfd.get_file_desc().timerfd_settime(TFD_TIMER_ABSTIME, its);
    }
}

void reactor::del_timer(timer* tmr) {
    _timers.remove(*tmr);
}

void reactor::complete_timers() {
    _timerfd.read_some(reinterpret_cast<char*>(&_timers_completed), sizeof(_timers_completed)).then(
            [this] (size_t n) {
        _timers.expire(clock_type::now());
        while (auto t = _timers.pop_expired()) {
            t->_pr.set_value();
            t->_pr = promise<>();
        }
        if (!_timers.empty()) {
            _next_timeout = _timers.get_next_timeout();
            itimerspec its;
            its.it_interval = {};
            its.it_value = to_timespec(_next_timeout);
            _timerfd.get_file_desc().timerfd_settime(TFD_TIMER_ABSTIME, its);
        }
        complete_timers();
    });
}

void reactor::run() {
    std::vector<std::unique_ptr<task>> current_tasks;
    _start_promise.set_value();
    complete_timers();
    while (true) {
        while (!_pending_tasks.empty()) {
            std::swap(_pending_tasks, current_tasks);
            for (auto&& tsk : current_tasks) {
                tsk->run();
                tsk.reset();
            }
            current_tasks.clear();
        }
        std::array<epoll_event, 128> eevt;
        int nr = ::epoll_wait(_epollfd.get(), eevt.data(), eevt.size(), -1);
        assert(nr != -1);
        for (int i = 0; i < nr; ++i) {
            auto& evt = eevt[i];
            auto pfd = reinterpret_cast<pollable_fd_state*>(evt.data.ptr);
            auto events = evt.events & (EPOLLIN | EPOLLOUT);
            std::unique_ptr<task> t_in, t_out;
            pfd->events_known |= events;
            auto events_to_remove = events & ~pfd->events_requested;
            complete_epoll_event(*pfd, &pollable_fd_state::pollin, events, EPOLLIN);
            complete_epoll_event(*pfd, &pollable_fd_state::pollout, events, EPOLLOUT);
            if (events_to_remove) {
                pfd->events_epoll &= ~events_to_remove;
                evt.events = pfd->events_epoll;
                auto op = evt.events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
                ::epoll_ctl(_epollfd.get(), op, pfd->fd.get(), &evt);
            }
        }
    }
}

thread_pool::thread_pool()
    : _pending(queue_length)
    , _completed(queue_length)
    , _start_eventfd(0)
    , _complete_eventfd(0)
    , _worker_thread([this] { work(); }) {
    _worker_thread.detach();
    complete();
}

void thread_pool::work() {
    while (true) {
        uint64_t count;
        auto r = ::read(_start_eventfd.get_read_fd(), &count, sizeof(count));
        assert(r == sizeof(count));
        auto nr = _pending.consume_all([this] (work_item* wi) {
            wi->process();
            _completed.push(wi);
        });
        count = nr;
        r = ::write(_complete_eventfd.get_write_fd(), &count, sizeof(count));
        assert(r == sizeof(count));
    }
}

void thread_pool::submit_item(thread_pool::work_item* item) {
    _queue_has_room.wait().then([this, item] {
        _pending.push(item);
        _start_eventfd.signal(1);
    });
}

void thread_pool::complete() {
    _complete_eventfd.wait().then([this] (size_t count) {
        auto nr = _completed.consume_all([this] (work_item* wi) {
            wi->complete();
            delete wi;
        });
        _queue_has_room.signal(nr);
        complete();
    });
}

file_desc writeable_eventfd::try_create_eventfd(size_t initial) {
    assert(size_t(int(initial)) == initial);
    return file_desc::eventfd(initial, EFD_CLOEXEC);
}

void writeable_eventfd::signal(size_t count) {
    uint64_t c = count;
    auto r = _fd.write(&c, sizeof(c));
    assert(r == sizeof(c));
}

file_desc readable_eventfd::try_create_eventfd(size_t initial) {
    assert(size_t(int(initial)) == initial);
    return file_desc::eventfd(initial, EFD_CLOEXEC | EFD_NONBLOCK);
}

future<size_t> readable_eventfd::wait() {
    return the_reactor.readable(*_fd._s).then([this] {
        uint64_t count;
        int r = ::read(_fd.get_fd(), &count, sizeof(count));
        assert(r == sizeof(count));
        return make_ready_future<size_t>(count);
    });
}

socket_address make_ipv4_address(ipv4_addr addr) {
    socket_address sa;
    sa.u.in.sin_family = AF_INET;
    sa.u.in.sin_port = htons(addr.port);
    std::memcpy(&sa.u.in.sin_addr, addr.host, 4);
    return sa;
}

reactor the_reactor;
<commit_msg>core: be more friendly to debuggers<commit_after>/*
 * reactor.cc
 *
 *  Created on: Aug 1, 2014
 *      Author: avi
 */

#include "reactor.hh"
#include <cassert>
#include <unistd.h>
#include <fcntl.h>
#include <sys/eventfd.h>

timespec to_timespec(clock_type::time_point t) {
    using ns = std::chrono::nanoseconds;
    auto n = std::chrono::duration_cast<ns>(t.time_since_epoch()).count();
    return { n / 1'000'000'000, n % 1'000'000'000 };
}

template <typename T>
struct syscall_result {
    T result;
    int error;
    void throw_if_error() {
        if (long(result) == -1) {
            throw std::system_error(error, std::system_category());
        }
    }
};

template <typename T>
syscall_result<T>
wrap_syscall(T result) {
    syscall_result<T> sr;
    sr.result = result;
    sr.error = errno;
    return sr;
}

reactor::reactor()
    : _epollfd(file_desc::epoll_create(EPOLL_CLOEXEC))
    , _io_eventfd()
    , _io_context(0)
    , _io_context_available(max_aio) {
    auto r = ::io_setup(max_aio, &_io_context);
    assert(r >= 0);
    _io_eventfd.wait().then([this] (size_t count) {
        process_io(count);
    });
}

future<> reactor::get_epoll_future(pollable_fd_state& pfd,
        promise<> pollable_fd_state::*pr, int event) {
    if (pfd.events_known & event) {
        pfd.events_known &= ~event;
        return make_ready_future();
    }
    pfd.events_requested |= event;
    if (!(pfd.events_epoll & event)) {
        auto ctl = pfd.events_epoll ? EPOLL_CTL_MOD : EPOLL_CTL_ADD;
        pfd.events_epoll |= event;
        ::epoll_event eevt;
        eevt.events = pfd.events_epoll;
        eevt.data.ptr = &pfd;
        int r = ::epoll_ctl(_epollfd.get(), ctl, pfd.fd.get(), &eevt);
        assert(r == 0);
    }
    pfd.*pr = promise<>();
    return (pfd.*pr).get_future();
}

future<> reactor::readable(pollable_fd_state& fd) {
    return get_epoll_future(fd, &pollable_fd_state::pollin, EPOLLIN);
}

future<> reactor::writeable(pollable_fd_state& fd) {
    return get_epoll_future(fd, &pollable_fd_state::pollout, EPOLLOUT);
}

void reactor::forget(pollable_fd_state& fd) {
    if (fd.events_epoll) {
        ::epoll_ctl(_epollfd.get(), EPOLL_CTL_DEL, fd.fd.get(), nullptr);
    }
}

pollable_fd
reactor::listen(socket_address sa, listen_options opts) {
    file_desc fd = file_desc::socket(sa.u.sa.sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    if (opts.reuse_address) {
        int opt = 1;
        fd.setsockopt(SOL_SOCKET, SO_REUSEADDR, opt);
    }

    fd.bind(sa.u.sa, sizeof(sa.u.sas));
    fd.listen(100);
    return pollable_fd(std::move(fd));
}

void reactor::complete_epoll_event(pollable_fd_state& pfd, promise<> pollable_fd_state::*pr,
        int events, int event) {
    if (pfd.events_requested & events & event) {
        pfd.events_requested &= ~EPOLLIN;
        pfd.events_known &= ~EPOLLIN;
        (pfd.*pr).set_value();
        pfd.*pr = promise<>();
    }
}

template <typename Func>
future<io_event>
reactor::submit_io(Func prepare_io) {
    return _io_context_available.wait(1).then([this, prepare_io = std::move(prepare_io)] () mutable {
        auto pr = std::make_unique<promise<io_event>>();
        iocb io;
        prepare_io(io);
        io.data = pr.get();
        io_set_eventfd(&io, _io_eventfd.get_write_fd());
        iocb* p = &io;
        auto r = ::io_submit(_io_context, 1, &p);
        throw_kernel_error(r);
        return pr.release()->get_future();
    });
}

void reactor::process_io(size_t count)
{
    io_event ev[max_aio];
    auto n = ::io_getevents(_io_context, count, count, ev, NULL);
    assert(n >= 0 && size_t(n) == count);
    for (size_t i = 0; i < size_t(n); ++i) {
        auto pr = reinterpret_cast<promise<io_event>*>(ev[i].data);
        pr->set_value(ev[i]);
        delete pr;
    }
    _io_context_available.signal(n);
    _io_eventfd.wait().then([this] (size_t count) {
        process_io(count);
    });
}

future<size_t>
reactor::write_dma(file& f, uint64_t pos, const void* buffer, size_t len) {
    return submit_io([&f, pos, buffer, len] (iocb& io) {
        io_prep_pwrite(&io, f._fd, const_cast<void*>(buffer), len, pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<size_t>
reactor::write_dma(file& f, uint64_t pos, std::vector<iovec> iov) {
    return submit_io([&f, pos, iov = std::move(iov)] (iocb& io) {
        io_prep_pwritev(&io, f._fd, iov.data(), iov.size(), pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<size_t>
reactor::read_dma(file& f, uint64_t pos, void* buffer, size_t len) {
    return submit_io([&f, pos, buffer, len] (iocb& io) {
        io_prep_pread(&io, f._fd, buffer, len, pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<size_t>
reactor::read_dma(file& f, uint64_t pos, std::vector<iovec> iov) {
    return submit_io([&f, pos, iov = std::move(iov)] (iocb& io) {
        io_prep_preadv(&io, f._fd, iov.data(), iov.size(), pos);
    }).then([] (io_event ev) {
        throw_kernel_error(long(ev.res));
        return make_ready_future<size_t>(size_t(ev.res));
    });
}

future<file>
reactor::open_file_dma(sstring name) {
    return _thread_pool.submit<syscall_result<int>>([name] {
        return wrap_syscall<int>(::open(name.c_str(), O_DIRECT | O_CLOEXEC | O_CREAT | O_RDWR, S_IRWXU));
    }).then([] (syscall_result<int> sr) {
        sr.throw_if_error();
        return make_ready_future<file>(file(sr.result));
    });
}

future<>
reactor::flush(file& f) {
    return _thread_pool.submit<syscall_result<int>>([&f] {
        return wrap_syscall<int>(::fsync(f._fd));
    }).then([] (syscall_result<int> sr) {
        sr.throw_if_error();
        return make_ready_future<>();
    });
}

void reactor::add_timer(timer* tmr) {
    if (_timers.insert(*tmr) && tmr->get_timeout() < _next_timeout) {
        itimerspec its;
        its.it_interval = {};
        its.it_value = to_timespec(_timers.get_next_timeout());
        _timerfd.get_file_desc().timerfd_settime(TFD_TIMER_ABSTIME, its);
    }
}

void reactor::del_timer(timer* tmr) {
    _timers.remove(*tmr);
}

void reactor::complete_timers() {
    _timerfd.read_some(reinterpret_cast<char*>(&_timers_completed), sizeof(_timers_completed)).then(
            [this] (size_t n) {
        _timers.expire(clock_type::now());
        while (auto t = _timers.pop_expired()) {
            t->_pr.set_value();
            t->_pr = promise<>();
        }
        if (!_timers.empty()) {
            _next_timeout = _timers.get_next_timeout();
            itimerspec its;
            its.it_interval = {};
            its.it_value = to_timespec(_next_timeout);
            _timerfd.get_file_desc().timerfd_settime(TFD_TIMER_ABSTIME, its);
        }
        complete_timers();
    });
}

void reactor::run() {
    std::vector<std::unique_ptr<task>> current_tasks;
    _start_promise.set_value();
    complete_timers();
    while (true) {
        while (!_pending_tasks.empty()) {
            std::swap(_pending_tasks, current_tasks);
            for (auto&& tsk : current_tasks) {
                tsk->run();
                tsk.reset();
            }
            current_tasks.clear();
        }
        std::array<epoll_event, 128> eevt;
        int nr = ::epoll_wait(_epollfd.get(), eevt.data(), eevt.size(), -1);
        if (nr == -1 && errno == EINTR) {
            continue; // gdb can cause this
        }
        assert(nr != -1);
        for (int i = 0; i < nr; ++i) {
            auto& evt = eevt[i];
            auto pfd = reinterpret_cast<pollable_fd_state*>(evt.data.ptr);
            auto events = evt.events & (EPOLLIN | EPOLLOUT);
            std::unique_ptr<task> t_in, t_out;
            pfd->events_known |= events;
            auto events_to_remove = events & ~pfd->events_requested;
            complete_epoll_event(*pfd, &pollable_fd_state::pollin, events, EPOLLIN);
            complete_epoll_event(*pfd, &pollable_fd_state::pollout, events, EPOLLOUT);
            if (events_to_remove) {
                pfd->events_epoll &= ~events_to_remove;
                evt.events = pfd->events_epoll;
                auto op = evt.events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
                ::epoll_ctl(_epollfd.get(), op, pfd->fd.get(), &evt);
            }
        }
    }
}

thread_pool::thread_pool()
    : _pending(queue_length)
    , _completed(queue_length)
    , _start_eventfd(0)
    , _complete_eventfd(0)
    , _worker_thread([this] { work(); }) {
    _worker_thread.detach();
    complete();
}

void thread_pool::work() {
    while (true) {
        uint64_t count;
        auto r = ::read(_start_eventfd.get_read_fd(), &count, sizeof(count));
        assert(r == sizeof(count));
        auto nr = _pending.consume_all([this] (work_item* wi) {
            wi->process();
            _completed.push(wi);
        });
        count = nr;
        r = ::write(_complete_eventfd.get_write_fd(), &count, sizeof(count));
        assert(r == sizeof(count));
    }
}

void thread_pool::submit_item(thread_pool::work_item* item) {
    _queue_has_room.wait().then([this, item] {
        _pending.push(item);
        _start_eventfd.signal(1);
    });
}

void thread_pool::complete() {
    _complete_eventfd.wait().then([this] (size_t count) {
        auto nr = _completed.consume_all([this] (work_item* wi) {
            wi->complete();
            delete wi;
        });
        _queue_has_room.signal(nr);
        complete();
    });
}

file_desc writeable_eventfd::try_create_eventfd(size_t initial) {
    assert(size_t(int(initial)) == initial);
    return file_desc::eventfd(initial, EFD_CLOEXEC);
}

void writeable_eventfd::signal(size_t count) {
    uint64_t c = count;
    auto r = _fd.write(&c, sizeof(c));
    assert(r == sizeof(c));
}

file_desc readable_eventfd::try_create_eventfd(size_t initial) {
    assert(size_t(int(initial)) == initial);
    return file_desc::eventfd(initial, EFD_CLOEXEC | EFD_NONBLOCK);
}

future<size_t> readable_eventfd::wait() {
    return the_reactor.readable(*_fd._s).then([this] {
        uint64_t count;
        int r = ::read(_fd.get_fd(), &count, sizeof(count));
        assert(r == sizeof(count));
        return make_ready_future<size_t>(count);
    });
}

socket_address make_ipv4_address(ipv4_addr addr) {
    socket_address sa;
    sa.u.in.sin_family = AF_INET;
    sa.u.in.sin_port = htons(addr.port);
    std::memcpy(&sa.u.in.sin_addr, addr.host, 4);
    return sa;
}

reactor the_reactor;
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkTrackingDeviceSourceConfigurator.h"
#include <mitkClaronTrackingDevice.h>
#include <mitkNDITrackingDevice.h>
#include <mitkNavigationTool.h>
#include <mitkTestingMacros.h>
#include <mitkIGTConfig.h>

static void TestInstantiation()
{
  // let's create an object of our class
  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;
  mitk::NavigationToolStorage::Pointer emptyStorage = mitk::NavigationToolStorage::New();
  mitk::TrackingDevice::Pointer dummyDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());
  testInstance = mitk::TrackingDeviceSourceConfigurator::New(emptyStorage,dummyDevice);
  MITK_TEST_CONDITION_REQUIRED(testInstance.IsNotNull(),"Testing instantiation:");
}

static void TestInvalidClaronTrackingDevice()
{
  MITK_TEST_OUTPUT(<<"Testing simple claron tracking device with 2 invalid tools");

  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;

  mitk::NavigationToolStorage::Pointer claronStorage = mitk::NavigationToolStorage::New();

  //create invalid tool 1
  mitk::NavigationTool::Pointer firstTool = mitk::NavigationTool::New();
  firstTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer firstNode = mitk::DataNode::New();
  firstNode->SetName("Tool1");
  firstTool->SetDataNode(firstNode);
  claronStorage->AddTool(firstTool);

  //create invalid tool 2
  mitk::NavigationTool::Pointer secondTool = mitk::NavigationTool::New();
  secondTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer secondNode = mitk::DataNode::New();
  secondNode->SetName("Tool2");
  secondTool->SetDataNode(secondNode);
  claronStorage->AddTool(secondTool);

  mitk::TrackingDevice::Pointer testDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  mitk::TrackingDeviceSource::Pointer testSource = testInstance->CreateTrackingDeviceSource();

  MITK_TEST_CONDITION_REQUIRED(testSource.IsNull(),"..testing return value");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetErrorMessage().size()>1,"..testing if there is an error message");

  MITK_TEST_OUTPUT(<<"Testing simple claron tracking device with another 2 invalid tools");

  secondTool->SetTrackingDeviceType(mitk::NDIAurora);
  claronStorage = mitk::NavigationToolStorage::New();
  claronStorage->AddTool(secondTool);

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  MITK_TEST_CONDITION_REQUIRED(!testInstance->IsCreateTrackingDeviceSourcePossible(),"..testing if factory class detects the invalid data");

  testSource = testInstance->CreateTrackingDeviceSource();

  MITK_TEST_CONDITION_REQUIRED(testSource.IsNull(),"..testing return value");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetErrorMessage().size()>1,"..testing if there is an error message");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetUpdatedNavigationToolStorage()->GetToolCount()==1,"..testing if navigation tool storage is still there");

  MITK_TEST_OUTPUT(<<"Testing other invalid test cases");
  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,NULL);
  MITK_TEST_CONDITION_REQUIRED(!testInstance->IsCreateTrackingDeviceSourcePossible(),"..(1) testing if factory class detects the invalid data");
  testInstance = mitk::TrackingDeviceSourceConfigurator::New(NULL,testDevice);
  MITK_TEST_CONDITION_REQUIRED(!testInstance->IsCreateTrackingDeviceSourcePossible(),"..(2) testing if factory class detects the invalid data");
}

static void TestValidClaronTrackingDevice()
{
  MITK_TEST_OUTPUT(<<"Testing simple claron tracking device with 2 valid tools");

  std::string toolFileName(MITK_IGT_DATA_DIR);
  toolFileName.append("/ClaronTool");

  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;
  mitk::NavigationToolStorage::Pointer claronStorage = mitk::NavigationToolStorage::New();

  //create valid tool 1
  mitk::NavigationTool::Pointer firstTool = mitk::NavigationTool::New();
  firstTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer firstNode = mitk::DataNode::New();
  firstNode->SetName("Tool1");
  firstTool->SetDataNode(firstNode);
  firstTool->SetCalibrationFile(toolFileName);
  firstTool->SetIdentifier("Tool#1");
  claronStorage->AddTool(firstTool);

  //create valid tool 2
  mitk::NavigationTool::Pointer secondTool = mitk::NavigationTool::New();
  secondTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer secondNode = mitk::DataNode::New();
  secondNode->SetName("Tool2");
  secondTool->SetDataNode(secondNode);
  secondTool->SetCalibrationFile(toolFileName);
  secondTool->SetIdentifier("Tool#2");
  claronStorage->AddTool(secondTool);

  mitk::TrackingDevice::Pointer testDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  mitk::TrackingDeviceSource::Pointer testSource = testInstance->CreateTrackingDeviceSource();

  MITK_TEST_CONDITION_REQUIRED(testSource->GetNumberOfOutputs()==2,"testing number of outputs");
  MITK_TEST_CONDITION_REQUIRED(testSource->GetTrackingDevice()->GetToolCount()==2,"testing tracking device");
}

/*
static void TestNDIAuroraTrackingDevice()
{

}
*/

/*
static void TestNDIPolarisTrackingDevice()
{
  MITK_TEST_OUTPUT(<<"Testing simple NDI Polaris tracking device with 1 valid tool");

  std::string toolFileName(MITK_IGT_DATA_DIR);
  toolFileName.append("/SROMFile.rom");

  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;

  mitk::NavigationToolStorage::Pointer polarisStorage = mitk::NavigationToolStorage::New();

  //create valid tool 1
  mitk::NavigationTool::Pointer firstTool = mitk::NavigationTool::New();
  firstTool->SetTrackingDeviceType(mitk::NDIPolaris);
  mitk::DataNode::Pointer firstNode = mitk::DataNode::New();
  firstNode->SetName("Tool1");
  firstTool->SetDataNode(firstNode);
  firstTool->SetCalibrationFile(toolFileName);
  firstTool->SetIdentifier("Tool#1");
  polarisStorage->AddTool(firstTool);

  mitk::NDITrackingDevice::Pointer ndiDevice = mitk::NDITrackingDevice::New();
  ndiDevice->SetType(mitk::NDIPolaris);
  mitk::TrackingDevice::Pointer testDevice = dynamic_cast<mitk::TrackingDevice*>(ndiDevice.GetPointer());

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(polarisStorage,testDevice);

  mitk::TrackingDeviceSource::Pointer testSource = testInstance->CreateTrackingDeviceSource();

  MITK_TEST_CONDITION_REQUIRED(testSource->GetNumberOfOutputs()==1,"..testing number of outputs");
  MITK_TEST_CONDITION_REQUIRED(testSource->GetTrackingDevice()->GetToolCount()==1,"..testing tracking device");
}
*/

static void TestAdditionalMethods()
{
  MITK_TEST_OUTPUT(<<"Testing additional methods of TrackingDeviceSourceCOnfigurator");
  MITK_TEST_OUTPUT(<<"..using claron tracking device for testing");

  std::string toolFileName(MITK_IGT_DATA_DIR);
  toolFileName.append("/ClaronTool");

  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;

  mitk::NavigationToolStorage::Pointer claronStorage = mitk::NavigationToolStorage::New();

  //create valid tool 1
  mitk::NavigationTool::Pointer firstTool = mitk::NavigationTool::New();
  firstTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer firstNode = mitk::DataNode::New();
  firstNode->SetName("Tool1");
  firstTool->SetDataNode(firstNode);
  firstTool->SetCalibrationFile(toolFileName);
  firstTool->SetIdentifier("Tool#1");
  claronStorage->AddTool(firstTool);

  //create valid tool 2
  mitk::NavigationTool::Pointer secondTool = mitk::NavigationTool::New();
  secondTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer secondNode = mitk::DataNode::New();
  secondNode->SetName("Tool2");
  secondTool->SetDataNode(secondNode);
  secondTool->SetCalibrationFile(toolFileName);
  secondTool->SetIdentifier("Tool#2");
  claronStorage->AddTool(secondTool);

  mitk::TrackingDevice::Pointer testDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  mitk::TrackingDeviceSource::Pointer testSource = testInstance->CreateTrackingDeviceSource();

  //numbers must be the same in case of MicronTracker
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolNumberInToolStorage(0)==0,"..testing method GetToolNumberInToolStorage()");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolIdentifierInToolStorage(0)=="Tool#1","..testing method GetToolIdentifierInToolStorage()");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolNumbersInToolStorage().at(0)==0,"..testing method GetToolNumbersInToolStorage()");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolIdentifiersInToolStorage().at(0)=="Tool#1","..testing method GetToolIdentifiersInToolStorage()");

}

int mitkTrackingDeviceSourceConfiguratorTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("TrackingDeviceConfigurator");

  TestInstantiation();
  TestInvalidClaronTrackingDevice();
  TestValidClaronTrackingDevice();
  TestAdditionalMethods();

  MITK_TEST_END();
}
<commit_msg>Removed two out-commented tests which were not belonging in that file. Created feature request 16919 to re-include these tests in a real hardware test.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkTrackingDeviceSourceConfigurator.h"
#include <mitkClaronTrackingDevice.h>
#include <mitkNDITrackingDevice.h>
#include <mitkNavigationTool.h>
#include <mitkTestingMacros.h>
#include <mitkIGTConfig.h>

static void TestInstantiation()
{
  // let's create an object of our class
  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;
  mitk::NavigationToolStorage::Pointer emptyStorage = mitk::NavigationToolStorage::New();
  mitk::TrackingDevice::Pointer dummyDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());
  testInstance = mitk::TrackingDeviceSourceConfigurator::New(emptyStorage,dummyDevice);
  MITK_TEST_CONDITION_REQUIRED(testInstance.IsNotNull(),"Testing instantiation:");
}

static void TestInvalidClaronTrackingDevice()
{
  MITK_TEST_OUTPUT(<<"Testing simple claron tracking device with 2 invalid tools");

  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;

  mitk::NavigationToolStorage::Pointer claronStorage = mitk::NavigationToolStorage::New();

  //create invalid tool 1
  mitk::NavigationTool::Pointer firstTool = mitk::NavigationTool::New();
  firstTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer firstNode = mitk::DataNode::New();
  firstNode->SetName("Tool1");
  firstTool->SetDataNode(firstNode);
  claronStorage->AddTool(firstTool);

  //create invalid tool 2
  mitk::NavigationTool::Pointer secondTool = mitk::NavigationTool::New();
  secondTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer secondNode = mitk::DataNode::New();
  secondNode->SetName("Tool2");
  secondTool->SetDataNode(secondNode);
  claronStorage->AddTool(secondTool);

  mitk::TrackingDevice::Pointer testDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  mitk::TrackingDeviceSource::Pointer testSource = testInstance->CreateTrackingDeviceSource();

  MITK_TEST_CONDITION_REQUIRED(testSource.IsNull(),"..testing return value");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetErrorMessage().size()>1,"..testing if there is an error message");

  MITK_TEST_OUTPUT(<<"Testing simple claron tracking device with another 2 invalid tools");

  secondTool->SetTrackingDeviceType(mitk::NDIAurora);
  claronStorage = mitk::NavigationToolStorage::New();
  claronStorage->AddTool(secondTool);

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  MITK_TEST_CONDITION_REQUIRED(!testInstance->IsCreateTrackingDeviceSourcePossible(),"..testing if factory class detects the invalid data");

  testSource = testInstance->CreateTrackingDeviceSource();

  MITK_TEST_CONDITION_REQUIRED(testSource.IsNull(),"..testing return value");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetErrorMessage().size()>1,"..testing if there is an error message");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetUpdatedNavigationToolStorage()->GetToolCount()==1,"..testing if navigation tool storage is still there");

  MITK_TEST_OUTPUT(<<"Testing other invalid test cases");
  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,NULL);
  MITK_TEST_CONDITION_REQUIRED(!testInstance->IsCreateTrackingDeviceSourcePossible(),"..(1) testing if factory class detects the invalid data");
  testInstance = mitk::TrackingDeviceSourceConfigurator::New(NULL,testDevice);
  MITK_TEST_CONDITION_REQUIRED(!testInstance->IsCreateTrackingDeviceSourcePossible(),"..(2) testing if factory class detects the invalid data");
}

static void TestValidClaronTrackingDevice()
{
  MITK_TEST_OUTPUT(<<"Testing simple claron tracking device with 2 valid tools");

  std::string toolFileName(MITK_IGT_DATA_DIR);
  toolFileName.append("/ClaronTool");

  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;
  mitk::NavigationToolStorage::Pointer claronStorage = mitk::NavigationToolStorage::New();

  //create valid tool 1
  mitk::NavigationTool::Pointer firstTool = mitk::NavigationTool::New();
  firstTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer firstNode = mitk::DataNode::New();
  firstNode->SetName("Tool1");
  firstTool->SetDataNode(firstNode);
  firstTool->SetCalibrationFile(toolFileName);
  firstTool->SetIdentifier("Tool#1");
  claronStorage->AddTool(firstTool);

  //create valid tool 2
  mitk::NavigationTool::Pointer secondTool = mitk::NavigationTool::New();
  secondTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer secondNode = mitk::DataNode::New();
  secondNode->SetName("Tool2");
  secondTool->SetDataNode(secondNode);
  secondTool->SetCalibrationFile(toolFileName);
  secondTool->SetIdentifier("Tool#2");
  claronStorage->AddTool(secondTool);

  mitk::TrackingDevice::Pointer testDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  mitk::TrackingDeviceSource::Pointer testSource = testInstance->CreateTrackingDeviceSource();

  MITK_TEST_CONDITION_REQUIRED(testSource->GetNumberOfOutputs()==2,"testing number of outputs");
  MITK_TEST_CONDITION_REQUIRED(testSource->GetTrackingDevice()->GetToolCount()==2,"testing tracking device");
}

static void TestAdditionalMethods()
{
  MITK_TEST_OUTPUT(<<"Testing additional methods of TrackingDeviceSourceCOnfigurator");
  MITK_TEST_OUTPUT(<<"..using claron tracking device for testing");

  std::string toolFileName(MITK_IGT_DATA_DIR);
  toolFileName.append("/ClaronTool");

  mitk::TrackingDeviceSourceConfigurator::Pointer testInstance;

  mitk::NavigationToolStorage::Pointer claronStorage = mitk::NavigationToolStorage::New();

  //create valid tool 1
  mitk::NavigationTool::Pointer firstTool = mitk::NavigationTool::New();
  firstTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer firstNode = mitk::DataNode::New();
  firstNode->SetName("Tool1");
  firstTool->SetDataNode(firstNode);
  firstTool->SetCalibrationFile(toolFileName);
  firstTool->SetIdentifier("Tool#1");
  claronStorage->AddTool(firstTool);

  //create valid tool 2
  mitk::NavigationTool::Pointer secondTool = mitk::NavigationTool::New();
  secondTool->SetTrackingDeviceType(mitk::ClaronMicron);
  mitk::DataNode::Pointer secondNode = mitk::DataNode::New();
  secondNode->SetName("Tool2");
  secondTool->SetDataNode(secondNode);
  secondTool->SetCalibrationFile(toolFileName);
  secondTool->SetIdentifier("Tool#2");
  claronStorage->AddTool(secondTool);

  mitk::TrackingDevice::Pointer testDevice = dynamic_cast<mitk::TrackingDevice*>(mitk::ClaronTrackingDevice::New().GetPointer());

  testInstance = mitk::TrackingDeviceSourceConfigurator::New(claronStorage,testDevice);

  mitk::TrackingDeviceSource::Pointer testSource = testInstance->CreateTrackingDeviceSource();

  //numbers must be the same in case of MicronTracker
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolNumberInToolStorage(0)==0,"..testing method GetToolNumberInToolStorage()");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolIdentifierInToolStorage(0)=="Tool#1","..testing method GetToolIdentifierInToolStorage()");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolNumbersInToolStorage().at(0)==0,"..testing method GetToolNumbersInToolStorage()");
  MITK_TEST_CONDITION_REQUIRED(testInstance->GetToolIdentifiersInToolStorage().at(0)=="Tool#1","..testing method GetToolIdentifiersInToolStorage()");

}

int mitkTrackingDeviceSourceConfiguratorTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("TrackingDeviceConfigurator");

  TestInstantiation();
  TestInvalidClaronTrackingDevice();
  TestValidClaronTrackingDevice();
  TestAdditionalMethods();

  MITK_TEST_END();
}
<|endoftext|>