<commit_before>#include "include/geom.h"
#include <assert.h>

Constructor::Constructor(MoveListener listener) :
    Scope(listener), angles() {}

Constructor::~Constructor()
{
    for (auto *a : angles)
        delete a;
    Scope::~Scope();
}

bool Constructor::contains(const Angle *a) const
{
    return a != nullptr &&
           std::count_if(angles.begin(), angles.end(), [a](const Angle *p) {return *p == *a; });
}

void Constructor::add(const Angle *a)
{
    if (!contains(a))
        angles.push_back(a);
}

#define _make_move(movetype, arg1, arg1type, arg2, arg2type, res, restype) do {               \
    if (res != nullptr) {                                                                     \
        Scope::add(res);                                                                       \
        Scope::listener(Move<arg1type,arg2type,restype>(MoveType::movetype, arg1, arg2, res)); \
    }} while (0)

const LineSegment *Constructor::join_segment(const Point &a, const Point &b)
{
    if (!Scope::contains(&a) || !Scope::contains(&b))
        return nullptr;

    const LineSegment *res = new LineSegment(a, b);
    Scope::add(res);
    _make_move(straightedge, &a, Point, &b, Point, res, Line);
    return res;
}

const Angle *Constructor::join_angle(const Point &end1, const Point &vertex, const Point &end2)
{
    if (!Scope::contains(&end1) || !Scope::contains(&vertex) || !Scope::contains(&end2))
        return nullptr;

    const Angle *res = new Angle(end1, vertex, end2);
    add(res);
    if (!Scope::contains(&res->l1)) {
        Scope::add(&res->l1);
        _make_move(straightedge, &vertex, Point, &end1, Point, &res->l1, Line);
    }
    if (!Scope::contains(&res->l2)) {
        Scope::add(&res->l2);
        _make_move(straightedge, &vertex, Point, &end2, Point, &res->l2, Line);
    }
    return res;
}

#undef _make_move

const Line *Constructor::perpendicular(const Line &l, const Point &p)
{
    const Point *o1, *o2;
    const Circle *c, *c1, *c2;
    const Line &l1 (l); // ensure containment for line segments

    if (!Scope::contains(&p) || !Scope::contains(&l))
        return nullptr;

    // generate two points on the line equidistant from p

    o1 = nullptr;
    for (auto *p2 : points)
        if (l1.contains(*p2) && *p2 != p) { o1 = p2; break; }
    assert(o1 != nullptr);

    c = join_circle(p, *o1);
    assert(c != nullptr);

    auto pair = meet(l1, *c); // the copy constructor works well with Scope::contains
    o2 = pair.first == o1 ? pair.second : pair.first;
    assert(o2 != nullptr);

    // create circles from o1 to o2 and from o2 to o1

    c1 = join_circle(*o1, *o2);
    c2 = join_circle(*o2, *o1);
    assert(c1 != nullptr);
    assert(c2 != nullptr);
    assert(*c1 != *c2); // o1 and o2 are different

    pair = meet(*c1, *c2);
    assert(pair.first != nullptr);
    assert(pair.second != nullptr);
    assert(*pair.first != *pair.second); // c1 and c2 are different

    return join_line(*pair.first, *pair.second);

    // the deletion of all these items are to be handled by ~Scope()
}

const Line *Constructor::parallel(const Line &l, const Point &p)
{
    if (l.contains(p))
        return &l;

    auto perp = perpendicular(l, p);
    if (perp == nullptr)
        return nullptr;

    return perpendicular(*perp, p);
}

const LineSegment *Constructor::translate(const LineSegment &l, const Point &start)
{
    const Line *par, *diff, *diff1;
    const Point *end;
    const LineSegment *res;

    par = parallel(l, start);
    if (par == nullptr) // l or start isn't added
        return nullptr;

    diff = join_line(l.start, start);
    assert(diff != nullptr);

    diff1 = parallel(*diff, l.end);
    assert(diff1 != nullptr);

    end = meet(*par, *diff1);
    assert(end != nullptr); // TODO move these assertions to Scope

    res = new LineSegment(start, *end);
    Scope::add(res);
    return res;
}

#define _ratio(l1, l2) ((l1).x_coeff == 0) ? sgn((l1).y_coeff * (l2).y_coeff) : sgn((l1).x_coeff * (l2).x_coeff)

const Angle *Constructor::translate(const Angle &a, const Point &p)
{
    const Line *l1 = parallel(a.l1, p),
               *l2 = parallel(a.l2, p);
    // the sign of the ratio of nonconstant coefficients for l1 and l2
    int r1 = _ratio(a.l1, *l1),
        r2 = _ratio(a.l2, *l2);

    const Angle *res = new Angle(*l1, *l2, r1 * a.region1, r2 * a.region2);
    add(res);
    return res;
}

#undef _ratio

const Line *Constructor::bisect(const Point &a, const Point &b)
{
    const Circle *c1 = join_circle(a, b),
                 *c2 = join_circle(b, a);

    if (c1 == nullptr || c2 == nullptr || c1 == c2)
        return nullptr;
    auto _meet = meet(*c1, *c2);
    assert(_meet.first != nullptr);
    assert(_meet.second != nullptr);

    return join_line(*_meet.first, *_meet.second);
}

const Line *Constructor::bisect(const LineSegment &l)
{
    return bisect(l.start, l.end);
}

const Line *Constructor::bisect(const Angle &a)
{
    if (a.l1 == a.l2)
        return &a.l1;

    // find point on l1 other than vertex
    const Point *p1 = nullptr;
    for (auto *p : points)
        if (a.l1.contains(*p) && *p != a.vertex) { p1 = p; break; }
    assert(p1 != nullptr);

    // find point on l2 with same region as p1
    const Circle *c = join_circle(a.vertex, *p1);
    auto _meet = meet(a.l2, *c);
    assert(_meet.first != nullptr);
    assert(_meet.second != nullptr);

    const Point *p2 = a.l1.precedes(a.vertex, *p1) == a.l1.precedes(a.vertex, *_meet.first) ? _meet.first : _meet.second;
    return join_line(*p1, *p2);
}

const Point *Constructor::midpoint(const Point &a, const Point &b)
{
    const Line *l1 = join_line(a, b),
               *l2 = bisect(a, b);
    if (l1 == nullptr || l2 == nullptr)
        return nullptr;
    return meet(*l1, *l2);
}

const Point *Constructor::midpoint(const LineSegment &a)
{
    return midpoint(a.start, a.end);
}

const Point *Constructor::reflect(const Point &a, const Point &pivot)
{
    const Line *l = join_line(a, pivot);
    const Circle *c = join_circle(pivot, a);
    auto _meet = meet(*l, *c);

    if (_meet.first == nullptr || _meet.second == nullptr)
        return nullptr;

    return *_meet.first == a ? _meet.second : _meet.first;
}

const Point *Constructor::reflect(const Point &a, const Line &pivot)
{
    const Line &p (pivot), // override within_boundary
               *l = perpendicular(p, a);

    if (l == nullptr)
        return nullptr;
    const Point *c = meet(p, *l);

    if (c == nullptr)
        return nullptr;
    return reflect(a, *c);
}

const Line *Constructor::reflect(const Line &a, const Point &pivot)
{
    const Line &l (a),
               *p = perpendicular(l, pivot);

    if (p == nullptr)
        return nullptr;
    const Point *b = reflect(*meet(l, *p), pivot);

    if (b == nullptr)
        return nullptr;
    return perpendicular(*p, *b);
}

const Line *Constructor::reflect(const Line &a, const Line &pivot)
{
    // different cases for a and pivot being parallel or not
    const Point *vertex = meet(a, pivot), *p1 = nullptr;

    if (vertex == nullptr) { // parallel
        // find point on pivot
        for (auto *p : points)
            if (pivot.contains(*p)) { p1 = p; break; }
        assert(p1 != nullptr);

        // reflect a by p1
        return reflect(a, *p1);
    }
    // not parallel

    // find point on a
    for (auto *p : points)
        if (a.contains(*p) && *p != *vertex) { p1 = p; break; }
    assert(p1 != nullptr);

    // reflect p1 around pivot
    const Point *p = reflect(*p1, pivot);

    if (p == nullptr)
        return nullptr;
    return join_line(*vertex, *p);
}

const Line *Constructor::rotate(const Line &l, const Angle &a, const Point &pivot)
{
    // find bisector of angle
    const Line *l1 = bisect(a);
    assert(l1 != nullptr);

    // get parallel of bisector at pivot
    l1 = parallel(*l1, pivot);
    assert(l1 != nullptr);

    // reflect line around parallel
    return reflect(l, *l1);
}

const LineSegment *Constructor::rotate(const LineSegment &l, const Angle &a)
{
    // find bisector of angle
    const Line *l1 = bisect(a);
    if (l1 == nullptr) return nullptr;

    // get parallel of bisector at l.start
    l1 = parallel(*l1, l.start);
    if (l1 == nullptr) return nullptr;

    // reflect end around parallel
    const Point *end = reflect(l.end, *l1);
    if (end == nullptr) return nullptr;

    // connect start and end
    return join_segment(l.start, *end);

    /* Awful previous algorithm:
    // - Translate l to the vertex of a, call the new segment l1
    const LineSegment *l1 = translate(l, a.vertex);

    // - Draw circle with center l1.start and touching l1.end
    if (l1 == nullptr)
        return nullptr;
    const Circle *c = join_circle(l1->start, l1->end);

    // - Pick the meets p1 and p2 of the circle with a.l1 and a.l2 that lie in a.region1 and a.region2
    auto meet1 = meet(a.l1, *c),
         meet2 = meet(a.l2, *c);
    assert(meet1.second != nullptr);
    assert(meet2.second != nullptr);
    const Point *p1 = a.l1.precedes(a.vertex, *meet1.first) == (a.region1 > 0) ? meet1.first : meet1.second,
                *p2 = a.l2.precedes(a.vertex, *meet2.first) == (a.region2 > 0) ? meet2.first : meet2.second;

    // - Find perpendicular bisector to l1.end and p2
    const Line *l2 = bisect(l1->end, *p2);
    assert(l2 != nullptr);

    // - Reflect p1 around the bisector
    const Point *p = reflect(*p1, *l2);
    assert(p != nullptr);

    // - Connect l1.start with p1 and translate the new line segment back to l.start
    const LineSegment *l3 = join_segment(l1->start, *p);
    assert(l3 != nullptr);

    return translate(*l3, l.start);
    */
}
<commit_msg>Added destructor for Constructor<commit_after>#include "include/geom.h"
#include <assert.h>

Constructor::Constructor(MoveListener listener) :
    Scope(listener), angles() {}

Constructor::~Constructor()
{
    for (auto *a : angles)
        delete a;
}

bool Constructor::contains(const Angle *a) const
{
    return a != nullptr &&
           std::count_if(angles.begin(), angles.end(), [a](const Angle *p) {return *p == *a; });
}

void Constructor::add(const Angle *a)
{
    if (!contains(a))
        angles.push_back(a);
}

#define _make_move(movetype, arg1, arg1type, arg2, arg2type, res, restype) do {               \
    if (res != nullptr) {                                                                     \
        Scope::add(res);                                                                       \
        Scope::listener(Move<arg1type,arg2type,restype>(MoveType::movetype, arg1, arg2, res)); \
    }} while (0)

const LineSegment *Constructor::join_segment(const Point &a, const Point &b)
{
    if (!Scope::contains(&a) || !Scope::contains(&b))
        return nullptr;

    const LineSegment *res = new LineSegment(a, b);
    Scope::add(res);
    _make_move(straightedge, &a, Point, &b, Point, res, Line);
    return res;
}

const Angle *Constructor::join_angle(const Point &end1, const Point &vertex, const Point &end2)
{
    if (!Scope::contains(&end1) || !Scope::contains(&vertex) || !Scope::contains(&end2))
        return nullptr;

    const Angle *res = new Angle(end1, vertex, end2);
    add(res);
    if (!Scope::contains(&res->l1)) {
        Scope::add(&res->l1);
        _make_move(straightedge, &vertex, Point, &end1, Point, &res->l1, Line);
    }
    if (!Scope::contains(&res->l2)) {
        Scope::add(&res->l2);
        _make_move(straightedge, &vertex, Point, &end2, Point, &res->l2, Line);
    }
    return res;
}

#undef _make_move

const Line *Constructor::perpendicular(const Line &l, const Point &p)
{
    const Point *o1, *o2;
    const Circle *c, *c1, *c2;
    const Line &l1 (l); // ensure containment for line segments

    if (!Scope::contains(&p) || !Scope::contains(&l))
        return nullptr;

    // generate two points on the line equidistant from p

    o1 = nullptr;
    for (auto *p2 : points)
        if (l1.contains(*p2) && *p2 != p) { o1 = p2; break; }
    assert(o1 != nullptr);

    c = join_circle(p, *o1);
    assert(c != nullptr);

    auto pair = meet(l1, *c); // the copy constructor works well with Scope::contains
    o2 = pair.first == o1 ? pair.second : pair.first;
    assert(o2 != nullptr);

    // create circles from o1 to o2 and from o2 to o1

    c1 = join_circle(*o1, *o2);
    c2 = join_circle(*o2, *o1);
    assert(c1 != nullptr);
    assert(c2 != nullptr);
    assert(*c1 != *c2); // o1 and o2 are different

    pair = meet(*c1, *c2);
    assert(pair.first != nullptr);
    assert(pair.second != nullptr);
    assert(*pair.first != *pair.second); // c1 and c2 are different

    return join_line(*pair.first, *pair.second);

    // the deletion of all these items are to be handled by ~Scope()
}

const Line *Constructor::parallel(const Line &l, const Point &p)
{
    if (l.contains(p))
        return &l;

    auto perp = perpendicular(l, p);
    if (perp == nullptr)
        return nullptr;

    return perpendicular(*perp, p);
}

const LineSegment *Constructor::translate(const LineSegment &l, const Point &start)
{
    const Line *par, *diff, *diff1;
    const Point *end;
    const LineSegment *res;

    par = parallel(l, start);
    if (par == nullptr) // l or start isn't added
        return nullptr;

    diff = join_line(l.start, start);
    assert(diff != nullptr);

    diff1 = parallel(*diff, l.end);
    assert(diff1 != nullptr);

    end = meet(*par, *diff1);
    assert(end != nullptr); // TODO move these assertions to Scope

    res = new LineSegment(start, *end);
    Scope::add(res);
    return res;
}

#define _ratio(l1, l2) ((l1).x_coeff == 0) ? sgn((l1).y_coeff * (l2).y_coeff) : sgn((l1).x_coeff * (l2).x_coeff)

const Angle *Constructor::translate(const Angle &a, const Point &p)
{
    const Line *l1 = parallel(a.l1, p),
               *l2 = parallel(a.l2, p);
    // the sign of the ratio of nonconstant coefficients for l1 and l2
    int r1 = _ratio(a.l1, *l1),
        r2 = _ratio(a.l2, *l2);

    const Angle *res = new Angle(*l1, *l2, r1 * a.region1, r2 * a.region2);
    add(res);
    return res;
}

#undef _ratio

const Line *Constructor::bisect(const Point &a, const Point &b)
{
    const Circle *c1 = join_circle(a, b),
                 *c2 = join_circle(b, a);

    if (c1 == nullptr || c2 == nullptr || c1 == c2)
        return nullptr;
    auto _meet = meet(*c1, *c2);
    assert(_meet.first != nullptr);
    assert(_meet.second != nullptr);

    return join_line(*_meet.first, *_meet.second);
}

const Line *Constructor::bisect(const LineSegment &l)
{
    return bisect(l.start, l.end);
}

const Line *Constructor::bisect(const Angle &a)
{
    if (a.l1 == a.l2)
        return &a.l1;

    // find point on l1 other than vertex
    const Point *p1 = nullptr;
    for (auto *p : points)
        if (a.l1.contains(*p) && *p != a.vertex) { p1 = p; break; }
    assert(p1 != nullptr);

    // find point on l2 with same region as p1
    const Circle *c = join_circle(a.vertex, *p1);
    auto _meet = meet(a.l2, *c);
    assert(_meet.first != nullptr);
    assert(_meet.second != nullptr);

    const Point *p2 = a.l1.precedes(a.vertex, *p1) == a.l1.precedes(a.vertex, *_meet.first) ? _meet.first : _meet.second;
    return join_line(*p1, *p2);
}

const Point *Constructor::midpoint(const Point &a, const Point &b)
{
    const Line *l1 = join_line(a, b),
               *l2 = bisect(a, b);
    if (l1 == nullptr || l2 == nullptr)
        return nullptr;
    return meet(*l1, *l2);
}

const Point *Constructor::midpoint(const LineSegment &a)
{
    return midpoint(a.start, a.end);
}

const Point *Constructor::reflect(const Point &a, const Point &pivot)
{
    const Line *l = join_line(a, pivot);
    const Circle *c = join_circle(pivot, a);
    auto _meet = meet(*l, *c);

    if (_meet.first == nullptr || _meet.second == nullptr)
        return nullptr;

    return *_meet.first == a ? _meet.second : _meet.first;
}

const Point *Constructor::reflect(const Point &a, const Line &pivot)
{
    const Line &p (pivot), // override within_boundary
               *l = perpendicular(p, a);

    if (l == nullptr)
        return nullptr;
    const Point *c = meet(p, *l);

    if (c == nullptr)
        return nullptr;
    return reflect(a, *c);
}

const Line *Constructor::reflect(const Line &a, const Point &pivot)
{
    const Line &l (a),
               *p = perpendicular(l, pivot);

    if (p == nullptr)
        return nullptr;
    const Point *b = reflect(*meet(l, *p), pivot);

    if (b == nullptr)
        return nullptr;
    return perpendicular(*p, *b);
}

const Line *Constructor::reflect(const Line &a, const Line &pivot)
{
    // different cases for a and pivot being parallel or not
    const Point *vertex = meet(a, pivot), *p1 = nullptr;

    if (vertex == nullptr) { // parallel
        // find point on pivot
        for (auto *p : points)
            if (pivot.contains(*p)) { p1 = p; break; }
        assert(p1 != nullptr);

        // reflect a by p1
        return reflect(a, *p1);
    }
    // not parallel

    // find point on a
    for (auto *p : points)
        if (a.contains(*p) && *p != *vertex) { p1 = p; break; }
    assert(p1 != nullptr);

    // reflect p1 around pivot
    const Point *p = reflect(*p1, pivot);

    if (p == nullptr)
        return nullptr;
    return join_line(*vertex, *p);
}

const Line *Constructor::rotate(const Line &l, const Angle &a, const Point &pivot)
{
    // find bisector of angle
    const Line *l1 = bisect(a);
    assert(l1 != nullptr);

    // get parallel of bisector at pivot
    l1 = parallel(*l1, pivot);
    assert(l1 != nullptr);

    // reflect line around parallel
    return reflect(l, *l1);
}

const LineSegment *Constructor::rotate(const LineSegment &l, const Angle &a)
{
    // find bisector of angle
    const Line *l1 = bisect(a);
    if (l1 == nullptr) return nullptr;

    // get parallel of bisector at l.start
    l1 = parallel(*l1, l.start);
    if (l1 == nullptr) return nullptr;

    // reflect end around parallel
    const Point *end = reflect(l.end, *l1);
    if (end == nullptr) return nullptr;

    // connect start and end
    return join_segment(l.start, *end);

    /* Awful previous algorithm:
    // - Translate l to the vertex of a, call the new segment l1
    const LineSegment *l1 = translate(l, a.vertex);

    // - Draw circle with center l1.start and touching l1.end
    if (l1 == nullptr)
        return nullptr;
    const Circle *c = join_circle(l1->start, l1->end);

    // - Pick the meets p1 and p2 of the circle with a.l1 and a.l2 that lie in a.region1 and a.region2
    auto meet1 = meet(a.l1, *c),
         meet2 = meet(a.l2, *c);
    assert(meet1.second != nullptr);
    assert(meet2.second != nullptr);
    const Point *p1 = a.l1.precedes(a.vertex, *meet1.first) == (a.region1 > 0) ? meet1.first : meet1.second,
                *p2 = a.l2.precedes(a.vertex, *meet2.first) == (a.region2 > 0) ? meet2.first : meet2.second;

    // - Find perpendicular bisector to l1.end and p2
    const Line *l2 = bisect(l1->end, *p2);
    assert(l2 != nullptr);

    // - Reflect p1 around the bisector
    const Point *p = reflect(*p1, *l2);
    assert(p != nullptr);

    // - Connect l1.start with p1 and translate the new line segment back to l.start
    const LineSegment *l3 = join_segment(l1->start, *p);
    assert(l3 != nullptr);

    return translate(*l3, l.start);
    */
}
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Microsoft Corporation
 *
 * -=- Robust Distributed System Nucleus (rDSN) -=-
 *
 * 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.
 */
# include <dsn/internal/task_worker.h>
# include "task_engine.h"
# include <sstream>
# include <errno.h>

# ifdef _WIN32

# else
# include <pthread.h>

# ifdef __FreeBSD__
# include <pthread_np.h>
# endif

# ifdef __APPLE__
# include <mach/thread_policy.h>
# endif

# endif

# ifdef __TITLE__
# undef __TITLE__
# endif
# define __TITLE__ "task.worker"

namespace dsn {

join_point<void, task_worker*> task_worker::on_start("task_worker::on_start");
join_point<void, task_worker*> task_worker::on_create("task_worker::on_create");

task_worker::task_worker(task_worker_pool* pool, task_queue* q, int index, task_worker* inner_provider)
{
    _owner_pool = pool;
    _input_queue = q;
    _index = index;
    _native_tid = ::dsn::utils::get_invalid_tid();

    char name[256];
    sprintf(name, "%5s.%s.%u", pool->node()->name(), pool->spec().name.c_str(), index);
    _name = std::string(name);
    _is_running = false;

    _thread = nullptr;
}

task_worker::~task_worker()
{
    stop();
}

void task_worker::start()
{
    if (_is_running)
        return;

    _is_running = true;

    _thread = new std::thread(std::bind(&task_worker::run_internal, this));

    _started.wait();
}

void task_worker::stop()
{
    if (!_is_running)
        return;

    _is_running = false;

    _thread->join();
    delete _thread;
    _thread = nullptr;

    _is_running = false;
}

void task_worker::set_name()
{
# ifdef _WIN32

    #ifndef MS_VC_EXCEPTION
    #define MS_VC_EXCEPTION 0x406D1388
    #endif

    typedef struct tagTHREADNAME_INFO
    {
        uint32_t  dwType; // Must be 0x1000.
        LPCSTR szName; // Pointer to name (in user addr space).
        uint32_t  dwThreadID; // Thread ID (-1=caller thread).
        uint32_t  dwFlags; // Reserved for future use, must be zero.
    }THREADNAME_INFO;

    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = name().c_str();
    info.dwThreadID = (uint32_t)-1;
    info.dwFlags = 0;

    __try
    {
        ::RaiseException (MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(uint32_t), (ULONG_PTR*)&info);
    }
    __except(EXCEPTION_CONTINUE_EXECUTION)
    {
    }

# else
    auto thread_name = name()
    # ifdef __linux__
        .substr(0, (16 - 1))
    # endif
    ;
    auto tid = _thread->native_handle();
    int err = 0;
    # ifdef __FreeBSD__
    pthread_set_name_np(tid, thread_name.c_str());
    # elif defined(__linux__)
    err = pthread_setname_np(tid, thread_name.c_str());
    # elif defined(__APPLE__)
    err = pthread_setname_np(thread_name.c_str());
    # endif
    if (err != 0)
    {
        dwarn("Fail to set pthread name. ret = %d", err);
    }
# endif
}

void task_worker::set_priority(worker_priority_t pri)
{
# ifndef _WIN32
    static int policy = SCHED_OTHER;
    static int prio_max =
    #ifdef __linux__
        -20;
    #else
        sched_get_priority_max(policy);
    #endif
    static int prio_min =
    #ifdef __linux__
        19;
    #else
        sched_get_priority_min(policy);
    #endif
    static int prio_middle = ((prio_min + prio_max + 1) / 2);
#endif

    static int g_thread_priority_map[] =
    {
# ifdef _WIN32
        THREAD_PRIORITY_LOWEST,
        THREAD_PRIORITY_BELOW_NORMAL,
        THREAD_PRIORITY_NORMAL,
        THREAD_PRIORITY_ABOVE_NORMAL,
        THREAD_PRIORITY_HIGHEST
# else
        prio_min,
        (prio_min + prio_middle) / 2,
        prio_middle,
        (prio_middle + prio_max) / 2,
        prio_max
# endif
    };

    static_assert(ARRAYSIZE(g_thread_priority_map) == THREAD_xPRIORITY_COUNT,
        "ARRAYSIZE(g_thread_priority_map) != THREAD_xPRIORITY_COUNT");

    int prio = g_thread_priority_map[static_cast<int>(pri)];
    bool succ = true;
# if !defined(_WIN32) && !defined(__linux__)
    struct sched_param param;
    memset(&param, 0, sizeof(struct sched_param));
    param.sched_priority = prio;
# endif

# ifdef _WIN32
    succ = (::SetThreadPriority(_thread->native_handle(), prio) == TRUE);
# elif defined(__linux__)
    if ((nice(prio) == -1) && (errno != 0))
    {
        succ = false;
    }
# else
    succ = (pthread_setschedparam(_thread->native_handle(), policy, &param) == 0);
//# error "not implemented"
# endif

    if (!succ)
    {
        dwarn("You may need priviledge to set thread priority. errno = %d.\n", errno);
    }
}

void task_worker::set_affinity(uint64_t affinity)
{
    dassert(affinity > 0, "affinity cannot be 0.");

    int nr_cpu = static_cast<int>(std::thread::hardware_concurrency());
    dassert(affinity <= (((uint64_t)1 << nr_cpu) - 1),
        "There are %d cpus in total, while setting thread affinity to a nonexistent one.", nr_cpu);

    auto tid = _thread->native_handle();
    int err;
# ifdef _WIN32
    if (::SetThreadAffinityMask(tid, static_cast<DWORD_PTR>(affinity)) == 0)
    {
        err = static_cast<int>::GetLastError();
    }
# elif defined(__APPLE__)
    thread_affinity_policy_data_t policy;
    policy.affinity_tag = static_cast<integer_t>(affinity);
    err = static_cast<int>(thread_policy_set(
        static_cast<thread_t>(::dsn::utils::get_current_tid()),
        THREAD_AFFINITY_POLICY,
        (thread_policy_t)&policy,
        THREAD_AFFINITY_POLICY_COUNT
        ));
# else
    # ifdef __FreeBSD__
        # ifndef cpu_set_t
            # define cpu_set_t cpuset_t
        # endif
    # endif
    cpu_set_t cpuset;
    int nr_bits = std::min(nr_cpu, static_cast<int>(sizeof(affinity) * 8));

    CPU_ZERO(&cpuset);
    for (int i = 0; i < nr_bits; i++)
    {
        if ((affinity & ((uint64_t)1 << i)) != 0)
        {
            CPU_SET(i, &cpuset);
        }
    }
    err = pthread_setaffinity_np(tid, sizeof(cpuset), &cpuset);
# endif

    if (err != 0)
    {
        dwarn("Fail to set thread affinity. err = %d", err);
    }
}

void task_worker::run_internal()
{
    while (_thread == nullptr)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    task::set_current_worker(this);

    _native_tid = ::dsn::utils::get_current_tid();
    set_name();
    set_priority(pool_spec().worker_priority);

    if (true == pool_spec().worker_share_core)
    {
        if (pool_spec().worker_affinity_mask > 0)
        {
            set_affinity(pool_spec().worker_affinity_mask);
        }
    }
    else
    {
        uint64_t current_mask = pool_spec().worker_affinity_mask;
        for (int i = 0; i < _index; ++i)
        {
            current_mask &= (current_mask - 1);
            if (0 == current_mask)
            {
                current_mask = pool_spec().worker_affinity_mask;
            }
        }
        current_mask -= (current_mask & (current_mask - 1));

        set_affinity(current_mask);
    }

    _started.notify();

    on_start.execute(this);

    loop();
}

void task_worker::loop()
{
    task_queue* q = queue();

    //try {
        while (_is_running)
        {
            task_ptr task = q->dequeue();
            if (task != nullptr)
            {
                task->exec_internal();
            }
        }
    /*}
    catch (std::exception& ex)
    {
        dassert (false, "%s: unhandled exception '%s'", name().c_str(), ex.what());
    }*/
}

const threadpool_spec& task_worker::pool_spec() const
{
    return pool()->spec();
}

} // end namespace
<commit_msg>Fix a typo.<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Microsoft Corporation
 *
 * -=- Robust Distributed System Nucleus (rDSN) -=-
 *
 * 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.
 */
# include <dsn/internal/task_worker.h>
# include "task_engine.h"
# include <sstream>
# include <errno.h>

# ifdef _WIN32

# else
# include <pthread.h>

# ifdef __FreeBSD__
# include <pthread_np.h>
# endif

# ifdef __APPLE__
# include <mach/thread_policy.h>
# endif

# endif

# ifdef __TITLE__
# undef __TITLE__
# endif
# define __TITLE__ "task.worker"

namespace dsn {

join_point<void, task_worker*> task_worker::on_start("task_worker::on_start");
join_point<void, task_worker*> task_worker::on_create("task_worker::on_create");

task_worker::task_worker(task_worker_pool* pool, task_queue* q, int index, task_worker* inner_provider)
{
    _owner_pool = pool;
    _input_queue = q;
    _index = index;
    _native_tid = ::dsn::utils::get_invalid_tid();

    char name[256];
    sprintf(name, "%5s.%s.%u", pool->node()->name(), pool->spec().name.c_str(), index);
    _name = std::string(name);
    _is_running = false;

    _thread = nullptr;
}

task_worker::~task_worker()
{
    stop();
}

void task_worker::start()
{
    if (_is_running)
        return;

    _is_running = true;

    _thread = new std::thread(std::bind(&task_worker::run_internal, this));

    _started.wait();
}

void task_worker::stop()
{
    if (!_is_running)
        return;

    _is_running = false;

    _thread->join();
    delete _thread;
    _thread = nullptr;

    _is_running = false;
}

void task_worker::set_name()
{
# ifdef _WIN32

    #ifndef MS_VC_EXCEPTION
    #define MS_VC_EXCEPTION 0x406D1388
    #endif

    typedef struct tagTHREADNAME_INFO
    {
        uint32_t  dwType; // Must be 0x1000.
        LPCSTR szName; // Pointer to name (in user addr space).
        uint32_t  dwThreadID; // Thread ID (-1=caller thread).
        uint32_t  dwFlags; // Reserved for future use, must be zero.
    }THREADNAME_INFO;

    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = name().c_str();
    info.dwThreadID = (uint32_t)-1;
    info.dwFlags = 0;

    __try
    {
        ::RaiseException (MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(uint32_t), (ULONG_PTR*)&info);
    }
    __except(EXCEPTION_CONTINUE_EXECUTION)
    {
    }

# else
    auto thread_name = name()
    # ifdef __linux__
        .substr(0, (16 - 1))
    # endif
    ;
    auto tid = _thread->native_handle();
    int err = 0;
    # ifdef __FreeBSD__
    pthread_set_name_np(tid, thread_name.c_str());
    # elif defined(__linux__)
    err = pthread_setname_np(tid, thread_name.c_str());
    # elif defined(__APPLE__)
    err = pthread_setname_np(thread_name.c_str());
    # endif
    if (err != 0)
    {
        dwarn("Fail to set pthread name. err = %d", err);
    }
# endif
}

void task_worker::set_priority(worker_priority_t pri)
{
# ifndef _WIN32
    static int policy = SCHED_OTHER;
    static int prio_max =
    #ifdef __linux__
        -20;
    #else
        sched_get_priority_max(policy);
    #endif
    static int prio_min =
    #ifdef __linux__
        19;
    #else
        sched_get_priority_min(policy);
    #endif
    static int prio_middle = ((prio_min + prio_max + 1) / 2);
#endif

    static int g_thread_priority_map[] =
    {
# ifdef _WIN32
        THREAD_PRIORITY_LOWEST,
        THREAD_PRIORITY_BELOW_NORMAL,
        THREAD_PRIORITY_NORMAL,
        THREAD_PRIORITY_ABOVE_NORMAL,
        THREAD_PRIORITY_HIGHEST
# else
        prio_min,
        (prio_min + prio_middle) / 2,
        prio_middle,
        (prio_middle + prio_max) / 2,
        prio_max
# endif
    };

    static_assert(ARRAYSIZE(g_thread_priority_map) == THREAD_xPRIORITY_COUNT,
        "ARRAYSIZE(g_thread_priority_map) != THREAD_xPRIORITY_COUNT");

    int prio = g_thread_priority_map[static_cast<int>(pri)];
    bool succ = true;
# if !defined(_WIN32) && !defined(__linux__)
    struct sched_param param;
    memset(&param, 0, sizeof(struct sched_param));
    param.sched_priority = prio;
# endif

# ifdef _WIN32
    succ = (::SetThreadPriority(_thread->native_handle(), prio) == TRUE);
# elif defined(__linux__)
    if ((nice(prio) == -1) && (errno != 0))
    {
        succ = false;
    }
# else
    succ = (pthread_setschedparam(_thread->native_handle(), policy, &param) == 0);
//# error "not implemented"
# endif

    if (!succ)
    {
        dwarn("You may need priviledge to set thread priority. errno = %d.\n", errno);
    }
}

void task_worker::set_affinity(uint64_t affinity)
{
    dassert(affinity > 0, "affinity cannot be 0.");

    int nr_cpu = static_cast<int>(std::thread::hardware_concurrency());
    dassert(affinity <= (((uint64_t)1 << nr_cpu) - 1),
        "There are %d cpus in total, while setting thread affinity to a nonexistent one.", nr_cpu);

    auto tid = _thread->native_handle();
    int err;
# ifdef _WIN32
    if (::SetThreadAffinityMask(tid, static_cast<DWORD_PTR>(affinity)) == 0)
    {
        err = static_cast<int>::GetLastError();
    }
# elif defined(__APPLE__)
    thread_affinity_policy_data_t policy;
    policy.affinity_tag = static_cast<integer_t>(affinity);
    err = static_cast<int>(thread_policy_set(
        static_cast<thread_t>(::dsn::utils::get_current_tid()),
        THREAD_AFFINITY_POLICY,
        (thread_policy_t)&policy,
        THREAD_AFFINITY_POLICY_COUNT
        ));
# else
    # ifdef __FreeBSD__
        # ifndef cpu_set_t
            # define cpu_set_t cpuset_t
        # endif
    # endif
    cpu_set_t cpuset;
    int nr_bits = std::min(nr_cpu, static_cast<int>(sizeof(affinity) * 8));

    CPU_ZERO(&cpuset);
    for (int i = 0; i < nr_bits; i++)
    {
        if ((affinity & ((uint64_t)1 << i)) != 0)
        {
            CPU_SET(i, &cpuset);
        }
    }
    err = pthread_setaffinity_np(tid, sizeof(cpuset), &cpuset);
# endif

    if (err != 0)
    {
        dwarn("Fail to set thread affinity. err = %d", err);
    }
}

void task_worker::run_internal()
{
    while (_thread == nullptr)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    task::set_current_worker(this);

    _native_tid = ::dsn::utils::get_current_tid();
    set_name();
    set_priority(pool_spec().worker_priority);

    if (true == pool_spec().worker_share_core)
    {
        if (pool_spec().worker_affinity_mask > 0)
        {
            set_affinity(pool_spec().worker_affinity_mask);
        }
    }
    else
    {
        uint64_t current_mask = pool_spec().worker_affinity_mask;
        for (int i = 0; i < _index; ++i)
        {
            current_mask &= (current_mask - 1);
            if (0 == current_mask)
            {
                current_mask = pool_spec().worker_affinity_mask;
            }
        }
        current_mask -= (current_mask & (current_mask - 1));

        set_affinity(current_mask);
    }

    _started.notify();

    on_start.execute(this);

    loop();
}

void task_worker::loop()
{
    task_queue* q = queue();

    //try {
        while (_is_running)
        {
            task_ptr task = q->dequeue();
            if (task != nullptr)
            {
                task->exec_internal();
            }
        }
    /*}
    catch (std::exception& ex)
    {
        dassert (false, "%s: unhandled exception '%s'", name().c_str(), ex.what());
    }*/
}

const threadpool_spec& task_worker::pool_spec() const
{
    return pool()->spec();
}

} // end namespace
<|endoftext|>


<commit_before><commit_msg>VariantAnnotateFrequency: fixed indel handling (uses normalized variant notation)<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 */

#ifndef __CPU_SIMPLE_TIMING_HH__
#define __CPU_SIMPLE_TIMING_HH__

#include "cpu/simple/base.hh"
#include "cpu/translation.hh"
#include "params/TimingSimpleCPU.hh"

class TimingSimpleCPU : public BaseSimpleCPU
{
  public:

    TimingSimpleCPU(TimingSimpleCPUParams * params);
    virtual ~TimingSimpleCPU();

    virtual void init();

  public:
    Event *drainEvent;

  private:

    /*
     * If an access needs to be broken into fragments, currently at most two,
     * the the following two classes are used as the sender state of the
     * packets so the CPU can keep track of everything. In the main packet
     * sender state, there's an array with a spot for each fragment. If a
     * fragment has already been accepted by the CPU, aka isn't waiting for
     * a retry, it's pointer is NULL. After each fragment has successfully
     * been processed, the "outstanding" counter is decremented. Once the
     * count is zero, the entire larger access is complete.
     */
    class SplitMainSenderState : public Packet::SenderState
    {
      public:
        int outstanding;
        PacketPtr fragments[2];

        int
        getPendingFragment()
        {
            if (fragments[0]) {
                return 0;
            } else if (fragments[1]) {
                return 1;
            } else {
                return -1;
            }
        }
    };

    class SplitFragmentSenderState : public Packet::SenderState
    {
      public:
        SplitFragmentSenderState(PacketPtr _bigPkt, int _index) :
            bigPkt(_bigPkt), index(_index)
        {}
        PacketPtr bigPkt;
        int index;

        void
        clearFromParent()
        {
            SplitMainSenderState * main_send_state =
                dynamic_cast<SplitMainSenderState *>(bigPkt->senderState);
            main_send_state->fragments[index] = NULL;
        }
    };

    class FetchTranslation : public BaseTLB::Translation
    {
      protected:
        TimingSimpleCPU *cpu;

      public:
        FetchTranslation(TimingSimpleCPU *_cpu)
            : cpu(_cpu)
        {}

        void
        markDelayed()
        {
            assert(cpu->_status == Running);
            cpu->_status = ITBWaitResponse;
        }

        void
        finish(Fault fault, RequestPtr req, ThreadContext *tc,
               BaseTLB::Mode mode)
        {
            cpu->sendFetch(fault, req, tc);
        }
    };
    FetchTranslation fetchTranslation;

    void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read);
    void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req,
                       uint8_t *data, bool read);

    void translationFault(Fault fault);

    void buildPacket(PacketPtr &pkt, RequestPtr req, bool read);
    void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
            RequestPtr req1, RequestPtr req2, RequestPtr req,
            uint8_t *data, bool read);

    bool handleReadPacket(PacketPtr pkt);
    // This function always implicitly uses dcache_pkt.
    bool handleWritePacket();

    /**
     * A TimingCPUPort overrides the default behaviour of the
     * recvTiming and recvRetry and implements events for the
     * scheduling of handling of incoming packets in the following
     * cycle.
     */
    class TimingCPUPort : public CpuPort
    {
      public:

        TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu)
            : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this)
        { }

      protected:

        /**
         * Snooping a coherence request, do nothing.
         */
        virtual void recvTimingSnoopReq(PacketPtr pkt) { }

        TimingSimpleCPU* cpu;

        struct TickEvent : public Event
        {
            PacketPtr pkt;
            TimingSimpleCPU *cpu;
            CpuPort *port;

            TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {}
            const char *description() const { return "Timing CPU tick"; }
            void schedule(PacketPtr _pkt, Tick t);
        };

        EventWrapper<Port, &Port::sendRetry> retryEvent;
    };

    class IcachePort : public TimingCPUPort
    {
      public:

        IcachePort(TimingSimpleCPU *_cpu)
            : TimingCPUPort(_cpu->name() + "-iport", _cpu),
              tickEvent(_cpu)
        { }

      protected:

        virtual bool recvTimingResp(PacketPtr pkt);

        virtual void recvRetry();

        struct ITickEvent : public TickEvent
        {

            ITickEvent(TimingSimpleCPU *_cpu)
                : TickEvent(_cpu) {}
            void process();
            const char *description() const { return "Timing CPU icache tick"; }
        };

        ITickEvent tickEvent;

    };

    class DcachePort : public TimingCPUPort
    {
      public:

        DcachePort(TimingSimpleCPU *_cpu)
            : TimingCPUPort(_cpu->name() + "-dport", _cpu), tickEvent(_cpu)
        { }

      protected:

        virtual bool recvTimingResp(PacketPtr pkt);

        virtual void recvRetry();

        struct DTickEvent : public TickEvent
        {
            DTickEvent(TimingSimpleCPU *_cpu)
                : TickEvent(_cpu) {}
            void process();
            const char *description() const { return "Timing CPU dcache tick"; }
        };

        DTickEvent tickEvent;

    };

    IcachePort icachePort;
    DcachePort dcachePort;

    PacketPtr ifetch_pkt;
    PacketPtr dcache_pkt;

    Tick previousTick;

  protected:

     /** Return a reference to the data port. */
    virtual CpuPort &getDataPort() { return dcachePort; }

    /** Return a reference to the instruction port. */
    virtual CpuPort &getInstPort() { return icachePort; }

  public:

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);

    virtual unsigned int drain(Event *drain_event);
    virtual void resume();

    void switchOut();
    void takeOverFrom(BaseCPU *oldCPU);

    virtual void activateContext(ThreadID thread_num, int delay);
    virtual void suspendContext(ThreadID thread_num);

    Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);

    Fault writeMem(uint8_t *data, unsigned size,
                   Addr addr, unsigned flags, uint64_t *res);

    void fetch();
    void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
    void completeIfetch(PacketPtr );
    void completeDataAccess(PacketPtr pkt);
    void advanceInst(Fault fault);

    /**
     * Print state of address in memory system via PrintReq (for
     * debugging).
     */
    void printAddr(Addr a);

    /**
     * Finish a DTB translation.
     * @param state The DTB translation state.
     */
    void finishTranslation(WholeTranslationState *state);

  private:

    typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
    FetchEvent fetchEvent;

    struct IprEvent : Event {
        Packet *pkt;
        TimingSimpleCPU *cpu;
        IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t);
        virtual void process();
        virtual const char *description() const;
    };

    void completeDrain();
};

#endif // __CPU_SIMPLE_TIMING_HH__
<commit_msg>Timing CPU: Remove a redundant port pointer<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 */

#ifndef __CPU_SIMPLE_TIMING_HH__
#define __CPU_SIMPLE_TIMING_HH__

#include "cpu/simple/base.hh"
#include "cpu/translation.hh"
#include "params/TimingSimpleCPU.hh"

class TimingSimpleCPU : public BaseSimpleCPU
{
  public:

    TimingSimpleCPU(TimingSimpleCPUParams * params);
    virtual ~TimingSimpleCPU();

    virtual void init();

  public:
    Event *drainEvent;

  private:

    /*
     * If an access needs to be broken into fragments, currently at most two,
     * the the following two classes are used as the sender state of the
     * packets so the CPU can keep track of everything. In the main packet
     * sender state, there's an array with a spot for each fragment. If a
     * fragment has already been accepted by the CPU, aka isn't waiting for
     * a retry, it's pointer is NULL. After each fragment has successfully
     * been processed, the "outstanding" counter is decremented. Once the
     * count is zero, the entire larger access is complete.
     */
    class SplitMainSenderState : public Packet::SenderState
    {
      public:
        int outstanding;
        PacketPtr fragments[2];

        int
        getPendingFragment()
        {
            if (fragments[0]) {
                return 0;
            } else if (fragments[1]) {
                return 1;
            } else {
                return -1;
            }
        }
    };

    class SplitFragmentSenderState : public Packet::SenderState
    {
      public:
        SplitFragmentSenderState(PacketPtr _bigPkt, int _index) :
            bigPkt(_bigPkt), index(_index)
        {}
        PacketPtr bigPkt;
        int index;

        void
        clearFromParent()
        {
            SplitMainSenderState * main_send_state =
                dynamic_cast<SplitMainSenderState *>(bigPkt->senderState);
            main_send_state->fragments[index] = NULL;
        }
    };

    class FetchTranslation : public BaseTLB::Translation
    {
      protected:
        TimingSimpleCPU *cpu;

      public:
        FetchTranslation(TimingSimpleCPU *_cpu)
            : cpu(_cpu)
        {}

        void
        markDelayed()
        {
            assert(cpu->_status == Running);
            cpu->_status = ITBWaitResponse;
        }

        void
        finish(Fault fault, RequestPtr req, ThreadContext *tc,
               BaseTLB::Mode mode)
        {
            cpu->sendFetch(fault, req, tc);
        }
    };
    FetchTranslation fetchTranslation;

    void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read);
    void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req,
                       uint8_t *data, bool read);

    void translationFault(Fault fault);

    void buildPacket(PacketPtr &pkt, RequestPtr req, bool read);
    void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
            RequestPtr req1, RequestPtr req2, RequestPtr req,
            uint8_t *data, bool read);

    bool handleReadPacket(PacketPtr pkt);
    // This function always implicitly uses dcache_pkt.
    bool handleWritePacket();

    /**
     * A TimingCPUPort overrides the default behaviour of the
     * recvTiming and recvRetry and implements events for the
     * scheduling of handling of incoming packets in the following
     * cycle.
     */
    class TimingCPUPort : public CpuPort
    {
      public:

        TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu)
            : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this)
        { }

      protected:

        /**
         * Snooping a coherence request, do nothing.
         */
        virtual void recvTimingSnoopReq(PacketPtr pkt) { }

        TimingSimpleCPU* cpu;

        struct TickEvent : public Event
        {
            PacketPtr pkt;
            TimingSimpleCPU *cpu;

            TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {}
            const char *description() const { return "Timing CPU tick"; }
            void schedule(PacketPtr _pkt, Tick t);
        };

        EventWrapper<Port, &Port::sendRetry> retryEvent;
    };

    class IcachePort : public TimingCPUPort
    {
      public:

        IcachePort(TimingSimpleCPU *_cpu)
            : TimingCPUPort(_cpu->name() + "-iport", _cpu),
              tickEvent(_cpu)
        { }

      protected:

        virtual bool recvTimingResp(PacketPtr pkt);

        virtual void recvRetry();

        struct ITickEvent : public TickEvent
        {

            ITickEvent(TimingSimpleCPU *_cpu)
                : TickEvent(_cpu) {}
            void process();
            const char *description() const { return "Timing CPU icache tick"; }
        };

        ITickEvent tickEvent;

    };

    class DcachePort : public TimingCPUPort
    {
      public:

        DcachePort(TimingSimpleCPU *_cpu)
            : TimingCPUPort(_cpu->name() + "-dport", _cpu), tickEvent(_cpu)
        { }

      protected:

        virtual bool recvTimingResp(PacketPtr pkt);

        virtual void recvRetry();

        struct DTickEvent : public TickEvent
        {
            DTickEvent(TimingSimpleCPU *_cpu)
                : TickEvent(_cpu) {}
            void process();
            const char *description() const { return "Timing CPU dcache tick"; }
        };

        DTickEvent tickEvent;

    };

    IcachePort icachePort;
    DcachePort dcachePort;

    PacketPtr ifetch_pkt;
    PacketPtr dcache_pkt;

    Tick previousTick;

  protected:

     /** Return a reference to the data port. */
    virtual CpuPort &getDataPort() { return dcachePort; }

    /** Return a reference to the instruction port. */
    virtual CpuPort &getInstPort() { return icachePort; }

  public:

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);

    virtual unsigned int drain(Event *drain_event);
    virtual void resume();

    void switchOut();
    void takeOverFrom(BaseCPU *oldCPU);

    virtual void activateContext(ThreadID thread_num, int delay);
    virtual void suspendContext(ThreadID thread_num);

    Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);

    Fault writeMem(uint8_t *data, unsigned size,
                   Addr addr, unsigned flags, uint64_t *res);

    void fetch();
    void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
    void completeIfetch(PacketPtr );
    void completeDataAccess(PacketPtr pkt);
    void advanceInst(Fault fault);

    /**
     * Print state of address in memory system via PrintReq (for
     * debugging).
     */
    void printAddr(Addr a);

    /**
     * Finish a DTB translation.
     * @param state The DTB translation state.
     */
    void finishTranslation(WholeTranslationState *state);

  private:

    typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
    FetchEvent fetchEvent;

    struct IprEvent : Event {
        Packet *pkt;
        TimingSimpleCPU *cpu;
        IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t);
        virtual void process();
        virtual const char *description() const;
    };

    void completeDrain();
};

#endif // __CPU_SIMPLE_TIMING_HH__
<|endoftext|>


<commit_before>//
// Created by Dawid Drozd aka Gelldur on 7/19/16.
//

#include "Preferences.h"

#include<cstdio>

#include <Poco/Data/Session.h>
#include <Poco/Data/SQLite/Connector.h>

#include <log.h>
#include <acme/MakeUnique.h>

Preferences::Preferences(const std::string& databaseName, const std::string& tableName)
		: TABLE_NAME(tableName)
		, DATABSE_FILE_NAME(databaseName)
{
	Poco::Data::SQLite::Connector::registerConnector();

	recreate();
}

Preferences::~Preferences()
{
	_session->close();
	Poco::Data::SQLite::Connector::unregisterConnector();
}

void Preferences::setValue(const std::string& key, const std::string& value)
{
	_cache[key] = value;

	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		return;
	}

	Poco::Data::Session& session = *_session;

	Poco::Data::Statement insert(session);
	insert << "INSERT OR REPLACE INTO " << TABLE_NAME << " VALUES(?, ?)",
			Poco::Data::Keywords::useRef(key),
			Poco::Data::Keywords::useRef(value);
	DLOG("Preferences: %s\n(%s)=(%s)", insert.toString().c_str(), key.c_str(), value.c_str());

	insert.execute();
}

std::string Preferences::getValue(const std::string& key, const std::string& defaultValue)
{
	auto found = _cache.find(key);
	if (found != _cache.end())
	{
		return found->second;
	}

	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		_cache[key] = defaultValue;
		return defaultValue;
	}

	std::string returnedValue = defaultValue;

	Poco::Data::Session& session = *_session;

	// a simple query
	Poco::Data::Statement select(session);
	select << "SELECT value FROM " << TABLE_NAME << " WHERE key=?",
			Poco::Data::Keywords::useRef(key),
			Poco::Data::Keywords::into(returnedValue); //  iterate over result set one row at a time

	DLOG("Select: %s\nkey:%s", select.toString().c_str(), key.c_str());
	select.execute();

	_cache[key] = returnedValue;
	return returnedValue;
}

void Preferences::clean()
{
	_cache.clear();
	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		return;
	}

	_session->close();

	if (std::remove(DATABSE_FILE_NAME.c_str()) != 0)
	{
		ELOG("Can't remove database: %s", DATABSE_FILE_NAME.c_str());
	}
	recreate();
}

void Preferences::recreate()
{
	_session = std::make_unique<Poco::Data::Session>("SQLite", DATABSE_FILE_NAME.c_str());

	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		return;
	}

	Poco::Data::Session& session = *_session;

	session << "CREATE TABLE IF NOT EXISTS `" << TABLE_NAME << "`("
			"`key` TEXT NOT NULL UNIQUE,"
			"`value` TEXT,"
			"PRIMARY KEY(key)"
			");", Poco::Data::Keywords::now;
}
<commit_msg>Fix NPE<commit_after>//
// Created by Dawid Drozd aka Gelldur on 7/19/16.
//

#include "Preferences.h"

#include<cstdio>

#include <Poco/Data/Session.h>
#include <Poco/Data/SQLite/Connector.h>

#include <log.h>
#include <acme/MakeUnique.h>

Preferences::Preferences(const std::string& databaseName, const std::string& tableName)
		: TABLE_NAME(tableName)
		, DATABSE_FILE_NAME(databaseName)
{
	Poco::Data::SQLite::Connector::registerConnector();

	recreate();
}

Preferences::~Preferences()
{
	if (_session != nullptr)
	{
		_session->close();
	}
	Poco::Data::SQLite::Connector::unregisterConnector();
}

void Preferences::setValue(const std::string& key, const std::string& value)
{
	_cache[key] = value;

	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		return;
	}

	Poco::Data::Session& session = *_session;

	Poco::Data::Statement insert(session);
	insert << "INSERT OR REPLACE INTO " << TABLE_NAME << " VALUES(?, ?)",
			Poco::Data::Keywords::useRef(key),
			Poco::Data::Keywords::useRef(value);
	DLOG("Preferences: %s\n(%s)=(%s)", insert.toString().c_str(), key.c_str(), value.c_str());

	insert.execute();
}

std::string Preferences::getValue(const std::string& key, const std::string& defaultValue)
{
	auto found = _cache.find(key);
	if (found != _cache.end())
	{
		return found->second;
	}

	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		_cache[key] = defaultValue;
		return defaultValue;
	}

	std::string returnedValue = defaultValue;

	Poco::Data::Session& session = *_session;

	// a simple query
	Poco::Data::Statement select(session);
	select << "SELECT value FROM " << TABLE_NAME << " WHERE key=?",
			Poco::Data::Keywords::useRef(key),
			Poco::Data::Keywords::into(returnedValue); //  iterate over result set one row at a time

	DLOG("Select: %s\nkey:%s", select.toString().c_str(), key.c_str());
	select.execute();

	_cache[key] = returnedValue;
	return returnedValue;
}

void Preferences::clean()
{
	_cache.clear();
	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		return;
	}

	_session->close();

	if (std::remove(DATABSE_FILE_NAME.c_str()) != 0)
	{
		ELOG("Can't remove database: %s", DATABSE_FILE_NAME.c_str());
	}
	recreate();
}

void Preferences::recreate()
{
	_session = std::make_unique<Poco::Data::Session>("SQLite", DATABSE_FILE_NAME.c_str());

	if (_session == nullptr)
	{
		ELOG("Session not created\nNo storage");
		return;
	}

	Poco::Data::Session& session = *_session;

	session << "CREATE TABLE IF NOT EXISTS `" << TABLE_NAME << "`("
			"`key` TEXT NOT NULL UNIQUE,"
			"`value` TEXT,"
			"PRIMARY KEY(key)"
			");", Poco::Data::Keywords::now;
}
<|endoftext|>


<commit_before>#include <stdexcept>

#include "python_api.h"

static int python_count=0;

Python::Python()
{
    this->_init(-1, NULL);
}

Python::Python(int argc, char* argv[])
{
    this->_init(argc, argv);
}

void Python::_init(int argc, char* argv[])
{
    python_count++;
    if (python_count == 1) {
        // This is a hack, so that we can load hermes_common below. Some better
        // mechanism should be used instead, once we figure out how to do it:
        putenv((char *)"PYTHONPATH=.:../..:../../../python");
        Py_Initialize();
        if (argc >= 0)
            PySys_SetArgv(argc, argv);
        if (import__hermes_common())
            throw std::runtime_error("hermes_common failed to import.");
    }
    this->_namespace = namespace_create();
}

Python::~Python()
{
    // Free the namespace. This frees all the dictionary items, so if there
    // are some numpy arrays (or your classes) in the namespace, they will be
    // deallocated at this time.
    Py_DECREF(this->_namespace);

    // free the interpreter if this was the last instance using it:
    python_count--;
    if (python_count == 0) {
        // don't finalize python, because the numpy package segfaults when
        // imported again:
        //Py_Finalize();
    }
}

void Python::print()
{
    namespace_print(_namespace);
}

void Python::exec(const char *text)
{
    run_cmd(text, this->_namespace);
}

void Python::push(const char *name, PyObject *o)
{
    namespace_push(this->_namespace, name, o);
    // namespace_push() is a regular Cython function and
    // as such, it increfs the object "o" before storing it in the namespace,
    // but we want to steal the reference, so we decref it here (there is still
    // at least one reference stored in the dictionary this->_namespace, so
    // it's safe). This is so that
    //     this->push("i", c2py_int(5));
    // doesn't leak (c2py_int() creates a python reference and push() destroys
    // this python reference)
    Py_DECREF(o);
}

PyObject *Python::pull(const char *name)
{
    PyObject *tmp = namespace_pull(this->_namespace, name);
    // namespace_pull() is a regular Cython function and
    // as such, it increfs the result before returning it, but we only want to
    // borrow a reference, so we decref it here (there is still at least one
    // reference stored in the dictionary this->_namespace, so it's safe)
    // This is so that
    //     int i = py2c_int(this->pull("i"));
    // doesn't leak (pull() borrows the reference, py2c_int() doesn't do
    // anything with the reference, so no leak nor segfault happens)
    Py_DECREF(tmp);
    return tmp;
}
<commit_msg>refactor setting up PYTHONPATH<commit_after>#include <stdexcept>

#include "python_api.h"
#include "matrix.h"

static int python_count=0;

Python::Python()
{
    this->_init(-1, NULL);
}

Python::Python(int argc, char* argv[])
{
    this->_init(argc, argv);
}

void Python::_init(int argc, char* argv[])
{
    python_count++;
    if (python_count == 1) {
        char *PYTHONPATH = getenv("PYTHONPATH");
        if (PYTHONPATH == NULL)
            _error("internal error in hermes_common: PYTHONPATH not defined");
        int max_len = 10000;
        char new_path[max_len];
        // This is a hack, so that we can load hermes_common below. Some better
        // mechanism should be used instead, once we figure out how to do it:
        int nchars = snprintf(new_path, max_len, "PYTHONPATH=.:../..:../../../python:../hermes_common/:../../hermes_common/:%s", PYTHONPATH);
        if (nchars >= max_len)
            _error("internal error in hermes_common: PYTHONPATH too long.");
        // We have to make a copy of the string, because new_path[] will get
        // deallocated:
        putenv(strdup(new_path));
        Py_Initialize();
        if (argc >= 0)
            PySys_SetArgv(argc, argv);
        if (import__hermes_common())
            throw std::runtime_error("hermes_common failed to import.");
    }
    this->_namespace = namespace_create();
}

Python::~Python()
{
    // Free the namespace. This frees all the dictionary items, so if there
    // are some numpy arrays (or your classes) in the namespace, they will be
    // deallocated at this time.
    Py_DECREF(this->_namespace);

    // The code below would free the interpreter if this was the last instance
    // using it. However, it is currently disabled, because the numpy package
    // segfaults when imported again; also the PYTHONPATH is set only once if
    // python_count is never decreased (which is what we want).
    /*python_count--;
    if (python_count == 0) {
        Py_Finalize();
    }
    */
}

void Python::print()
{
    namespace_print(_namespace);
}

void Python::exec(const char *text)
{
    run_cmd(text, this->_namespace);
}

void Python::push(const char *name, PyObject *o)
{
    namespace_push(this->_namespace, name, o);
    // namespace_push() is a regular Cython function and
    // as such, it increfs the object "o" before storing it in the namespace,
    // but we want to steal the reference, so we decref it here (there is still
    // at least one reference stored in the dictionary this->_namespace, so
    // it's safe). This is so that
    //     this->push("i", c2py_int(5));
    // doesn't leak (c2py_int() creates a python reference and push() destroys
    // this python reference)
    Py_DECREF(o);
}

PyObject *Python::pull(const char *name)
{
    PyObject *tmp = namespace_pull(this->_namespace, name);
    // namespace_pull() is a regular Cython function and
    // as such, it increfs the result before returning it, but we only want to
    // borrow a reference, so we decref it here (there is still at least one
    // reference stored in the dictionary this->_namespace, so it's safe)
    // This is so that
    //     int i = py2c_int(this->pull("i"));
    // doesn't leak (pull() borrows the reference, py2c_int() doesn't do
    // anything with the reference, so no leak nor segfault happens)
    Py_DECREF(tmp);
    return tmp;
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2016 Genome Research Ltd.

  Author: Jouni Siren <jouni.siren@iki.fi>

  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.
*/

#include "gcsa.h"

using namespace gcsa;

//------------------------------------------------------------------------------

int
main(int argc, char** argv)
{
  if(argc < 3)
  {
    std::cerr << "usage: query_gcsa base_name patterns" << std::endl;
    std::cerr << std::endl;
    std::exit(EXIT_SUCCESS);
  }

  std::string base_name = argv[1];
  std::string pattern_name = argv[2];
  std::cout << "GCSA2 query benchmark" << std::endl;
  std::cout << std::endl;
  printHeader("Base name"); std::cout << base_name << std::endl;
  printHeader("Pattern file"); std::cout << pattern_name << std::endl;
  std::cout << std::endl;

  GCSA index;
  std::string gcsa_name = base_name + GCSA::EXTENSION;
  sdsl::load_from_file(index, gcsa_name);
  printHeader("GCSA"); std::cout << inMegabytes(sdsl::size_in_bytes(index)) << " MB" << std::endl;

  std::vector<std::string> patterns;
  size_type pattern_total = readRows(pattern_name, patterns, true);
  printHeader("Patterns");
  std::cout << patterns.size() << " (total " << inMegabytes(pattern_total) << " MB)" << std::endl;
  std::cout << std::endl;

  std::vector<range_type> ranges; ranges.reserve(patterns.size());
  {
    double start = readTimer();
    for(size_type i = 0; i < patterns.size(); i++)
    {
      range_type temp = index.find(patterns[i]);
      if(!Range::empty(temp)) { ranges.push_back(temp); }
    }
    double seconds = readTimer() - start;
    printTime("find()", patterns.size(), seconds);
    printHeader("find()");
    std::cout << "Found " << ranges.size() << " patterns ("
              << (inMegabytes(pattern_total) / seconds) << " MB/s)" << std::endl;
    std::cout << std::endl;
  }

  std::vector<size_type> counts(ranges.size());
  {
    double start = readTimer();
    for(size_type i = 0; i < ranges.size(); i++)
    {
      counts[i] = index.count(ranges[i]);
    }
    double seconds = readTimer() - start;
    printTime("count()", ranges.size(), seconds);
    std::cout << std::endl;
  }

  {
    double start = readTimer();
    std::vector<node_type> results;
    size_type total = 0;
    for(size_type i = 0; i < ranges.size(); i++)
    {
      index.locate(ranges[i], results);
      counts[i] -= results.size();
      total += results.size();
    }
    double seconds = readTimer() - start;
    printTime("locate()", ranges.size(), seconds);
    printHeader("locate()");
    std::cout << "Found " << total << " occurrences (" <<
              (total / seconds) << " / second)" << std::endl;
    std::cout << std::endl;
  }

  bool ok = true;
  for(size_type i = 0; i < counts.size(); i++)
  {
    if(counts[i] != 0) { ok = false; }
  }
  if(!ok)
  {
    std::cout << "Warning: count() and locate() returned inconsistent results" << std::endl;
    std::cout << std::endl;
  }

  return 0;
}

//------------------------------------------------------------------------------
<commit_msg>Filter patterns of Ns in the benchmark<commit_after>/*
  Copyright (c) 2016 Genome Research Ltd.

  Author: Jouni Siren <jouni.siren@iki.fi>

  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.
*/

#include "gcsa.h"

using namespace gcsa;

//------------------------------------------------------------------------------

void filter(std::vector<std::string>& patterns);

int
main(int argc, char** argv)
{
  if(argc < 3)
  {
    std::cerr << "usage: query_gcsa base_name patterns" << std::endl;
    std::cerr << std::endl;
    std::exit(EXIT_SUCCESS);
  }

  std::string base_name = argv[1];
  std::string pattern_name = argv[2];
  std::cout << "GCSA2 query benchmark" << std::endl;
  std::cout << std::endl;
  printHeader("Base name"); std::cout << base_name << std::endl;
  printHeader("Pattern file"); std::cout << pattern_name << std::endl;
  std::cout << std::endl;

  GCSA index;
  std::string gcsa_name = base_name + GCSA::EXTENSION;
  sdsl::load_from_file(index, gcsa_name);
  printHeader("GCSA"); std::cout << inMegabytes(sdsl::size_in_bytes(index)) << " MB" << std::endl;

  std::vector<std::string> patterns;
  size_type pattern_total = readRows(pattern_name, patterns, true);
  filter(patterns);
  printHeader("Patterns");
  std::cout << patterns.size() << " (total " << inMegabytes(pattern_total) << " MB)" << std::endl;
  std::cout << std::endl;

  std::vector<range_type> ranges; ranges.reserve(patterns.size());
  {
    double start = readTimer();
    for(size_type i = 0; i < patterns.size(); i++)
    {
      range_type temp = index.find(patterns[i]);
      if(!Range::empty(temp)) { ranges.push_back(temp); }
    }
    double seconds = readTimer() - start;
    printTime("find()", patterns.size(), seconds);
    printHeader("find()");
    std::cout << "Found " << ranges.size() << " patterns ("
              << (inMegabytes(pattern_total) / seconds) << " MB/s)" << std::endl;
    std::cout << std::endl;
  }

  std::vector<size_type> counts(ranges.size());
  {
    double start = readTimer();
    for(size_type i = 0; i < ranges.size(); i++)
    {
      counts[i] = index.count(ranges[i]);
    }
    double seconds = readTimer() - start;
    printTime("count()", ranges.size(), seconds);
    std::cout << std::endl;
  }

  {
    double start = readTimer();
    std::vector<node_type> results;
    size_type total = 0;
    for(size_type i = 0; i < ranges.size(); i++)
    {
      index.locate(ranges[i], results);
      counts[i] -= results.size();
      total += results.size();
    }
    double seconds = readTimer() - start;
    printTime("locate()", ranges.size(), seconds);
    printHeader("locate()");
    std::cout << "Found " << total << " occurrences (" <<
              (total / seconds) << " / second)" << std::endl;
    std::cout << std::endl;
  }

  bool ok = true;
  for(size_type i = 0; i < counts.size(); i++)
  {
    if(counts[i] != 0) { ok = false; }
  }
  if(!ok)
  {
    std::cout << "Warning: count() and locate() returned inconsistent results" << std::endl;
    std::cout << std::endl;
  }

  return 0;
}

//------------------------------------------------------------------------------

void
filter(std::vector<std::string>& patterns)
{
  size_type tail = 0;
  for(size_type i = 0; i < patterns.size(); i++)
  {
    const std::string& curr = patterns[i];
    for(size_type j = 0; j < curr.length(); j++)
    {
      if(curr[j] != 'N') { patterns[tail] = curr; tail++; break; }
    }
  }
  patterns.resize(tail);
}

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>// Copyright 2013 Sean McKenna
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//

// a ray tracer in C++

// libraries, namespace
#include <thread>
#include <fstream>
#include "xmlload.cpp"
#include "scene.cpp"
using namespace std;

// variables for ray tracing
int w;
int h;
int size;
Color24 white = {233, 233, 233};
Color24 black = {33, 33, 33};
Color24* img;
float* zImg;

// variables for threading
static const int numThreads = 8;
void rayTracing(int i);

// variables for camera ray generation
void cameraRayVars();
Point3 *imageTopLeftV;
Point3 *dXV;
Point3 *dYV;
Point3 firstPixel;
Point3 cameraPos;
Point3 cameraDir;
Transformation* c;
Point3 cameraRay(int pX, int pY);

// trace a ray against all objects
void objectIntersection(Node &n, Ray r, int pixel);

// ray tracer
int main(){

  // load scene: root node, camera, image
  LoadScene("scenes/prj1.xml");

  // set up background image color
  renderImage.setBackground(black);

  // variables for ray tracing
  w = renderImage.GetWidth();
  h = renderImage.GetHeight();
  size = w * h;
  img = renderImage.GetPixels();
  zImg = renderImage.GetZBuffer();

  // variables for generating camera rays
  cameraRayVars();

  // ray tracing loop (in parallel with threads)
  std::thread t[numThreads];
  for(int i = 0; i < numThreads; i++)
    t[i] = std::thread(rayTracing, i);

  // join threads back to main
  for(int i = 0; i < numThreads; i++)
    t[i].join();

  // output ray-traced image & z-buffer
  renderImage.SaveImage("images/image.ppm");
  renderImage.ComputeZBufferImage();
  renderImage.SaveZImage("images/imageZ.ppm");
}

// ray tracing loop (for an individual pixel)
void rayTracing(int i){

  // initial starting pixel
  int pixel = i;

  // thread continuation condition
  while(pixel < size){

    // establish pixel location
    int pX = pixel % w;
    int pY = pixel / w;

    // transform ray into world space
    Point3 rayDir = cameraRay(pX, pY);
    Ray *ray = new Ray();
    ray->p = cameraPos;
    ray->dir = c->TransformFrom(rayDir);

    // traverse through scene DOM
    // transform rays into model space
    // detect ray intersections & update pixel
    objectIntersection(rootNode, *ray, pixel);

    // re-assign next pixel
    pixel += numThreads;
  }
}

// create variables for camera ray generation
void cameraRayVars(){
  float fov = camera.fov * M_PI / 180.0;
  float aspectRatio = (float) w / (float) h;
  float imageDistance = 1.0;
  float imageTipY = imageDistance * tan(fov / 2.0);
  float imageTipX = imageTipY * aspectRatio;
  float dX = (2.0 * imageTipX) / (float) w;
  float dY = (2.0 * imageTipY) / (float) h;
  imageTopLeftV = new Point3(-imageTipX, imageTipY, -imageDistance);
  dXV = new Point3(dX, 0.0, 0.0);
  dYV = new Point3(0.0, -dY, 0.0);
  firstPixel = *imageTopLeftV + (*dXV * 0.5) + (*dYV * 0.5);

  // set up camera transformation (translation + rotation)
  Point3 cameraPos = camera.pos;
  c = new Transformation();
  c->Translate(cameraPos);
  Matrix3 *rotate = new cyMatrix3f();
  Point3 cameraDir = camera.dir;
  Point3 cameraUp = camera.up;
  cameraDir.Normalize();
  cameraUp.Normalize();
  Point3 cameraCross = cameraDir ^ cameraUp;
  cameraCross.Normalize();
  rotate->Set(cameraCross, cameraUp, -cameraDir);
  c->Transform(*rotate);
}

// compute camera rays
Point3 cameraRay(int pX, int pY){
  Point3 ray = firstPixel + (*dXV * pX) + (*dYV * pY);
  ray.Normalize();
  return ray;
}

// recursive object intersection through all scene objects
void objectIntersection(Node &n, Ray r, int pixel){

  // loop on child nodes
  int j = 0;
  int numChild = n.GetNumChild();
  while(j < numChild){

    // grab child node
    Node *child = n.GetChild(j);
    Object *obj = child->GetObject();

    // transform rays into model space (or local space)
    Ray r2 = child->ToNodeCoords(r);

    // compute ray intersections
    HitInfo h = HitInfo();
    bool hit = obj->IntersectRay(r2, h);

    // check the ray computation, update pixel & z-buffer
    if(hit){
      img[pixel] = white;
      if(h.z < zImg[pixel])
        zImg[pixel] = h.z;
    }

    // recursively check this child's children
    objectIntersection(*child, r2, pixel);
    j++;
  }
}
<commit_msg>refactor ray-tracer to clean up and better comments<commit_after>// Copyright 2013 Sean McKenna
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//

// a ray tracer in C++

// libraries, namespace
#include <thread>
#include <fstream>
#include "xmlload.cpp"
#include "scene.cpp"
using namespace std;

// for ray tracing
int w;
int h;
int size;
Color24 white = {233, 233, 233};
Color24 black = {33, 33, 33};
Color24* img;
float* zImg;

// for threading
static const int numThreads = 8;
void rayTracing(int i);

// for camera ray generation
void cameraRayVars();
Point3 *imageTopLeftV;
Point3 *dXV;
Point3 *dYV;
Point3 firstPixel;
Point3 cameraPos;
Point3 cameraDir;
Transformation* c;
Point3 cameraRay(int pX, int pY);

// for tracing rays to objects
void objectIntersection(Node &n, Ray r, int pixel);

// ray tracer
int main(){

  // load scene: root node, camera, image
  LoadScene("scenes/prj1.xml");

  // set up background image color
  renderImage.setBackground(black);

  // set variables for ray tracing
  w = renderImage.GetWidth();
  h = renderImage.GetHeight();
  size = w * h;
  img = renderImage.GetPixels();
  zImg = renderImage.GetZBuffer();

  // set variables for generating camera rays
  cameraRayVars();

  // start ray tracing loop (in parallel with threads)
  thread t[numThreads];
  for(int i = 0; i < numThreads; i++)
    t[i] = thread(rayTracing, i);

  // when finished, join all threads back to main
  for(int i = 0; i < numThreads; i++)
    t[i].join();

  // output ray-traced image & z-buffer
  renderImage.SaveImage("images/image.ppm");
  renderImage.ComputeZBufferImage();
  renderImage.SaveZImage("images/imageZ.ppm");
}

// ray tracing loop (for an individual pixel)
void rayTracing(int i){

  // initial starting pixel
  int pixel = i;

  // thread continuation condition
  while(pixel < size){

    // establish pixel location
    int pX = pixel % w;
    int pY = pixel / w;

    // transform ray into world space
    Point3 rayDir = cameraRay(pX, pY);
    Ray *ray = new Ray();
    ray->p = cameraPos;
    ray->dir = c->TransformFrom(rayDir);

    // traverse through scene DOM
    // transform rays into model space
    // detect ray intersections & update pixel
    objectIntersection(rootNode, *ray, pixel);

    // re-assign next pixel (naive, but works)
    pixel += numThreads;
  }
}

// create variables for camera ray generation
void cameraRayVars(){
  float fov = camera.fov * M_PI / 180.0;
  float aspectRatio = (float) w / (float) h;
  float imageDistance = 1.0;
  float imageTipY = imageDistance * tan(fov / 2.0);
  float imageTipX = imageTipY * aspectRatio;
  float dX = (2.0 * imageTipX) / (float) w;
  float dY = (2.0 * imageTipY) / (float) h;
  imageTopLeftV = new Point3(-imageTipX, imageTipY, -imageDistance);
  dXV = new Point3(dX, 0.0, 0.0);
  dYV = new Point3(0.0, -dY, 0.0);
  firstPixel = *imageTopLeftV + (*dXV * 0.5) + (*dYV * 0.5);

  // set up camera transformation (translation + rotation)
  Point3 cameraPos = camera.pos;
  c = new Transformation();
  c->Translate(cameraPos);
  Matrix3 *rotate = new cyMatrix3f();
  Point3 cameraDir = camera.dir;
  Point3 cameraUp = camera.up;
  cameraDir.Normalize();
  cameraUp.Normalize();
  Point3 cameraCross = cameraDir ^ cameraUp;
  cameraCross.Normalize();
  rotate->Set(cameraCross, cameraUp, -cameraDir);
  c->Transform(*rotate);
}

// compute camera rays
Point3 cameraRay(int pX, int pY){
  Point3 ray = firstPixel + (*dXV * pX) + (*dYV * pY);
  ray.Normalize();
  return ray;
}

// recursive object intersection through all scene objects
void objectIntersection(Node &n, Ray r, int pixel){

  // loop on child nodes
  int j = 0;
  int numChild = n.GetNumChild();
  while(j < numChild){

    // grab child node
    Node *child = n.GetChild(j);
    Object *obj = child->GetObject();

    // transform rays into model space (or local space)
    Ray r2 = child->ToNodeCoords(r);

    // compute ray intersections
    HitInfo h = HitInfo();
    bool hit = obj->IntersectRay(r2, h);

    // check the ray computation, update pixel & z-buffer
    if(hit){
      img[pixel] = white;
      if(h.z < zImg[pixel])
        zImg[pixel] = h.z;
    }

    // recursively check this child's children
    objectIntersection(*child, r2, pixel);
    j++;
  }
}
<|endoftext|>