<commit_before>#ifndef BNI_GRAPH_HPP
#define BNI_GRAPH_HPP

#include <vector>
#include <cstdint>
#include <memory>
#include <limits>
#include <algorithm>
#include <unordered_map>
#include "matrix.hpp"
#include "cpt.hpp"

namespace bn {

struct vertex_t;
struct edge_t;
typedef std::shared_ptr<vertex_t> vertex_type;
typedef std::shared_ptr<edge_t>   edge_type;

struct vertex_t {
    int id;
    std::size_t selectable_num = 0; // 取りうる値の数
    std::pair<bool, matrix_type> evidence;

    cpt_t cpt;
};

struct edge_t {
};

class graph_t {
public:

    graph_t() = default;
    virtual ~graph_t() = default;

    // copy ctor
    graph_t(graph_t const& other)
        : vertex_list_(other.vertex_list_)
        , edge_list_(other.edge_list_)
        , adjacent_list_(other.adjacent_list_)
    {
    }

    // move ctor
    graph_t(graph_t && other)
        : vertex_list_(std::move(other.vertex_list_))
        , edge_list_(std::move(other.edge_list_))
        , adjacent_list_(std::move(other.adjacent_list_))
    {
    }

    std::vector<vertex_type> const& vertex_list() const
    {
        return vertex_list_;
    }

    // 頂点を生成し，そのshared_ptrを返す
    // 必ず成功する
    vertex_type add_vertex()
    {
        // 登録
        auto v = std::make_shared<vertex_t>();
        vertex_list_.push_back(v);

        // adjacent_list_を1行1段増やす
        auto const new_size = vertex_list_.size();
        for(auto& line : adjacent_list_) line.resize(new_size, nullptr); // 既存のリサイズ
        adjacent_list_.emplace_back(new_size, nullptr); // 新規追加

        return v;
    }

    // 引数を元に辺を生成し，そのshared_ptrを返す
    // 既に辺が存在していた場合，nullptrなshared_ptrを即座に返却する
    // 頂点が存在していなかった場合も同様
    edge_type add_edge(vertex_type const& from, vertex_type const& to)
    {
        auto const index_from = index_search(from);
        auto const index_to   = index_search(to);

        // indexの溢れがあるかどうか
        if(index_from >= vertex_list_.size() || index_to >= vertex_list_.size()) return nullptr;

        // 辺の存在を確認
        if(adjacent_list_[index_from][index_to]) return nullptr;

        // 登録
        auto e = std::make_shared<edge_t>();
        edge_list_.push_back(e);
        adjacent_list_[index_from][index_to] = e;
        return e;
    }

    // 引数を元に一致する頂点を削除する
    // その際，その頂点に入出辺も同時に削除する
    // 削除に成功した場合はtrueを返却する
    bool erase_vertex(vertex_type const& v)
    {
        auto const index = index_search(v);
        if(index >= vertex_list_.size()) return false;

        vertex_list_.erase(vertex_list_.begin() + index);
        adjacent_list_.erase(adjacent_list_.begin() + index);
        for(auto& line : adjacent_list_) line.erase(line.begin() + index);
        return true;
    }

    // 引数を元に一致する辺を削除する
    // 削除に成功した場合はtrueを返却する
    bool erase_edge(edge_type const& e)
    {
        auto index = edge_search(e);
        if(index.first >= vertex_list_.size() || index.second >= vertex_list_.size()) return false;

        adjacent_list_[index.first][index.second] = nullptr;
        return true;
    }

    // 引数の頂点から出て行く辺を列挙する
    std::vector<edge_type> out_edges(vertex_type const& from) const
    {
        auto const index = index_search(from);

        std::vector<edge_type> ret;
        for(std::size_t i = 0; i < vertex_list_.size(); ++i)
        {
            if(adjacent_list_[index][i])
            {
                ret.push_back(adjacent_list_[index][i]);
            }
        }
        return ret;
    }

    // 引数の頂点へ入っていく辺を列挙する
    std::vector<edge_type> in_edges(vertex_type const& to) const
    {
        auto const index = index_search(to);

        std::vector<edge_type> ret;
        for(std::size_t i = 0; i < vertex_list_.size(); ++i)
        {
            if(adjacent_list_[i][index])
            {
                ret.push_back(adjacent_list_[i][index]);
            }
        }
        return ret;
    }

    // 辺の先を探す
    vertex_type source(edge_type const& edge) const
    {
        auto const index = edge_search(edge);
        auto const tmp = std::numeric_limits<std::size_t>::max();
        if(index.first == tmp || index.second == tmp) return nullptr;

        return vertex_list_[index.first];
    }

    // 辺の元を探す
    vertex_type target(edge_type const& edge) const
    {
        auto const index = edge_search(edge);
        auto const tmp = std::numeric_limits<std::size_t>::max();
        if(index.first == tmp || index.second == tmp) return nullptr;

        return vertex_list_[index.second];
    }

private:
    std::size_t index_search(vertex_type const& vertex) const
    {
        auto const iterator = std::find(vertex_list_.cbegin(), vertex_list_.cend(), vertex);
        return std::distance(vertex_list_.cbegin(), iterator);
    }

    std::pair<std::size_t, std::size_t> edge_search(edge_type const& edge) const
    {
        for(std::size_t i = 0; i < vertex_list_.size(); ++i)
        {
            for(std::size_t j = 0; j < vertex_list_.size(); ++j)
            {
                if(adjacent_list_.at(i).at(j) == edge)
                {
                    return std::make_pair(i, j);
                }
            }
        }

        auto const tmp = std::numeric_limits<std::size_t>::max();
        return std::make_pair(tmp, tmp);
    }

    std::vector<vertex_type> vertex_list_;
    std::vector<edge_type>   edge_list_;
    std::vector<std::vector<edge_type>> adjacent_list_;
};

} // namespace bn

#endif // #ifndef BNI_MATRIX_HPP

<commit_msg>update: nearby graph_t ctor's problem were solved.<commit_after>#ifndef BNI_GRAPH_HPP
#define BNI_GRAPH_HPP

#include <vector>
#include <cstdint>
#include <memory>
#include <limits>
#include <algorithm>
#include <unordered_map>
#include "matrix.hpp"
#include "cpt.hpp"

namespace bn {

struct vertex_t;
struct edge_t;
typedef std::shared_ptr<vertex_t> vertex_type;
typedef std::shared_ptr<edge_t>   edge_type;

struct vertex_t {
    int id;
    std::size_t selectable_num = 0; // 取りうる値の数
    std::pair<bool, matrix_type> evidence;

    cpt_t cpt;
};

struct edge_t {
};

class graph_t {
public:
    graph_t() = default;
    virtual ~graph_t() = default;

    // copy/move ctor
    graph_t(graph_t const& other) = default;
    graph_t(graph_t && other) = default;

    graph_t& operator=(graph_t const& rhs)
    {
        graph_t(rhs).swap(*this);
        return *this;
    }

    graph_t& operator=(graph_t&& rhs) = default;

    void swap(graph_t& other) noexcept
    {
        std::swap(vertex_list_, other.vertex_list_);
        std::swap(edge_list_, other.edge_list_);
        std::swap(adjacent_list_, other.adjacent_list_);
    }

    friend void swap(graph_t& lhs, graph_t& rhs) noexcept
    {
        lhs.swap(rhs);
    }

    std::vector<vertex_type> const& vertex_list() const
    {
        return vertex_list_;
    }

    // 頂点を生成し，そのshared_ptrを返す
    // 必ず成功する
    vertex_type add_vertex()
    {
        // 登録
        auto v = std::make_shared<vertex_t>();
        vertex_list_.push_back(v);

        // adjacent_list_を1行1段増やす
        auto const new_size = vertex_list_.size();
        for(auto& line : adjacent_list_) line.resize(new_size, nullptr); // 既存のリサイズ
        adjacent_list_.emplace_back(new_size, nullptr); // 新規追加

        return v;
    }

    // 引数を元に辺を生成し，そのshared_ptrを返す
    // 既に辺が存在していた場合，nullptrなshared_ptrを即座に返却する
    // 頂点が存在していなかった場合も同様
    edge_type add_edge(vertex_type const& from, vertex_type const& to)
    {
        auto const index_from = index_search(from);
        auto const index_to   = index_search(to);

        // indexの溢れがあるかどうか
        if(index_from >= vertex_list_.size() || index_to >= vertex_list_.size()) return nullptr;

        // 辺の存在を確認
        if(adjacent_list_[index_from][index_to]) return nullptr;

        // 登録
        auto e = std::make_shared<edge_t>();
        edge_list_.push_back(e);
        adjacent_list_[index_from][index_to] = e;
        return e;
    }

    // 引数を元に一致する頂点を削除する
    // その際，その頂点に入出辺も同時に削除する
    // 削除に成功した場合はtrueを返却する
    bool erase_vertex(vertex_type const& v)
    {
        auto const index = index_search(v);
        if(index >= vertex_list_.size()) return false;

        vertex_list_.erase(vertex_list_.begin() + index);
        adjacent_list_.erase(adjacent_list_.begin() + index);
        for(auto& line : adjacent_list_) line.erase(line.begin() + index);
        return true;
    }

    // 引数を元に一致する辺を削除する
    // 削除に成功した場合はtrueを返却する
    bool erase_edge(edge_type const& e)
    {
        auto index = edge_search(e);
        if(index.first >= vertex_list_.size() || index.second >= vertex_list_.size()) return false;

        adjacent_list_[index.first][index.second] = nullptr;
        return true;
    }

    // 引数の頂点から出て行く辺を列挙する
    std::vector<edge_type> out_edges(vertex_type const& from) const
    {
        auto const index = index_search(from);

        std::vector<edge_type> ret;
        for(std::size_t i = 0; i < vertex_list_.size(); ++i)
        {
            if(adjacent_list_[index][i])
            {
                ret.push_back(adjacent_list_[index][i]);
            }
        }
        return ret;
    }

    // 引数の頂点へ入っていく辺を列挙する
    std::vector<edge_type> in_edges(vertex_type const& to) const
    {
        auto const index = index_search(to);

        std::vector<edge_type> ret;
        for(std::size_t i = 0; i < vertex_list_.size(); ++i)
        {
            if(adjacent_list_[i][index])
            {
                ret.push_back(adjacent_list_[i][index]);
            }
        }
        return ret;
    }

    // 辺の先を探す
    vertex_type source(edge_type const& edge) const
    {
        auto const index = edge_search(edge);
        auto const tmp = std::numeric_limits<std::size_t>::max();
        if(index.first == tmp || index.second == tmp) return nullptr;

        return vertex_list_[index.first];
    }

    // 辺の元を探す
    vertex_type target(edge_type const& edge) const
    {
        auto const index = edge_search(edge);
        auto const tmp = std::numeric_limits<std::size_t>::max();
        if(index.first == tmp || index.second == tmp) return nullptr;

        return vertex_list_[index.second];
    }

private:
    std::size_t index_search(vertex_type const& vertex) const
    {
        auto const iterator = std::find(vertex_list_.cbegin(), vertex_list_.cend(), vertex);
        return std::distance(vertex_list_.cbegin(), iterator);
    }

    std::pair<std::size_t, std::size_t> edge_search(edge_type const& edge) const
    {
        for(std::size_t i = 0; i < vertex_list_.size(); ++i)
        {
            for(std::size_t j = 0; j < vertex_list_.size(); ++j)
            {
                if(adjacent_list_.at(i).at(j) == edge)
                {
                    return std::make_pair(i, j);
                }
            }
        }

        auto const tmp = std::numeric_limits<std::size_t>::max();
        return std::make_pair(tmp, tmp);
    }

    std::vector<vertex_type> vertex_list_;
    std::vector<edge_type>   edge_list_;
    std::vector<std::vector<edge_type>> adjacent_list_;
};

} // namespace bn

#endif // #ifndef BNI_MATRIX_HPP

<|endoftext|>


<commit_before>#ifndef ATOMS_H
#define ATOMS_H
#include<string>
#include<iostream>
#include<map>
#include<set>
#include<boost/shared_ptr.hpp>
#include<stdexcept>
#include"heaps.hpp"

class Globals;

class Atom {
private:
	Generic* value;
protected:
	Atom() : value(NULL){};
	Atom(Atom&){};
public:
	virtual ~Atom(){};
	friend class Globals;
};

class GlobalAtom : public Atom {
private:
	std::string utf8string;
public:
	GlobalAtom(std::string& s) : utf8string(s){};
	virtual ~GlobalAtom(){};
	void emit(void) const {
		std::cout << utf8string;
	};
};

/*from (uniq)*/
class LocalAtom : public Atom {
public:
	virtual ~LocalAtom(){};
};

/*NOTE!  intended to be instantiated only once (singleton)*/
class Globals : public Heap {
private:
	std::map< std::string, boost::shared_ptr<GlobalAtom> > string_to_atom;
	std::set<boost::shared_ptr<Atom> > assigned_local_atoms;
	/*insert mutex here*/
	/*The mutex must be locked for the following cases:
	1. Setting of global variables
	2. Garbage collection.  1 & 2 will probably need to be done
	   right after one another.
	3. Actual reading of variable (if variable is not in cache)
	*/
protected:
	virtual void get_root_set(std::stack<Generic**>&);
public:
	boost::shared_ptr<Atom> lookup(std::string& s){
		/*insert locking of string_to_atom table here*/
		std::map< std::string, boost::shared_ptr<GlobalAtom> >::iterator i;
		i = string_to_atom.find(s);
		if(i != string_to_atom.end()){
			std::map< std::string,
				boost::shared_ptr<Atom> >::value_type v = *i;
			return v.second;
		} else {
			boost::shared_ptr<GlobalAtom> tmp(new GlobalAtom(s));
			string_to_atom[s].swap(tmp);
			return string_to_atom[s];
		}
	}
	boost::shared_ptr<Atom> lookup(char const * s){
		std::string ss(s);
		return lookup(ss);
	}
	/*precondition: lock for globals must be acquired*/
	/*requirements: g must be in the given semispace ns*/
	void assign(boost::shared_ptr<Atom> a,
		    boost::shared_ptr<Semispace> ns,
		    Generic* g){
		other_spaces.push_back(ns);
		a->value = g;
		/*check if local atom*/
		LocalAtom* lp = dynamic_cast<LocalAtom*>(&*a);
		if(lp != NULL){
			/*add a to set*/
			assigned_local_atoms.insert(a);
			/*TODO: figure out how to dynamic_cast shared_ptr<Base>
			to shared_ptr<Derived>, so that assigned_local_atoms
			are indeed local atoms
			*/
		}
	}
	Generic* get(boost::shared_ptr<Atom> a){
		GlobalAtom* gp = dynamic_cast<GlobalAtom*>(&*a);
		if(gp == NULL) throw std::runtime_error("read from non-global");
		return gp->value;
	}
	void GC(void){Heap::GC(0);};
	virtual ~Globals(){};
};

#endif //ATOMS_H

<commit_msg>Allowed getting the value of non-global atoms<commit_after>#ifndef ATOMS_H
#define ATOMS_H
#include<string>
#include<iostream>
#include<map>
#include<set>
#include<boost/shared_ptr.hpp>
#include<stdexcept>
#include"heaps.hpp"

class Globals;

class Atom {
private:
	Generic* value;
protected:
	Atom() : value(NULL){};
	Atom(Atom&){};
public:
	virtual ~Atom(){};
	friend class Globals;
};

class GlobalAtom : public Atom {
private:
	std::string utf8string;
public:
	GlobalAtom(std::string& s) : utf8string(s){};
	virtual ~GlobalAtom(){};
	void emit(void) const {
		std::cout << utf8string;
	};
};

/*from (uniq)*/
class LocalAtom : public Atom {
public:
	virtual ~LocalAtom(){};
};

/*NOTE!  intended to be instantiated only once (singleton)*/
class Globals : public Heap {
private:
	std::map< std::string, boost::shared_ptr<GlobalAtom> > string_to_atom;
	std::set<boost::shared_ptr<Atom> > assigned_local_atoms;
	/*insert mutex here*/
	/*The mutex must be locked for the following cases:
	1. Setting of global variables
	2. Garbage collection.  1 & 2 will probably need to be done
	   right after one another.
	3. Actual reading of variable (if variable is not in cache)
	*/
protected:
	virtual void get_root_set(std::stack<Generic**>&);
public:
	boost::shared_ptr<Atom> lookup(std::string& s){
		/*insert locking of string_to_atom table here*/
		std::map< std::string, boost::shared_ptr<GlobalAtom> >::iterator i;
		i = string_to_atom.find(s);
		if(i != string_to_atom.end()){
			std::map< std::string,
				boost::shared_ptr<Atom> >::value_type v = *i;
			return v.second;
		} else {
			boost::shared_ptr<GlobalAtom> tmp(new GlobalAtom(s));
			string_to_atom[s].swap(tmp);
			return string_to_atom[s];
		}
	}
	boost::shared_ptr<Atom> lookup(char const * s){
		std::string ss(s);
		return lookup(ss);
	}
	/*precondition: lock for globals must be acquired*/
	/*requirements: g must be in the given semispace ns*/
	void assign(boost::shared_ptr<Atom> a,
		    boost::shared_ptr<Semispace> ns,
		    Generic* g){
		other_spaces.push_back(ns);
		a->value = g;
		/*check if local atom*/
		LocalAtom* lp = dynamic_cast<LocalAtom*>(&*a);
		if(lp != NULL){
			/*add a to set*/
			assigned_local_atoms.insert(a);
			/*TODO: figure out how to dynamic_cast shared_ptr<Base>
			to shared_ptr<Derived>, so that assigned_local_atoms
			are indeed local atoms
			*/
		}
	}
	Generic* get(boost::shared_ptr<Atom> a){
		return a->value;
	}
	void GC(void){Heap::GC(0);};
	virtual ~Globals(){};
};

#endif //ATOMS_H

<|endoftext|>


<commit_before>#ifndef TYPES_H
#define TYPES_H
/*
Defines a set of types for use on the hl-side.
*/

#include"objects.hpp"

class GenericTraverser {
public:
	virtual void traverse(Object::ref&) =0;
	virtual ~GenericTraverser();
};

/*-----------------------------------------------------------------------------
Generic
-----------------------------------------------------------------------------*/

class Generic {
public:

	virtual void traverse_references(GenericTraverser* gt) {
		/*default to having no references to traverse*/
		/*example for Cons:
		gt->traverse(a);
		gt->traverse(d);
		*/
	}

	/*some objects have extra allocated space at their ends
	(e.g. Closure).
 	This virtual function returns the total size of the class
	plus extra allocated space.
	*/
	virtual size_t real_size(void) const =0;

	/*hash functions for table-ident and table-is*/
	virtual size_t hash_ident(void) const {
		return reinterpret_cast<size_t>(this);
	}
	virtual size_t hash_is(void) const {
		return reinterpret_cast<size_t>(this);
	}

	/*broken hearts for GC*/
	virtual void break_heart(Object::ref) =0;

	/*dtor*/
	virtual ~Generic() { }
};

/*-----------------------------------------------------------------------------
Broken Heart tags
-----------------------------------------------------------------------------*/

void throw_OverBrokenHeart(Generic*);

class BrokenHeart : public Generic {
public:
	Generic* to;
	virtual bool break_heart(Generic* to) {
		/*already broken - don't break too much!*/
		throw_OverBrokenHeart(to);
	}
	BrokenHeart(Object::ref nto) : to(nto) { }
};

template<class T>
class BrokenHeartFor : public BrokenHeart {
public:
	virtual bool real_size(void) const {
		return sizeof(T);
	}
	explicit BrokenHeartFor<T>(Object::ref x) : BrokenHeart(x) { }
};

template<class T>
class BrokenHeartForVariadic : public BrokenHeart {
private:
	size_t sz;
public:
	virtual bool real_size(void) const {
		return sizeof(T) + sz * sizeof(Object::ref);
	}
	BrokenHeartForVariadic<T>(Object::ref x, size_t nsz)
		: BrokenHeart(x), sz(nsz) { }
};

/*-----------------------------------------------------------------------------
Base classes for Generic-derived objects
-----------------------------------------------------------------------------*/

template<class T>
class GenericDerived : public Generic {
public:
	virtual size_t real_size(void) const {
		return sizeof(T);
	}
	virtual void break_heart(Generic* to) {
		Generic* gp = this;
		gp->~Generic();
		new((void*) gp) BrokenHeartFor<T>(to);
	};
};

/*This class implements a variable-size object by informing the
memory system to reserve extra space.
*/
template<class T>
class GenericDerivedVariadic : public Generic {
	GenericDerivedVariadic<T>(); // disallowed!
protected:
	/*number of extra Object::ref's*/
	size_t sz;
	/*used by the derived classes to get access to
	the variadic data at the end of the object.
	*/
	Object::ref& index(size_t i) {
		void* vp = this;
		char* cp = (char*) vp;
		cp = cp + sizeof(T);
		Object::ref* op = (void*) cp;
		return op[i];
	}
	GenericDerivedVariadic<T>(size_t nsz) : sz(nsz) {
		/*clear the extra references*/
		for(size_t i; i < nsz; ++i) {
			index(i) = Object::nil();
		}
	}
public:
	virtual size_t real_size(void) const {
		return sizeof(T) + sz * sizeof(Object::ref);
	}
	virtual void break_heart(Object::ref to) {
		Generic* gp = this;
		size_t nsz = sz; //save this before dtoring!
		gp->~Generic();
		new((void*) gp) BrokenHeartForVariadic<T>(to, nsz);
	}
};

#endif //TYPES_H

<commit_msg>inc/types.hpp: Corrected types for break_heart() etc.<commit_after>#ifndef TYPES_H
#define TYPES_H
/*
Defines a set of types for use on the hl-side.
*/

#include"objects.hpp"

class GenericTraverser {
public:
	virtual void traverse(Object::ref&) =0;
	virtual ~GenericTraverser();
};

/*-----------------------------------------------------------------------------
Generic
-----------------------------------------------------------------------------*/

class Generic {
public:

	virtual void traverse_references(GenericTraverser* gt) {
		/*default to having no references to traverse*/
		/*example for Cons:
		gt->traverse(a);
		gt->traverse(d);
		*/
	}

	/*some objects have extra allocated space at their ends
	(e.g. Closure).
 	This virtual function returns the total size of the class
	plus extra allocated space.
	*/
	virtual size_t real_size(void) const =0;

	/*hash functions for table-ident and table-is*/
	virtual size_t hash_ident(void) const {
		return reinterpret_cast<size_t>(this);
	}
	virtual size_t hash_is(void) const {
		return reinterpret_cast<size_t>(this);
	}

	/*broken hearts for GC*/
	virtual void break_heart(Generic*) =0;

	/*dtor*/
	virtual ~Generic() { }
};

/*-----------------------------------------------------------------------------
Broken Heart tags
-----------------------------------------------------------------------------*/

void throw_OverBrokenHeart(Generic*);

class BrokenHeart : public Generic {
public:
	Generic* to;
	virtual bool break_heart(Generic* to) {
		/*already broken - don't break too much!*/
		throw_OverBrokenHeart(to);
	}
	BrokenHeart(Generic* nto) : to(nto) { }
};

template<class T>
class BrokenHeartFor : public BrokenHeart {
public:
	virtual bool real_size(void) const {
		return sizeof(T);
	}
	explicit BrokenHeartFor<T>(Generic* x) : BrokenHeart(x) { }
};

template<class T>
class BrokenHeartForVariadic : public BrokenHeart {
private:
	size_t sz;
public:
	virtual bool real_size(void) const {
		return sizeof(T) + sz * sizeof(Object::ref);
	}
	BrokenHeartForVariadic<T>(Generic* x, size_t nsz)
		: BrokenHeart(x), sz(nsz) { }
};

/*-----------------------------------------------------------------------------
Base classes for Generic-derived objects
-----------------------------------------------------------------------------*/

template<class T>
class GenericDerived : public Generic {
public:
	virtual size_t real_size(void) const {
		return sizeof(T);
	}
	virtual void break_heart(Generic* to) {
		Generic* gp = this;
		gp->~Generic();
		new((void*) gp) BrokenHeartFor<T>(to);
	};
};

/*This class implements a variable-size object by informing the
memory system to reserve extra space.
Note that classes which derive from this should provide
a factory function!
*/
template<class T>
class GenericDerivedVariadic : public Generic {
	GenericDerivedVariadic<T>(); // disallowed!
protected:
	/*number of extra Object::ref's*/
	size_t sz;
	/*used by the derived classes to get access to
	the variadic data at the end of the object.
	*/
	Object::ref& index(size_t i) {
		void* vp = this;
		char* cp = (char*) vp;
		cp = cp + sizeof(T);
		Object::ref* op = (void*) cp;
		return op[i];
	}
	GenericDerivedVariadic<T>(size_t nsz) : sz(nsz) {
		/*clear the extra references*/
		for(size_t i; i < nsz; ++i) {
			index(i) = Object::nil();
		}
	}
public:
	virtual size_t real_size(void) const {
		return sizeof(T) + sz * sizeof(Object::ref);
	}
	virtual void break_heart(Object::ref to) {
		Generic* gp = this;
		size_t nsz = sz; //save this before dtoring!
		gp->~Generic();
		new((void*) gp) BrokenHeartForVariadic<T>(to, nsz);
	}
};

#endif //TYPES_H

<|endoftext|>


<commit_before>#include "query.h"

ID fstrftime, fto_s, fusec;
VALUE dtformat, tzformat;

VALUE query_execute(Query *query) {
  try {
    return UINT2NUM(
      query->bind.size() == 0
        ? query->handle->conn()->execute(query->sql)
        : query->handle->conn()->execute(query->sql, query->bind)
    );
  }
  catch (dbi::Error &e) {
    query->error = e.what();
    return Qfalse;
  }
}

VALUE query_execute_statement(Query *query) {
  try {
    return UINT2NUM(
      query->bind.size() == 0
        ? query->statement->execute()
        : query->statement->execute(query->bind)
    );
  }
  catch (dbi::Error &e) {
    query->error = e.what();
    return Qfalse;
  }
}

void query_bind_values(Query *query, VALUE bind_values, std::string driver) {
  for (int i = 0; i < RARRAY_LEN(bind_values); i++) {
    VALUE bind_value = rb_ary_entry(bind_values, i);

    if (bind_value == Qnil) {
      query->bind.push_back(dbi::PARAM(dbi::null()));
    }
    else if (bind_value == Qtrue) {
      query->bind.push_back(dbi::PARAM("1"));
    }
    else if (bind_value == Qfalse) {
      query->bind.push_back(dbi::PARAM("0"));
    }
    else if (rb_obj_is_kind_of(bind_value, rb_cIO) ==  Qtrue || rb_obj_is_kind_of(bind_value, cStringIO) ==  Qtrue) {
      bind_value = rb_funcall(bind_value, rb_intern("read"), 0);
      query->bind.push_back(dbi::PARAM_BINARY((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
    }
    // TODO convert timestamps to server timezone if @timezone is set in adapter.
    else if (rb_obj_is_kind_of(bind_value, rb_cTime)) {
      std::string timestamp = RSTRING_PTR(rb_funcall(bind_value, fstrftime, 1, dtformat));

      timestamp += RSTRING_PTR(rb_funcall(rb_funcall(bind_value, fusec, 0), fto_s, 0));
      if (driver != "db2")
        timestamp += RSTRING_PTR(rb_funcall(bind_value, fstrftime, 1, tzformat));

      query->bind.push_back(dbi::PARAM(timestamp));
    }
    else {
      bind_value = TO_S(bind_value);
      if (strcmp(rb_enc_get(bind_value)->name, "UTF-8") != 0)
        bind_value = rb_str_encode(bind_value, rb_str_new2("UTF-8"), 0, Qnil);
      query->bind.push_back(dbi::PARAM((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
    }
  }
}

void init_swift_query() {
  fstrftime = rb_intern("strftime");
  fto_s     = rb_intern("to_s");
  fusec     = rb_intern("usec");
  dtformat  = rb_str_new2("%F %T.");
  tzformat  = rb_str_new2("%z");
}
<commit_msg>save global vars from gc<commit_after>#include "query.h"

ID fstrftime, fto_s, fusec;
VALUE dtformat, tzformat, utf8;

VALUE query_execute(Query *query) {
  try {
    return UINT2NUM(
      query->bind.size() == 0
        ? query->handle->conn()->execute(query->sql)
        : query->handle->conn()->execute(query->sql, query->bind)
    );
  }
  catch (dbi::Error &e) {
    query->error = e.what();
    return Qfalse;
  }
}

VALUE query_execute_statement(Query *query) {
  try {
    return UINT2NUM(
      query->bind.size() == 0
        ? query->statement->execute()
        : query->statement->execute(query->bind)
    );
  }
  catch (dbi::Error &e) {
    query->error = e.what();
    return Qfalse;
  }
}

void query_bind_values(Query *query, VALUE bind_values, std::string driver) {
  for (int i = 0; i < RARRAY_LEN(bind_values); i++) {
    VALUE bind_value = rb_ary_entry(bind_values, i);

    if (bind_value == Qnil) {
      query->bind.push_back(dbi::PARAM(dbi::null()));
    }
    else if (bind_value == Qtrue) {
      query->bind.push_back(dbi::PARAM("1"));
    }
    else if (bind_value == Qfalse) {
      query->bind.push_back(dbi::PARAM("0"));
    }
    else if (rb_obj_is_kind_of(bind_value, rb_cIO) ==  Qtrue || rb_obj_is_kind_of(bind_value, cStringIO) ==  Qtrue) {
      bind_value = rb_funcall(bind_value, rb_intern("read"), 0);
      query->bind.push_back(dbi::PARAM_BINARY((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
    }
    // TODO convert timestamps to server timezone if @timezone is set in adapter.
    else if (rb_obj_is_kind_of(bind_value, rb_cTime)) {
      std::string timestamp = RSTRING_PTR(rb_funcall(bind_value, fstrftime, 1, dtformat));

      timestamp += RSTRING_PTR(rb_funcall(rb_funcall(bind_value, fusec, 0), fto_s, 0));
      if (driver != "db2")
        timestamp += RSTRING_PTR(rb_funcall(bind_value, fstrftime, 1, tzformat));

      query->bind.push_back(dbi::PARAM(timestamp));
    }
    else {
      bind_value = TO_S(bind_value);
      if (strcmp(rb_enc_get(bind_value)->name, "UTF-8") != 0)
        bind_value = rb_str_encode(bind_value, utf8, 0, Qnil);
      query->bind.push_back(dbi::PARAM((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
    }
  }
}

void init_swift_query() {
  fstrftime = rb_intern("strftime");
  fto_s     = rb_intern("to_s");
  fusec     = rb_intern("usec");
  dtformat  = rb_str_new2("%F %T.");
  tzformat  = rb_str_new2("%z");
  utf8      = rb_str_new2("UTF-8");

  rb_global_variable(&utf8);
  rb_global_variable(&tzformat);
  rb_global_variable(&dtformat);
}
<|endoftext|>


<commit_before><commit_msg>Fixed multi_handler.hxx not getting included in cl.hxx<commit_after><|endoftext|>


<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/

#pragma once

#include <algorithm>
#include <string>
#include <vector>

#include <Tensile/Properties.hpp>
#include <Tensile/Utils.hpp>

namespace Tensile
{
    namespace Predicates
    {
        template <typename Object>
        using Predicate = Property<Object, bool>;

        template <typename Class, typename Object>
        using Predicate_CRTP = Property_CRTP<Class, Object, bool>;

        template <typename Object>
        class True: public Predicate_CRTP<True<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = false };
            static std::string Type() { return "TruePred"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const&) const
            {
                return true;
            }
        };

        template <typename Object>
        class False: public Predicate_CRTP<False<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = false };
            static std::string Type() { return "FalsePred"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const&) const
            {
                return false;
            }
        };

        template <typename Object>
        class And: public Predicate_CRTP<And<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            std::vector<std::shared_ptr<Predicate<Object>>> value;

            And() = default;
            And(std::initializer_list<std::shared_ptr<Predicate<Object>>> init) : value(init) { }
            And(std::vector<std::shared_ptr<Predicate<Object>>>    const& init) : value(init) { }

            static std::string Type() { return "And"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const& obj) const
            {
                return std::all_of(value.begin(), value.end(),
                        [&obj](std::shared_ptr<Predicate<Object>> pred) { return (*pred)(obj); });
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const
            {
                bool rv = (*this)(obj);

                stream << type() << "(";

                bool first = true;
                for(auto const& term: value)
                {
                    if(!first)
                        stream << ", ";
                    first = false;

                    term->debugEval(obj, stream);
                }

                stream << "): " << rv;
                return rv;
            }
        };

        template <typename Object>
        class Or: public Predicate_CRTP<Or<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            std::vector<std::shared_ptr<Predicate<Object>>> value;

            Or() = default;
            Or(std::initializer_list<std::shared_ptr<Predicate<Object>>> init) : value(init) { }
            Or(std::vector<std::shared_ptr<Predicate<Object>>>    const& init) : value(init) { }

            static std::string Type() { return "Or"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const& obj) const
            {
                return std::any_of(value.begin(), value.end(),
                        [&obj](std::shared_ptr<Predicate<Object>> pred) { return (*pred)(obj); });
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const
            {
                bool rv = (*this)(obj);

                stream << type() << "(";

                bool first = true;
                for(auto const& term: value)
                {
                    if(!first)
                        stream << ", ";
                    first = false;

                    term->debugEval(obj, stream);
                }

                stream << "): " << rv;
                return rv;
            }
        };

        template <typename Object>
        class Not: public Predicate_CRTP<Not<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            std::shared_ptr<Predicate<Object>> value;
            Not() = default;
            Not(std::shared_ptr<Predicate<Object>> init) : value(init) { }

            static std::string Type() { return "Not"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const& obj) const
            {
                return !(*value)(obj);
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const
            {
                bool rv = (*this)(obj);

                stream << type() << "(";
                value->debugEval(obj, stream);
                stream << "): " << rv;

                return rv;
            }
        };

        template <typename Object, typename Subclass>
        class IsSubclass: public Predicate_CRTP<IsSubclass<Object, Subclass>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            static_assert(std::is_base_of<Object, Subclass>::value, "Subclass must be derived from Object.");

            std::shared_ptr<Predicate<Subclass>> value;

            IsSubclass() = default;
            IsSubclass(std::shared_ptr<Predicate<Subclass>> init) : value(init) { }

            static std::string Type() { return Subclass::Type(); }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const& obj) const
            {
                auto const* sc = dynamic_cast<Subclass const*>(&obj);
                if(!sc) return false;

                return (*value)(*sc);
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const override
            {
                bool rv = (*this)(obj);

                stream << type() << "(";

                auto const* sc = dynamic_cast<Subclass const*>(&obj);

                if(sc)
                {
                    stream << " matches: ";
                    value->debugEval(*sc, stream);
                }
                else
                {
                    stream << " no match. actual type: " << typeid(obj).name();
                }

                stream << "): " << rv;

                return rv;
            }
        };
    }
}

<commit_msg>Add some missing keywords.<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/

#pragma once

#include <algorithm>
#include <string>
#include <vector>

#include <Tensile/Properties.hpp>
#include <Tensile/Utils.hpp>

namespace Tensile
{
    namespace Predicates
    {
        template <typename Object>
        using Predicate = Property<Object, bool>;

        template <typename Class, typename Object>
        using Predicate_CRTP = Property_CRTP<Class, Object, bool>;

        template <typename Object>
        class True: public Predicate_CRTP<True<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = false };
            static std::string Type() { return "TruePred"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const&) const
            {
                return true;
            }
        };

        template <typename Object>
        class False: public Predicate_CRTP<False<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = false };
            static std::string Type() { return "FalsePred"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const&) const
            {
                return false;
            }
        };

        template <typename Object>
        class And: public Predicate_CRTP<And<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            std::vector<std::shared_ptr<Predicate<Object>>> value;

            And() = default;
            And(std::initializer_list<std::shared_ptr<Predicate<Object>>> init) : value(init) { }
            And(std::vector<std::shared_ptr<Predicate<Object>>>    const& init) : value(init) { }

            static std::string Type() { return "And"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const& obj) const
            {
                return std::all_of(value.begin(), value.end(),
                        [&obj](std::shared_ptr<Predicate<Object>> pred) { return (*pred)(obj); });
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const
            {
                bool rv = (*this)(obj);

                stream << type() << "(";

                bool first = true;
                for(auto const& term: value)
                {
                    if(!first)
                        stream << ", ";
                    first = false;

                    term->debugEval(obj, stream);
                }

                stream << "): " << rv;
                return rv;
            }
        };

        template <typename Object>
        class Or: public Predicate_CRTP<Or<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            std::vector<std::shared_ptr<Predicate<Object>>> value;

            Or() = default;
            Or(std::initializer_list<std::shared_ptr<Predicate<Object>>> init) : value(init) { }
            Or(std::vector<std::shared_ptr<Predicate<Object>>>    const& init) : value(init) { }

            static std::string Type() { return "Or"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const& obj) const
            {
                return std::any_of(value.begin(), value.end(),
                        [&obj](std::shared_ptr<Predicate<Object>> pred) { return (*pred)(obj); });
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const
            {
                bool rv = (*this)(obj);

                stream << type() << "(";

                bool first = true;
                for(auto const& term: value)
                {
                    if(!first)
                        stream << ", ";
                    first = false;

                    term->debugEval(obj, stream);
                }

                stream << "): " << rv;
                return rv;
            }
        };

        template <typename Object>
        class Not: public Predicate_CRTP<Not<Object>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            std::shared_ptr<Predicate<Object>> value;
            Not() = default;
            Not(std::shared_ptr<Predicate<Object>> init) : value(init) { }

            static std::string Type() { return "Not"; }
            virtual std::string type() const { return Type(); }

            virtual bool operator()(Object const& obj) const
            {
                return !(*value)(obj);
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const
            {
                bool rv = (*this)(obj);

                stream << type() << "(";
                value->debugEval(obj, stream);
                stream << "): " << rv;

                return rv;
            }
        };

        template <typename Object, typename Subclass>
        class IsSubclass: public Predicate_CRTP<IsSubclass<Object, Subclass>, Object>
        {
        public:
            enum { HasIndex = false, HasValue = true };
            static_assert(std::is_base_of<Object, Subclass>::value, "Subclass must be derived from Object.");

            std::shared_ptr<Predicate<Subclass>> value;

            IsSubclass() = default;
            IsSubclass(std::shared_ptr<Predicate<Subclass>> init) : value(init) { }

            static std::string Type() { return Subclass::Type(); }
            virtual std::string type() const override { return Type(); }

            virtual bool operator()(Object const& obj) const override
            {
                auto const* sc = dynamic_cast<Subclass const*>(&obj);
                if(!sc) return false;

                return (*value)(*sc);
            }

            virtual bool debugEval(Object const& obj, std::ostream & stream) const override
            {
                bool rv = (*this)(obj);

                stream << type() << "(";

                auto const* sc = dynamic_cast<Subclass const*>(&obj);

                if(sc)
                {
                    stream << " matches: ";
                    value->debugEval(*sc, stream);
                }
                else
                {
                    stream << " no match. actual type: " << typeid(obj).name();
                }

                stream << "): " << rv;

                return rv;
            }
        };
    }
}

<|endoftext|>


<commit_before>/*
 *
 */
#include <stdio.h>
#include "sync.h"
#include "topo.h"
#include "mp.h"
#include "measurement_framework.h"
#include <pthread.h>
#include <unistd.h>

#include "model_defs.h"

__thread struct sk_measurement m;

int NUM_THREADS;
#define NUM_RUNS 100 // 10000 // Tested up to 1.000.000

pthread_barrier_t ab_barrier;

/**
 * \brief Message ping-pong between LAST_NODE and SEQUENTIALIZER
 */
void* pingpong(void* a)
{
    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);
    sk_m_init(&m, NUM_RUNS, "pingpong", buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);

        if (get_thread_id()==LAST_NODE) {
            mp_send(SEQUENTIALIZER, epoch);
            mp_receive(SEQUENTIALIZER);
        }
        else if (get_thread_id()==SEQUENTIALIZER) {
            mp_receive(LAST_NODE);
            mp_send(LAST_NODE, epoch);
        }

        sk_m_add(&m);
    }

    if (get_thread_id() == LAST_NODE ||
        get_thread_id() == SEQUENTIALIZER) {

        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

/**
 * \brief Broadcast trigger by LAST_NODE until back to LAST_NODE
 */
void* ab(void* a)
{
    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);
    sk_m_init(&m, NUM_RUNS, "ab", buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);

        if (get_thread_id()==LAST_NODE) {
            mp_send(SEQUENTIALIZER, 0);
        }

        if (get_thread_id()==SEQUENTIALIZER) {
            mp_send_ab(mp_receive(LAST_NODE));
        }
        else {
            mp_receive_forward(0);
        }

        sk_m_add(&m);
    }

    if (get_thread_id() == LAST_NODE) {
        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

extern void shl_barrier_shm(int b_count);

/**
 * \brief Reduction
 */
void* reduction(void* a)
{
    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);
    sk_m_init(&m, NUM_RUNS, "reduction", buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);
        mp_reduce(tid);
        sk_m_add(&m);

        pthread_barrier_wait(&ab_barrier);
    }

    if (get_thread_id() == SEQUENTIALIZER) {
        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

/**
 * \brief
 */
void* reduction_ln(void* a)
{
    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);
    sk_m_init(&m, NUM_RUNS, "reduction-ln", buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);
        mp_reduce(tid);

        if (tid==SEQUENTIALIZER) {
            mp_send(LAST_NODE, 0);
        } else if (tid==LAST_NODE) {
            mp_receive(SEQUENTIALIZER);
        }
        sk_m_add(&m);
    }

    if (get_thread_id() == LAST_NODE) {
        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

void* barrier(void* a)
{
    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);
    sk_m_init(&m, NUM_RUNS, "barriers", buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        mp_barrier(NULL);

        if (tid==LAST_NODE) sk_m_add(&m);
    }

    if (get_thread_id()==SEQUENTIALIZER ||
        get_thread_id()==LAST_NODE) {

        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

#define NUM_EXP 5

int main(int argc, char **argv)
{
    NUM_THREADS = sysconf(_SC_NPROCESSORS_CONF);

    pthread_barrier_init(&ab_barrier, NULL, NUM_THREADS);

    typedef void* (worker_func_t)(void*);
    worker_func_t* workers[NUM_EXP] = {
        &pingpong,
        &ab,
        &reduction,
        &reduction_ln,
        &barrier
    };

    const char *labels[NUM_EXP] = {
        "Ping pong",
        "Atomic broadcast",
        "Reduction",
        "Reduction (last node)",
        "barrier"
    };

    __sync_init(NUM_THREADS);

    pthread_t ptds[NUM_THREADS];
    int tids[NUM_THREADS];

    for (int j=0; j<NUM_EXP; j++) {

        printf("----------------------------------------\n");
        printf("Executing experiment %d - %s\n", (j+1), labels[j]);
        printf("----------------------------------------\n");

        // Yield to reduce the risk of getting de-scheduled later
        sched_yield();

        // Create
        for (int i=1; i<NUM_THREADS; i++) {
            tids[i] = i;
            pthread_create(ptds+i, NULL, workers[j], (void*) (tids+i));
        }

        // Master thread executes work for node 0
        tids[0] = 0;
        workers[j]((void*) (tids+0));

        // Join
        for (int i=1; i<NUM_THREADS; i++) {
            pthread_join(ptds[i], NULL);
        }
    }

    pthread_barrier_destroy(&ab_barrier);

}
<commit_msg>bench: Run all topologies<commit_after>/*
 *
 */
#include <stdio.h>
#include "sync.h"
#include "topo.h"
#include "mp.h"
#include "measurement_framework.h"
#include <pthread.h>
#include <unistd.h>

#include "model_defs.h"

__thread struct sk_measurement m;

int NUM_THREADS;
#define NUM_RUNS 50 // 10000 // Tested up to 1.000.000

pthread_barrier_t ab_barrier;

#define TOPO_NAME(x,y) sprintf(x, "%s_%s", y, topo_get_name());

/**
 * \brief Message ping-pong between LAST_NODE and SEQUENTIALIZER
 */
void* pingpong(void* a)
{
    char outname[1024];

     int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);

    TOPO_NAME(outname, "pingpong");
    sk_m_init(&m, NUM_RUNS, outname, buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);

        if (get_thread_id()==LAST_NODE) {
            mp_send(SEQUENTIALIZER, epoch);
            mp_receive(SEQUENTIALIZER);
        }
        else if (get_thread_id()==SEQUENTIALIZER) {
            mp_receive(LAST_NODE);
            mp_send(LAST_NODE, epoch);
        }

        sk_m_add(&m);
    }

    if (get_thread_id() == LAST_NODE ||
        get_thread_id() == SEQUENTIALIZER) {

        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

/**
 * \brief Broadcast trigger by LAST_NODE until back to LAST_NODE
 */
void* ab(void* a)
{
    char outname[1024];

   int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);

    TOPO_NAME(outname, "ab");
    sk_m_init(&m, NUM_RUNS, outname, buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);

        if (get_thread_id()==LAST_NODE) {
            mp_send(SEQUENTIALIZER, 0);
        }

        if (get_thread_id()==SEQUENTIALIZER) {
            mp_send_ab(mp_receive(LAST_NODE));
        }
        else {
            mp_receive_forward(0);
        }

        sk_m_add(&m);
    }

    if (get_thread_id() == LAST_NODE) {
        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

extern void shl_barrier_shm(int b_count);

/**
 * \brief Reduction
 */
void* reduction(void* a)
{
    char outname[1024];

    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);

    TOPO_NAME(outname, "reduction");
    sk_m_init(&m, NUM_RUNS, outname, buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);
        mp_reduce(tid);
        sk_m_add(&m);

        pthread_barrier_wait(&ab_barrier);
    }

    if (get_thread_id() == SEQUENTIALIZER) {
        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

/**
 * \brief
 */
void* reduction_ln(void* a)
{
    char outname[1024];

    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);

    TOPO_NAME(outname, "reduction-ln");
    sk_m_init(&m, NUM_RUNS, outname, buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        sk_m_restart_tsc(&m);
        mp_reduce(tid);

        if (tid==SEQUENTIALIZER) {
            mp_send(LAST_NODE, 0);
        } else if (tid==LAST_NODE) {
            mp_receive(SEQUENTIALIZER);
        }
        sk_m_add(&m);
    }

    if (get_thread_id() == LAST_NODE) {
        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

void* barrier(void* a)
{
    char outname[1024];

    int tid = *((int*) a);
    __thread_init(tid, NUM_THREADS);

    // Setup buffer for measurements
    cycles_t *buf = (cycles_t*) malloc(sizeof(cycles_t)*NUM_RUNS);

    TOPO_NAME(outname, "barriers");
    sk_m_init(&m, NUM_RUNS, outname, buf);

    for (int epoch=0; epoch<NUM_RUNS; epoch++) {

        mp_barrier(NULL);

        if (tid==LAST_NODE) sk_m_add(&m);
    }

    if (get_thread_id()==SEQUENTIALIZER ||
        get_thread_id()==LAST_NODE) {

        sk_m_print(&m);
    }

    __thread_end();
    return NULL;
}

#define NUM_EXP 5

int main(int argc, char **argv)
{
    NUM_THREADS = sysconf(_SC_NPROCESSORS_CONF);

    pthread_barrier_init(&ab_barrier, NULL, NUM_THREADS);

    typedef void* (worker_func_t)(void*);
    worker_func_t* workers[NUM_EXP] = {
        &pingpong,
        &ab,
        &reduction,
        &reduction_ln,
        &barrier
    };

    const char *labels[NUM_EXP] = {
        "Ping pong",
        "Atomic broadcast",
        "Reduction",
        "Reduction (last node)",
        "barrier"
    };

    __sync_init(NUM_THREADS);

    pthread_t ptds[NUM_THREADS];
    int tids[NUM_THREADS];

    for (int e=0; e<NUM_TOPOS; e++) {

        for (int j=0; j<NUM_EXP; j++) {

            printf("----------------------------------------\n");
            printf("Executing experiment %d - %s\n", (j+1), labels[j]);
            printf("----------------------------------------\n");

            // Yield to reduce the risk of getting de-scheduled later
            sched_yield();

            // Create
            for (int i=1; i<NUM_THREADS; i++) {
                tids[i] = i;
                pthread_create(ptds+i, NULL, workers[j], (void*) (tids+i));
            }

            // Master thread executes work for node 0
            tids[0] = 0;
            workers[j]((void*) (tids+0));

            // Join
            for (int i=1; i<NUM_THREADS; i++) {
                pthread_join(ptds[i], NULL);
            }
        }

        switch_topo();
    }

    pthread_barrier_destroy(&ab_barrier);

}
<|endoftext|>


<commit_before>/*
 * D-Bus AT-SPI, Qt Adaptor
 *
 * Copyright 2008-2011 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright 2008, 2009      Codethink Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "bridge.h"

#include "adaptor.h"
#include "accessible.h"
#include "application.h"
#include "cache.h"
#include "constant_mappings.h"
#include "dbusconnection.h"
#include "struct_marshallers.h"

#include "generated/dec_proxy.h"
#include "generated/event_adaptor.h"

#include <QEvent>
#include <QKeyEvent>

#define QSPI_DEC_NAME        "/org/a11y/atspi/Registry"
#define QSPI_DEC_OBJECT_PATH "/org/a11y/atspi/registry/deviceeventcontroller"

QSpiAccessibleBridge* QSpiAccessibleBridge::self = 0;

QSpiAccessibleBridge::QSpiAccessibleBridge()
    : cache(0), initialized(false)
{
    Q_ASSERT(self == 0);
    self = this;

    dbusConnection = new DBusConnection();
    if (!dBusConnection().isConnected()) {
        qWarning() << "Could not connect to dbus.";
    }

    qSpiInitializeStructTypes();
    qSpiInitializeConstantMappings();

    /* Create the cache of accessible objects */
    cache = new QSpiDBusCache(dBusConnection(), this);
    dec = new DeviceEventControllerProxy(this);

    bool reg = dBusConnection().registerObject(QSPI_DEC_OBJECT_PATH, this, QDBusConnection::ExportAdaptors);
    qDebug() << "Registered DEC: " << reg;

    QAccessibleInterface* i = QAccessible::queryAccessibleInterface(qApp);
    QSpiAdaptor* applicationAccessible = new QSpiApplication(dbusConnection->connection(), i);
    adaptors.insert(QString(QSPI_OBJECT_PATH_ROOT), applicationAccessible);
    connect(applicationAccessible, SIGNAL(windowActivated(QObject*)), this, SLOT(windowActivated(QObject*)));
}

void QSpiAccessibleBridge::windowActivated(QObject* window)
{
    QSpiAdaptor* a = spiBridge->objectToAccessible(window);
    QSpiAccessible* acc = static_cast<QSpiAccessible*>(a);
    acc->windowActivated();
}

QSpiAccessibleBridge::~QSpiAccessibleBridge()
{
    delete dbusConnection;
} // Qt currently doesn't delete plugins.

QDBusConnection QSpiAccessibleBridge::dBusConnection() const
{
    return dbusConnection->connection();
}

void QSpiAccessibleBridge::setRootObject(QAccessibleInterface *interface)
{
    initialized = true;

    // the interface we get will be for the QApplication object.
    // we already cache it in the constructor.
    Q_ASSERT(interface->object() == qApp);
}

QSpiObjectReference QSpiAccessibleBridge::getRootReference() const
{
    return QSpiObjectReference(dBusConnection(), QDBusObjectPath(QSPI_OBJECT_PATH_ROOT));
}

void QSpiAccessibleBridge::notifyAccessibilityUpdate(int reason, QAccessibleInterface *interface, int index)
{
    Q_ASSERT(interface && interface->isValid());

    if (!initialized)
        return;

    // this gets deleted, so create one if we don't have it yet
    QSpiAdaptor* accessible = interfaceToAccessible(interface, index, false);
    //Q_ASSERT(accessible->associatedInterface()->object() == interface->object());
    if (accessible->associatedInterface()->object() == interface->object()) {
        qWarning() << "Creating accessible with different object than the original interface!";
    }

    switch (reason) {

    case QAccessible::ObjectCreated:
        qDebug() << "created" << interface->object();
        break;

    case QAccessible::ObjectShow:
        qDebug() << "show" << interface->object();
        break;

    case QAccessible::Focus: {
        static QSpiAccessible *lastFocused = 0;
        if (lastFocused) {
            QDBusVariant data;
            data.setVariant(QVariant::fromValue(lastFocused->getReference()));
            emit lastFocused->StateChanged("focused", 0, 0, data, getRootReference());
        }
        lastFocused = qobject_cast<QSpiAccessible*>(accessible);
    }
    }
//    qDebug() << "QSpiAccessibleBridge::notifyAccessibilityUpdate" << QString::number(reason, 16)
//             << " obj: " << interface->object()
//             << (interface->isValid() ? interface->object()->objectName() : " invalid interface!")
//             << accessible->interface;
    accessible->accessibleEvent((QAccessible::Event)reason);
}

QSpiAdaptor* QSpiAccessibleBridge::objectToAccessible(QObject *object)
{
    Q_ASSERT(object);

    QString path = QSpiAccessible::pathForObject(object);
    if (adaptors.contains(path))
        return adaptors.value(path);

    QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(object);
    if (!interface) {
        qWarning() << "Create accessible for object which cannot create an accessible interface." << object;
        return 0;
    }

    return interfaceToAccessible(interface, 0, true);
}

QSpiAdaptor* QSpiAccessibleBridge::interfaceToAccessible(QAccessibleInterface* interface, int index, bool takeOwnershipOfInterface)
{
    Q_ASSERT(interface && interface->isValid());

    QString path = QSpiAccessible::pathForInterface(interface, index);
    // optimize?
    if (adaptors.contains(path)) {
        if (adaptors.value(path)->associatedInterface()->object() != interface->object()) {

            QSpiAdaptor* originalAdaptor = adaptors.take(path);
            qDebug() << "not the same: " << originalAdaptor->associatedInterface()->object() << interface->object()
                     << " at path: " << path;

            // ItemViews create qobjects for rows/cells later as needed.
            // Those may initially be 0.

            // remove object
            // add new interface
            cache->emitRemoveAccessible(originalAdaptor->getReference());
            delete originalAdaptor;
//            Q_ASSERT(0);
        } else {
            return adaptors.value(path);
        }
    }

// FIXME if this works, we can save code below...
//    QAccessibleInterface* copy(QAccessibleInterface(*interface));

    // if we cannot keep the interface around (notifyAccessibility will delete interfaces)
    // we need to ask for one that we can keep
    if (!takeOwnershipOfInterface) {
        QAccessibleInterface* ownedInterface = QAccessible::queryAccessibleInterface(interface->object());
        if (!ownedInterface) {
            QAccessibleInterface* parentInterface;
            interface->navigate(QAccessible::Ancestor, 1, &parentInterface);
            Q_ASSERT(parentInterface);
            int index = parentInterface->indexOfChild(interface);
            parentInterface->navigate(QAccessible::Child, index, &ownedInterface);
            delete parentInterface;
        }
        Q_ASSERT(ownedInterface);
        Q_ASSERT(interface->object() == ownedInterface->object());
        interface = ownedInterface;
    }
    QSpiAdaptor *accessible = new QSpiAccessible(interface, index);

    // put ourself in the list of accessibles
    adaptors.insert(path, accessible);

    notifyAboutCreation(accessible);
    return accessible;
}

void QSpiAccessibleBridge::notifyAboutCreation(QSpiAdaptor* accessible)
{
    // say hello to d-bus
    cache->emitAddAccessible(accessible->getCacheItem());

    // notify about the new child of our parent
    int childCount = 0;
    QSpiAdaptor* parentAdaptor = 0;
    if (accessible->childIndex() == 0) {
        QAccessibleInterface *parent = 0;
        accessible->associatedInterface()->navigate(QAccessible::Ancestor, 1, &parent);
        if (parent) {
            parentAdaptor = interfaceToAccessible(parent, 0, true);
            childCount = parent->childCount();
        }
    } else {
        parentAdaptor = interfaceToAccessible(accessible->associatedInterface(), 0, true);
        childCount = accessible->associatedInterface()->childCount();
    }

    if (parentAdaptor) {
        QSpiObjectReference r = accessible->getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        parentAdaptor->signalChildrenChanged("add", childCount, 0, data);
    }
}

void QSpiAccessibleBridge::objectDestroyed(QObject* o)
{
    QString path = QSpiAccessible::pathForObject(o);
    adaptors.remove(path);
}

void QSpiAccessibleBridge::removeAdaptor(QSpiAdaptor *adaptor)
{
    adaptors.remove(adaptor->getReference().path.path());
}
<commit_msg>Pay attention to QAccessible::ObjectCreated.<commit_after>/*
 * D-Bus AT-SPI, Qt Adaptor
 *
 * Copyright 2008-2011 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright 2008, 2009      Codethink Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "bridge.h"

#include "adaptor.h"
#include "accessible.h"
#include "application.h"
#include "cache.h"
#include "constant_mappings.h"
#include "dbusconnection.h"
#include "struct_marshallers.h"

#include "generated/dec_proxy.h"
#include "generated/event_adaptor.h"

#include <QEvent>
#include <QKeyEvent>

#define QSPI_DEC_NAME        "/org/a11y/atspi/Registry"
#define QSPI_DEC_OBJECT_PATH "/org/a11y/atspi/registry/deviceeventcontroller"

QSpiAccessibleBridge* QSpiAccessibleBridge::self = 0;

QSpiAccessibleBridge::QSpiAccessibleBridge()
    : cache(0), initialized(false)
{
    Q_ASSERT(self == 0);
    self = this;

    dbusConnection = new DBusConnection();
    if (!dBusConnection().isConnected()) {
        qWarning() << "Could not connect to dbus.";
    }

    qSpiInitializeStructTypes();
    qSpiInitializeConstantMappings();

    /* Create the cache of accessible objects */
    cache = new QSpiDBusCache(dBusConnection(), this);
    dec = new DeviceEventControllerProxy(this);

    bool reg = dBusConnection().registerObject(QSPI_DEC_OBJECT_PATH, this, QDBusConnection::ExportAdaptors);
    qDebug() << "Registered DEC: " << reg;

    QAccessibleInterface* i = QAccessible::queryAccessibleInterface(qApp);
    QSpiAdaptor* applicationAccessible = new QSpiApplication(dbusConnection->connection(), i);
    adaptors.insert(QString(QSPI_OBJECT_PATH_ROOT), applicationAccessible);
    connect(applicationAccessible, SIGNAL(windowActivated(QObject*)), this, SLOT(windowActivated(QObject*)));
}

void QSpiAccessibleBridge::windowActivated(QObject* window)
{
    QSpiAdaptor* a = spiBridge->objectToAccessible(window);
    QSpiAccessible* acc = static_cast<QSpiAccessible*>(a);
    acc->windowActivated();
}

QSpiAccessibleBridge::~QSpiAccessibleBridge()
{
    delete dbusConnection;
} // Qt currently doesn't delete plugins.

QDBusConnection QSpiAccessibleBridge::dBusConnection() const
{
    return dbusConnection->connection();
}

void QSpiAccessibleBridge::setRootObject(QAccessibleInterface *interface)
{
    initialized = true;

    // the interface we get will be for the QApplication object.
    // we already cache it in the constructor.
    Q_ASSERT(interface->object() == qApp);
}

QSpiObjectReference QSpiAccessibleBridge::getRootReference() const
{
    return QSpiObjectReference(dBusConnection(), QDBusObjectPath(QSPI_OBJECT_PATH_ROOT));
}

void QSpiAccessibleBridge::notifyAccessibilityUpdate(int reason, QAccessibleInterface *interface, int index)
{
    Q_ASSERT(interface && interface->isValid());

    if (!initialized)
        return;

    // this gets deleted, so create one if we don't have it yet
    QSpiAdaptor* accessible = interfaceToAccessible(interface, index, false);
    //Q_ASSERT(accessible->associatedInterface()->object() == interface->object());
    if (accessible->associatedInterface()->object() == interface->object()) {
        qWarning() << "Creating accessible with different object than the original interface!";
    }

    switch (reason) {

    case QAccessible::ObjectCreated:
        qDebug() << "created" << interface->object();
        // make sure we don't duplicate this. seems to work for qml loaders.
        notifyAboutCreation(accessible);
        break;

    case QAccessible::ObjectShow:
        qDebug() << "show" << interface->object();
        break;

    case QAccessible::Focus: {
        static QSpiAccessible *lastFocused = 0;
        if (lastFocused) {
            QDBusVariant data;
            data.setVariant(QVariant::fromValue(lastFocused->getReference()));
            emit lastFocused->StateChanged("focused", 0, 0, data, getRootReference());
        }
        lastFocused = qobject_cast<QSpiAccessible*>(accessible);
    }
    }
//    qDebug() << "QSpiAccessibleBridge::notifyAccessibilityUpdate" << QString::number(reason, 16)
//             << " obj: " << interface->object()
//             << (interface->isValid() ? interface->object()->objectName() : " invalid interface!")
//             << accessible->interface;
    accessible->accessibleEvent((QAccessible::Event)reason);
}

QSpiAdaptor* QSpiAccessibleBridge::objectToAccessible(QObject *object)
{
    Q_ASSERT(object);

    QString path = QSpiAccessible::pathForObject(object);
    if (adaptors.contains(path))
        return adaptors.value(path);

    QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(object);
    if (!interface) {
        qWarning() << "Create accessible for object which cannot create an accessible interface." << object;
        return 0;
    }

    return interfaceToAccessible(interface, 0, true);
}

QSpiAdaptor* QSpiAccessibleBridge::interfaceToAccessible(QAccessibleInterface* interface, int index, bool takeOwnershipOfInterface)
{
    Q_ASSERT(interface && interface->isValid());

    QString path = QSpiAccessible::pathForInterface(interface, index);
    // optimize?
    if (adaptors.contains(path)) {
        if (adaptors.value(path)->associatedInterface()->object() != interface->object()) {

            QSpiAdaptor* originalAdaptor = adaptors.take(path);
            qDebug() << "not the same: " << originalAdaptor->associatedInterface()->object() << interface->object()
                     << " at path: " << path;

            // ItemViews create qobjects for rows/cells later as needed.
            // Those may initially be 0.

            // remove object
            // add new interface
            cache->emitRemoveAccessible(originalAdaptor->getReference());
            delete originalAdaptor;
//            Q_ASSERT(0);
        } else {
            return adaptors.value(path);
        }
    }

// FIXME if this works, we can save code below...
//    QAccessibleInterface* copy(QAccessibleInterface(*interface));

    // if we cannot keep the interface around (notifyAccessibility will delete interfaces)
    // we need to ask for one that we can keep
    if (!takeOwnershipOfInterface) {
        QAccessibleInterface* ownedInterface = QAccessible::queryAccessibleInterface(interface->object());
        if (!ownedInterface) {
            QAccessibleInterface* parentInterface;
            interface->navigate(QAccessible::Ancestor, 1, &parentInterface);
            Q_ASSERT(parentInterface);
            int index = parentInterface->indexOfChild(interface);
            parentInterface->navigate(QAccessible::Child, index, &ownedInterface);
            delete parentInterface;
        }
        Q_ASSERT(ownedInterface);
        Q_ASSERT(interface->object() == ownedInterface->object());
        interface = ownedInterface;
    }
    QSpiAdaptor *accessible = new QSpiAccessible(interface, index);

    // put ourself in the list of accessibles
    adaptors.insert(path, accessible);

    notifyAboutCreation(accessible);
    return accessible;
}

void QSpiAccessibleBridge::notifyAboutCreation(QSpiAdaptor* accessible)
{
    // say hello to d-bus
    cache->emitAddAccessible(accessible->getCacheItem());

    // notify about the new child of our parent
    int childCount = 0;
    QSpiAdaptor* parentAdaptor = 0;
    if (accessible->childIndex() == 0) {
        QAccessibleInterface *parent = 0;
        accessible->associatedInterface()->navigate(QAccessible::Ancestor, 1, &parent);
        if (parent) {
            parentAdaptor = interfaceToAccessible(parent, 0, true);
            childCount = parent->childCount();
        }
    } else {
        parentAdaptor = interfaceToAccessible(accessible->associatedInterface(), 0, true);
        childCount = accessible->associatedInterface()->childCount();
    }

    if (parentAdaptor) {
        QSpiObjectReference r = accessible->getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        parentAdaptor->signalChildrenChanged("add", childCount, 0, data);
    }
}

void QSpiAccessibleBridge::objectDestroyed(QObject* o)
{
    QString path = QSpiAccessible::pathForObject(o);
    adaptors.remove(path);
}

void QSpiAccessibleBridge::removeAdaptor(QSpiAdaptor *adaptor)
{
    adaptors.remove(adaptor->getReference().path.path());
}
<|endoftext|>


<commit_before><commit_msg>We now only need one bit of information here<commit_after><|endoftext|>


<commit_before>//=============================================================================
// File      : SALOME_PYQT_GUI.cxx
// Created   : mer jun  4 17:17:20 UTC 2003
// Author    : Paul RASCLE, EDF
// Project   : SALOME
// Copyright : EDF 2003
// $Header$
//=============================================================================

#include "SALOME_PYQT_GUI.h"

#include "QAD_Desktop.h"

#include "SALOME_Selection.h"
#include "SALOME_InteractiveObject.hxx"
#include "SALOMEGUI_QtCatchCorbaException.hxx"
#include "utilities.h"

#include <sipSalomePyQtDeclSalomePyQt.h>
#include <sipqtQWorkspace.h>
#include <sipqtQPopupMenu.h>

#include <map>
#include <string>

using namespace std;

static PyInterp_PyQt *interp = NULL;
static map<int,PyInterp_PyQt*> mapInterp;

//=============================================================================
/*!
 *  Calls module.setWorkSpace with PyQt QWorkspace object to use with
 *  interpreter.
 */
//=============================================================================

void SALOME_PYQT_GUI::setWorkSpace()
{
  MESSAGE("setWorkSpace");
  PyLockWrapper aLock = interp->GetLockWrapper();

  //   Try to import qt module. If it's not possible don't go on
  PyObjWrapper qtmodule(PyImport_ImportModule("qt"));
  if(!qtmodule){
    PyErr_Print();
    return ;
  }

  PyObjWrapper pyws(sipMapCppToSelf( QAD_Application::getDesktop()->getMainFrame(),
				     sipClass_QWorkspace));
  PyObjWrapper res(PyObject_CallMethod(_module,"setWorkSpace","O",pyws.get()));
  SCRUTE(pyws->ob_refcnt);
  if(!res){
    PyErr_Print();
    return ;
  }
}

//=============================================================================
/*!
 *  Import Python module (from _moduleName)
 */
//=============================================================================
void SALOME_PYQT_GUI::importModule()
{
  PyLockWrapper aLock = interp->GetLockWrapper();

  _module=PyImport_ImportModule((char*)_moduleName.c_str());
  if(!_module){
    MESSAGE ( " Problem... " );
    PyErr_Print();
    return;
  }
}

//=============================================================================
/*!
 *  Initialises python interpreter (only one per study), imports python module
 *  from given module name, sets static reference to module,
 *  sets module workspace.
 */
//=============================================================================

void SALOME_PYQT_GUI::initInterp(int StudyID)
{
  MESSAGE("SALOME_PYQT_GUI::initInterp");
  if(mapInterp.find(StudyID) != mapInterp.end()){
    MESSAGE ( "SALOME_PYQT_GUI::initInterp StudyID is found " << StudyID );
    interp = mapInterp[StudyID];
    return;
  }else{
    MESSAGE ( "SALOME_PYQT_GUI::initInterp StudyID is not found " << StudyID );
    /*
     * The creation of Python interpretor must be protected par a C++ Lock because of C threads
     */
    ThreadLock aPyLock = GetPyThreadLock("SALOME_PYQT_GUI::initInterp");
    interp = new PyInterp_PyQt();
    interp->initialize();
    mapInterp[StudyID] = interp;
  }
  // imports Python GUI module and puts it in _module attribute
  importModule();
  // calls _module.setWorkspace and passes the SIP object main workspace
  setWorkSpace();

}

//=============================================================================
/*!
 * constructor : only calls SALOMEGUI constructor
 */
//=============================================================================
SALOME_PYQT_GUI::SALOME_PYQT_GUI( const QString& theName, QObject* theParent ) :
    SALOMEGUI( theName, theParent ),_module(0)
{
    MESSAGE("SALOME_PYQT_GUI::SALOME_PYQT_GUI");
}

//=============================================================================
/*!
 * destructor : do nothing
 */
//=============================================================================
SALOME_PYQT_GUI::~SALOME_PYQT_GUI()
{
}

//=============================================================================
/*!
 *  Calls python module.OnGUIEvent(theCommandID)
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnGUIEvent (int theCommandID,
				  QAD_Desktop* parent)
{
  MESSAGE("SALOME_PYQT_GUI::OnGUIEvent");
  ThreadLock aPyLock = GetPyThreadLock("SALOME_PYQT_GUI::OnGUIEvent");
  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper res(PyObject_CallMethod(_module,"OnGUIEvent","i",theCommandID));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 *  no call to python module.OnKeyPress()
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnKeyPress (QKeyEvent* pe,
				  QAD_Desktop* parent,
				  QAD_StudyFrame* studyFrame)
{
  MESSAGE("SALOME_PYQT_GUI::OnKeyPress");
  return true;
}

//=============================================================================
/*!
 *  no call to python module.OnMousePress()
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnMousePress (QMouseEvent* pe ,
				    QAD_Desktop* parent,
				    QAD_StudyFrame* studyFrame)
{
  MESSAGE("SALOME_PYQT_GUI::OnMousePress");
  return false;
}

//=============================================================================
/*!
 *  no call to python module.OnMouseMove()
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnMouseMove (QMouseEvent* pe ,
				   QAD_Desktop* parent,
				   QAD_StudyFrame* studyFrame)
{
  // Commented out to avoid multiple traces ...
  // MESSAGE("SALOME_PYQT_GUI::OnMouseMove");
  return true;
}

//=============================================================================
/*!
 *  Calls initInterp to initialise python interpreter (only one per study) and
 *  to import python module. Calls module.setSettings()
 */
//=============================================================================

bool SALOME_PYQT_GUI::SetSettings (QAD_Desktop* parent, char* moduleName)
{
  MESSAGE("SALOME_PYQT_GUI::SetSettings");
  int StudyID = QAD_Application::getDesktop()->getActiveStudy()->getStudyId();
  SCRUTE ( StudyID );
  _moduleName = moduleName + string("GUI");
  SCRUTE(_moduleName);

  // initializes one Python interpreter by study and puts it in interp global variable
  // imports Python GUI module and puts it in _module attribute
  // calls _module.setWorkspace and passes the SIP object main workspace
  initInterp(StudyID);

  PyLockWrapper aLock = interp->GetLockWrapper();

  _module = PyImport_ImportModule((char*)_moduleName.c_str());
  if(!_module){
    PyErr_Print();
    return false;
  }

  PyObjWrapper res(PyObject_CallMethod(_module,"setSettings",""));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 * Calls module.customPopup with popup menu to custom, and string values of
 * context, parent and selected object (strings defined by DefinePopup, which
 * is called before).
 */
//=============================================================================

bool SALOME_PYQT_GUI::CustomPopup ( QAD_Desktop* parent,
				    QPopupMenu* popup,
				    const QString & theContext,
				    const QString & theParent,
				    const QString & theObject )
{
  MESSAGE("SALOME_PYQT_GUI::CustomPopup");

  MESSAGE ( " theContext : " << theContext.latin1() );
  MESSAGE ( " theParent : " << theParent.latin1() );
  MESSAGE ( " theObject : " << theObject.latin1() );

  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper pypop(sipMapCppToSelf( popup, sipClass_QPopupMenu));

  PyObjWrapper res(PyObject_CallMethod(_module,"customPopup",
				       "Osss",pypop.get(),
				       theContext.latin1(),
				       theObject.latin1(),
				       theParent.latin1()));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 * Calls module.definePopup to modify the strings that define context parent
 * and selected object. Called before CustomPopup.
 */
//=============================================================================

void SALOME_PYQT_GUI::DefinePopup( QString & theContext,
				   QString & theParent,
				   QString & theObject )
{
  MESSAGE("SALOME_PYQT_GUI::DefinePopup");
  theContext = "";
  theObject = "";
  theParent = "";

  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper res(PyObject_CallMethod(_module,"definePopup","sss",
				       theContext.latin1(),
				       theObject.latin1(),
				       theParent.latin1()));
  if(!res){
    PyErr_Print();
    return;
  }
  char *co, *ob, *pa;
  if(!PyArg_ParseTuple(res, "sss", &co, &ob, &pa))
  {
    // It's not a valid tuple. Do nothing.
    return;
  }

  MESSAGE ("parseOk ");
  MESSAGE (" --- " << co << " " << ob << " " << pa);

  theContext = co;
  theObject = ob;
  theParent = pa;

  MESSAGE ( " theContext : " << theContext.latin1() );
  MESSAGE ( " theParent : " << theParent.latin1() );
  MESSAGE ( " theObject : " << theObject.latin1() );
}

//=============================================================================
/*!
 * Initialize new interpreter (if not exists) with new study ID.
 * Calls module.activeStudyChanged with new study ID. Called twice.
 */
//=============================================================================

bool SALOME_PYQT_GUI::ActiveStudyChanged( QAD_Desktop* parent )
{

  int StudyID = parent->getActiveApp()->getActiveStudy()->getStudyId();
  MESSAGE("SALOME_PYQT_GUI::ActiveStudyChanged"<<StudyID<<" - " <<this);
  initInterp(StudyID);

  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper res(PyObject_CallMethod(_module,"activeStudyChanged","i", StudyID ));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 *  no call to python module.BuildPresentation() (not yet ???)
 */
//=============================================================================
void SALOME_PYQT_GUI::BuildPresentation( const Handle(SALOME_InteractiveObject)&,
                                         QAD_ViewFrame* )
{
}

//=============================================================================
/*!
 *  no call to python module.SupportedViewType() (not yet ???)
 */
//=============================================================================
void SALOME_PYQT_GUI::SupportedViewType(int* /*buffer*/, int /*bufferSize*/ )
{
}

//=============================================================================
/*!
 *  no call to python module.Deactivate() (not yet ???)
 */
//=============================================================================
void SALOME_PYQT_GUI::Deactivate()
{
}

//=============================================================================
/*!
 *  Component GUI Factory : returns a new GUI obj at each call
 */
//=============================================================================

extern "C"
{
  Standard_EXPORT SALOMEGUI* GetComponentGUI() {
    MESSAGE("SALOME_PYQT_GUI::GetComponentGUI");
    SALOMEGUI* aGUI = new SALOME_PYQT_GUI("");
    return aGUI;
  }
}
<commit_msg>PR: add   import salome   salome.salome_init() before import moduleGUI<commit_after>//=============================================================================
// File      : SALOME_PYQT_GUI.cxx
// Created   : mer jun  4 17:17:20 UTC 2003
// Author    : Paul RASCLE, EDF
// Project   : SALOME
// Copyright : EDF 2003
// $Header$
//=============================================================================

#include "SALOME_PYQT_GUI.h"

#include "QAD_Desktop.h"

#include "SALOME_Selection.h"
#include "SALOME_InteractiveObject.hxx"
#include "SALOMEGUI_QtCatchCorbaException.hxx"
#include "utilities.h"

#include <sipSalomePyQtDeclSalomePyQt.h>
#include <sipqtQWorkspace.h>
#include <sipqtQPopupMenu.h>

#include <map>
#include <string>

using namespace std;

static PyInterp_PyQt *interp = NULL;
static map<int,PyInterp_PyQt*> mapInterp;

//=============================================================================
/*!
 *  Calls module.setWorkSpace with PyQt QWorkspace object to use with
 *  interpreter.
 */
//=============================================================================

void SALOME_PYQT_GUI::setWorkSpace()
{
  MESSAGE("setWorkSpace");
  PyLockWrapper aLock = interp->GetLockWrapper();

  //   Try to import qt module. If it's not possible don't go on
  PyObjWrapper qtmodule(PyImport_ImportModule("qt"));
  if(!qtmodule){
    PyErr_Print();
    return ;
  }

  PyObjWrapper pyws(sipMapCppToSelf( QAD_Application::getDesktop()->getMainFrame(),
				     sipClass_QWorkspace));
  PyObjWrapper res(PyObject_CallMethod(_module,"setWorkSpace","O",pyws.get()));
  SCRUTE(pyws->ob_refcnt);
  if(!res){
    PyErr_Print();
    return ;
  }
}

//=============================================================================
/*!
 *  Import Python module (from _moduleName)
 */
//=============================================================================
void SALOME_PYQT_GUI::importModule()
{
  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper amod = PyImport_ImportModule("salome");
  if(!amod){
    MESSAGE ( " Problem import salome... " );
    PyErr_Print();
    return;
  }

  PyObjWrapper res(PyObject_CallMethod(amod,"salome_init",""));
  if(!res){
    MESSAGE ( " Problem... " );
    PyErr_Print();
    return;
  }

  _module=PyImport_ImportModule((char*)_moduleName.c_str());
  if(!_module){
    MESSAGE ( " Problem... " );
    PyErr_Print();
    return;
  }
}

//=============================================================================
/*!
 *  Initialises python interpreter (only one per study), imports python module
 *  from given module name, sets static reference to module,
 *  sets module workspace.
 */
//=============================================================================

void SALOME_PYQT_GUI::initInterp(int StudyID)
{
  MESSAGE("SALOME_PYQT_GUI::initInterp");
  if(mapInterp.find(StudyID) != mapInterp.end()){
    MESSAGE ( "SALOME_PYQT_GUI::initInterp StudyID is found " << StudyID );
    interp = mapInterp[StudyID];
    return;
  }else{
    MESSAGE ( "SALOME_PYQT_GUI::initInterp StudyID is not found " << StudyID );
    /*
     * The creation of Python interpretor must be protected par a C++ Lock because of C threads
     */
    ThreadLock aPyLock = GetPyThreadLock("SALOME_PYQT_GUI::initInterp");
    interp = new PyInterp_PyQt();
    interp->initialize();
    mapInterp[StudyID] = interp;
  }
  // imports Python GUI module and puts it in _module attribute
  importModule();
  // calls _module.setWorkspace and passes the SIP object main workspace
  setWorkSpace();

}

//=============================================================================
/*!
 * constructor : only calls SALOMEGUI constructor
 */
//=============================================================================
SALOME_PYQT_GUI::SALOME_PYQT_GUI( const QString& theName, QObject* theParent ) :
    SALOMEGUI( theName, theParent ),_module(0)
{
    MESSAGE("SALOME_PYQT_GUI::SALOME_PYQT_GUI");
}

//=============================================================================
/*!
 * destructor : do nothing
 */
//=============================================================================
SALOME_PYQT_GUI::~SALOME_PYQT_GUI()
{
}

//=============================================================================
/*!
 *  Calls python module.OnGUIEvent(theCommandID)
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnGUIEvent (int theCommandID,
				  QAD_Desktop* parent)
{
  MESSAGE("SALOME_PYQT_GUI::OnGUIEvent");
  ThreadLock aPyLock = GetPyThreadLock("SALOME_PYQT_GUI::OnGUIEvent");
  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper res(PyObject_CallMethod(_module,"OnGUIEvent","i",theCommandID));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 *  no call to python module.OnKeyPress()
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnKeyPress (QKeyEvent* pe,
				  QAD_Desktop* parent,
				  QAD_StudyFrame* studyFrame)
{
  MESSAGE("SALOME_PYQT_GUI::OnKeyPress");
  return true;
}

//=============================================================================
/*!
 *  no call to python module.OnMousePress()
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnMousePress (QMouseEvent* pe ,
				    QAD_Desktop* parent,
				    QAD_StudyFrame* studyFrame)
{
  MESSAGE("SALOME_PYQT_GUI::OnMousePress");
  return false;
}

//=============================================================================
/*!
 *  no call to python module.OnMouseMove()
 */
//=============================================================================

bool SALOME_PYQT_GUI::OnMouseMove (QMouseEvent* pe ,
				   QAD_Desktop* parent,
				   QAD_StudyFrame* studyFrame)
{
  // Commented out to avoid multiple traces ...
  // MESSAGE("SALOME_PYQT_GUI::OnMouseMove");
  return true;
}

//=============================================================================
/*!
 *  Calls initInterp to initialise python interpreter (only one per study) and
 *  to import python module. Calls module.setSettings()
 */
//=============================================================================

bool SALOME_PYQT_GUI::SetSettings (QAD_Desktop* parent, char* moduleName)
{
  MESSAGE("SALOME_PYQT_GUI::SetSettings");
  int StudyID = QAD_Application::getDesktop()->getActiveStudy()->getStudyId();
  SCRUTE ( StudyID );
  _moduleName = moduleName + string("GUI");
  SCRUTE(_moduleName);

  // initializes one Python interpreter by study and puts it in interp global variable
  // imports Python GUI module and puts it in _module attribute
  // calls _module.setWorkspace and passes the SIP object main workspace
  initInterp(StudyID);

  PyLockWrapper aLock = interp->GetLockWrapper();

  _module = PyImport_ImportModule((char*)_moduleName.c_str());
  if(!_module){
    PyErr_Print();
    return false;
  }

  PyObjWrapper res(PyObject_CallMethod(_module,"setSettings",""));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 * Calls module.customPopup with popup menu to custom, and string values of
 * context, parent and selected object (strings defined by DefinePopup, which
 * is called before).
 */
//=============================================================================

bool SALOME_PYQT_GUI::CustomPopup ( QAD_Desktop* parent,
				    QPopupMenu* popup,
				    const QString & theContext,
				    const QString & theParent,
				    const QString & theObject )
{
  MESSAGE("SALOME_PYQT_GUI::CustomPopup");

  MESSAGE ( " theContext : " << theContext.latin1() );
  MESSAGE ( " theParent : " << theParent.latin1() );
  MESSAGE ( " theObject : " << theObject.latin1() );

  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper pypop(sipMapCppToSelf( popup, sipClass_QPopupMenu));

  PyObjWrapper res(PyObject_CallMethod(_module,"customPopup",
				       "Osss",pypop.get(),
				       theContext.latin1(),
				       theObject.latin1(),
				       theParent.latin1()));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 * Calls module.definePopup to modify the strings that define context parent
 * and selected object. Called before CustomPopup.
 */
//=============================================================================

void SALOME_PYQT_GUI::DefinePopup( QString & theContext,
				   QString & theParent,
				   QString & theObject )
{
  MESSAGE("SALOME_PYQT_GUI::DefinePopup");
  theContext = "";
  theObject = "";
  theParent = "";

  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper res(PyObject_CallMethod(_module,"definePopup","sss",
				       theContext.latin1(),
				       theObject.latin1(),
				       theParent.latin1()));
  if(!res){
    PyErr_Print();
    return;
  }
  char *co, *ob, *pa;
  if(!PyArg_ParseTuple(res, "sss", &co, &ob, &pa))
  {
    // It's not a valid tuple. Do nothing.
    return;
  }

  MESSAGE ("parseOk ");
  MESSAGE (" --- " << co << " " << ob << " " << pa);

  theContext = co;
  theObject = ob;
  theParent = pa;

  MESSAGE ( " theContext : " << theContext.latin1() );
  MESSAGE ( " theParent : " << theParent.latin1() );
  MESSAGE ( " theObject : " << theObject.latin1() );
}

//=============================================================================
/*!
 * Initialize new interpreter (if not exists) with new study ID.
 * Calls module.activeStudyChanged with new study ID. Called twice.
 */
//=============================================================================

bool SALOME_PYQT_GUI::ActiveStudyChanged( QAD_Desktop* parent )
{

  int StudyID = parent->getActiveApp()->getActiveStudy()->getStudyId();
  MESSAGE("SALOME_PYQT_GUI::ActiveStudyChanged"<<StudyID<<" - " <<this);
  initInterp(StudyID);

  PyLockWrapper aLock = interp->GetLockWrapper();

  PyObjWrapper res(PyObject_CallMethod(_module,"activeStudyChanged","i", StudyID ));
  if(!res){
    PyErr_Print();
    return false;
  }
  return true;
}

//=============================================================================
/*!
 *  no call to python module.BuildPresentation() (not yet ???)
 */
//=============================================================================
void SALOME_PYQT_GUI::BuildPresentation( const Handle(SALOME_InteractiveObject)&,
                                         QAD_ViewFrame* )
{
}

//=============================================================================
/*!
 *  no call to python module.SupportedViewType() (not yet ???)
 */
//=============================================================================
void SALOME_PYQT_GUI::SupportedViewType(int* /*buffer*/, int /*bufferSize*/ )
{
}

//=============================================================================
/*!
 *  no call to python module.Deactivate() (not yet ???)
 */
//=============================================================================
void SALOME_PYQT_GUI::Deactivate()
{
}

//=============================================================================
/*!
 *  Component GUI Factory : returns a new GUI obj at each call
 */
//=============================================================================

extern "C"
{
  Standard_EXPORT SALOMEGUI* GetComponentGUI() {
    MESSAGE("SALOME_PYQT_GUI::GetComponentGUI");
    SALOMEGUI* aGUI = new SALOME_PYQT_GUI("");
    return aGUI;
  }
}
<|endoftext|>