<commit_before>#ifndef __Data_course__
#define __Data_course__

#include "data-general.hpp"
#include "data-major.hpp"
#include "data-department.hpp"

using namespace std;

class Course {
	void copy(const Course& c) {
		id = c.id;
		number = c.number;
		title = c.title;
		description = c.description;
		section = c.section;
		majors = c.majors;
		department = c.department;
		concentrations = c.concentrations;
		conversations = c.conversations;
		professor = c.professor;

		half_semester = c.half_semester;
		pass_fail = c.pass_fail;
		credits = c.credits;
		location = c.location;

		lab = c.lab;
		geneds = c.geneds;

		for (int i = 0; i < 7; ++i){
			days[i] = c.days[i];
			time[i] = c.time[i];
		}
	}
protected:
	string id;
	int number;
	string title;
	string description;
	char section;

	vector<Major> majors;
	vector<Department> department;
	string concentrations;
	string conversations;
	string professor;

	int half_semester;
	bool pass_fail;
	float credits;
	string location;

	bool lab;
	GenEd* geneds;

	bool days[7];
	float time[7];
public:
	Course() {

	}
	Course(const Course& c) {
		copy(c);
	}
	Course(istream &is) {
		if (!is) return;

		string tmpLine;
		getline(is, tmpLine); // do this twice: once to not break the program,
		getline(is, tmpLine); // and once to remove the extra data of course status.

		vector<string> record = split(tmpLine, ',');
		for (vector<string>::iterator i=record.begin(); i != record.end(); ++i) {
			*i = removeAllQuotes(*i);
			*i = removeTrailingSlashes(*i);
		}

		/*
			cout << record.at(0) << ", ";
			cout << record.at(1) << ", ";
			cout << record.at(2) << ", ";
			cout << record.at(3) << ", ";
			cout << record.at(4) << ", ";
			cout << record.at(5) << ", ";
			cout << record.at(6) << ", ";
			cout << record.at(7) << ", ";
			cout << record.at(8) << ", ";
			cout << record.at(9) << ", ";
			cout << record.at(10) << ", ";
			cout << record.at(11) << ", ";
			if (record.size() == 13)
				cout << record.at(12) << endl;
		*/

		// Ignore the first column;
		record.at(0);

		// so, the *first* column (that we care about) has the course id,
		id = record.at(1);
		parseid(id);

		// Second column has the section,
		section = record.at(2)[0];

		// Third holds the lab boolean,
		if (record.at(3).empty()) lab = false;
		else                      lab = true;

		// while Fourth contains the title of the course;
		title = record.at(4);
		cleanTitle();

		// Fifth hands over the length (half semester or not)
		// it's actually an int that tells us how many times the course is offered per semester.
		half_semester = stringToInt(record.at(5));
		if (half_semester != 0 && half_semester != 1 && half_semester != 2)
			half_semester = 0;

		// Sixth tells us the number of credits,
		credits = stringToFloat(record.at(6));

		// Seventh shows us if it can be taken pass/no-pass,
		if (record.at(7) == "Y")
			pass_fail = true;
		else
			pass_fail = false;

		// while Eighth gives us the GEs of the course,
		// GEreqs = record.at(8);

		// and Nine spits out the days and times;
		// Times = record.at(9);

		// Ten holds the location,
		location = record.at(10);
		location = deDoubleString(location);

		// and Eleven knows who teaches.
		if (record.size() == 13) {
			string profLastName = record.at(11);
			string profFirstName = record.at(12);
			profFirstName.erase(0, 1); // remove the extra space from the start of the name
			professor = profFirstName + " " + profLastName;
		}
		else {
			professor = record.at(11);
		}
	}

	void cleanTitle() {
		vector<string> badEndings, badBeginnings;
		badEndings.push_back("Prerequisite");
		badEndings.push_back("Prerequsiite");
		badEndings.push_back("This course has class");
		badEndings.push_back("This course is open to ");
		badEndings.push_back("First-Year Students may register only");
		badEndings.push_back("Open to ");
		badEndings.push_back("Especially for ");
		badEndings.push_back("Registration by permission of instructor only.");
		badEndings.push_back("Permission of instructor required.");
		badEndings.push_back("Not open to first-year students.");
		badEndings.push_back("Film screenings");
		badEndings.push_back("Open only to ");
		badEndings.push_back("This course has been canceled.");
		badEndings.push_back("This course has been cancelled.");
		badEndings.push_back("Open only to seniors");
		badEndings.push_back("Closed during web registration.");
		badEndings.push_back("During course submission process");
		badEndings.push_back("Taught in English.");
		badEndings.push_back("Closed to First-Year Students.");
		badEndings.push_back("Closed to first-year students.");
		badEndings.push_back("New course");
		badEndings.push_back("This course does");
		badEndings.push_back("This course open to seniors only.");
		badEndings.push_back("This lab has been canceled.");
		badEndings.push_back("Permission of the instructor");
		badEndings.push_back("Registration restricted");
		badBeginnings.push_back("Top: ");
		badBeginnings.push_back("Sem: ");
		badBeginnings.push_back("Res: ");

		badEndings.push_back("Students in " + department[0].getFullName() + " " + tostring(number));
		badEndings.push_back("Students in " + department[0].getName() + " " + tostring(number));
		// cout << badEndings.back() << endl;

		for (vector<string>::iterator i=badEndings.begin(); i != badEndings.end(); ++i)
			title = removeTrailingText(title, *i);
		for (vector<string>::iterator i=badBeginnings.begin(); i != badBeginnings.end(); ++i)
			title = removeStartingText(title, *i);
	}

	void parseid(string str) {
		// Get the number of the course, aka the last three slots.
		stringstream(str.substr(str.size() - 3)) >> number;

		// Check if it's one of those dastardly "split courses".
		string dept = str.substr(0,str.size()-3);

		if (str.find('/') != string::npos) {
			department.push_back(Department(dept.substr(0,2)));
			department.push_back(Department(dept.substr(2,2)));
		}
		else {
			department.push_back(Department(dept));
		}
	}

	void updateID() {
		string dept;
		for (std::vector<Department>::iterator i = department.begin(); i != department.end(); ++i) {
			dept += i->getName();
			if (department.size() > 1)
				dept += "/";
		}
		id = dept + " " + tostring(number) + section;
	}
	string getID() {
		return id;
	}

	ostream& getData(ostream &os) {
		updateID();
		os << id << " - ";
		os << title << " | ";
		if (professor.length() > 0 && professor != " ")
			os << professor;
		return os;
	}
	void display();

	void showAll() {
		cout << id << section << endl;
		cout << "Title: " << title << endl;
		cout << "Professor: " << professor << endl;
		cout << "Lab? " << lab << endl;
		cout << "Half-semester? " << half_semester << endl;
		cout << "Credits: " << credits << endl;
		cout << "Pass/Fail? " << pass_fail << endl;
		cout << "Location: " << location << endl;
		cout << endl;
	}
};

ostream &operator<<(ostream &os, Course &item) { return item.getData(os); }
void Course::display() { if(this==0) cout << *this << endl; }

#endif

<commit_msg>Add the beginnings of a lookupCourse function<commit_after>#ifndef __Data_course__
#define __Data_course__

#include "data-general.hpp"
#include "data-major.hpp"
#include "data-department.hpp"

using namespace std;

class Course {
private:
	void init(string dept, int num) {
		string identifier = dept + tostring(num);
		parseID(identifier);
		lookupCourse(id);
	}
	void copy(const Course& c) {
		id = c.id;
		number = c.number;
		title = c.title;
		description = c.description;
		section = c.section;
		majors = c.majors;
		department = c.department;
		concentrations = c.concentrations;
		conversations = c.conversations;
		professor = c.professor;

		half_semester = c.half_semester;
		pass_fail = c.pass_fail;
		credits = c.credits;
		location = c.location;

		lab = c.lab;
		geneds = c.geneds;

		for (int i = 0; i < 7; ++i){
			days[i] = c.days[i];
			time[i] = c.time[i];
		}
	}
protected:
	string id;
	int number;
	string title;
	string description;
	char section;

	vector<Major> majors;
	vector<Department> department;
	string concentrations;
	string conversations;
	string professor;

	int half_semester;
	bool pass_fail;
	float credits;
	string location;

	bool lab;
	GenEd* geneds;

	bool days[7];
	float time[7];
public:
	Course() {

	}
	Course(const Course& c) {
		copy(c);
	}
	Course(istream &is) {
		if (!is) return;

		string tmpLine;
		getline(is, tmpLine); // do this twice: once to not break the program,
		getline(is, tmpLine); // and once to remove the extra data of course status.

		vector<string> record = split(tmpLine, ',');
		for (vector<string>::iterator i=record.begin(); i != record.end(); ++i) {
			*i = removeAllQuotes(*i);
			*i = removeTrailingSlashes(*i);
		}

		/*
			cout << record.at(0) << ", ";
			cout << record.at(1) << ", ";
			cout << record.at(2) << ", ";
			cout << record.at(3) << ", ";
			cout << record.at(4) << ", ";
			cout << record.at(5) << ", ";
			cout << record.at(6) << ", ";
			cout << record.at(7) << ", ";
			cout << record.at(8) << ", ";
			cout << record.at(9) << ", ";
			cout << record.at(10) << ", ";
			cout << record.at(11) << ", ";
			if (record.size() == 13)
				cout << record.at(12) << endl;
		*/

		// Ignore the first column;
		record.at(0);

		// so, the *first* column (that we care about) has the course id,
		id = record.at(1);
		parseid(id);

		// Second column has the section,
		section = record.at(2)[0];

		// Third holds the lab boolean,
		if (record.at(3).empty()) lab = false;
		else                      lab = true;

		// while Fourth contains the title of the course;
		title = record.at(4);
		cleanTitle();

		// Fifth hands over the length (half semester or not)
		// it's actually an int that tells us how many times the course is offered per semester.
		half_semester = stringToInt(record.at(5));
		if (half_semester != 0 && half_semester != 1 && half_semester != 2)
			half_semester = 0;

		// Sixth tells us the number of credits,
		credits = stringToFloat(record.at(6));

		// Seventh shows us if it can be taken pass/no-pass,
		if (record.at(7) == "Y")
			pass_fail = true;
		else
			pass_fail = false;

		// while Eighth gives us the GEs of the course,
		// GEreqs = record.at(8);

		// and Nine spits out the days and times;
		// Times = record.at(9);

		// Ten holds the location,
		location = record.at(10);
		location = deDoubleString(location);

		// and Eleven knows who teaches.
		if (record.size() == 13) {
			string profLastName = record.at(11);
			string profFirstName = record.at(12);
			profFirstName.erase(0, 1); // remove the extra space from the start of the name
			professor = profFirstName + " " + profLastName;
		}
		else {
			professor = record.at(11);
		}
	}

	Course* lookupCourse(string identifier)  {
		return this;
	}

	void cleanTitle() {
		vector<string> badEndings, badBeginnings;
		badEndings.push_back("Prerequisite");
		badEndings.push_back("Prerequsiite");
		badEndings.push_back("This course has class");
		badEndings.push_back("This course is open to ");
		badEndings.push_back("First-Year Students may register only");
		badEndings.push_back("Open to ");
		badEndings.push_back("Especially for ");
		badEndings.push_back("Registration by permission of instructor only.");
		badEndings.push_back("Permission of instructor required.");
		badEndings.push_back("Not open to first-year students.");
		badEndings.push_back("Film screenings");
		badEndings.push_back("Open only to ");
		badEndings.push_back("This course has been canceled.");
		badEndings.push_back("This course has been cancelled.");
		badEndings.push_back("Open only to seniors");
		badEndings.push_back("Closed during web registration.");
		badEndings.push_back("During course submission process");
		badEndings.push_back("Taught in English.");
		badEndings.push_back("Closed to First-Year Students.");
		badEndings.push_back("Closed to first-year students.");
		badEndings.push_back("New course");
		badEndings.push_back("This course does");
		badEndings.push_back("This course open to seniors only.");
		badEndings.push_back("This lab has been canceled.");
		badEndings.push_back("Permission of the instructor");
		badEndings.push_back("Registration restricted");
		badBeginnings.push_back("Top: ");
		badBeginnings.push_back("Sem: ");
		badBeginnings.push_back("Res: ");

		badEndings.push_back("Students in " + department[0].getFullName() + " " + tostring(number));
		badEndings.push_back("Students in " + department[0].getName() + " " + tostring(number));
		// cout << badEndings.back() << endl;

		for (vector<string>::iterator i=badEndings.begin(); i != badEndings.end(); ++i)
			title = removeTrailingText(title, *i);
		for (vector<string>::iterator i=badBeginnings.begin(); i != badBeginnings.end(); ++i)
			title = removeStartingText(title, *i);
	}

	void parseid(string str) {
		// Get the number of the course, aka the last three slots.
		stringstream(str.substr(str.size() - 3)) >> number;

		// Check if it's one of those dastardly "split courses".
		string dept = str.substr(0,str.size()-3);

		if (str.find('/') != string::npos) {
			department.push_back(Department(dept.substr(0,2)));
			department.push_back(Department(dept.substr(2,2)));
		}
		else {
			department.push_back(Department(dept));
		}
	}

	void updateID() {
		string dept;
		for (std::vector<Department>::iterator i = department.begin(); i != department.end(); ++i) {
			dept += i->getName();
			if (department.size() > 1)
				dept += "/";
		}
		id = dept + " " + tostring(number) + section;
	}
	string getID() {
		return id;
	}

	ostream& getData(ostream &os) {
		updateID();
		os << id << " - ";
		os << title << " | ";
		if (professor.length() > 0 && professor != " ")
			os << professor;
		return os;
	}
	void display();

	void showAll() {
		cout << id << section << endl;
		cout << "Title: " << title << endl;
		cout << "Professor: " << professor << endl;
		cout << "Lab? " << lab << endl;
		cout << "Half-semester? " << half_semester << endl;
		cout << "Credits: " << credits << endl;
		cout << "Pass/Fail? " << pass_fail << endl;
		cout << "Location: " << location << endl;
		cout << endl;
	}
};

ostream &operator<<(ostream &os, Course &item) { return item.getData(os); }
void Course::display() { if(this==0) cout << *this << endl; }

#endif

<|endoftext|>


<commit_before><commit_msg>Fix incorrect gtk cursors. se-resize and sw-resize are reversed.<commit_after><|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>

    Permission to use, copy, modify, and distribute this software
    and its documentation for any purpose and without fee is hereby
    granted, provided that the above copyright notice appear in all
    copies and that both that the copyright notice and this
    permission notice and warranty disclaimer appear in supporting
    documentation, and that the name of the author not be used in
    advertising or publicity pertaining to distribution of the
    software without specific, written prior permission.

    The author disclaim all warranties with regard to this
    software, including all implied warranties of merchantability
    and fitness.  In no event shall the author be liable for any
    special, indirect or consequential damages or any damages
    whatsoever resulting from loss of use, data or profits, whether
    in an action of contract, negligence or other tortious action,
    arising out of or in connection with the use or performance of
    this software.

*/

#include "tutorial3.h"

#include <Phonon/MediaObject>
#include <Phonon/AudioPath>
#include <Phonon/AudioOutput>
#include <Phonon/Global>

#include <QtGui/QApplication>

#include <kcomponentdata.h>
#include <QtGui/QHBoxLayout>
#include <QtGui/QFrame>
#include <Phonon/VolumeSlider>
#include <QtGui/QVBoxLayout>
#include <Phonon/SeekSlider>

PlayerWidget::PlayerWidget()
    : m_media(0)
{
}

void PlayerWidget::delayedInit()
{
    if (!m_media) {
        m_media = new Phonon::MediaObject(this);
        Phonon::AudioPath *audioPath = new Phonon::AudioPath(this);
        Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
        m_media->addAudioPath(audioPath);
        audioPath->addOutput(audioOutput);

        QHBoxLayout *topLayout = new QHBoxLayout(this);
        QVBoxLayout *leftLayout = new QVBoxLayout(this);
        topLayout->addLayout(leftLayout);
        Phonon::VolumeSlider *vs = new Phonon::VolumeSlider(audioOutput, this);
        vs->setOrientation(Qt::Vertical);
        topLayout->addWidget(vs);
        leftLayout->addWidget(new Phonon::SeekSlider(m_media, this));
    }
}

void PlayerWidget::play(const QString &filename)
{
    delayedInit();
    m_media->setCurrentSource(filename);
    m_media->play();
}

MainWindow::MainWindow()
    : m_fileView(this)
{
    setCentralWidget(&m_fileView);
    m_fileView.setModel(&m_model);
    m_fileView.setPreviewWidget(&m_player);

    connect(&m_fileView, SIGNAL(updatePreviewWidget(const QModelIndex &)), SLOT(providePlayer(const QModelIndex &)));
}

void MainWindow::providePlayer(const QModelIndex &index)
{
    m_player.play(m_model.filePath(index));
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    KComponentData("phonon-tutorial1");
    MainWindow mw;
    mw.show();
    return app.exec();
}

#include "tutorial3.moc"
<commit_msg>nicer layout (code and GUI)<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2007 Matthias Kretz <kretz@kde.org>

    Permission to use, copy, modify, and distribute this software
    and its documentation for any purpose and without fee is hereby
    granted, provided that the above copyright notice appear in all
    copies and that both that the copyright notice and this
    permission notice and warranty disclaimer appear in supporting
    documentation, and that the name of the author not be used in
    advertising or publicity pertaining to distribution of the
    software without specific, written prior permission.

    The author disclaim all warranties with regard to this
    software, including all implied warranties of merchantability
    and fitness.  In no event shall the author be liable for any
    special, indirect or consequential damages or any damages
    whatsoever resulting from loss of use, data or profits, whether
    in an action of contract, negligence or other tortious action,
    arising out of or in connection with the use or performance of
    this software.

*/

#include "tutorial3.h"

#include <Phonon/MediaObject>
#include <Phonon/AudioPath>
#include <Phonon/AudioOutput>
#include <Phonon/Global>

#include <QtGui/QApplication>

#include <kcomponentdata.h>
#include <QtGui/QHBoxLayout>
#include <QtGui/QFrame>
#include <Phonon/VolumeSlider>
#include <QtGui/QVBoxLayout>
#include <Phonon/SeekSlider>

PlayerWidget::PlayerWidget()
    : m_media(0)
{
}

void PlayerWidget::delayedInit()
{
    if (!m_media) {
        m_media = new Phonon::MediaObject(this);
        Phonon::AudioPath *audioPath = new Phonon::AudioPath(this);
        Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
        m_media->addAudioPath(audioPath);
        audioPath->addOutput(audioOutput);

        QHBoxLayout *topLayout = new QHBoxLayout(this);
        QVBoxLayout *leftLayout = new QVBoxLayout(this);
        Phonon::VolumeSlider *vs = new Phonon::VolumeSlider(audioOutput, this);
        vs->setOrientation(Qt::Vertical);

        topLayout->addLayout(leftLayout);
        topLayout->addWidget(vs);

        leftLayout->addWidget(new Phonon::SeekSlider(m_media, this));
        leftLayout->addStretch();
    }
}

void PlayerWidget::play(const QString &filename)
{
    delayedInit();
    m_media->setCurrentSource(filename);
    m_media->play();
}

MainWindow::MainWindow()
    : m_fileView(this)
{
    setCentralWidget(&m_fileView);
    m_fileView.setModel(&m_model);
    m_fileView.setPreviewWidget(&m_player);

    connect(&m_fileView, SIGNAL(updatePreviewWidget(const QModelIndex &)), SLOT(providePlayer(const QModelIndex &)));
}

void MainWindow::providePlayer(const QModelIndex &index)
{
    m_player.play(m_model.filePath(index));
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    KComponentData("phonon-tutorial1");
    MainWindow mw;
    mw.show();
    return app.exec();
}

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


<commit_before>#pragma once

#include <set>
#include <vector>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

#include <stdio.h>

#include <sys/mman.h>

#include "channel9.hpp"
#include "memcheck.h"
#include "bittwiddle.hpp"
#include "forwardtable.hpp"

namespace Channel9
{
	class GC::Markcompact : protected GC
	{
		struct Block;
		struct Chunk;

	public:
		typedef unsigned char uchar;

		struct Data
		{
			uint16_t m_type;
			uint8_t  m_block_size; //so (this & ~((1<<blocksize)-1)) gives the pointer to the block header
			bool     m_mark;
			uint32_t m_count;   //number of bytes of memory in this allocation
			uchar    m_data[0]; //the actual data, 8 byte aligned

			Data * next() const { return (Data*)((uchar*)(this + 1) + m_count); }
			Block * block() const { return (Block *)((uintptr_t)this & ~((1 << m_block_size)-1)); }
			static Data *ptr_for(const void *ptr) { return (Data*)ptr - 1; }
		};

	private:

		static const double   GC_GROWTH_LIMIT = 2.0;
		static const uint64_t CHUNK_SIZE = 21;
		static const uint64_t BLOCK_SIZE = 12;

		struct Block
		{
			uint32_t m_capacity;   //in bytes, total size not including this header
			uint32_t m_next_alloc; //in bytes, offset to the next allocation
			uint32_t m_in_use;     //in bytes, how much is actually used, is m_next - unmarked Data pieces
			uint8_t  m_skipped;    //how many times a block has skipped compaction
			uint8_t  m_block_size; //used to initialize Data::m_block_size
			bool     m_mark;       //has this anything block been reached yet?
			uchar    m_data[0];    //actual memory

			void init(uint8_t block_size)
			{
				m_capacity = 1 << block_size;
				m_next_alloc = 0;
				m_in_use = 0;
				m_skipped = 0;
				m_block_size = block_size;
				m_mark = false;
				DO_DEBUG VALGRIND_CREATE_MEMPOOL(m_data, 0, false);
			}

			Data * alloc(size_t size)
			{
				if(m_next_alloc + size <= m_capacity)
				{
					Data * ret = (Data*)(m_data + m_next_alloc);
					m_next_alloc += size;
					DO_DEBUG VALGRIND_MEMPOOL_ALLOC(m_data, ret, size);
					return ret;
				}
				return NULL;
			}
			Data * begin() const { return (Data *) m_data; }
			Data * end()   const { return (Data *) (m_data + m_next_alloc); }
			Block * next() const { return (Block*)((uchar*)(this + 1) + m_capacity); }

			void deadbeef()
			{
				uint32_t * i = (uint32_t *) m_data,
				         * e = (uint32_t *) (m_data + m_capacity);
				for(; i < e; ++i)
					*i = 0xDEADBEEF;
			}
		};

		struct Chunk
		{
			uint32_t m_capacity; //in bytes
			uchar *  m_data;     //pointer to actual memory

			void init(uint32_t c, Block * b)
			{
				m_capacity = c;
				m_data = (uchar *) b;
			}

			Block * begin(){ return (Block *) m_data; }
			Block * end()  { return (Block *) (m_data + m_capacity); }
		};

		std::vector<Chunk>   m_chunks;       // list of all chunks
		std::vector<Block *> m_empty_blocks; // list of empty blocks
		Block * m_cur_block;

		ForwardTable forward;

		enum GCPhase { Running, Marking, Compacting, Updating };

		GCPhase  m_gc_phase;
		uint64_t m_alloced;  //how much memory are in all pools (active or not) combined
		uint64_t m_used;     //how much memory is used by data blocks, not including the header
		uint64_t m_data_blocks; //how many data allocations are in the current pool
		uint64_t m_next_gc;  //garbage collect when m_next_gc < m_used

		std::set<GCRoot*> m_roots;

		void collect();

		uchar *next(size_t size, uint16_t type)
		{
			assert(size < 8000);

			if(m_gc_phase == Running)
				DO_TRACEGC printf("Alloc %u type %x ... ", (unsigned)size, type);

			size += (8 - size % 8) % 8; //8 byte align

			while(1){
				Data * data = m_cur_block->alloc(size + sizeof(Data));

				if(data){
					m_used += size;
					m_data_blocks++;

					data->m_type = type;
					data->m_block_size = m_cur_block->m_block_size;
					data->m_mark = false;
					data->m_count = size;

					if(m_gc_phase == Running)
						DO_TRACEGC printf("alloc return %p\n", data->m_data);

					return data->m_data;
				}

				if(m_empty_blocks.empty())
					alloc_chunk();

				m_cur_block = m_empty_blocks.back();
				m_empty_blocks.pop_back();
			}
			return NULL;
		}

		void alloc_chunk(unsigned int size = 0){
			if(size)
				size = ceil_power2(size);
			else
				size = 1<<CHUNK_SIZE;

			Block * b = (Block *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

			printf("alloc chunk %p, %i zeros\n", b, count_bottom_zeros4((uintptr_t)b));

			assert(count_bottom_zeros4((uintptr_t)b) >= BLOCK_SIZE); //make sure blocks will be properly aligned

			m_alloced += size;

			Chunk c;
			c.init(size, b);

			m_chunks.push_back(c);

			for(Block * i = b; i != c.end(); i++){
				i->init(BLOCK_SIZE);
				m_empty_blocks.push_back(i);
			}
		}

	public:
		Markcompact()
		 : m_cur_block(NULL), m_gc_phase(Running), m_alloced(0), m_used(0), m_data_blocks(0), m_next_gc(0.9*(1<<CHUNK_SIZE))
		{

			alloc_chunk();

			m_cur_block = m_empty_blocks.back();
			m_empty_blocks.pop_back();

		}

		template <typename tObj>
		tObj *alloc(size_t extra, uint16_t type)
		{
			return reinterpret_cast<tObj*>(next(sizeof(tObj) + extra, type));
		}

		template <typename tObj>
		bool validate(tObj * from)
		{
			if(m_gc_phase != Running)
				return true;
			else
				return (Data::ptr_for(from)->m_mark == false);
		}

		template <typename tObj>
		bool mark(tObj ** from)
		{
			Data * d = Data::ptr_for(*from);
			switch(m_gc_phase)
			{
			case Running:
				assert(m_gc_phase != Running); //shouldn't be calling mark when not in gc mode
			case Marking: {
				if(d->m_mark)
					return false;

				d->m_mark = true;

				m_data_blocks++;
				m_used += d->m_count;

				Block * b = d->block();
				if(!b->m_mark)
				{
					b->m_mark = true;
					b->m_in_use = 0;
				}
				b->m_in_use += d->m_count;

				gc_scan(*from);

				return false;
			}
			case Updating: {
				tObj * to = (tObj*)forward.get(d);

				bool ret = (to == *from);
				if(ret)
				{
					*from = to;
					d = Data::ptr_for(to);
				}

				if(d->m_mark)
				{
					d->m_mark = false;
					gc_scan(*from);
				}

				return ret;
			}
			}
		}

		// make sure this object is ready to be read from
		template <typename tObj>
		void read_barrier(tObj * obj) { }

		// tell the GC that obj will contain a reference to the object pointed to by ptr
		template <typename tObj, typename tPtr>
		void write_barrier(tObj * obj, tPtr * ptr) { }

		// now is a valid time to stop the world
		void safe_point() {
			if(m_next_gc < m_used)
				collect();
		}

		void register_root(GCRoot *root);
		void unregister_root(GCRoot *root);
	};
}

<commit_msg>Fix warning and non-portable flag in markcompact collector.<commit_after>#pragma once

#include <set>
#include <vector>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

#include <stdio.h>

#include <sys/mman.h>

#include "channel9.hpp"
#include "memcheck.h"
#include "bittwiddle.hpp"
#include "forwardtable.hpp"

namespace Channel9
{
	class GC::Markcompact : protected GC
	{
		struct Block;
		struct Chunk;

	public:
		typedef unsigned char uchar;

		struct Data
		{
			uint16_t m_type;
			uint8_t  m_block_size; //so (this & ~((1<<blocksize)-1)) gives the pointer to the block header
			bool     m_mark;
			uint32_t m_count;   //number of bytes of memory in this allocation
			uchar    m_data[0]; //the actual data, 8 byte aligned

			Data * next() const { return (Data*)((uchar*)(this + 1) + m_count); }
			Block * block() const { return (Block *)((uintptr_t)this & ~((1 << m_block_size)-1)); }
			static Data *ptr_for(const void *ptr) { return (Data*)ptr - 1; }
		};

	private:

		static const double   GC_GROWTH_LIMIT = 2.0;
		static const uint64_t CHUNK_SIZE = 21;
		static const uint64_t BLOCK_SIZE = 12;

		struct Block
		{
			uint32_t m_capacity;   //in bytes, total size not including this header
			uint32_t m_next_alloc; //in bytes, offset to the next allocation
			uint32_t m_in_use;     //in bytes, how much is actually used, is m_next - unmarked Data pieces
			uint8_t  m_skipped;    //how many times a block has skipped compaction
			uint8_t  m_block_size; //used to initialize Data::m_block_size
			bool     m_mark;       //has this anything block been reached yet?
			uchar    m_data[0];    //actual memory

			void init(uint8_t block_size)
			{
				m_capacity = 1 << block_size;
				m_next_alloc = 0;
				m_in_use = 0;
				m_skipped = 0;
				m_block_size = block_size;
				m_mark = false;
				DO_DEBUG VALGRIND_CREATE_MEMPOOL(m_data, 0, false);
			}

			Data * alloc(size_t size)
			{
				if(m_next_alloc + size <= m_capacity)
				{
					Data * ret = (Data*)(m_data + m_next_alloc);
					m_next_alloc += size;
					DO_DEBUG VALGRIND_MEMPOOL_ALLOC(m_data, ret, size);
					return ret;
				}
				return NULL;
			}
			Data * begin() const { return (Data *) m_data; }
			Data * end()   const { return (Data *) (m_data + m_next_alloc); }
			Block * next() const { return (Block*)((uchar*)(this + 1) + m_capacity); }

			void deadbeef()
			{
				uint32_t * i = (uint32_t *) m_data,
				         * e = (uint32_t *) (m_data + m_capacity);
				for(; i < e; ++i)
					*i = 0xDEADBEEF;
			}
		};

		struct Chunk
		{
			uint32_t m_capacity; //in bytes
			uchar *  m_data;     //pointer to actual memory

			void init(uint32_t c, Block * b)
			{
				m_capacity = c;
				m_data = (uchar *) b;
			}

			Block * begin(){ return (Block *) m_data; }
			Block * end()  { return (Block *) (m_data + m_capacity); }
		};

		std::vector<Chunk>   m_chunks;       // list of all chunks
		std::vector<Block *> m_empty_blocks; // list of empty blocks
		Block * m_cur_block;

		ForwardTable forward;

		enum GCPhase { Running, Marking, Compacting, Updating };

		GCPhase  m_gc_phase;
		uint64_t m_alloced;  //how much memory are in all pools (active or not) combined
		uint64_t m_used;     //how much memory is used by data blocks, not including the header
		uint64_t m_data_blocks; //how many data allocations are in the current pool
		uint64_t m_next_gc;  //garbage collect when m_next_gc < m_used

		std::set<GCRoot*> m_roots;

		void collect();

		uchar *next(size_t size, uint16_t type)
		{
			assert(size < 8000);

			if(m_gc_phase == Running)
				DO_TRACEGC printf("Alloc %u type %x ... ", (unsigned)size, type);

			size += (8 - size % 8) % 8; //8 byte align

			while(1){
				Data * data = m_cur_block->alloc(size + sizeof(Data));

				if(data){
					m_used += size;
					m_data_blocks++;

					data->m_type = type;
					data->m_block_size = m_cur_block->m_block_size;
					data->m_mark = false;
					data->m_count = size;

					if(m_gc_phase == Running)
						DO_TRACEGC printf("alloc return %p\n", data->m_data);

					return data->m_data;
				}

				if(m_empty_blocks.empty())
					alloc_chunk();

				m_cur_block = m_empty_blocks.back();
				m_empty_blocks.pop_back();
			}
			return NULL;
		}

		void alloc_chunk(unsigned int size = 0){
			if(size)
				size = ceil_power2(size);
			else
				size = 1<<CHUNK_SIZE;

			Block * b = (Block *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);

			printf("alloc chunk %p, %i zeros\n", b, (int)count_bottom_zeros4((uintptr_t)b));

			assert(count_bottom_zeros4((uintptr_t)b) >= BLOCK_SIZE); //make sure blocks will be properly aligned

			m_alloced += size;

			Chunk c;
			c.init(size, b);

			m_chunks.push_back(c);

			for(Block * i = b; i != c.end(); i++){
				i->init(BLOCK_SIZE);
				m_empty_blocks.push_back(i);
			}
		}

	public:
		Markcompact()
		 : m_cur_block(NULL), m_gc_phase(Running), m_alloced(0), m_used(0), m_data_blocks(0), m_next_gc(0.9*(1<<CHUNK_SIZE))
		{

			alloc_chunk();

			m_cur_block = m_empty_blocks.back();
			m_empty_blocks.pop_back();

		}

		template <typename tObj>
		tObj *alloc(size_t extra, uint16_t type)
		{
			return reinterpret_cast<tObj*>(next(sizeof(tObj) + extra, type));
		}

		template <typename tObj>
		bool validate(tObj * from)
		{
			if(m_gc_phase != Running)
				return true;
			else
				return (Data::ptr_for(from)->m_mark == false);
		}

		template <typename tObj>
		bool mark(tObj ** from)
		{
			Data * d = Data::ptr_for(*from);
			switch(m_gc_phase)
			{
			case Running:
				assert(m_gc_phase != Running); //shouldn't be calling mark when not in gc mode
			case Marking: {
				if(d->m_mark)
					return false;

				d->m_mark = true;

				m_data_blocks++;
				m_used += d->m_count;

				Block * b = d->block();
				if(!b->m_mark)
				{
					b->m_mark = true;
					b->m_in_use = 0;
				}
				b->m_in_use += d->m_count;

				gc_scan(*from);

				return false;
			}
			case Updating: {
				tObj * to = (tObj*)forward.get(d);

				bool ret = (to == *from);
				if(ret)
				{
					*from = to;
					d = Data::ptr_for(to);
				}

				if(d->m_mark)
				{
					d->m_mark = false;
					gc_scan(*from);
				}

				return ret;
			}
			}
		}

		// make sure this object is ready to be read from
		template <typename tObj>
		void read_barrier(tObj * obj) { }

		// tell the GC that obj will contain a reference to the object pointed to by ptr
		template <typename tObj, typename tPtr>
		void write_barrier(tObj * obj, tPtr * ptr) { }

		// now is a valid time to stop the world
		void safe_point() {
			if(m_next_gc < m_used)
				collect();
		}

		void register_root(GCRoot *root);
		void unregister_root(GCRoot *root);
	};
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      file.cpp
// Purpose:   Implementation of class wxExFile
// Author:    Anton van Wezenbeek
// Copyright: (c) 2012 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/file.h>

wxExFile::wxExFile(bool open_file)
  : m_OpenFile(open_file)
  , m_HasRead(false)
  , m_FileName()
  , m_Stat()
{
}

wxExFile::wxExFile(
  const wxFileName& filename,
  wxFile::OpenMode mode,
  bool open_file)
  : wxFile(filename.GetFullPath(), mode)
  , m_OpenFile(open_file)
  , m_HasRead(false)
  , m_Stat(filename.GetFullPath())
{
  m_FileName.Assign(filename);
  MakeAbsolute();
}

bool wxExFile::CheckSync()
{
  // Might be used without wxApp.
  wxConfigBase* config = wxConfigBase::Get(false);

  if ( IsOpened() ||
      !m_FileName.m_Stat.IsOk() ||
      (config != NULL && !config->ReadBool("AllowSync", true)))
  {
    return false;
  }

  if (m_FileName.m_Stat.Sync())
  {
    bool sync_needed = false;

    if (m_FileName.m_Stat.st_mtime != m_Stat.st_mtime)
    {
      // Do not check return value,
      // we sync anyhow, to force nex time no sync.
      Get(true);

      sync_needed = true;
    }

    if (m_FileName.m_Stat.IsReadOnly() != m_Stat.IsReadOnly())
    {
      sync_needed = true;
    }

    if (sync_needed)
    {
          // Update the stat member, so next time no sync.
      if (!m_Stat.Sync())
      {
        wxLogError("Could not sync: " + m_FileName.GetFullPath());
      }

      return true;
    }
  }

  return false;
}

bool wxExFile::FileLoad(const wxExFileName& filename)
{
  Assign(filename);
  return m_FileName.FileExists() && MakeAbsolute() && Get(false);
}

void wxExFile::FileNew(const wxExFileName& filename)
{
  // Do not check return value, as file will not (yet)
  // exist.
  Assign(filename);
  DoFileNew();
}

bool wxExFile::FileSave(const wxExFileName& filename)
{
  bool save_as = false;

  if (filename.IsOk())
  {
    Assign(filename);
    MakeAbsolute();
    save_as = true;
  }

  if (m_OpenFile && !Open(m_FileName.GetFullPath(), wxFile::write))
  {
    return false;
  }

  DoFileSave(save_as);

  if (IsOpened())
  {
    Close();
  }

  ResetContentsChanged();

  m_FileName.m_Stat.Sync();
  m_Stat.Sync();

  return true;
}

bool wxExFile::Get(bool synced)
{
  // Do not log error messages if opening fails.
  {
    wxLogNull logNo;

    if (
       synced && !Open(m_FileName.GetFullPath()) ||
      !synced && m_OpenFile && !Open(m_FileName.GetFullPath()))
    {
      return false;
    }
  }

  if (!DoFileLoad(synced))
  {
    if (IsOpened())
    {
      Close();
    }

    return false;
  }

  if (IsOpened())
  {
    Close();
  }

  ResetContentsChanged();

  return true;
}

const wxCharBuffer wxExFile::Read(wxFileOffset seek_position)
{
  wxASSERT(IsOpened());

  if ((!m_HasRead && seek_position > 0) ||
      ( m_HasRead && Tell() != seek_position))
  {
    Seek(seek_position);
  }

  const wxFileOffset bytes_to_read = Length() - seek_position;

  wxCharBuffer buffer(bytes_to_read);

  if (wxFile::Read(buffer.data(), bytes_to_read) != bytes_to_read)
  {
    wxFAIL;
  }

  m_HasRead = true;

  return buffer;
}
<commit_msg>use wxLogStatus ot prevent reappearing dialogs<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      file.cpp
// Purpose:   Implementation of class wxExFile
// Author:    Anton van Wezenbeek
// Copyright: (c) 2014 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/file.h>

wxExFile::wxExFile(bool open_file)
  : m_OpenFile(open_file)
  , m_HasRead(false)
  , m_FileName()
  , m_Stat()
{
}

wxExFile::wxExFile(
  const wxFileName& filename,
  wxFile::OpenMode mode,
  bool open_file)
  : wxFile(filename.GetFullPath(), mode)
  , m_OpenFile(open_file)
  , m_HasRead(false)
  , m_Stat(filename.GetFullPath())
{
  m_FileName.Assign(filename);
  MakeAbsolute();
}

bool wxExFile::CheckSync()
{
  // Might be used without wxApp.
  wxConfigBase* config = wxConfigBase::Get(false);

  if ( IsOpened() ||
      !m_FileName.m_Stat.IsOk() ||
      (config != NULL && !config->ReadBool("AllowSync", true)))
  {
    return false;
  }

  if (m_FileName.m_Stat.Sync())
  {
    bool sync_needed = false;

    if (m_FileName.m_Stat.st_mtime != m_Stat.st_mtime)
    {
      // Do not check return value,
      // we sync anyhow, to force nex time no sync.
      Get(true);

      sync_needed = true;
    }

    if (m_FileName.m_Stat.IsReadOnly() != m_Stat.IsReadOnly())
    {
      sync_needed = true;
    }

    if (sync_needed)
    {
      // Update the stat member, so next time no sync.
      if (!m_Stat.Sync())
      {
        // This might be reported in an OnIdele, so do not use wxLogError.
        wxLogStatus("Could not sync: " + m_FileName.GetFullPath());
      }

      return true;
    }
  }

  return false;
}

bool wxExFile::FileLoad(const wxExFileName& filename)
{
  Assign(filename);
  return m_FileName.FileExists() && MakeAbsolute() && Get(false);
}

void wxExFile::FileNew(const wxExFileName& filename)
{
  // Do not check return value, as file will not (yet)
  // exist.
  Assign(filename);
  DoFileNew();
}

bool wxExFile::FileSave(const wxExFileName& filename)
{
  bool save_as = false;

  if (filename.IsOk())
  {
    Assign(filename);
    MakeAbsolute();
    save_as = true;
  }

  if (m_OpenFile && !Open(m_FileName.GetFullPath(), wxFile::write))
  {
    return false;
  }

  DoFileSave(save_as);

  if (IsOpened())
  {
    Close();
  }

  ResetContentsChanged();

  m_FileName.m_Stat.Sync();
  m_Stat.Sync();

  return true;
}

bool wxExFile::Get(bool synced)
{
  // Do not log error messages if opening fails.
  {
    wxLogNull logNo;

    if (
       synced && !Open(m_FileName.GetFullPath()) ||
      !synced && m_OpenFile && !Open(m_FileName.GetFullPath()))
    {
      return false;
    }
  }

  if (!DoFileLoad(synced))
  {
    if (IsOpened())
    {
      Close();
    }

    return false;
  }

  if (IsOpened())
  {
    Close();
  }

  ResetContentsChanged();

  return true;
}

const wxCharBuffer wxExFile::Read(wxFileOffset seek_position)
{
  wxASSERT(IsOpened());

  if ((!m_HasRead && seek_position > 0) ||
      ( m_HasRead && Tell() != seek_position))
  {
    Seek(seek_position);
  }

  const wxFileOffset bytes_to_read = Length() - seek_position;

  wxCharBuffer buffer(bytes_to_read);

  if (wxFile::Read(buffer.data(), bytes_to_read) != bytes_to_read)
  {
    wxFAIL;
  }

  m_HasRead = true;

  return buffer;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <memory>
#include "procinfo.h"
#include "elfinfo.h"
#include "dwarf.h"

extern "C" {
#include "proc_service.h"
}

static int
globmatchR(const char *pattern, const char *name)
{
    for (;; name++) {
        switch (*pattern) {
        case '*':
            // if the rest of the name matches the bit of pattern after '*',
            for (;;) {
                ++name;
                if (globmatchR(pattern + 1, name))
                    return 1;
                if (*name == 0) // exhuasted name without finding a match
                    return 0;
            }
        default:
            if (*name != *pattern)
                return 0;
        }
        if (*pattern++ == 0)
            return 1;
    }
}

static int
globmatch(std::string pattern, std::string name)
{
    return globmatchR(pattern.c_str(), name.c_str());
}

struct ListedSymbol {
    Elf_Sym sym;
    Elf_Off objbase;
    std::string objname;
    size_t count;
    std::string name;
    ListedSymbol(const Elf_Sym &sym_, Elf_Off objbase_, std::string name_, std::string object)
        : sym(sym_)
        , objbase(objbase_)
        , name(name_)
        , count(0)
        , objname(object)

    {
    }
    Elf_Off memaddr() const { return  sym.st_value + objbase; }
};

const bool operator < (const ListedSymbol &sym, Elf_Off addr) {
    return sym.memaddr() + sym.sym.st_size < addr;
}

struct Symcounter {
    Elf_Off addr;
    std::string name;
    unsigned count;
    struct ListedSymbol *sym;
};

std::vector<Symcounter> counters;

static const char *virtpattern = "_ZTV*"; /* wildcard for all vtbls */

int
main(int argc, char *argv[])
{
    std::shared_ptr<ElfObject> exec;
    std::shared_ptr<ElfObject> core;
    std::shared_ptr<Process> process;
    int c;
    int verbose = 0;

    while ((c = getopt(argc, argv, "vh")) != -1) {
        switch (c) {
            case 'v':
                debug = &std::clog;
                verbose++;
                break;
            case 'h':
                std::clog << "usage: canal [exec] <core>" << std::endl;
                return 0;
            case 'X':
                ps_lgetfpregs(0, 0, 0);
        }
    }

    if (argc - optind >= 2) {
        auto file = std::make_shared<FileReader>(argv[optind]);
        // It's a file:
        exec = std::make_shared<ElfObject>(file);
        optind++;
    }

    if (argc - optind >= 1) {
        char *eoa;
        pid_t pid = strtol(argv[optind], &eoa, 10);
        core = std::make_shared<ElfObject>(std::make_shared<FileReader>(argv[optind]));
        process = std::make_shared<CoreProcess>(exec, core);
    }
    std::clog << "opened process " << process << std::endl;

    std::vector<ListedSymbol> listed;
    for (auto &loaded : process->objects) {
        size_t count = 0;
        for (const auto sym : loaded.object->getSymbols(".dynsym")) {
            if (globmatch(virtpattern, sym.second)) {
                listed.push_back(ListedSymbol(sym.first, loaded.reloc, sym.second, loaded.object->io->describe()));
                count++;
            }
        }
        if (debug)
            *debug << "found " << count << " symbols in " << loaded.object->io->describe() << std::endl;
    }
    std::sort(listed.begin()
        , listed.end()
        , [] (const ListedSymbol &l, const ListedSymbol &r) { return l.memaddr() < r.memaddr(); });

    // Now run through the corefile, searching for virtual objects.
    for (auto hdr : core->getSegments()) {
        if (hdr.p_type != PT_LOAD)
            continue;
        Elf_Off p;
        auto loc = hdr.p_vaddr;
        auto end = loc + hdr.p_filesz;
        if (debug)
            *debug << "scan " << std::hex << loc <<  " to " << end;

        for (Elf_Off readCount = 0; loc  < hdr.p_vaddr + hdr.p_filesz; loc += sizeof p) {
            if (verbose && (loc - hdr.p_vaddr) % (1024 * 1024) == 0)
                std::clog << '.';
            process->io->readObj(loc, &p);
            auto found = std::lower_bound(listed.begin(), listed.end(), p);
            if (found != listed.end() && found->memaddr() <= p && found->memaddr() + found->sym.st_size > p) {
                // std::cout << found->name << " " << loc << std::endl;
                found->count++;
            }
        }
        if (debug)
            *debug << std::endl;
    }

    std::sort(listed.begin()
        , listed.end()
        , [] (const ListedSymbol &l, const ListedSymbol &r) { return l.count > r.count; });

    for (auto &i : listed)
        if (i.count)
            std::cout << std::dec << i.count << " " << i.name << " ( from " << i.objname << ")" << std::endl;
}
<commit_msg>Fix "canal"<commit_after>#include <iostream>
#include <algorithm>
#include <memory>
#include "procinfo.h"
#include "elfinfo.h"
#include "dwarf.h"

extern "C" {
#include "proc_service.h"
}

static int
globmatchR(const char *pattern, const char *name)
{
    for (;; name++) {
        switch (*pattern) {
        case '*':
            // if the rest of the name matches the bit of pattern after '*',
            for (;;) {
                ++name;
                if (globmatchR(pattern + 1, name))
                    return 1;
                if (*name == 0) // exhuasted name without finding a match
                    return 0;
            }
        default:
            if (*name != *pattern)
                return 0;
        }
        if (*pattern++ == 0)
            return 1;
    }
}

static int
globmatch(std::string pattern, std::string name)
{
    return globmatchR(pattern.c_str(), name.c_str());
}

struct ListedSymbol {
    Elf_Sym sym;
    Elf_Off objbase;
    std::string objname;
    size_t count;
    std::string name;
    ListedSymbol(const Elf_Sym &sym_, Elf_Off objbase_, std::string name_, std::string object)
        : sym(sym_)
        , objbase(objbase_)
        , name(name_)
        , count(0)
        , objname(object)

    {
    }
    Elf_Off memaddr() const { return  sym.st_value + objbase; }
};

const bool operator < (const ListedSymbol &sym, Elf_Off addr) {
    return sym.memaddr() + sym.sym.st_size < addr;
}

struct Symcounter {
    Elf_Off addr;
    std::string name;
    unsigned count;
    struct ListedSymbol *sym;
};

std::vector<Symcounter> counters;

static const char *virtpattern = "_ZTV*"; /* wildcard for all vtbls */

int
main(int argc, char *argv[])
{
    std::shared_ptr<ElfObject> exec;
    std::shared_ptr<ElfObject> core;
    std::shared_ptr<Process> process;
    int c;
    int verbose = 0;

    while ((c = getopt(argc, argv, "vh")) != -1) {
        switch (c) {
            case 'v':
                debug = &std::clog;
                verbose++;
                break;
            case 'h':
                std::clog << "usage: canal [exec] <core>" << std::endl;
                return 0;
            case 'X':
                ps_lgetfpregs(0, 0, 0);
        }
    }

    if (argc - optind >= 2) {
        auto file = std::make_shared<FileReader>(argv[optind]);
        // It's a file:
        exec = std::make_shared<ElfObject>(file);
        optind++;
    }

    if (argc - optind >= 1) {
        char *eoa;
        pid_t pid = strtol(argv[optind], &eoa, 10);
        core = std::make_shared<ElfObject>(std::make_shared<FileReader>(argv[optind]));
        process = std::make_shared<CoreProcess>(exec, core);
    }
    process->load();
    std::clog << "opened process " << process << std::endl;

    std::vector<ListedSymbol> listed;
    for (auto &loaded : process->objects) {
        size_t count = 0;
        for (const auto sym : loaded.object->getSymbols(".dynsym")) {
            if (globmatch(virtpattern, sym.second)) {
                listed.push_back(ListedSymbol(sym.first, loaded.reloc, sym.second, loaded.object->io->describe()));
                count++;
            }
        }
        if (debug)
            *debug << "found " << count << " symbols in " << loaded.object->io->describe() << std::endl;
    }
    std::sort(listed.begin()
        , listed.end()
        , [] (const ListedSymbol &l, const ListedSymbol &r) { return l.memaddr() < r.memaddr(); });

    // Now run through the corefile, searching for virtual objects.
    for (auto hdr : core->getSegments()) {
        if (hdr.p_type != PT_LOAD)
            continue;
        Elf_Off p;
        auto loc = hdr.p_vaddr;
        auto end = loc + hdr.p_filesz;
        if (debug)
            *debug << "scan " << std::hex << loc <<  " to " << end;

        for (Elf_Off readCount = 0; loc  < hdr.p_vaddr + hdr.p_filesz; loc += sizeof p) {
            if (verbose && (loc - hdr.p_vaddr) % (1024 * 1024) == 0)
                std::clog << '.';
            process->io->readObj(loc, &p);
            auto found = std::lower_bound(listed.begin(), listed.end(), p);
            if (found != listed.end() && found->memaddr() <= p && found->memaddr() + found->sym.st_size > p) {
                // std::cout << found->name << " " << loc << std::endl;
                found->count++;
            }
        }
        if (debug)
            *debug << std::endl;
    }

    std::sort(listed.begin()
        , listed.end()
        , [] (const ListedSymbol &l, const ListedSymbol &r) { return l.count > r.count; });

    for (auto &i : listed)
        if (i.count)
            std::cout << std::dec << i.count << " " << i.name << " ( from " << i.objname << ")" << std::endl;
}
<|endoftext|>


<commit_before>#include "ofApp.h"

using namespace ofxCv;
using namespace cv;

void ofApp::setup() {
	//ofSetVerticalSync(true);
	//ofSetFrameRate(120);
	finder.setup("haarcascade_frontalface_default.xml");
	finder.setPreset(ObjectFinder::Fast);
	finder.setFindBiggestObject(true);
	//finder.getTracker().setSmoothingRate(.3);
	// samller = smoother
	finder.getTracker().setSmoothingRate(0.2);
	// ignore low-contrast regions
	finder.setCannyPruning(true);
	//cam.listDevices();
	cam.setDeviceID(0);
	cam.setup(CAM_WIDTH, CAM_HEIGHT);
	//cam.setup(640,480);
	//sunglasses.load("sunglasses.png");
	//ofEnableAlphaBlending();
	drawcam = false;
	b.init();
	ofBackground(ofColor(20, 20, 20));

	reset_game();
	faceCenter.set(CAM_WIDTH / 2.0, CAM_HEIGHT / 2.0);
	//ofRectMode(OF_RECTMODE_CENTER);

	// set up font
	//font.loadFont("verdana.ttf", 36, true, false, true, 0.1);
	font.loadFont("Hyperspace.otf", 36, true, false, true, 0.1);

	// set up field
	/*field.addVertex(ofVec3f(20, 20));
	field.addColor(ofColor::red);
	field.addVertex(ofVec3f(40, 20));
	field.addColor(ofColor::red);
	field.addVertex(ofVec3f(40, 40));
	field.addColor(ofColor::red);
	field.addVertex(ofVec3f(20, 40));
	field.addColor(ofColor::red);
	field.setMode(OF_PRIMITIVE_TRIANGLE_FAN);
*/

	float f_width = fabs(Z_FIELD_END - Z_FIELD_START);
	field = field.plane(f_width / 2., f_width, 11, 21);
	//field.setMode(OF_PRIMITIVE_TRIANGLE_FAN);
	goalRect.set(ofGetWidth() / 2 - 200., ofGetHeight() - 100, 400, 200);

}

void ofApp::reset_game(void) {
	// draw the score and the game world
	ofApp::drop_faces = 0;
	score = 0;
	paddleSize = 300;
	state.set(S_IDLE, 0);
	b.reset();
	cout << "RESET\n";

}

void ofApp::update() {

	cam.update();
	if (cam.isFrameNew()) {
		finder.update(cam);
	}

	if (finder.size() > 0) {

		int i = 0;
		faceRect = finder.getObjectSmoothed(i);
		// flip X coordinate
		faceRect.x = CAM_WIDTH - faceRect.x - faceRect.width;

		ofPoint fc = faceRect.getCenter();
		// scale center so we can reach the entire screen
		float border = SCREEN_WIDTH*(SCALE_FACE_POS - 1.);
		fc.x = ofMap(fc.x, 0., CAM_WIDTH, -border, SCREEN_WIDTH + border);
		border = SCREEN_HEIGHT*(SCALE_FACE_POS - 1.);
		fc.y = ofMap(fc.y, 0., CAM_HEIGHT,  -border, SCREEN_HEIGHT + border );
		fc.x -= paddleSize / 2;
		fc.y -= paddleSize / 2;
		paddleRect.set(fc.x, fc.y, paddleSize, paddleSize);

	}

	b.update(state.state);

	// if we got here, we've missed
	if (b.pos.z > Z_NEAR) {
		cout << "MISS!\n";
		b.reset();
	}

	switch (state.state) {
	case S_IDLE:
		if (finder.size()) {
			state.set(S_FORWARD,0);
			drop_faces = 0;
		}
		break;

	case S_FORWARD:
		if (finder.size() == 0) {
			drop_faces++;
			if (drop_faces > DROPPED_FACES_THRESH) {
				drop_faces = 0;
				reset_game();
			}
		}
		else {
			drop_faces = 0;
		}

		// test for collision
		if ((b.pos.z > Z_CLOSE)) {
			if (paddleRect.inside(b.pos.x, b.pos.y)) {
				cout << "Bounce!\n";
				state.set(S_BACKWARD,0);
				if (loc_flag) {
					// get distance of ball impact from paddle center
					ofPoint bc = ofPoint(b.pos.x, b.pos.y, b.pos.z);
					ofPoint pc = paddleRect.getCenter();
					// make it at the same z plane as ball
					ofVec3f spin = pc - bc;
					// we don't care about Z distance
					spin.z = 0;
					// compute return vector to make ball hit center of goal
					ofPoint gc = goalRect.getCenter();
					gc.z = Z_FIELD_END;
					// move goal center by scaled spin offset. Increasing spin means harder
					gc = gc + (4 * spin);
					ofVec3f straight = gc - bc;
					b.bounce(straight / 100.0);
					break;

				}
				else {
					cv::Vec2f v = finder.getVelocity(0);
					ofVec2f spin = toOf(v);

				}

			}
			else {
				state.set(S_IDLE,0);
			}

		}
		break;
	case S_BACKWARD:
		cout << "ball:" << b.getCenter() << " Z " << b.pos.z;
		cout << " goal " << goalRect.getCenter() << " Z " <<  Z_FIELD_END << "\n";

		if (b.pos.z < Z_FIELD_END) {
			b.reset();
			celebrate = Z_FAR / 2;
			score++;
			cout << "WIN!" << "score " << score << "\n";
			state.set(S_CELEBRATE,0);
		}
		break;
	case S_CELEBRATE:
		if (celebrate > 300) {
			b.reset();
			state.set(S_IDLE,0);
		}
		break;

	}

}

void ofApp::draw_world(void) {
	// draw the score and the game world
	//draw score

	for (int i = 0; i<arguments.size(); ++i) {
		ofDrawBitmapString(arguments.at(i), 20.0f, 20.0f*i);
	}

	ofPushMatrix();
	ofTranslate(0, 0, 0);
	ofSetColor(0, 255, 0);//stroke color
	sprintf(score_str, "SCORE %02d", score);
	font.drawString(score_str, ofGetWidth() - 220, 50);
	//font.drawStringAsShapes("test", ofGetWidth() / 2 + 20, ofGetHeight() / 2);
	ofPopMatrix();

	// draw goal
	ofPushMatrix();
	ofSetColor(0, 128, 0, 128);
	ofFill();
	ofTranslate(0., 0., Z_FIELD_END);
	ofDrawRectRounded(goalRect, 20);
	ofPopMatrix();

	// draw field
	ofPushMatrix();
	ofTranslate(ofGetWidth() / 2., ofGetHeight(), Z_FIELD_START);
	//ofTranslate(ofGetWidth() / 2., ofGetHeight() / 2., 30);
	ofRotateX(90.);
	ofNoFill();
	ofSetColor(0, 255, 0);
	field.drawWireframe();
	ofPopMatrix();

}

void ofApp::draw() {
	float spinX = sin(ofGetElapsedTimef()*.35f);
	float spinY = cos(ofGetElapsedTimef()*.075f);

	ofPolyline debug;
	ofPoint gc = ofPoint(goalRect.getCenter());
	gc.z = Z_FIELD_END;
	ofPoint bc = ofPoint(b.pos.x, b.pos.y, b.pos.z);

	debug.addVertex(bc);
	debug.addVertex(gc);
	ofSetColor(255, 0, 0);
	debug.draw();

	ofDrawBitmapString("fps: " + ofToString(ofGetFrameRate()), 20, 20);

	if (drawcam) {
		ofSetColor(255, 255, 255);//stroke color
		cam.draw(CAM_WIDTH, 0, -CAM_WIDTH, CAM_HEIGHT);
	}

	draw_world();
	// future work, pick biggest face rectangle
	//for (int i = 0; i < finder.size(); i++) {

	// draw paddle
	ofNoFill();
	// Draw paddle
	for (float z = Z_NEAR; z > Z_NEAR - 151; z -= 50) {
		ofPushMatrix();
		ofSetColor(0, 255, 255); //stroke color
		ofTranslate(0., 0., z);
		ofDrawRectRounded(paddleRect, 30);
		ofPopMatrix();
	}

	//ofPushMatrix();
	//ofTranslate(0, 0, Z_CLOSE);
	//ofDrawRectRounded(paddleRect, 50);
	//ofPopMatrix();

	switch (state.state) {
	case S_FORWARD:
	case S_BACKWARD:
	case S_IDLE:
		b.draw();
		break;
	case S_CELEBRATE:
		update_celebrate(1);
		break;
	}

}

void ofApp::update_celebrate(int win) {

	celebrate += 10;

	ofPushMatrix();
	//ofTranslate(ofGetWidth() / 2., ofGetHeight() / 2., Z_FAR);

	ofTranslate(ofGetWidth() / 2., ofGetHeight() / 2., celebrate);
	if (win) {
		ofRotateX(float(celebrate / 2.));
		ofRectangle rect = font.getStringBoundingBox("GOAL!!!", 0, 0);
		font.drawStringAsShapes("GOAL!!!", -rect.width / 2., 0);

	}
	else {
		ofRectangle rect = font.getStringBoundingBox("MISS", 0, 0);
		font.drawStringAsShapes("MISS", -rect.width / 2., -Z_FAR - celebrate);
	}
	ofPopMatrix();

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key) {

	ofPoint gc = goalRect.getCenter();
	gc.z = Z_FIELD_END;
	ofPoint bc = ofPoint(b.pos.x, b.pos.y, b.pos.z);

	ofVec3f straight = gc - bc;

	switch (key) {
	case 'c':
		drawcam = !drawcam;
		break;

	case 'f':
		ofSetFullscreen(true);
		break;

	case 'n':
		ofSetFullscreen(false);
		break;

	case 'b':
		// bounce
		cout << "bounce request \n";
		cout << "ball:" << b.getCenter() << " Z " << b.pos.z;
		cout << " goal " << goalRect.getCenter() << " Z " << Z_FIELD_END << "\n";
		cout << " direction: " << straight << "\n";

		state.set(S_BACKWARD,0);
		b.bounce(straight / 100.0);
		break;

	case 'x':
		ofExit();
		break;

	}

}

// State machine handling ------------------------------------------------------------
void StateMach::set(int next_state, float timeout) {
	state = next_state;
	timeout_time = timeout;
	// default no timeout
	if (timeout >= 0) {
		ofResetElapsedTimeCounter();
		reset_timer();
	}
	print();
}

void StateMach::reset_timer(void) {
	start_time = ofGetElapsedTimef();
}

float StateMach::time_elapsed(void) {
	return(ofGetElapsedTimef() - start_time);
}

// return the fraction of elapsed time that has passed
float StateMach::frac_time_elapsed(void) {
	if (time_elapsed() > timeout_time) {
		return 1.0;
	}
	return(time_elapsed() / timeout_time);
}

bool StateMach::timeout(void) {
	if (timeout_time < 0)
		return(true);
	if (time_elapsed() > timeout_time)
		return(true);
	return(false);
}

void StateMach::print(void) {
	switch (state) {
	case S_IDLE:
		cout << "State: IDLE\n";
		break;
	case S_FORWARD:
		cout << "State: FORWARD\n";
		break;
	case S_BACKWARD:
		cout << "State: BACKWARD\n";
		break;
	case S_CELEBRATE:
		cout << "State: CELEBRATE\n";
		break;
	}
}
void ofApp::clean_exit(int signal) {
	// clean exit, signal handler
	cout << "FACEBALL Exit signal caught, bye!\n";
	ofExit();
}
<commit_msg>print fps<commit_after>#include "ofApp.h"

using namespace ofxCv;
using namespace cv;

void ofApp::setup() {
	//ofSetVerticalSync(true);
	//ofSetFrameRate(120);
	finder.setup("haarcascade_frontalface_default.xml");
	finder.setPreset(ObjectFinder::Fast);
	finder.setFindBiggestObject(true);
	//finder.getTracker().setSmoothingRate(.3);
	// samller = smoother
	finder.getTracker().setSmoothingRate(0.2);
	// ignore low-contrast regions
	//finder.setCannyPruning(true);
	//cam.listDevices();
	cam.setDeviceID(0);
	cam.setup(CAM_WIDTH, CAM_HEIGHT);
	//cam.setup(640,480);
	//sunglasses.load("sunglasses.png");
	//ofEnableAlphaBlending();
	drawcam = false;
	b.init();
	ofBackground(ofColor(20, 20, 20));

	reset_game();
	faceCenter.set(CAM_WIDTH / 2.0, CAM_HEIGHT / 2.0);
	//ofRectMode(OF_RECTMODE_CENTER);

	// set up font
	//font.loadFont("verdana.ttf", 36, true, false, true, 0.1);
	font.loadFont("Hyperspace.otf", 36, true, false, true, 0.1);

	// set up field
	/*field.addVertex(ofVec3f(20, 20));
	field.addColor(ofColor::red);
	field.addVertex(ofVec3f(40, 20));
	field.addColor(ofColor::red);
	field.addVertex(ofVec3f(40, 40));
	field.addColor(ofColor::red);
	field.addVertex(ofVec3f(20, 40));
	field.addColor(ofColor::red);
	field.setMode(OF_PRIMITIVE_TRIANGLE_FAN);
*/

	float f_width = fabs(Z_FIELD_END - Z_FIELD_START);
	field = field.plane(f_width / 2., f_width, 11, 21);
	//field.setMode(OF_PRIMITIVE_TRIANGLE_FAN);
	goalRect.set(ofGetWidth() / 2 - 200., ofGetHeight() - 100, 400, 200);

}

void ofApp::reset_game(void) {
	// draw the score and the game world
	ofApp::drop_faces = 0;
	score = 0;
	paddleSize = 300;
	state.set(S_IDLE, 0);
	b.reset();
	cout << "RESET\n";

}

void ofApp::update() {

	cam.update();
	if (cam.isFrameNew()) {
		finder.update(cam);
	}

	if (finder.size() > 0) {

		int i = 0;
		faceRect = finder.getObjectSmoothed(i);
		// flip X coordinate
		faceRect.x = CAM_WIDTH - faceRect.x - faceRect.width;

		ofPoint fc = faceRect.getCenter();
		// scale center so we can reach the entire screen
		float border = SCREEN_WIDTH*(SCALE_FACE_POS - 1.);
		fc.x = ofMap(fc.x, 0., CAM_WIDTH, -border, SCREEN_WIDTH + border);
		border = SCREEN_HEIGHT*(SCALE_FACE_POS - 1.);
		fc.y = ofMap(fc.y, 0., CAM_HEIGHT,  -border, SCREEN_HEIGHT + border );
		fc.x -= paddleSize / 2;
		fc.y -= paddleSize / 2;
		paddleRect.set(fc.x, fc.y, paddleSize, paddleSize);

	}

	b.update(state.state);

	// if we got here, we've missed
	if (b.pos.z > Z_NEAR) {
		cout << "MISS!\n";
		b.reset();
	}

	switch (state.state) {
	case S_IDLE:
		if (finder.size()) {
			state.set(S_FORWARD,0);
			drop_faces = 0;
		}
		break;

	case S_FORWARD:
		if (finder.size() == 0) {
			drop_faces++;
			if (drop_faces > DROPPED_FACES_THRESH) {
				drop_faces = 0;
				reset_game();
			}
		}
		else {
			drop_faces = 0;
		}

		// test for collision
		if ((b.pos.z > Z_CLOSE)) {
			if (paddleRect.inside(b.pos.x, b.pos.y)) {
				cout << "Bounce!\n";
				state.set(S_BACKWARD,0);
				if (loc_flag) {
					// get distance of ball impact from paddle center
					ofPoint bc = ofPoint(b.pos.x, b.pos.y, b.pos.z);
					ofPoint pc = paddleRect.getCenter();
					// make it at the same z plane as ball
					ofVec3f spin = pc - bc;
					// we don't care about Z distance
					spin.z = 0;
					// compute return vector to make ball hit center of goal
					ofPoint gc = goalRect.getCenter();
					gc.z = Z_FIELD_END;
					// move goal center by scaled spin offset. Increasing spin means harder
					gc = gc + (4 * spin);
					ofVec3f straight = gc - bc;
					b.bounce(straight / 100.0);
					break;

				}
				else {
					cv::Vec2f v = finder.getVelocity(0);
					ofVec2f spin = toOf(v);

				}

			}
			else {
				state.set(S_IDLE,0);
			}

		}
		break;
	case S_BACKWARD:
		cout << "ball:" << b.getCenter() << " Z " << b.pos.z;
		cout << " goal " << goalRect.getCenter() << " Z " <<  Z_FIELD_END << "\n";

		if (b.pos.z < Z_FIELD_END) {
			b.reset();
			celebrate = Z_FAR / 2;
			score++;
			cout << "WIN!" << "score " << score << "\n";
			state.set(S_CELEBRATE,0);
		}
		break;
	case S_CELEBRATE:
		if (celebrate > 300) {
			b.reset();
			state.set(S_IDLE,0);
		}
		break;

	}

}

void ofApp::draw_world(void) {
	// draw the score and the game world
	//draw score

	for (int i = 0; i<arguments.size(); ++i) {
		ofDrawBitmapString(arguments.at(i), 20.0f, 20.0f*i);
	}

	ofPushMatrix();
	ofTranslate(0, 0, 0);
	ofSetColor(0, 255, 0);//stroke color
	sprintf(score_str, "SCORE %02d", score);
	font.drawString(score_str, ofGetWidth() - 220, 50);
	//font.drawStringAsShapes("test", ofGetWidth() / 2 + 20, ofGetHeight() / 2);
	ofPopMatrix();

	// draw goal
	ofPushMatrix();
	ofSetColor(0, 128, 0, 128);
	ofFill();
	ofTranslate(0., 0., Z_FIELD_END);
	ofDrawRectRounded(goalRect, 20);
	ofPopMatrix();

	// draw field
	ofPushMatrix();
	ofTranslate(ofGetWidth() / 2., ofGetHeight(), Z_FIELD_START);
	//ofTranslate(ofGetWidth() / 2., ofGetHeight() / 2., 30);
	ofRotateX(90.);
	ofNoFill();
	ofSetColor(0, 255, 0);
	field.drawWireframe();
	ofPopMatrix();

}

void ofApp::draw() {
	float spinX = sin(ofGetElapsedTimef()*.35f);
	float spinY = cos(ofGetElapsedTimef()*.075f);

	ofPolyline debug;
	ofPoint gc = ofPoint(goalRect.getCenter());
	gc.z = Z_FIELD_END;
	ofPoint bc = ofPoint(b.pos.x, b.pos.y, b.pos.z);

	debug.addVertex(bc);
	debug.addVertex(gc);
	ofSetColor(255, 0, 0);
	debug.draw();

	ofDrawBitmapString("fps: " + ofToString(ofGetFrameRate()), 50, 100);

	if (drawcam) {
		ofSetColor(255, 255, 255);//stroke color
		cam.draw(CAM_WIDTH, 0, -CAM_WIDTH, CAM_HEIGHT);
	}

	draw_world();
	// future work, pick biggest face rectangle
	//for (int i = 0; i < finder.size(); i++) {

	// draw paddle
	ofNoFill();
	// Draw paddle
	for (float z = Z_NEAR; z > Z_NEAR - 151; z -= 50) {
		ofPushMatrix();
		ofSetColor(0, 255, 255); //stroke color
		ofTranslate(0., 0., z);
		ofDrawRectRounded(paddleRect, 30);
		ofPopMatrix();
	}

	//ofPushMatrix();
	//ofTranslate(0, 0, Z_CLOSE);
	//ofDrawRectRounded(paddleRect, 50);
	//ofPopMatrix();

	switch (state.state) {
	case S_FORWARD:
	case S_BACKWARD:
	case S_IDLE:
		b.draw();
		break;
	case S_CELEBRATE:
		update_celebrate(1);
		break;
	}

}

void ofApp::update_celebrate(int win) {

	celebrate += 10;

	ofPushMatrix();
	//ofTranslate(ofGetWidth() / 2., ofGetHeight() / 2., Z_FAR);

	ofTranslate(ofGetWidth() / 2., ofGetHeight() / 2., celebrate);
	if (win) {
		ofRotateX(float(celebrate / 2.));
		ofRectangle rect = font.getStringBoundingBox("GOAL!!!", 0, 0);
		font.drawStringAsShapes("GOAL!!!", -rect.width / 2., 0);

	}
	else {
		ofRectangle rect = font.getStringBoundingBox("MISS", 0, 0);
		font.drawStringAsShapes("MISS", -rect.width / 2., -Z_FAR - celebrate);
	}
	ofPopMatrix();

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key) {

	ofPoint gc = goalRect.getCenter();
	gc.z = Z_FIELD_END;
	ofPoint bc = ofPoint(b.pos.x, b.pos.y, b.pos.z);

	ofVec3f straight = gc - bc;

	switch (key) {
	case 'c':
		drawcam = !drawcam;
		break;

	case 'f':
		ofSetFullscreen(true);
		break;

	case 'n':
		ofSetFullscreen(false);
		break;

	case 'b':
		// bounce
		cout << "bounce request \n";
		cout << "ball:" << b.getCenter() << " Z " << b.pos.z;
		cout << " goal " << goalRect.getCenter() << " Z " << Z_FIELD_END << "\n";
		cout << " direction: " << straight << "\n";

		state.set(S_BACKWARD,0);
		b.bounce(straight / 100.0);
		break;

	case 'x':
		ofExit();
		break;

	}

}

// State machine handling ------------------------------------------------------------
void StateMach::set(int next_state, float timeout) {
	state = next_state;
	timeout_time = timeout;
	// default no timeout
	if (timeout >= 0) {
		ofResetElapsedTimeCounter();
		reset_timer();
	}
	print();
}

void StateMach::reset_timer(void) {
	start_time = ofGetElapsedTimef();
}

float StateMach::time_elapsed(void) {
	return(ofGetElapsedTimef() - start_time);
}

// return the fraction of elapsed time that has passed
float StateMach::frac_time_elapsed(void) {
	if (time_elapsed() > timeout_time) {
		return 1.0;
	}
	return(time_elapsed() / timeout_time);
}

bool StateMach::timeout(void) {
	if (timeout_time < 0)
		return(true);
	if (time_elapsed() > timeout_time)
		return(true);
	return(false);
}

void StateMach::print(void) {
	switch (state) {
	case S_IDLE:
		cout << "State: IDLE\n";
		break;
	case S_FORWARD:
		cout << "State: FORWARD\n";
		break;
	case S_BACKWARD:
		cout << "State: BACKWARD\n";
		break;
	case S_CELEBRATE:
		cout << "State: CELEBRATE\n";
		break;
	}
}
void ofApp::clean_exit(int signal) {
	// clean exit, signal handler
	cout << "FACEBALL Exit signal caught, bye!\n";
	ofExit();
}
<|endoftext|>


<commit_before>#include "cell.h"
/*
Cell::Cell(const bool& alive, const unsigned int& x, const unsigned int& y) : alive(alive), next(alive), x(x), y(y)
{

}
*/
<commit_msg>Delete cell.cpp<commit_after><|endoftext|>


<commit_before>#include <iostream>

#include "cify.hpp"

int main()
{
  int a = 10;

  auto f(gnr::cify([a]{std::cout << a << std::endl;}));

  f();

  return 0;
}
<commit_msg>some fixes<commit_after>#include <iostream>

#include "cify.hpp"

int main()
{
  int a = 10;

  auto f(gnr::cify([a]{std::cout << a << std::endl;}));

  f();

  f = gnr::cify_once([&a]{std::cout << ++a << std::endl;});

  f();

  return 0;
}
<|endoftext|>


<commit_before>//Copyright (C) 2011  Carl Rogers
//Released under MIT License
//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php

#include"cnpy.h"
#include<complex>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iomanip>

char cnpy::BigEndianTest() {
    unsigned char x[] = {1,0};
    short y = *(short*) x;
    return y == 1 ? '<' : '>';
}

char cnpy::map_type(const std::type_info& t)
{
    if(t == typeid(float) ) return 'f';
    if(t == typeid(double) ) return 'f';
    if(t == typeid(long double) ) return 'f';

    if(t == typeid(int) ) return 'i';
    if(t == typeid(char) ) return 'i';
    if(t == typeid(short) ) return 'i';
    if(t == typeid(long) ) return 'i';
    if(t == typeid(long long) ) return 'i';

    if(t == typeid(unsigned char) ) return 'u';
    if(t == typeid(unsigned short) ) return 'u';
    if(t == typeid(unsigned long) ) return 'u';
    if(t == typeid(unsigned long long) ) return 'u';
    if(t == typeid(unsigned int) ) return 'u';

    if(t == typeid(bool) ) return 'b';

    if(t == typeid(std::complex<float>) ) return 'c';
    if(t == typeid(std::complex<double>) ) return 'c';
    if(t == typeid(std::complex<long double>) ) return 'c';

    else return '?';
}

template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const std::string rhs) {
    lhs.insert(lhs.end(),rhs.begin(),rhs.end());
    return lhs;
}

template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const char* rhs) {
    //write in little endian
    char len = strlen(rhs);
    for(char byte = 0; byte < len; byte++) {
        lhs.push_back(rhs[byte]);
    }
    return lhs;
}

void cnpy::parse_npy_header(FILE* fp, unsigned int& word_size, unsigned int*& shape, unsigned int& ndims) {
    char buffer[256];
    fread(buffer,sizeof(char),11,fp);
    std::string header = fgets(buffer,256,fp);
    assert(header[header.size()-1] == '\n');

    int loc1, loc2;

    //fortran order
    loc1 = header.find("fortran_order")+16;
    bool fortran_order = (header.substr(loc1,5) == "True" ? true : false);
    assert(!fortran_order);

    //shape
    loc1 = header.find("(");
    loc2 = header.find(")");
    std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
    if(str_shape[str_shape.size()-1] == ',') ndims = 1;
    else ndims = std::count(str_shape.begin(),str_shape.end(),',')+1;
    shape = new unsigned int[ndims];
    for(int i = 0;i < ndims;i++) {
        loc1 = str_shape.find(",");
        shape[i] = atoi(str_shape.substr(0,loc1).c_str());
        str_shape = str_shape.substr(loc1+1);
    }

    //endian, word size, data type
    loc1 = header.find("descr")+9;
    bool littleEndian = (header[loc1] == '<' ? true : false);
    assert(littleEndian);

    char type = header[loc1+1];
    //assert(type == map_type(T));

    std::string str_ws = header.substr(loc1+2);
    loc2 = str_ws.find("'");
    word_size = atoi(str_ws.substr(0,loc2).c_str());
}

void cnpy::parse_zip_footer(FILE* fp, unsigned short& nrecs, unsigned int& global_header_size, unsigned int& global_header_offset)
{
    std::vector<char> footer(22);
    fseek(fp,-22,SEEK_END);
    fread(&footer[0],sizeof(char),22,fp);

    unsigned short disk_no, disk_start, nrecs_on_disk, comment_len;
    disk_no = *(unsigned short*) &footer[4];
    disk_start = *(unsigned short*) &footer[6];
    nrecs_on_disk = *(unsigned short*) &footer[8];
    nrecs = *(unsigned short*) &footer[10];
    global_header_size = *(unsigned int*) &footer[12];
    global_header_offset = *(unsigned int*) &footer[16];
    comment_len = *(unsigned short*) &footer[20];

    assert(disk_no == 0);
    assert(disk_start == 0);
    assert(nrecs_on_disk == nrecs);
    assert(comment_len == 0);
}

cnpy::NpyArray load_the_npy_file(FILE* fp) {
    unsigned int* shape;
    unsigned int ndims, word_size;
    cnpy::parse_npy_header(fp,word_size,shape,ndims);
    unsigned int size = 1;
    for(int i = 0;i < ndims;i++) size *= shape[i];

    cnpy::NpyArray arr;
    arr.word_size = word_size;
    arr.shape = std::vector<unsigned int>(shape,shape+ndims);
    arr.data = new char[size*word_size];
    int nread = fread(arr.data,word_size,size,fp);
    return arr;
}

std::map<std::string,cnpy::NpyArray> cnpy::npz_load(std::string fname) {
    FILE* fp = fopen(fname.c_str(),"rb");

    if(!fp) printf("npz_load: Error! Unable to open file %s!\n",fname.c_str());
    assert(fp);

    std::map<std::string,NpyArray> arrays;

    while(1) {
        std::vector<char> local_header(30);
        fread(&local_header[0],sizeof(char),30,fp);

        //if we've reached the global header, stop reading
        if(local_header[2] != 0x03 || local_header[3] != 0x04) break;

        //read in the variable name
        unsigned short name_len = *(unsigned short*) &local_header[26];
        std::string varname(name_len,' ');
        fread(&varname[0],sizeof(char),name_len,fp);

        //erase the lagging .npy
        varname.erase(varname.end()-4,varname.end());

        //read in the extra field
        unsigned short extra_field_len = *(unsigned short*) &local_header[28];
        if(extra_field_len > 0) {
            std::vector<char> buff(extra_field_len);
            fread(&buff[0],sizeof(char),extra_field_len,fp);
        }

        arrays[varname] = load_the_npy_file(fp);
    }

    fclose(fp);
    return arrays;
}

cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) {
    FILE* fp = fopen(fname.c_str(),"rb");

    if(!fp) {
        printf("npz_load: Error! Unable to open file %s!\n",fname.c_str());
        abort();
    }

    while(1) {
        std::vector<char> local_header(30);
        fread(&local_header[0],sizeof(char),30,fp);

        //if we've reached the global header, stop reading
        if(local_header[2] != 0x03 || local_header[3] != 0x04) break;

        //read in the variable name
        unsigned short name_len = *(unsigned short*) &local_header[26];
        std::string vname(name_len,' ');
        fread(&vname[0],sizeof(char),name_len,fp);
        vname.erase(vname.end()-4,vname.end()); //erase the lagging .npy

        //read in the extra field
        unsigned short extra_field_len = *(unsigned short*) &local_header[28];
        fseek(fp,extra_field_len,SEEK_CUR); //skip past the extra field

        if(vname == varname) {
            NpyArray array = load_the_npy_file(fp);
            fclose(fp);
            return array;
        }
        else {
            //skip past the data
            unsigned int size = *(unsigned int*) &local_header[22];
            fseek(fp,size,SEEK_CUR);
        }
    }

    fclose(fp);
    printf("npz_load: Error! Variable name %s not found in %s!\n",varname.c_str(),fname.c_str());
    abort();
}

cnpy::NpyArray cnpy::npy_load(std::string fname) {

    FILE* fp = fopen(fname.c_str(), "rb");

    if(!fp) {
        printf("npy_load: Error! Unable to open file %s!\n",fname.c_str());
        abort();
    }

    NpyArray arr = load_the_npy_file(fp);

    fclose(fp);
    return arr;
}

<commit_msg>fixing load_the_npy_file to not overflow for files with nbytes greater than unsigned int range<commit_after>//Copyright (C) 2011  Carl Rogers
//Released under MIT License
//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php

#include"cnpy.h"
#include<complex>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iomanip>

char cnpy::BigEndianTest() {
    unsigned char x[] = {1,0};
    short y = *(short*) x;
    return y == 1 ? '<' : '>';
}

char cnpy::map_type(const std::type_info& t)
{
    if(t == typeid(float) ) return 'f';
    if(t == typeid(double) ) return 'f';
    if(t == typeid(long double) ) return 'f';

    if(t == typeid(int) ) return 'i';
    if(t == typeid(char) ) return 'i';
    if(t == typeid(short) ) return 'i';
    if(t == typeid(long) ) return 'i';
    if(t == typeid(long long) ) return 'i';

    if(t == typeid(unsigned char) ) return 'u';
    if(t == typeid(unsigned short) ) return 'u';
    if(t == typeid(unsigned long) ) return 'u';
    if(t == typeid(unsigned long long) ) return 'u';
    if(t == typeid(unsigned int) ) return 'u';

    if(t == typeid(bool) ) return 'b';

    if(t == typeid(std::complex<float>) ) return 'c';
    if(t == typeid(std::complex<double>) ) return 'c';
    if(t == typeid(std::complex<long double>) ) return 'c';

    else return '?';
}

template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const std::string rhs) {
    lhs.insert(lhs.end(),rhs.begin(),rhs.end());
    return lhs;
}

template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const char* rhs) {
    //write in little endian
    char len = strlen(rhs);
    for(char byte = 0; byte < len; byte++) {
        lhs.push_back(rhs[byte]);
    }
    return lhs;
}

void cnpy::parse_npy_header(FILE* fp, unsigned int& word_size, unsigned int*& shape, unsigned int& ndims) {
    char buffer[256];
    fread(buffer,sizeof(char),11,fp);
    std::string header = fgets(buffer,256,fp);
    assert(header[header.size()-1] == '\n');

    int loc1, loc2;

    //fortran order
    loc1 = header.find("fortran_order")+16;
    bool fortran_order = (header.substr(loc1,5) == "True" ? true : false);
    assert(!fortran_order);

    //shape
    loc1 = header.find("(");
    loc2 = header.find(")");
    std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
    if(str_shape[str_shape.size()-1] == ',') ndims = 1;
    else ndims = std::count(str_shape.begin(),str_shape.end(),',')+1;
    shape = new unsigned int[ndims];
    for(int i = 0;i < ndims;i++) {
        loc1 = str_shape.find(",");
        shape[i] = atoi(str_shape.substr(0,loc1).c_str());
        str_shape = str_shape.substr(loc1+1);
    }

    //endian, word size, data type
    loc1 = header.find("descr")+9;
    bool littleEndian = (header[loc1] == '<' ? true : false);
    assert(littleEndian);

    char type = header[loc1+1];
    //assert(type == map_type(T));

    std::string str_ws = header.substr(loc1+2);
    loc2 = str_ws.find("'");
    word_size = atoi(str_ws.substr(0,loc2).c_str());
}

void cnpy::parse_zip_footer(FILE* fp, unsigned short& nrecs, unsigned int& global_header_size, unsigned int& global_header_offset)
{
    std::vector<char> footer(22);
    fseek(fp,-22,SEEK_END);
    fread(&footer[0],sizeof(char),22,fp);

    unsigned short disk_no, disk_start, nrecs_on_disk, comment_len;
    disk_no = *(unsigned short*) &footer[4];
    disk_start = *(unsigned short*) &footer[6];
    nrecs_on_disk = *(unsigned short*) &footer[8];
    nrecs = *(unsigned short*) &footer[10];
    global_header_size = *(unsigned int*) &footer[12];
    global_header_offset = *(unsigned int*) &footer[16];
    comment_len = *(unsigned short*) &footer[20];

    assert(disk_no == 0);
    assert(disk_start == 0);
    assert(nrecs_on_disk == nrecs);
    assert(comment_len == 0);
}

cnpy::NpyArray load_the_npy_file(FILE* fp) {
    unsigned int* shape;
    unsigned int ndims, word_size;
    cnpy::parse_npy_header(fp,word_size,shape,ndims);
    unsigned long long size = 1; //long long so no overflow when multiplying by word_size
    for(int i = 0;i < ndims;i++) size *= shape[i];

    cnpy::NpyArray arr;
    arr.word_size = word_size;
    arr.shape = std::vector<unsigned int>(shape,shape+ndims);
    arr.data = new char[size*word_size];
    int nread = fread(arr.data,word_size,size,fp);
    return arr;
}

std::map<std::string,cnpy::NpyArray> cnpy::npz_load(std::string fname) {
    FILE* fp = fopen(fname.c_str(),"rb");

    if(!fp) printf("npz_load: Error! Unable to open file %s!\n",fname.c_str());
    assert(fp);

    std::map<std::string,NpyArray> arrays;

    while(1) {
        std::vector<char> local_header(30);
        fread(&local_header[0],sizeof(char),30,fp);

        //if we've reached the global header, stop reading
        if(local_header[2] != 0x03 || local_header[3] != 0x04) break;

        //read in the variable name
        unsigned short name_len = *(unsigned short*) &local_header[26];
        std::string varname(name_len,' ');
        fread(&varname[0],sizeof(char),name_len,fp);

        //erase the lagging .npy
        varname.erase(varname.end()-4,varname.end());

        //read in the extra field
        unsigned short extra_field_len = *(unsigned short*) &local_header[28];
        if(extra_field_len > 0) {
            std::vector<char> buff(extra_field_len);
            fread(&buff[0],sizeof(char),extra_field_len,fp);
        }

        arrays[varname] = load_the_npy_file(fp);
    }

    fclose(fp);
    return arrays;
}

cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) {
    FILE* fp = fopen(fname.c_str(),"rb");

    if(!fp) {
        printf("npz_load: Error! Unable to open file %s!\n",fname.c_str());
        abort();
    }

    while(1) {
        std::vector<char> local_header(30);
        fread(&local_header[0],sizeof(char),30,fp);

        //if we've reached the global header, stop reading
        if(local_header[2] != 0x03 || local_header[3] != 0x04) break;

        //read in the variable name
        unsigned short name_len = *(unsigned short*) &local_header[26];
        std::string vname(name_len,' ');
        fread(&vname[0],sizeof(char),name_len,fp);
        vname.erase(vname.end()-4,vname.end()); //erase the lagging .npy

        //read in the extra field
        unsigned short extra_field_len = *(unsigned short*) &local_header[28];
        fseek(fp,extra_field_len,SEEK_CUR); //skip past the extra field

        if(vname == varname) {
            NpyArray array = load_the_npy_file(fp);
            fclose(fp);
            return array;
        }
        else {
            //skip past the data
            unsigned int size = *(unsigned int*) &local_header[22];
            fseek(fp,size,SEEK_CUR);
        }
    }

    fclose(fp);
    printf("npz_load: Error! Variable name %s not found in %s!\n",varname.c_str(),fname.c_str());
    abort();
}

cnpy::NpyArray cnpy::npy_load(std::string fname) {

    FILE* fp = fopen(fname.c_str(), "rb");

    if(!fp) {
        printf("npy_load: Error! Unable to open file %s!\n",fname.c_str());
        abort();
    }

    NpyArray arr = load_the_npy_file(fp);

    fclose(fp);
    return arr;
}

<|endoftext|>


<commit_before>#include <cassert>
#include <chrono>
#include <iostream>
#include <memory>
#include <set>

#include <boost/range/algorithm/for_each.hpp>

#include "mc/classic/count_tokens.hh"
#include "mc/classic/dead.hh"
#include "mc/classic/firing_rule.hh"
#include "mc/classic/make_order.hh"
#include "mc/classic/sdd.hh"
#include "mc/classic/sharp_output.hh"
#include "mc/classic/threads.hh"
#include "mc/classic/worker.hh"
#include "mc/shared/exceptions.hh"
#include "mc/shared/export.hh"
#include "mc/shared/results.hh"
#include "mc/shared/statistics.hh"
#include "mc/shared/step.hh"
#include "support/util/timer.hh"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

namespace pnmc { namespace mc { namespace classic {

/*------------------------------------------------------------------------------------------------*/

SDD
initial_state(const sdd::order<sdd_conf>& order, const pn::net& net)
{
  std::map<std::string, std::reference_wrapper<const pn::transition>> timed;
  boost::range::for_each( net.transitions()
                        , [&](const auto& t){if (t.timed()) timed.emplace(t.id, t);});

  return {order, [&](const auto& id)
                    {
                      const auto cit = net.places().find(id);
                      if (cit != end(net.places()))
                      {
                        return flat_set{cit->marking};
                      }
                      else
                      {
                        const auto t_cit = timed.find(id);
                        assert(t_cit != timed.end());
                        return net.enabled(t_cit->second.get().id)
                             ? flat_set{0}
                             : flat_set{pn::sharp};
                      }}};
}

/*------------------------------------------------------------------------------------------------*/

SDD
dead_states(const conf::configuration&, const order& o, const pn::net& net, const SDD& state_space)
{
  std::set<homomorphism> and_operands;
  std::set<homomorphism> or_operands;

  for (const auto& transition : net.transitions())
  {
    // We are only interested in pre actions.
    for (const auto& arc : transition.pre)
    {
      or_operands.insert(function(o, arc.first, dead{arc.second.weight}));
    }

    and_operands.insert(sum(o, or_operands.cbegin(), or_operands.cend()));
    or_operands.clear();
  }
  const auto tmp = intersection(o, and_operands.cbegin(), and_operands.cend());

  return sdd::rewrite(o, tmp)(o, state_space); // compute dead states
}

/*------------------------------------------------------------------------------------------------*/

void
worker::operator()(const pn::net& net)
const
{
  if (conf.compute_dead_states and net.timed())
  {
    std::cerr << "Computation of dead states for Time Petri Nets is not supported yet.\n";
  }

  using conf::filename;
  using dot_sdd = shared::dot_sdd<sdd_conf>;

  util::timer total_timer;

  // Configure libsdd.
  sdd_conf sconf;
  sconf.sdd_unique_table_size = conf.ut_sizes.at("sdd");
  sconf.sdd_difference_cache_size = conf.cache_sizes.at("diff");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("inter");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("sum");
  sconf.hom_unique_table_size = conf.ut_sizes.at("hom");
  sconf.hom_cache_size = conf.cache_sizes.at("hom");

  // Initialize libsdd.
  auto manager_ptr = std::make_unique<sdd::manager<sdd_conf>>(sdd::init(sconf));
  auto& manager = *manager_ptr;

  auto stats = statistics{};
  stats.max_time = conf.max_time;
  if (conf.stats_conf.count(shared::stats::pn))
  {
    stats.pn_statistics = pn::statistics(net);
  }
  auto res = results{};

  // Set to true by an asynchrous thread when the time limit is reached.
  bool stop_flag = false;

  std::cout << "\n-- Steps\n";

  // Build the order.
  res.order = make_order(conf, stats, net);
  assert(not res.order->empty() && "Empty order");
  shared::export_json(conf, filename::json_order, *res.order);

  // Get the initial state.
  res.m0 = initial_state(*res.order, net);

  // Map of live transitions.
  boost::dynamic_bitset<> live_transitions(net.transitions().size());

  // Compute the transition relation.
  const auto h_operands = [&]
  {
    shared::step("firing rule", &stats.relation_duration);
    return firing_rule(conf, *res.order, net, live_transitions, stop_flag);
  }();
  const auto h = fixpoint(sum(*res.order, begin(h_operands), end(h_operands)));

  // Rewrite the transition relation.
  const auto h_opt = [&]
  {
    shared::step("rewrite", &stats.rewrite_duration);
    return sdd::rewrite(*res.order, h);
  }();

  // Compute the state space.
  {
    shared::step s{"state space", &stats.state_space_duration};
    threads _{conf, stats, stop_flag, manager, s.timer}; // threads will be stopped at scope exit
    try
    {
      res.states = h_opt(*res.order, *res.m0);
    }
    catch (const shared::bound_error& e)
    {
      stats.interrupted = true;
      std::cout << "Place " << e.place << " marking >=" << conf.marking_bound << '\n';
    }
    catch (const shared::interrupted&)
    {
      stats.interrupted = true;
      std::cout << "Computation interrupted after " << s.timer.duration().count() << "s\n";
    }
    if (stats.interrupted)
    {
      shared::export_json(conf, filename::json_stats, stats);
      shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
      return;
    }
  }

  if (conf.count_tokens)
  {
    stats.tokens_duration.emplace();
    shared::step s{"count tokens", &*stats.tokens_duration};
    count_tokens(res, *res.states, net);
  }

  if (conf.compute_dead_transitions)
  {
    shared::step{"dead transitions"};
    res.dead_transitions.emplace();
    for (std::size_t i = 0; i < net.transitions().size(); ++i)
    {
      if (not live_transitions[i])
      {
        res.dead_transitions->push_back(net.get_transition_by_index(i).id);
      }
    }
  }

  if (conf.compute_dead_states and not net.timed())
  {
    stats.dead_states_duration.emplace();
    shared::step s{"dead states", &*stats.dead_states_duration};
    res.dead_states = dead_states(conf, *res.order, net, *res.states);
  }

  if (conf.stats_conf.count(shared::stats::final_sdd))
  {
    stats.sdd_statistics = sdd::tools::statistics(*res.states);
  }
  stats.manager_statistics = sdd::tools::statistics(manager);

  stats.total_duration = total_timer.duration();
  std::cout << "total" << std::setw(15) << ": " << stats.total_duration.count() << "s";
  std::cout << "\n\n-- Results\n";
  std::cout << res;

  shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
  shared::export_dot(conf, filename::dot_m0, dot_sdd{*res.m0, *res.order});
  shared::export_dot(conf, filename::dot_final, dot_sdd{*res.states, *res.order});
  shared::export_json(conf, filename::json_stats, stats);
  shared::export_json(conf, filename::json_results, res);
  shared::export_json(conf, filename::json_h, h, filename::json_h_opt, h_opt);

  if (conf.fast_exit)
  {
    manager_ptr.release(); // manager's destructor won't be called
  }
}

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::classic

#pragma GCC diagnostic pop
<commit_msg>Fast exit even if the computation is interrupted<commit_after>#include <cassert>
#include <chrono>
#include <iostream>
#include <memory>
#include <set>

#include <boost/range/algorithm/for_each.hpp>

#include "mc/classic/count_tokens.hh"
#include "mc/classic/dead.hh"
#include "mc/classic/firing_rule.hh"
#include "mc/classic/make_order.hh"
#include "mc/classic/sdd.hh"
#include "mc/classic/sharp_output.hh"
#include "mc/classic/threads.hh"
#include "mc/classic/worker.hh"
#include "mc/shared/exceptions.hh"
#include "mc/shared/export.hh"
#include "mc/shared/results.hh"
#include "mc/shared/statistics.hh"
#include "mc/shared/step.hh"
#include "support/util/timer.hh"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

namespace pnmc { namespace mc { namespace classic {

/*------------------------------------------------------------------------------------------------*/

SDD
initial_state(const sdd::order<sdd_conf>& order, const pn::net& net)
{
  std::map<std::string, std::reference_wrapper<const pn::transition>> timed;
  boost::range::for_each( net.transitions()
                        , [&](const auto& t){if (t.timed()) timed.emplace(t.id, t);});

  return {order, [&](const auto& id)
                    {
                      const auto cit = net.places().find(id);
                      if (cit != end(net.places()))
                      {
                        return flat_set{cit->marking};
                      }
                      else
                      {
                        const auto t_cit = timed.find(id);
                        assert(t_cit != timed.end());
                        return net.enabled(t_cit->second.get().id)
                             ? flat_set{0}
                             : flat_set{pn::sharp};
                      }}};
}

/*------------------------------------------------------------------------------------------------*/

SDD
dead_states(const conf::configuration&, const order& o, const pn::net& net, const SDD& state_space)
{
  std::set<homomorphism> and_operands;
  std::set<homomorphism> or_operands;

  for (const auto& transition : net.transitions())
  {
    // We are only interested in pre actions.
    for (const auto& arc : transition.pre)
    {
      or_operands.insert(function(o, arc.first, dead{arc.second.weight}));
    }

    and_operands.insert(sum(o, or_operands.cbegin(), or_operands.cend()));
    or_operands.clear();
  }
  const auto tmp = intersection(o, and_operands.cbegin(), and_operands.cend());

  return sdd::rewrite(o, tmp)(o, state_space); // compute dead states
}

/*------------------------------------------------------------------------------------------------*/

void
worker::operator()(const pn::net& net)
const
{
  if (conf.compute_dead_states and net.timed())
  {
    std::cerr << "Computation of dead states for Time Petri Nets is not supported yet.\n";
  }

  using conf::filename;
  using dot_sdd = shared::dot_sdd<sdd_conf>;

  util::timer total_timer;

  // Configure libsdd.
  sdd_conf sconf;
  sconf.sdd_unique_table_size = conf.ut_sizes.at("sdd");
  sconf.sdd_difference_cache_size = conf.cache_sizes.at("diff");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("inter");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("sum");
  sconf.hom_unique_table_size = conf.ut_sizes.at("hom");
  sconf.hom_cache_size = conf.cache_sizes.at("hom");

  // Initialize libsdd.
  auto manager_ptr = std::make_unique<sdd::manager<sdd_conf>>(sdd::init(sconf));
  auto& manager = *manager_ptr;

  auto stats = statistics{};
  stats.max_time = conf.max_time;
  if (conf.stats_conf.count(shared::stats::pn))
  {
    stats.pn_statistics = pn::statistics(net);
  }
  auto res = results{};

  // Set to true by an asynchrous thread when the time limit is reached.
  bool stop_flag = false;

  std::cout << "\n-- Steps\n";

  // Build the order.
  res.order = make_order(conf, stats, net);
  assert(not res.order->empty() && "Empty order");
  shared::export_json(conf, filename::json_order, *res.order);

  // Get the initial state.
  res.m0 = initial_state(*res.order, net);

  // Map of live transitions.
  boost::dynamic_bitset<> live_transitions(net.transitions().size());

  // Compute the transition relation.
  const auto h_operands = [&]
  {
    shared::step("firing rule", &stats.relation_duration);
    return firing_rule(conf, *res.order, net, live_transitions, stop_flag);
  }();
  const auto h = fixpoint(sum(*res.order, begin(h_operands), end(h_operands)));

  // Rewrite the transition relation.
  const auto h_opt = [&]
  {
    shared::step("rewrite", &stats.rewrite_duration);
    return sdd::rewrite(*res.order, h);
  }();

  // Compute the state space.
  {
    shared::step s{"state space", &stats.state_space_duration};
    threads _{conf, stats, stop_flag, manager, s.timer}; // threads will be stopped at scope exit
    try
    {
      res.states = h_opt(*res.order, *res.m0);
    }
    catch (const shared::bound_error& e)
    {
      stats.interrupted = true;
      std::cout << "Place " << e.place << " marking >=" << conf.marking_bound << '\n';
    }
    catch (const shared::interrupted&)
    {
      stats.interrupted = true;
      std::cout << "Computation interrupted after " << s.timer.duration().count() << "s\n";
    }
    if (stats.interrupted)
    {
      shared::export_json(conf, filename::json_stats, stats);
      shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
      if (conf.fast_exit)
      {
        manager_ptr.release(); // manager's destructor won't be called
      }
      return;
    }
  }

  if (conf.count_tokens)
  {
    stats.tokens_duration.emplace();
    shared::step s{"count tokens", &*stats.tokens_duration};
    count_tokens(res, *res.states, net);
  }

  if (conf.compute_dead_transitions)
  {
    shared::step{"dead transitions"};
    res.dead_transitions.emplace();
    for (std::size_t i = 0; i < net.transitions().size(); ++i)
    {
      if (not live_transitions[i])
      {
        res.dead_transitions->push_back(net.get_transition_by_index(i).id);
      }
    }
  }

  if (conf.compute_dead_states and not net.timed())
  {
    stats.dead_states_duration.emplace();
    shared::step s{"dead states", &*stats.dead_states_duration};
    res.dead_states = dead_states(conf, *res.order, net, *res.states);
  }

  if (conf.stats_conf.count(shared::stats::final_sdd))
  {
    stats.sdd_statistics = sdd::tools::statistics(*res.states);
  }
  stats.manager_statistics = sdd::tools::statistics(manager);

  stats.total_duration = total_timer.duration();
  std::cout << "total" << std::setw(15) << ": " << stats.total_duration.count() << "s";
  std::cout << "\n\n-- Results\n";
  std::cout << res;

  shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
  shared::export_dot(conf, filename::dot_m0, dot_sdd{*res.m0, *res.order});
  shared::export_dot(conf, filename::dot_final, dot_sdd{*res.states, *res.order});
  shared::export_json(conf, filename::json_stats, stats);
  shared::export_json(conf, filename::json_results, res);
  shared::export_json(conf, filename::json_h, h, filename::json_h_opt, h_opt);

  if (conf.fast_exit)
  {
    manager_ptr.release(); // manager's destructor won't be called
  }
}

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::classic

#pragma GCC diagnostic pop
<|endoftext|>


<commit_before>#ifndef CODEX_WORKER_BROKER_CONNECTION_H
#define CODEX_WORKER_BROKER_CONNECTION_H

#include <zmq.hpp>
#include <map>

#include "worker_config.hpp"

template <typename proxy, typename task_callback>
class broker_connection {
private:
	const worker_config &config;
	proxy *socket;

	/**
	 * Send the ACK command to the broker
	 */
	void command_ack ()
	{

	}

public:
	broker_connection (const worker_config &config, proxy *socket) : config(config), socket(socket)
	{
	}

	/**
	 * Send the INIT command to the broker.
	 */
	void connect ()
	{
		const worker_config::header_map_t &headers = config.get_headers();

		socket->connect(config.get_broker_uri());
		socket->send("init", 4, ZMQ_SNDMORE);

		auto &last = --headers.end();

		for (auto it = headers.begin(); it != headers.end(); ++it) {
			auto pair = *it;

			char buf[256];
			int count = snprintf(buf, sizeof(buf), "%s=%s", pair.first.c_str(), pair.second.c_str());

			if (count < 0) {
				throw;
			}

			socket->send(buf, (size_t) count, it == last ? 0 : ZMQ_SNDMORE);
		}
	}

	/**
	 * Receive a single task
	 */
	void receive_task ()
	{
		task_callback cb;
		zmq::message_t request;

		socket->recv(request);
		cb();
	}
};

#endif //CODEX_WORKER_BROKER_CONNECTION_H
<commit_msg>cleaner check for last iteration<commit_after>#ifndef CODEX_WORKER_BROKER_CONNECTION_H
#define CODEX_WORKER_BROKER_CONNECTION_H

#include <zmq.hpp>
#include <map>

#include "worker_config.hpp"

template <typename proxy, typename task_callback>
class broker_connection {
private:
	const worker_config &config;
	proxy *socket;

	/**
	 * Send the ACK command to the broker
	 */
	void command_ack ()
	{

	}

public:
	broker_connection (const worker_config &config, proxy *socket) : config(config), socket(socket)
	{
	}

	/**
	 * Send the INIT command to the broker.
	 */
	void connect ()
	{
		const worker_config::header_map_t &headers = config.get_headers();

		socket->connect(config.get_broker_uri());
		socket->send("init", 4, ZMQ_SNDMORE);

		for (auto it = headers.begin(); it != headers.end(); ++it) {
			auto pair = *it;

			char buf[256];
			int count = snprintf(buf, sizeof(buf), "%s=%s", pair.first.c_str(), pair.second.c_str());

			if (count < 0) {
				throw;
			}

			socket->send(buf, (size_t) count, std::next(it) == headers.end() ? 0 : ZMQ_SNDMORE);
		}
	}

	/**
	 * Receive a single task
	 */
	void receive_task ()
	{
		task_callback cb;
		zmq::message_t request;

		socket->recv(request);
		cb();
	}
};

#endif //CODEX_WORKER_BROKER_CONNECTION_H
<|endoftext|>