<commit_before>
/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <stdint.h>
#include <memory>
#include "bytes.hh"
#include "utils/allocation_strategy.hh"
#include <seastar/core/unaligned.hh>
#include <unordered_map>
#include <type_traits>

struct blob_storage {
    struct [[gnu::packed]] ref_type {
        blob_storage* ptr;

        ref_type() {}
        ref_type(blob_storage* ptr) : ptr(ptr) {}
        operator blob_storage*() const { return ptr; }
        blob_storage* operator->() const { return ptr; }
        blob_storage& operator*() const { return *ptr; }
    };
    using size_type = uint32_t;
    using char_type = bytes_view::value_type;

    ref_type* backref;
    size_type size;
    size_type frag_size;
    ref_type next;
    char_type data[];

    blob_storage(ref_type* backref, size_type size, size_type frag_size) noexcept
        : backref(backref)
        , size(size)
        , frag_size(frag_size)
        , next(nullptr)
    {
        *backref = this;
    }

    blob_storage(blob_storage&& o) noexcept
        : backref(o.backref)
        , size(o.size)
        , frag_size(o.frag_size)
        , next(o.next)
    {
        *backref = this;
        o.next = nullptr;
        if (next) {
            next->backref = &next;
        }
        memcpy(data, o.data, frag_size);
    }
} __attribute__((packed));

// A managed version of "bytes" (can be used with LSA).
class managed_bytes {
    struct linearization_context {
        unsigned _nesting = 0;
        // Map from first blob_storage address to linearized version
        // We use the blob_storage address to be insentive to moving
        // a managed_bytes object.
        std::unordered_map<const blob_storage*, std::unique_ptr<bytes_view::value_type[]>> _state;
        void enter() {
            ++_nesting;
        }
        void leave() {
            if (!--_nesting) {
                _state.clear();
            }
        }
        void forget(const blob_storage* p) noexcept;
    };
    static thread_local linearization_context _linearization_context;
public:
    struct linearization_context_guard {
        linearization_context_guard() {
            _linearization_context.enter();
        }
        ~linearization_context_guard() {
            _linearization_context.leave();
        }
    };
private:
    static constexpr size_t max_inline_size = 15;
    struct small_blob {
        bytes_view::value_type data[max_inline_size];
        int8_t size; // -1 -> use blob_storage
    };
    union u {
        u() {}
        ~u() {}
        blob_storage::ref_type ptr;
        small_blob small;
    } _u;
    static_assert(sizeof(small_blob) > sizeof(blob_storage*), "inline size too small");
private:
    bool external() const {
        return _u.small.size < 0;
    }
    size_t max_seg(allocation_strategy& alctr) {
        return alctr.preferred_max_contiguous_allocation() - sizeof(blob_storage);
    }
    void free_chain(blob_storage* p) noexcept {
        if (p->next && _linearization_context._nesting) {
            _linearization_context.forget(p);
        }
        auto& alctr = current_allocator();
        while (p) {
            auto n = p->next;
            alctr.destroy(p);
            p = n;
        }
    }
    const bytes_view::value_type* read_linearize() const {
        if (!external()) {
            return _u.small.data;
        } else  if (!_u.ptr->next) {
            return _u.ptr->data;
        } else {
            return do_linearize();
        }
    }
    bytes_view::value_type& value_at_index(blob_storage::size_type index) {
        if (!external()) {
            return _u.small.data[index];
        }
        blob_storage* a = _u.ptr;
        while (index >= a->frag_size) {
            index -= a->frag_size;
            a = a->next;
        }
        return a->data[index];
    }
    const bytes_view::value_type* do_linearize() const;
public:
    using size_type = blob_storage::size_type;
    struct initialized_later {};

    managed_bytes() {
        _u.small.size = 0;
    }

    managed_bytes(const blob_storage::char_type* ptr, size_type size)
        : managed_bytes(bytes_view(ptr, size)) {}

    managed_bytes(const bytes& b) : managed_bytes(static_cast<bytes_view>(b)) {}

    managed_bytes(initialized_later, size_type size) {
        if (size <= max_inline_size) {
            _u.small.size = size;
        } else {
            _u.small.size = -1;
            auto& alctr = current_allocator();
            auto maxseg = max_seg(alctr);
            auto now = std::min(size_t(size), maxseg);
            void* p = alctr.alloc(&standard_migrator<blob_storage>::object,
                sizeof(blob_storage) + now, alignof(blob_storage));
            auto first = new (p) blob_storage(&_u.ptr, size, now);
            auto last = first;
            size -= now;
            try {
                while (size) {
                    auto now = std::min(size_t(size), maxseg);
                    void* p = alctr.alloc(&standard_migrator<blob_storage>::object,
                        sizeof(blob_storage) + now, alignof(blob_storage));
                    last = new (p) blob_storage(&last->next, 0, now);
                    size -= now;
                }
            } catch (...) {
                free_chain(first);
                throw;
            }
        }
    }

    managed_bytes(bytes_view v) : managed_bytes(initialized_later(), v.size()) {
        if (!external()) {
            std::copy(v.begin(), v.end(), _u.small.data);
            return;
        }
        auto p = v.data();
        auto s = v.size();
        auto b = _u.ptr;
        while (s) {
            memcpy(b->data, p, b->frag_size);
            p += b->frag_size;
            s -= b->frag_size;
            b = b->next;
        }
        assert(!b);
    }

    managed_bytes(std::initializer_list<bytes::value_type> b) : managed_bytes(b.begin(), b.size()) {}

    ~managed_bytes() noexcept {
        if (external()) {
            free_chain(_u.ptr);
        }
    }

    managed_bytes(const managed_bytes& o) : managed_bytes(initialized_later(), o.size()) {
        if (!external()) {
            memcpy(data(), o.data(), size());
            return;
        }
        auto s = size();
        const blob_storage::ref_type* next_src = &o._u.ptr;
        blob_storage* blob_src = nullptr;
        size_type size_src = 0;
        size_type offs_src = 0;
        blob_storage::ref_type* next_dst = &_u.ptr;
        blob_storage* blob_dst = nullptr;
        size_type size_dst = 0;
        size_type offs_dst = 0;
        while (s) {
            if (!size_src) {
                blob_src = *next_src;
                next_src = &blob_src->next;
                size_src = blob_src->frag_size;
                offs_src = 0;
            }
            if (!size_dst) {
                blob_dst = *next_dst;
                next_dst = &blob_dst->next;
                size_dst = blob_dst->frag_size;
                offs_dst = 0;
            }
            auto now = std::min(size_src, size_dst);
            memcpy(blob_dst->data + offs_dst, blob_src->data + offs_src, now);
            s -= now;
            offs_src += now; size_src -= now;
            offs_dst += now; size_dst -= now;
        }
        assert(size_src == 0 && size_dst == 0);
    }

    managed_bytes(managed_bytes&& o) noexcept
        : _u(o._u)
    {
        if (external()) {
            if (_u.ptr) {
                _u.ptr->backref = &_u.ptr;
            }
        }
        o._u.small.size = 0;
    }

    managed_bytes& operator=(managed_bytes&& o) noexcept {
        if (this != &o) {
            this->~managed_bytes();
            new (this) managed_bytes(std::move(o));
        }
        return *this;
    }

    managed_bytes& operator=(const managed_bytes& o) {
        if (this != &o) {
            managed_bytes tmp(o);
            this->~managed_bytes();
            new (this) managed_bytes(std::move(tmp));
        }
        return *this;
    }

    bool operator==(const managed_bytes& o) const {
        if (size() != o.size()) {
            return false;
        }
        if (!external()) {
            return bytes_view(*this) == bytes_view(o);
        } else {
            auto a = _u.ptr;
            auto a_data = a->data;
            auto a_remain = a->frag_size;
            a = a->next;
            auto b = o._u.ptr;
            auto b_data = b->data;
            auto b_remain = b->frag_size;
            b = b->next;
            while (a_remain || b_remain) {
                auto now = std::min(a_remain, b_remain);
                if (bytes_view(a_data, now) != bytes_view(b_data, now)) {
                    return false;
                }
                a_data += now;
                a_remain -= now;
                if (!a_remain && a) {
                    a_data = a->data;
                    a_remain = a->frag_size;
                    a = a->next;
                }
                b_data += now;
                b_remain -= now;
                if (!b_remain && b) {
                    b_data = b->data;
                    b_remain = b->frag_size;
                    b = b->next;
                }
            }
            return true;
        }
    }

    bool operator!=(const managed_bytes& o) const {
        return !(*this == o);
    }

    operator bytes_view() const {
        return { data(), size() };
    }

    bool is_fragmented() const {
        return external() && _u.ptr->next;
    }

    operator bytes_mutable_view() {
        assert(!is_fragmented());
        return { data(), size() };
    };

    bytes_view::value_type& operator[](size_type index) {
        return value_at_index(index);
    }

    const bytes_view::value_type& operator[](size_type index) const {
        return const_cast<const bytes_view::value_type&>(
                const_cast<managed_bytes*>(this)->value_at_index(index));
    }

    size_type size() const {
        if (external()) {
            return _u.ptr->size;
        } else {
            return _u.small.size;
        }
    }

    const blob_storage::char_type* begin() const {
        return data();
    }

    const blob_storage::char_type* end() const {
        return data() + size();
    }

    blob_storage::char_type* begin() {
        return data();
    }

    blob_storage::char_type* end() {
        return data() + size();
    }

    bool empty() const {
        return _u.small.size == 0;
    }

    blob_storage::char_type* data() {
        if (external()) {
            assert(!_u.ptr->next);  // must be linearized
            return _u.ptr->data;
        } else {
            return _u.small.data;
        }
    }

    const blob_storage::char_type* data() const {
        return read_linearize();
    }

    // Returns the amount of external memory used.
    size_t external_memory_usage() const {
        if (external()) {
            size_t mem = 0;
            blob_storage* blob = _u.ptr;
            while (blob) {
                mem += blob->frag_size + sizeof(blob_storage);
                blob = blob->next;
            }
            return mem;
        }
        return 0;
    }

    template <typename Func>
    friend std::result_of_t<Func()> with_linearized_managed_bytes(Func&& func);
};

// Run func() while ensuring that reads of managed_bytes objects are
// temporarlily linearized
template <typename Func>
inline
std::result_of_t<Func()>
with_linearized_managed_bytes(Func&& func) {
    managed_bytes::linearization_context_guard g;
    return func();
}

namespace std {

template <>
struct hash<managed_bytes> {
    size_t operator()(const managed_bytes& v) const {
        return hash<bytes_view>()(v);
    }
};

}

// blob_storage is a variable-size type
inline
size_t
size_for_allocation_strategy(const blob_storage& bs) {
    return sizeof(bs) + bs.frag_size;
}
<commit_msg>managed_bytes: Declare copy constructor as allocation point<commit_after>
/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <stdint.h>
#include <memory>
#include "bytes.hh"
#include "utils/allocation_strategy.hh"
#include <seastar/core/unaligned.hh>
#include <seastar/util/alloc_failure_injector.hh>
#include <unordered_map>
#include <type_traits>

struct blob_storage {
    struct [[gnu::packed]] ref_type {
        blob_storage* ptr;

        ref_type() {}
        ref_type(blob_storage* ptr) : ptr(ptr) {}
        operator blob_storage*() const { return ptr; }
        blob_storage* operator->() const { return ptr; }
        blob_storage& operator*() const { return *ptr; }
    };
    using size_type = uint32_t;
    using char_type = bytes_view::value_type;

    ref_type* backref;
    size_type size;
    size_type frag_size;
    ref_type next;
    char_type data[];

    blob_storage(ref_type* backref, size_type size, size_type frag_size) noexcept
        : backref(backref)
        , size(size)
        , frag_size(frag_size)
        , next(nullptr)
    {
        *backref = this;
    }

    blob_storage(blob_storage&& o) noexcept
        : backref(o.backref)
        , size(o.size)
        , frag_size(o.frag_size)
        , next(o.next)
    {
        *backref = this;
        o.next = nullptr;
        if (next) {
            next->backref = &next;
        }
        memcpy(data, o.data, frag_size);
    }
} __attribute__((packed));

// A managed version of "bytes" (can be used with LSA).
class managed_bytes {
    struct linearization_context {
        unsigned _nesting = 0;
        // Map from first blob_storage address to linearized version
        // We use the blob_storage address to be insentive to moving
        // a managed_bytes object.
        std::unordered_map<const blob_storage*, std::unique_ptr<bytes_view::value_type[]>> _state;
        void enter() {
            ++_nesting;
        }
        void leave() {
            if (!--_nesting) {
                _state.clear();
            }
        }
        void forget(const blob_storage* p) noexcept;
    };
    static thread_local linearization_context _linearization_context;
public:
    struct linearization_context_guard {
        linearization_context_guard() {
            _linearization_context.enter();
        }
        ~linearization_context_guard() {
            _linearization_context.leave();
        }
    };
private:
    static constexpr size_t max_inline_size = 15;
    struct small_blob {
        bytes_view::value_type data[max_inline_size];
        int8_t size; // -1 -> use blob_storage
    };
    union u {
        u() {}
        ~u() {}
        blob_storage::ref_type ptr;
        small_blob small;
    } _u;
    static_assert(sizeof(small_blob) > sizeof(blob_storage*), "inline size too small");
private:
    bool external() const {
        return _u.small.size < 0;
    }
    size_t max_seg(allocation_strategy& alctr) {
        return alctr.preferred_max_contiguous_allocation() - sizeof(blob_storage);
    }
    void free_chain(blob_storage* p) noexcept {
        if (p->next && _linearization_context._nesting) {
            _linearization_context.forget(p);
        }
        auto& alctr = current_allocator();
        while (p) {
            auto n = p->next;
            alctr.destroy(p);
            p = n;
        }
    }
    const bytes_view::value_type* read_linearize() const {
        if (!external()) {
            return _u.small.data;
        } else  if (!_u.ptr->next) {
            return _u.ptr->data;
        } else {
            return do_linearize();
        }
    }
    bytes_view::value_type& value_at_index(blob_storage::size_type index) {
        if (!external()) {
            return _u.small.data[index];
        }
        blob_storage* a = _u.ptr;
        while (index >= a->frag_size) {
            index -= a->frag_size;
            a = a->next;
        }
        return a->data[index];
    }
    const bytes_view::value_type* do_linearize() const;
public:
    using size_type = blob_storage::size_type;
    struct initialized_later {};

    managed_bytes() {
        _u.small.size = 0;
    }

    managed_bytes(const blob_storage::char_type* ptr, size_type size)
        : managed_bytes(bytes_view(ptr, size)) {}

    managed_bytes(const bytes& b) : managed_bytes(static_cast<bytes_view>(b)) {}

    managed_bytes(initialized_later, size_type size) {
        memory::on_alloc_point();
        if (size <= max_inline_size) {
            _u.small.size = size;
        } else {
            _u.small.size = -1;
            auto& alctr = current_allocator();
            auto maxseg = max_seg(alctr);
            auto now = std::min(size_t(size), maxseg);
            void* p = alctr.alloc(&standard_migrator<blob_storage>::object,
                sizeof(blob_storage) + now, alignof(blob_storage));
            auto first = new (p) blob_storage(&_u.ptr, size, now);
            auto last = first;
            size -= now;
            try {
                while (size) {
                    auto now = std::min(size_t(size), maxseg);
                    void* p = alctr.alloc(&standard_migrator<blob_storage>::object,
                        sizeof(blob_storage) + now, alignof(blob_storage));
                    last = new (p) blob_storage(&last->next, 0, now);
                    size -= now;
                }
            } catch (...) {
                free_chain(first);
                throw;
            }
        }
    }

    managed_bytes(bytes_view v) : managed_bytes(initialized_later(), v.size()) {
        if (!external()) {
            std::copy(v.begin(), v.end(), _u.small.data);
            return;
        }
        auto p = v.data();
        auto s = v.size();
        auto b = _u.ptr;
        while (s) {
            memcpy(b->data, p, b->frag_size);
            p += b->frag_size;
            s -= b->frag_size;
            b = b->next;
        }
        assert(!b);
    }

    managed_bytes(std::initializer_list<bytes::value_type> b) : managed_bytes(b.begin(), b.size()) {}

    ~managed_bytes() noexcept {
        if (external()) {
            free_chain(_u.ptr);
        }
    }

    managed_bytes(const managed_bytes& o) : managed_bytes(initialized_later(), o.size()) {
        if (!external()) {
            memcpy(data(), o.data(), size());
            return;
        }
        auto s = size();
        const blob_storage::ref_type* next_src = &o._u.ptr;
        blob_storage* blob_src = nullptr;
        size_type size_src = 0;
        size_type offs_src = 0;
        blob_storage::ref_type* next_dst = &_u.ptr;
        blob_storage* blob_dst = nullptr;
        size_type size_dst = 0;
        size_type offs_dst = 0;
        while (s) {
            if (!size_src) {
                blob_src = *next_src;
                next_src = &blob_src->next;
                size_src = blob_src->frag_size;
                offs_src = 0;
            }
            if (!size_dst) {
                blob_dst = *next_dst;
                next_dst = &blob_dst->next;
                size_dst = blob_dst->frag_size;
                offs_dst = 0;
            }
            auto now = std::min(size_src, size_dst);
            memcpy(blob_dst->data + offs_dst, blob_src->data + offs_src, now);
            s -= now;
            offs_src += now; size_src -= now;
            offs_dst += now; size_dst -= now;
        }
        assert(size_src == 0 && size_dst == 0);
    }

    managed_bytes(managed_bytes&& o) noexcept
        : _u(o._u)
    {
        if (external()) {
            if (_u.ptr) {
                _u.ptr->backref = &_u.ptr;
            }
        }
        o._u.small.size = 0;
    }

    managed_bytes& operator=(managed_bytes&& o) noexcept {
        if (this != &o) {
            this->~managed_bytes();
            new (this) managed_bytes(std::move(o));
        }
        return *this;
    }

    managed_bytes& operator=(const managed_bytes& o) {
        if (this != &o) {
            managed_bytes tmp(o);
            this->~managed_bytes();
            new (this) managed_bytes(std::move(tmp));
        }
        return *this;
    }

    bool operator==(const managed_bytes& o) const {
        if (size() != o.size()) {
            return false;
        }
        if (!external()) {
            return bytes_view(*this) == bytes_view(o);
        } else {
            auto a = _u.ptr;
            auto a_data = a->data;
            auto a_remain = a->frag_size;
            a = a->next;
            auto b = o._u.ptr;
            auto b_data = b->data;
            auto b_remain = b->frag_size;
            b = b->next;
            while (a_remain || b_remain) {
                auto now = std::min(a_remain, b_remain);
                if (bytes_view(a_data, now) != bytes_view(b_data, now)) {
                    return false;
                }
                a_data += now;
                a_remain -= now;
                if (!a_remain && a) {
                    a_data = a->data;
                    a_remain = a->frag_size;
                    a = a->next;
                }
                b_data += now;
                b_remain -= now;
                if (!b_remain && b) {
                    b_data = b->data;
                    b_remain = b->frag_size;
                    b = b->next;
                }
            }
            return true;
        }
    }

    bool operator!=(const managed_bytes& o) const {
        return !(*this == o);
    }

    operator bytes_view() const {
        return { data(), size() };
    }

    bool is_fragmented() const {
        return external() && _u.ptr->next;
    }

    operator bytes_mutable_view() {
        assert(!is_fragmented());
        return { data(), size() };
    };

    bytes_view::value_type& operator[](size_type index) {
        return value_at_index(index);
    }

    const bytes_view::value_type& operator[](size_type index) const {
        return const_cast<const bytes_view::value_type&>(
                const_cast<managed_bytes*>(this)->value_at_index(index));
    }

    size_type size() const {
        if (external()) {
            return _u.ptr->size;
        } else {
            return _u.small.size;
        }
    }

    const blob_storage::char_type* begin() const {
        return data();
    }

    const blob_storage::char_type* end() const {
        return data() + size();
    }

    blob_storage::char_type* begin() {
        return data();
    }

    blob_storage::char_type* end() {
        return data() + size();
    }

    bool empty() const {
        return _u.small.size == 0;
    }

    blob_storage::char_type* data() {
        if (external()) {
            assert(!_u.ptr->next);  // must be linearized
            return _u.ptr->data;
        } else {
            return _u.small.data;
        }
    }

    const blob_storage::char_type* data() const {
        return read_linearize();
    }

    // Returns the amount of external memory used.
    size_t external_memory_usage() const {
        if (external()) {
            size_t mem = 0;
            blob_storage* blob = _u.ptr;
            while (blob) {
                mem += blob->frag_size + sizeof(blob_storage);
                blob = blob->next;
            }
            return mem;
        }
        return 0;
    }

    template <typename Func>
    friend std::result_of_t<Func()> with_linearized_managed_bytes(Func&& func);
};

// Run func() while ensuring that reads of managed_bytes objects are
// temporarlily linearized
template <typename Func>
inline
std::result_of_t<Func()>
with_linearized_managed_bytes(Func&& func) {
    managed_bytes::linearization_context_guard g;
    return func();
}

namespace std {

template <>
struct hash<managed_bytes> {
    size_t operator()(const managed_bytes& v) const {
        return hash<bytes_view>()(v);
    }
};

}

// blob_storage is a variable-size type
inline
size_t
size_for_allocation_strategy(const blob_storage& bs) {
    return sizeof(bs) + bs.frag_size;
}
<|endoftext|>


<commit_before>//! @Alan
//! Exercise 10.12:
//! Write a function named compareIsbn that compares the isbn() members of two Sales_data objects.
//! Use that function to sort a vector that holds Sales_data objects.
//!

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include "../ch07/ex7_26.h"     // Sales_data class.

inline bool
compareIsbn(const Sales_data &sd1, const Sales_data &sd2)
{
    return sd1.isbn().size() < sd2.isbn().size();
}

int main()
{
    Sales_data d1("aa"), d2("aaaa"), d3("aaa"), d4("z"), d5("aaaaz");
    std::vector<Sales_data> v{d1, d2, d3, d4, d5};

    //! @note   the elements the iterators pointing to
    //!         must match the parameters of the predicate.
    std::sort(v.begin(), v.end(), compareIsbn);

    for(const auto &element : v)
        std::cout << element.isbn() << " ";
    std::cout << std::endl;

    return 0;
}
<commit_msg>Update ex10_12.cpp<commit_after>//! @Yue Wang
//! Exercise 10.12:
//! Write a function named compareIsbn that compares the isbn() members of two Sales_data objects.
//! Use that function to sort a vector that holds Sales_data objects.
//!

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include "../ch07/ex7_26.h"     // Sales_data class.

inline bool compareIsbn(const Sales_data &sd1, const Sales_data &sd2)
{
    return sd1.isbn().size() < sd2.isbn().size();
}

int main()
{
    Sales_data d1("aa"), d2("aaaa"), d3("aaa"), d4("z"), d5("aaaaz");
    std::vector<Sales_data> v{d1, d2, d3, d4, d5};

    //! @note   the elements the iterators pointing to
    //!         must match the parameters of the predicate.
    std::sort(v.begin(), v.end(), compareIsbn);

    for(const auto &element : v)
        std::cout << element.isbn() << " ";
    std::cout << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>//
//  ex11_31.cpp
//  Exercise 11.31
//
//  Created by pezy on 12/17/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  Write a program that defines a multimap of authors and their works.
//  Use **find** to find **an element** in the multimap and erase that element.
//  Be sure your program works correctly if the element you look for is not in
//  the map.

#include <iostream>
#include <map>
#include <string>

using namespace std;

int main()
{
    multimap<string, string> authors={{"alan", "DMA"}, {"pezy", "LeetCode"}, {"alan", "CLRS"}, {"wang", "FTP"}, {"pezy", "CP5"}, {"wang", "CPP-Concurrency"}};
    // want to delete an element that author is Alan, work is CP5
    string author="pezy";
    string work="CP5";

    auto found=authors.find(author);
    auto cnt=authors.count(author);

    while(cnt)
    {
        if(found->second==work)
        {
            authors.erase(found);
            break;
        }
        ++found;
        --cnt;
    }

    for(const auto &author:authors)
        cout<<author.first<<" "<<author.second<<endl;
}
<commit_msg>Update ex11_31.cpp<commit_after>//
//  ex11_31.cpp
//  Exercise 11.31
//
//  Created by pezy on 12/17/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  Write a program that defines a multimap of authors and their works.
//  Use **find** to find **an element** in the multimap and erase that element.
//  Be sure your program works correctly if the element you look for is not in
//  the map.

#include <iostream>
#include <map>
#include <string>

using namespace std;

int main()
{
    multimap<string, string> authors={{"alan", "DMA"}, {"pezy", "LeetCode"}, {"alan", "CLRS"}, {"wang", "FTP"}, {"pezy", "CP5"}, {"wang", "CPP-Concurrency"}};
    // want to delete an element that author is pezy, work is CP5
    string author="pezy";
    string work="CP5";

    auto found=authors.find(author);
    auto cnt=authors.count(author);

    while(cnt)
    {
        if(found->second==work)
        {
            authors.erase(found);
            break;
        }
        ++found;
        --cnt;
    }

    for(const auto &author:authors)
        cout<<author.first<<" "<<author.second<<endl;
}
<|endoftext|>


<commit_before>#include <osg/LOD>

#include <algorithm>

using namespace osg;

LOD::LOD(const LOD& lod,const CopyOp& copyop):
        Group(lod,copyop),
        _centerMode(lod._centerMode),
        _userDefinedCenter(lod._userDefinedCenter),
        _rangeList(lod._rangeList)
{
}

void LOD::traverse(NodeVisitor& nv)
{
    switch(nv.getTraversalMode())
    {
        case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
            std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
            break;
        case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
        {
            float distance = nv.getDistanceToEyePoint(getCenter(),true);
            unsigned int numChildren = _children.size();
            if (_rangeList.size()<numChildren) numChildren=_rangeList.size();

            for(unsigned int i=0;i<numChildren;++i)
            {
                if (_rangeList[i].first<=distance && distance<_rangeList[i].second)
                {
                    _children[i]->accept(nv);
                }
            }
           break;
        }
        default:
            break;
    }
}

bool LOD::addChild( Node *child )
{
    float maxRange = 0.0f;
    if (!_rangeList.empty()) maxRange=_rangeList.back().second;
    return addChild(child,maxRange,maxRange);
}

bool LOD::addChild(Node *child, float min, float max)
{
    if (Group::addChild(child))
    {
        if (_children.size()>_rangeList.size()) _rangeList.resize(_children.size(),MinMaxPair(min,min));
        _rangeList[_children.size()-1].first = min;
        _rangeList[_children.size()-1].second = max;
        return true;
    }
    return false;
}

bool LOD::removeChild( Node *child )
{
    // find the child's position.
    unsigned int pos=findChildNo(child);
    if (pos==_children.size()) return false;

    _rangeList.erase(_rangeList.begin()+pos);

    return Group::removeChild(child);
}

void LOD::setRange(unsigned int childNo, float min,float max)
{
    if (childNo>=_rangeList.size()) _rangeList.resize(childNo+1,MinMaxPair(min,min));
    _rangeList[childNo].first=min;
    _rangeList[childNo].second=max;
}
<commit_msg>Fixed bug in osg::LOD::addChild() which was forcing all ranges to be identical values.<commit_after>#include <osg/LOD>

#include <algorithm>

using namespace osg;

LOD::LOD(const LOD& lod,const CopyOp& copyop):
        Group(lod,copyop),
        _centerMode(lod._centerMode),
        _userDefinedCenter(lod._userDefinedCenter),
        _rangeList(lod._rangeList)
{
}

void LOD::traverse(NodeVisitor& nv)
{
    switch(nv.getTraversalMode())
    {
        case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
            std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
            break;
        case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
        {
            float distance = nv.getDistanceToEyePoint(getCenter(),true);
            unsigned int numChildren = _children.size();
            if (_rangeList.size()<numChildren) numChildren=_rangeList.size();

            for(unsigned int i=0;i<numChildren;++i)
            {
                if (_rangeList[i].first<=distance && distance<_rangeList[i].second)
                {
                    _children[i]->accept(nv);
                }
            }
           break;
        }
        default:
            break;
    }
}

bool LOD::addChild( Node *child )
{
    if (Group::addChild(child))
    {
        float maxRange = 0.0f;
        if (!_rangeList.empty()) maxRange=_rangeList.back().second;

        if (_children.size()>_rangeList.size()) _rangeList.resize(_children.size(),MinMaxPair(maxRange,maxRange));

        return true;
    }
    return false;
}

bool LOD::addChild(Node *child, float min, float max)
{
    if (Group::addChild(child))
    {
        if (_children.size()>_rangeList.size()) _rangeList.resize(_children.size(),MinMaxPair(min,min));
        _rangeList[_children.size()-1].first = min;
        _rangeList[_children.size()-1].second = max;
        return true;
    }
    return false;
}

bool LOD::removeChild( Node *child )
{
    // find the child's position.
    unsigned int pos=findChildNo(child);
    if (pos==_children.size()) return false;

    _rangeList.erase(_rangeList.begin()+pos);

    return Group::removeChild(child);
}

void LOD::setRange(unsigned int childNo, float min,float max)
{
    if (childNo>=_rangeList.size()) _rangeList.resize(childNo+1,MinMaxPair(min,min));
    _rangeList[childNo].first=min;
    _rangeList[childNo].second=max;
}
<|endoftext|>


<commit_before>//
//  ex12_14.cpp
//  Exercise 12.14
//
//  Created by pezy on 12/22/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  Write your own version of a function that uses a shared_ptr to manage a
//  connection.

#include <iostream>
#include <string>
#include <memory>

struct connection {
    std::string ip;
    int port;
    connection(std::string ip_, int port_) : ip(ip_), port(port_) {}
};
struct destination {
    std::string ip;
    int port;
    destination(std::string ip_, int port_) : ip(ip_), port(port_) {}
};

connection connect(destination* pDest)
{
    std::shared_ptr<connection> pConn(new connection(pDest->ip, pDest->port));
    std::cout << "creating connection(" << pConn.use_count() << ")"
              << std::endl;
    return *pConn;
}

void disconnect(connection pConn)
{
    std::cout << "connection close(" << pConn.ip << ":" << pConn.port << ")"
              << std::endl;
}

void end_connection(connection* pConn)
{
    disconnect(*pConn);
}

void f(destination& d)
{
    connection conn = connect(&d);
    std::shared_ptr<connection> p(&conn, end_connection);
    std::cout << "connecting now(" << p.use_count() << ")" << std::endl;
}

int main()
{
    destination dest("202.118.176.67", 3316);
    f(dest);
}<commit_msg>Update ex12_14.cpp<commit_after>//
//  ex12_14.cpp
//  Exercise 12.14
//
//  Created by pezy on 12/22/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  Write your own version of a function that uses a shared_ptr to manage a
//  connection.

#include <iostream>
#include <memory>
#include <string>

using namespace std;

struct destination {
    string ip;
    int port;
    destination(string ip_, int port_):ip(ip_), port(port_) {}
};

struct connection {
    string ip;
    int port;
    connection(string ip_, int port_):ip(ip_), port(port_) {}
};

connection connect(destination *pDest)
{
    shared_ptr<connection> pConn(new connection(pDest->ip, pDest->port));
    cout<<"creating connection("<<pConn.use_count()<<")"<<endl;
    return *pConn;
}

void disconnect(connection pConn)
{
    cout<<"connection close("<<pConn.ip<<":"<<pConn.port<<")"<<endl;
}

void end_connection(connection *pConn)
{
    disconnect(*pConn);
}

void f(destination &d)
{
    connection conn=connect(&d);
    shared_ptr<connection> p(&conn, end_connection);
    cout<<"connecting now("<<p.use_count()<<")"<<endl;
}

int main()
{
    destination dest("202.118.176.67", 3316);
    f(dest);
}
<|endoftext|>


<commit_before>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Miodrag Milanovic <miodrag@symbioticeda.com>
 *  Copyright (C) 2018  Serge Bazanski <q3k@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "treemodel.h"
#include "log.h"

NEXTPNR_NAMESPACE_BEGIN

namespace TreeModel {

// converts 'aa123bb432' -> ['aa', '123', 'bb', '432']
std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
{
    std::vector<QString> res;
    QString current_part;

    bool number = true;
    for (const auto c : str) {
        if (current_part.size() == 0 && res.size() == 0) {
            current_part.push_back(c);
            number = c.isNumber();
            continue;
        }

        if (number != c.isNumber()) {
            number = c.isNumber();
            res.push_back(current_part);
            current_part.clear();
        }

        current_part.push_back(c);
    }

    res.push_back(current_part);

    return res;
}

void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
{
    bool changed = false;

    // For any elements that are not yet in managed_, created them.
    std::unordered_set<IdString> element_set;
    for (auto elem : elements) {
        element_set.insert(elem);
        auto existing = managed_.find(elem);
        if (existing == managed_.end()) {
            auto item = new IdStringItem(ctx, elem, this, child_type_);
            managed_.emplace(elem, std::unique_ptr<IdStringItem>(item));
            changed = true;
        }
    }

    // For any elements that are in managed_ but not in new, delete them.
    for (auto &pair : managed_) {
        if (element_set.count(pair.first) != 0) {
            continue;
        }
        managed_.erase(pair.first);
        changed = true;
    }

    // Return early if there are no changes.
    if (!changed)
        return;

    // Rebuild children list.
    children_.clear();
    for (auto &pair : managed_) {
        if (element_set.count(pair.first) != 0) {
            children_.push_back(pair.second.get());
        }
    }

    // Sort new children
    qSort(children_.begin(), children_.end(), [&](const Item *a, const Item *b){
        auto parts_a = alphaNumSplit(a->name());
        auto parts_b = alphaNumSplit(b->name());

        // Short-circuit for different part count.
        if (parts_a.size() != parts_b.size()) {
            return parts_a.size() < parts_b.size();
        }

        for (size_t i = 0; i < parts_a.size(); i++) {
            auto &part_a = parts_a.at(i);
            auto &part_b = parts_b.at(i);

            bool a_is_number, b_is_number;
            int a_number = part_a.toInt(&a_is_number);
            int b_number = part_b.toInt(&b_is_number);

            // If both parts are numbers, compare numerically.
            // If they're equal, continue to next part.
            if (a_is_number && b_is_number) {
                if (a_number != b_number) {
                    return a_number < b_number;
                } else {
                    continue;
                }
            }

            // For different alpha/nonalpha types, make numeric parts appear
            // first.
            if (a_is_number != b_is_number) {
                return a_is_number;
            }

            // If both parts are numbers, compare lexically.
            // If they're equal, continue to next part.
            if (part_a == part_b) {
                continue;
            }
            return part_a < part_b;
        }

        // Same string.
        return true;
    });
}

void IdStringList::search(QList<Item*> &results, QString text, int limit)
{
    for (const auto &child : children_) {
        if (limit != -1 && results.size() > limit)
            return;

        if (child->name().contains(text))
            results.push_back(child);
    }
}

Model::Model(QObject *parent) :
        QAbstractItemModel(parent),
        root_(new Item("Elements", nullptr)) {}

Model::~Model() {}

void Model::loadContext(Context *ctx)
{
    if (!ctx)
        return;
    ctx_ = ctx;

    beginResetModel();

    // Currently we lack an API to get a proper hierarchy of bels/pip/wires
    // cross-arch. So we only do this for ICE40 by querying the ChipDB
    // directly.
    // TODO(q3k): once AnyId and the tree API land in Arch, move this over.
#ifdef ARCH_ICE40
    {
        std::map<std::pair<int, int>, std::vector<BelId>> belMap;
        for (auto bel : ctx->getBels()) {
            auto loc = ctx->getBelLocation(bel);
            belMap[std::pair<int, int>(loc.x, loc.y)].push_back(bel);
        }
        auto belGetter = [](Context *ctx, BelId id) { return ctx->getBelName(id); };
        bel_root_ = std::unique_ptr<BelXYRoot>(new BelXYRoot(ctx, "Bels", root_.get(), belMap, belGetter, ElementType::BEL));

        std::map<std::pair<int, int>, std::vector<WireId>> wireMap;
        for (int i = 0; i < ctx->chip_info->num_wires; i++) {
            const auto wire = &ctx->chip_info->wire_data[i];
            WireId wireid;
            wireid.index = i;
            wireMap[std::pair<int, int>(wire->x, wire->y)].push_back(wireid);
        }
        auto wireGetter = [](Context *ctx, WireId id) { return ctx->getWireName(id); };
        wire_root_ = std::unique_ptr<WireXYRoot>(new WireXYRoot(ctx, "Wires", root_.get(), wireMap, wireGetter, ElementType::WIRE));

        std::map<std::pair<int, int>, std::vector<PipId>> pipMap;
        for (int i = 0; i < ctx->chip_info->num_pips; i++) {
            const auto pip = &ctx->chip_info->pip_data[i];
            PipId pipid;
            pipid.index = i;
            pipMap[std::pair<int, int>(pip->x, pip->y)].push_back(pipid);
        }
        printf("generating pip static tree...\n");
        auto pipGetter = [](Context *ctx, PipId id) { return ctx->getPipName(id); };
        pip_root_ = std::unique_ptr<PipXYRoot>(new PipXYRoot(ctx, "Pips", root_.get(), pipMap, pipGetter, ElementType::PIP));
    }
#endif

    cell_root_ = std::unique_ptr<IdStringList>(new IdStringList(QString("Cells"), root_.get(), ElementType::CELL));
    net_root_ = std::unique_ptr<IdStringList>(new IdStringList(QString("Nets"), root_.get(), ElementType::NET));

    endResetModel();

    updateCellsNets(ctx);
}

void Model::updateCellsNets(Context *ctx)
{
    if (!ctx)
        return;

    beginResetModel();

    std::vector<IdString> cells;
    for (auto &pair : ctx->cells) {
        cells.push_back(pair.first);
    }
    cell_root_->updateElements(ctx, cells);

    std::vector<IdString> nets;
    for (auto &pair : ctx->nets) {
        nets.push_back(pair.first);
    }
    net_root_->updateElements(ctx, nets);

    endResetModel();
}

int Model::rowCount(const QModelIndex &parent) const { return nodeFromIndex(parent)->count(); }

int Model::columnCount(const QModelIndex &parent) const { return 1; }

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
    Item *node = nodeFromIndex(parent);
    if (row >= node->count())
        return QModelIndex();

    return createIndex(row, column, node->child(row));
}

QModelIndex Model::parent(const QModelIndex &child) const
{
    Item *parent = nodeFromIndex(child)->parent();
    if (parent == root_.get())
        return QModelIndex();
    Item *node = parent->parent();
    return createIndex(node->indexOf(parent), 0, parent);
}

QVariant Model::data(const QModelIndex &index, int role) const
{
    if (index.column() != 0)
        return QVariant();
    if (role != Qt::DisplayRole)
        return QVariant();
    Item *node = nodeFromIndex(index);
    return node->name();
}

QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section);
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return QString("Items");

    return QVariant();
}

Item *Model::nodeFromIndex(const QModelIndex &idx) const
{
    if (idx.isValid())
        return (Item *)idx.internalPointer();
    return root_.get();
}

Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
    Item *node = nodeFromIndex(index);
    return Qt::ItemIsEnabled | (node->type() != ElementType::NONE ? Qt::ItemIsSelectable : Qt::NoItemFlags);
}

void Model::fetchMore(const QModelIndex &parent)
{
    if (ctx_ == nullptr)
        return;

    std::lock_guard<std::mutex> lock_ui(ctx_->ui_mutex);
    std::lock_guard<std::mutex> lock(ctx_->mutex);

    nodeFromIndex(parent)->fetchMore();
}

bool Model::canFetchMore(const QModelIndex &parent) const
{
    return nodeFromIndex(parent)->canFetchMore();
}

QList<QModelIndex> Model::search(QString text)
{
    const int limit = 500;
    QList<Item*> list;
    cell_root_->search(list, text, limit);
    net_root_->search(list, text, limit);
    bel_root_->search(list, text, limit);
    wire_root_->search(list, text, limit);
    pip_root_->search(list, text, limit);

    QList<QModelIndex> res;
    for (auto i : list) {
        res.push_back(indexFromNode(i));
    }
    return res;
}

}; // namespace TreeModel

NEXTPNR_NAMESPACE_END
<commit_msg>gui: cosmetics<commit_after>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Miodrag Milanovic <miodrag@symbioticeda.com>
 *  Copyright (C) 2018  Serge Bazanski <q3k@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "treemodel.h"
#include "log.h"

NEXTPNR_NAMESPACE_BEGIN

namespace TreeModel {

// converts 'aa123bb432' -> ['aa', '123', 'bb', '432']
std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
{
    std::vector<QString> res;
    QString current_part;

    bool number = true;
    for (const auto c : str) {
        if (current_part.size() == 0 && res.size() == 0) {
            current_part.push_back(c);
            number = c.isNumber();
            continue;
        }

        if (number != c.isNumber()) {
            number = c.isNumber();
            res.push_back(current_part);
            current_part.clear();
        }

        current_part.push_back(c);
    }

    res.push_back(current_part);

    return res;
}

void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
{
    bool changed = false;

    // For any elements that are not yet in managed_, created them.
    std::unordered_set<IdString> element_set;
    for (auto elem : elements) {
        element_set.insert(elem);
        auto existing = managed_.find(elem);
        if (existing == managed_.end()) {
            auto item = new IdStringItem(ctx, elem, this, child_type_);
            managed_.emplace(elem, std::unique_ptr<IdStringItem>(item));
            changed = true;
        }
    }

    // For any elements that are in managed_ but not in new, delete them.
    for (auto &pair : managed_) {
        if (element_set.count(pair.first) != 0) {
            continue;
        }
        managed_.erase(pair.first);
        changed = true;
    }

    // Return early if there are no changes.
    if (!changed)
        return;

    // Rebuild children list.
    children_.clear();
    for (auto &pair : managed_) {
        if (element_set.count(pair.first) != 0) {
            children_.push_back(pair.second.get());
        }
    }

    // Sort new children
    qSort(children_.begin(), children_.end(), [&](const Item *a, const Item *b){
        auto parts_a = alphaNumSplit(a->name());
        auto parts_b = alphaNumSplit(b->name());

        // Short-circuit for different part count.
        if (parts_a.size() != parts_b.size()) {
            return parts_a.size() < parts_b.size();
        }

        for (size_t i = 0; i < parts_a.size(); i++) {
            auto &part_a = parts_a.at(i);
            auto &part_b = parts_b.at(i);

            bool a_is_number, b_is_number;
            int a_number = part_a.toInt(&a_is_number);
            int b_number = part_b.toInt(&b_is_number);

            // If both parts are numbers, compare numerically.
            // If they're equal, continue to next part.
            if (a_is_number && b_is_number) {
                if (a_number != b_number) {
                    return a_number < b_number;
                } else {
                    continue;
                }
            }

            // For different alpha/nonalpha types, make numeric parts appear
            // first.
            if (a_is_number != b_is_number) {
                return a_is_number;
            }

            // If both parts are numbers, compare lexically.
            // If they're equal, continue to next part.
            if (part_a == part_b) {
                continue;
            }
            return part_a < part_b;
        }

        // Same string.
        return true;
    });
}

void IdStringList::search(QList<Item*> &results, QString text, int limit)
{
    for (const auto &child : children_) {
        if (limit != -1 && results.size() > limit)
            return;

        if (child->name().contains(text))
            results.push_back(child);
    }
}

Model::Model(QObject *parent) :
        QAbstractItemModel(parent),
        root_(new Item("Elements", nullptr)) {}

Model::~Model() {}

void Model::loadContext(Context *ctx)
{
    if (!ctx)
        return;
    ctx_ = ctx;

    beginResetModel();

    // Currently we lack an API to get a proper hierarchy of bels/pip/wires
    // cross-arch. So we only do this for ICE40 by querying the ChipDB
    // directly.
    // TODO(q3k): once AnyId and the tree API land in Arch, move this over.
#ifdef ARCH_ICE40
    {
        std::map<std::pair<int, int>, std::vector<BelId>> belMap;
        for (auto bel : ctx->getBels()) {
            auto loc = ctx->getBelLocation(bel);
            belMap[std::pair<int, int>(loc.x, loc.y)].push_back(bel);
        }
        auto belGetter = [](Context *ctx, BelId id) { return ctx->getBelName(id); };
        bel_root_ = std::unique_ptr<BelXYRoot>(new BelXYRoot(ctx, "Bels", root_.get(), belMap, belGetter, ElementType::BEL));

        std::map<std::pair<int, int>, std::vector<WireId>> wireMap;
        for (int i = 0; i < ctx->chip_info->num_wires; i++) {
            const auto wire = &ctx->chip_info->wire_data[i];
            WireId wireid;
            wireid.index = i;
            wireMap[std::pair<int, int>(wire->x, wire->y)].push_back(wireid);
        }
        auto wireGetter = [](Context *ctx, WireId id) { return ctx->getWireName(id); };
        wire_root_ = std::unique_ptr<WireXYRoot>(new WireXYRoot(ctx, "Wires", root_.get(), wireMap, wireGetter, ElementType::WIRE));

        std::map<std::pair<int, int>, std::vector<PipId>> pipMap;
        for (int i = 0; i < ctx->chip_info->num_pips; i++) {
            const auto pip = &ctx->chip_info->pip_data[i];
            PipId pipid;
            pipid.index = i;
            pipMap[std::pair<int, int>(pip->x, pip->y)].push_back(pipid);
        }
        auto pipGetter = [](Context *ctx, PipId id) { return ctx->getPipName(id); };
        pip_root_ = std::unique_ptr<PipXYRoot>(new PipXYRoot(ctx, "Pips", root_.get(), pipMap, pipGetter, ElementType::PIP));
    }
#endif

    cell_root_ = std::unique_ptr<IdStringList>(new IdStringList(QString("Cells"), root_.get(), ElementType::CELL));
    net_root_ = std::unique_ptr<IdStringList>(new IdStringList(QString("Nets"), root_.get(), ElementType::NET));

    endResetModel();

    updateCellsNets(ctx);
}

void Model::updateCellsNets(Context *ctx)
{
    if (!ctx)
        return;

    beginResetModel();

    std::vector<IdString> cells;
    for (auto &pair : ctx->cells) {
        cells.push_back(pair.first);
    }
    cell_root_->updateElements(ctx, cells);

    std::vector<IdString> nets;
    for (auto &pair : ctx->nets) {
        nets.push_back(pair.first);
    }
    net_root_->updateElements(ctx, nets);

    endResetModel();
}

int Model::rowCount(const QModelIndex &parent) const { return nodeFromIndex(parent)->count(); }

int Model::columnCount(const QModelIndex &parent) const { return 1; }

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
    Item *node = nodeFromIndex(parent);
    if (row >= node->count())
        return QModelIndex();

    return createIndex(row, column, node->child(row));
}

QModelIndex Model::parent(const QModelIndex &child) const
{
    Item *parent = nodeFromIndex(child)->parent();
    if (parent == root_.get())
        return QModelIndex();
    Item *node = parent->parent();
    return createIndex(node->indexOf(parent), 0, parent);
}

QVariant Model::data(const QModelIndex &index, int role) const
{
    if (index.column() != 0)
        return QVariant();
    if (role != Qt::DisplayRole)
        return QVariant();
    Item *node = nodeFromIndex(index);
    return node->name();
}

QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section);
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return QString("Items");

    return QVariant();
}

Item *Model::nodeFromIndex(const QModelIndex &idx) const
{
    if (idx.isValid())
        return (Item *)idx.internalPointer();
    return root_.get();
}

Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
    Item *node = nodeFromIndex(index);
    return Qt::ItemIsEnabled | (node->type() != ElementType::NONE ? Qt::ItemIsSelectable : Qt::NoItemFlags);
}

void Model::fetchMore(const QModelIndex &parent)
{
    if (ctx_ == nullptr)
        return;

    std::lock_guard<std::mutex> lock_ui(ctx_->ui_mutex);
    std::lock_guard<std::mutex> lock(ctx_->mutex);

    nodeFromIndex(parent)->fetchMore();
}

bool Model::canFetchMore(const QModelIndex &parent) const
{
    return nodeFromIndex(parent)->canFetchMore();
}

QList<QModelIndex> Model::search(QString text)
{
    const int limit = 500;
    QList<Item*> list;
    cell_root_->search(list, text, limit);
    net_root_->search(list, text, limit);
    bel_root_->search(list, text, limit);
    wire_root_->search(list, text, limit);
    pip_root_->search(list, text, limit);

    QList<QModelIndex> res;
    for (auto i : list) {
        res.push_back(indexFromNode(i));
    }
    return res;
}

}; // namespace TreeModel

NEXTPNR_NAMESPACE_END
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "compaction_manager.hh"
#include "sstables/compaction_manager.hh"
#include "api/api-doc/compaction_manager.json.hh"
#include "db/system_keyspace.hh"
#include "column_family.hh"
#include <utility>

namespace api {

namespace cm = httpd::compaction_manager_json;
using namespace json;

static future<json::json_return_type> get_cm_stats(http_context& ctx,
        int64_t compaction_manager::stats::*f) {
    return ctx.db.map_reduce0([f](database& db) {
        return db.get_compaction_manager().get_stats().*f;
    }, int64_t(0), std::plus<int64_t>()).then([](const int64_t& res) {
        return make_ready_future<json::json_return_type>(res);
    });
}
static std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash> sum_pending_tasks(std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>&& a,
        const std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>& b) {
    for (auto&& i : b) {
        if (i.second) {
            a[i.first] += i.second;
        }
    }
    return std::move(a);
}

void set_compaction_manager(http_context& ctx, routes& r) {
    cm::get_compactions.set(r, [&ctx] (std::unique_ptr<request> req) {
        return ctx.db.map_reduce0([](database& db) {
            std::vector<cm::summary> summaries;
            const compaction_manager& cm = db.get_compaction_manager();

            for (const auto& c : cm.get_compactions()) {
                cm::summary s;
                s.ks = c->ks_name;
                s.cf = c->cf_name;
                s.unit = "keys";
                s.task_type = sstables::compaction_name(c->type);
                s.completed = c->total_keys_written;
                s.total = c->total_partitions;
                summaries.push_back(std::move(s));
            }
            return summaries;
        }, std::vector<cm::summary>(), concat<cm::summary>).then([](const std::vector<cm::summary>& res) {
            return make_ready_future<json::json_return_type>(res);
        });
    });

    cm::get_pending_tasks_by_table.set(r, [&ctx] (std::unique_ptr<request> req) {
        return ctx.db.map_reduce0([&ctx](database& db) {
            std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash> tasks;
            return do_for_each(db.get_column_families(), [&tasks](const std::pair<utils::UUID, seastar::lw_shared_ptr<table>>& i) {
                table& cf = *i.second.get();
                tasks[std::make_pair(cf.schema()->ks_name(), cf.schema()->cf_name())] = cf.get_compaction_strategy().estimated_pending_compactions(cf);
                return make_ready_future<>();
            }).then([&tasks] {
                return tasks;
            });
        }, std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>(), sum_pending_tasks).then(
                [](const std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>& task_map) {
            std::vector<cm::pending_compaction> res;
            res.reserve(task_map.size());
            for (auto i : task_map) {
                cm::pending_compaction task;
                task.ks = i.first.first;
                task.cf = i.first.second;
                task.task = i.second;
                res.emplace_back(std::move(task));
            }
            return make_ready_future<json::json_return_type>(res);
        });
    });

    cm::force_user_defined_compaction.set(r, [] (std::unique_ptr<request> req) {
        //TBD
        // FIXME
        warn(unimplemented::cause::API);
        return make_ready_future<json::json_return_type>(json_void());
    });

    cm::stop_compaction.set(r, [&ctx] (std::unique_ptr<request> req) {
        auto type = req->get_query_param("type");
        return ctx.db.invoke_on_all([type] (database& db) {
            auto& cm = db.get_compaction_manager();
            cm.stop_compaction(type);
        }).then([] {
            return make_ready_future<json::json_return_type>(json_void());
        });
    });

    cm::get_pending_tasks.set(r, [&ctx] (std::unique_ptr<request> req) {
        return map_reduce_cf(ctx, int64_t(0), [](column_family& cf) {
            return cf.get_compaction_strategy().estimated_pending_compactions(cf);
        }, std::plus<int64_t>());
    });

    cm::get_completed_tasks.set(r, [&ctx] (std::unique_ptr<request> req) {
        return get_cm_stats(ctx, &compaction_manager::stats::completed_tasks);
    });

    cm::get_total_compactions_completed.set(r, [] (std::unique_ptr<request> req) {
        // FIXME
        // We are currently dont have an API for compaction
        // so returning a 0 as the number of total compaction is ok
        return make_ready_future<json::json_return_type>(0);
    });

    cm::get_bytes_compacted.set(r, [] (std::unique_ptr<request> req) {
        //TBD
        // FIXME
        warn(unimplemented::cause::API);
        return make_ready_future<json::json_return_type>(0);
    });

    cm::get_compaction_history.set(r, [] (std::unique_ptr<request> req) {
        std::function<future<>(output_stream<char>&&)> f = [](output_stream<char>&& s) {
            return do_with(output_stream<char>(std::move(s)), true, [] (output_stream<char>& s, bool& first){
                return s.write("[").then([&s, &first] {
                    return db::system_keyspace::get_compaction_history([&s, &first](const db::system_keyspace::compaction_history_entry& entry) mutable {
                        cm::history h;
                        h.id = entry.id.to_sstring();
                        h.ks = std::move(entry.ks);
                        h.cf = std::move(entry.cf);
                        h.compacted_at = entry.compacted_at;
                        h.bytes_in = entry.bytes_in;
                        h.bytes_out =  entry.bytes_out;
                        for (auto it : entry.rows_merged) {
                            httpd::compaction_manager_json::row_merged e;
                            e.key = it.first;
                            e.value = it.second;
                            h.rows_merged.push(std::move(e));
                        }
                        auto fut = first ? make_ready_future<>() : s.write(", ");
                        first = false;
                        return fut.then([&s, h = std::move(h)] {
                            return formatter::write(s, h);
                        });
                    }).then([&s] {
                        return s.write("]").then([&s] {
                            return s.close();
                        });
                    });
                });
            });
        };
        return make_ready_future<json::json_return_type>(std::move(f));
    });

    cm::get_compaction_info.set(r, [] (std::unique_ptr<request> req) {
        //TBD
        // FIXME
        warn(unimplemented::cause::API);
        std::vector<cm::compaction_info> res;
        return make_ready_future<json::json_return_type>(res);
    });

}

}

<commit_msg>api/compaction_manager: do not hold map on the stack<commit_after>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "compaction_manager.hh"
#include "sstables/compaction_manager.hh"
#include "api/api-doc/compaction_manager.json.hh"
#include "db/system_keyspace.hh"
#include "column_family.hh"
#include <utility>

namespace api {

namespace cm = httpd::compaction_manager_json;
using namespace json;

static future<json::json_return_type> get_cm_stats(http_context& ctx,
        int64_t compaction_manager::stats::*f) {
    return ctx.db.map_reduce0([f](database& db) {
        return db.get_compaction_manager().get_stats().*f;
    }, int64_t(0), std::plus<int64_t>()).then([](const int64_t& res) {
        return make_ready_future<json::json_return_type>(res);
    });
}
static std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash> sum_pending_tasks(std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>&& a,
        const std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>& b) {
    for (auto&& i : b) {
        if (i.second) {
            a[i.first] += i.second;
        }
    }
    return std::move(a);
}

void set_compaction_manager(http_context& ctx, routes& r) {
    cm::get_compactions.set(r, [&ctx] (std::unique_ptr<request> req) {
        return ctx.db.map_reduce0([](database& db) {
            std::vector<cm::summary> summaries;
            const compaction_manager& cm = db.get_compaction_manager();

            for (const auto& c : cm.get_compactions()) {
                cm::summary s;
                s.ks = c->ks_name;
                s.cf = c->cf_name;
                s.unit = "keys";
                s.task_type = sstables::compaction_name(c->type);
                s.completed = c->total_keys_written;
                s.total = c->total_partitions;
                summaries.push_back(std::move(s));
            }
            return summaries;
        }, std::vector<cm::summary>(), concat<cm::summary>).then([](const std::vector<cm::summary>& res) {
            return make_ready_future<json::json_return_type>(res);
        });
    });

    cm::get_pending_tasks_by_table.set(r, [&ctx] (std::unique_ptr<request> req) {
        return ctx.db.map_reduce0([&ctx](database& db) {
            return do_with(std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>(), [&ctx, &db](std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>& tasks) {
            return do_for_each(db.get_column_families(), [&tasks](const std::pair<utils::UUID, seastar::lw_shared_ptr<table>>& i) {
                table& cf = *i.second.get();
                tasks[std::make_pair(cf.schema()->ks_name(), cf.schema()->cf_name())] = cf.get_compaction_strategy().estimated_pending_compactions(cf);
                return make_ready_future<>();
            }).then([&tasks] {
                return std::move(tasks);
            });
            });
        }, std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>(), sum_pending_tasks).then(
                [](const std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_hash>& task_map) {
            std::vector<cm::pending_compaction> res;
            res.reserve(task_map.size());
            for (auto i : task_map) {
                cm::pending_compaction task;
                task.ks = i.first.first;
                task.cf = i.first.second;
                task.task = i.second;
                res.emplace_back(std::move(task));
            }
            return make_ready_future<json::json_return_type>(res);
        });
    });

    cm::force_user_defined_compaction.set(r, [] (std::unique_ptr<request> req) {
        //TBD
        // FIXME
        warn(unimplemented::cause::API);
        return make_ready_future<json::json_return_type>(json_void());
    });

    cm::stop_compaction.set(r, [&ctx] (std::unique_ptr<request> req) {
        auto type = req->get_query_param("type");
        return ctx.db.invoke_on_all([type] (database& db) {
            auto& cm = db.get_compaction_manager();
            cm.stop_compaction(type);
        }).then([] {
            return make_ready_future<json::json_return_type>(json_void());
        });
    });

    cm::get_pending_tasks.set(r, [&ctx] (std::unique_ptr<request> req) {
        return map_reduce_cf(ctx, int64_t(0), [](column_family& cf) {
            return cf.get_compaction_strategy().estimated_pending_compactions(cf);
        }, std::plus<int64_t>());
    });

    cm::get_completed_tasks.set(r, [&ctx] (std::unique_ptr<request> req) {
        return get_cm_stats(ctx, &compaction_manager::stats::completed_tasks);
    });

    cm::get_total_compactions_completed.set(r, [] (std::unique_ptr<request> req) {
        // FIXME
        // We are currently dont have an API for compaction
        // so returning a 0 as the number of total compaction is ok
        return make_ready_future<json::json_return_type>(0);
    });

    cm::get_bytes_compacted.set(r, [] (std::unique_ptr<request> req) {
        //TBD
        // FIXME
        warn(unimplemented::cause::API);
        return make_ready_future<json::json_return_type>(0);
    });

    cm::get_compaction_history.set(r, [] (std::unique_ptr<request> req) {
        std::function<future<>(output_stream<char>&&)> f = [](output_stream<char>&& s) {
            return do_with(output_stream<char>(std::move(s)), true, [] (output_stream<char>& s, bool& first){
                return s.write("[").then([&s, &first] {
                    return db::system_keyspace::get_compaction_history([&s, &first](const db::system_keyspace::compaction_history_entry& entry) mutable {
                        cm::history h;
                        h.id = entry.id.to_sstring();
                        h.ks = std::move(entry.ks);
                        h.cf = std::move(entry.cf);
                        h.compacted_at = entry.compacted_at;
                        h.bytes_in = entry.bytes_in;
                        h.bytes_out =  entry.bytes_out;
                        for (auto it : entry.rows_merged) {
                            httpd::compaction_manager_json::row_merged e;
                            e.key = it.first;
                            e.value = it.second;
                            h.rows_merged.push(std::move(e));
                        }
                        auto fut = first ? make_ready_future<>() : s.write(", ");
                        first = false;
                        return fut.then([&s, h = std::move(h)] {
                            return formatter::write(s, h);
                        });
                    }).then([&s] {
                        return s.write("]").then([&s] {
                            return s.close();
                        });
                    });
                });
            });
        };
        return make_ready_future<json::json_return_type>(std::move(f));
    });

    cm::get_compaction_info.set(r, [] (std::unique_ptr<request> req) {
        //TBD
        // FIXME
        warn(unimplemented::cause::API);
        std::vector<cm::compaction_info> res;
        return make_ready_future<json::json_return_type>(res);
    });

}

}

<|endoftext|>


<commit_before>#include <iostream>
#include "SdlApplication.h"
#include "vgl.h"
#include "LoadShaders.h"

enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };

GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];

const GLuint NumVertices = 6;

class MyApplication: public SdlApplication {
public:
//    MyApplication();
    int init(int width, int height);
    void Render();
};

// MyApplication::MyApplication()
//     : SdlApplication()
// {
// }

int MyApplication::init(int width, int height)
{
    int retval = SdlApplication::init(width, height);

    glGenVertexArrays(NumVAOs, VAOs);
    glBindVertexArray(VAOs[Triangles]);
    GLfloat vertices[NumVertices][2] = {
        { -0.90, -0.90 }, // Triangle 1
        {  0.85, -0.90 },
        { -0.90,  0.85 },
        {  0.90, -0.85 }, // Triangle 2
        {  0.90,  0.90 },
        { -0.85,  0.90 },
    };
    glGenBuffers(NumBuffers, Buffers);
    glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    ShaderInfo shaders[] = {
        { GL_VERTEX_SHADER, "triangles.vert" },
        { GL_FRAGMENT_SHADER, "triangles.frag" },
        { GL_NONE, NULL}
    };
    GLuint program = LoadShaders(shaders);
    glUseProgram(program);
    glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(vPosition);

    return retval;
}

void MyApplication::Render()
{
    /* This makes our buffer swap syncronized with the monitor's vertical refresh */
    SDL_GL_SetSwapInterval(1);

    glClear(GL_COLOR_BUFFER_BIT);
    glBindVertexArray(VAOs[Triangles]);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    glFlush();

    /* Swap our back buffer to the front */
    SDL_GL_SwapWindow(win);
}

int main(int argc, char* argv[])
{
	MyApplication app;
	return app.run(640, 480);
}

<commit_msg>Removed commented out unnecessary mess<commit_after>#include <iostream>
#include "SdlApplication.h"
#include "vgl.h"
#include "LoadShaders.h"

enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };

GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];

const GLuint NumVertices = 6;

class MyApplication: public SdlApplication {
public:
    int init(int width, int height);
    void Render();
};

int MyApplication::init(int width, int height)
{
    int retval = SdlApplication::init(width, height);

    glGenVertexArrays(NumVAOs, VAOs);
    glBindVertexArray(VAOs[Triangles]);
    GLfloat vertices[NumVertices][2] = {
        { -0.90, -0.90 }, // Triangle 1
        {  0.85, -0.90 },
        { -0.90,  0.85 },
        {  0.90, -0.85 }, // Triangle 2
        {  0.90,  0.90 },
        { -0.85,  0.90 },
    };
    glGenBuffers(NumBuffers, Buffers);
    glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    ShaderInfo shaders[] = {
        { GL_VERTEX_SHADER, "triangles.vert" },
        { GL_FRAGMENT_SHADER, "triangles.frag" },
        { GL_NONE, NULL}
    };
    GLuint program = LoadShaders(shaders);
    glUseProgram(program);
    glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(vPosition);

    return retval;
}

void MyApplication::Render()
{
    /* This makes our buffer swap syncronized with the monitor's vertical refresh */
    SDL_GL_SetSwapInterval(1);

    glClear(GL_COLOR_BUFFER_BIT);
    glBindVertexArray(VAOs[Triangles]);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    glFlush();

    /* Swap our back buffer to the front */
    SDL_GL_SwapWindow(win);
}

int main(int argc, char* argv[])
{
	MyApplication app;
	return app.run(640, 480);
}

<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#include "itkCommand.h"

namespace itk
{
  Command::Command() = default;

  Command::~Command() = default;

  CStyleCommand::CStyleCommand()

  {}

  CStyleCommand::~CStyleCommand()
    {
    if ( m_ClientDataDeleteCallback )
      {
      m_ClientDataDeleteCallback(m_ClientData);
      }
    }

  void CStyleCommand::SetClientData(void *cd)
    {
    m_ClientData = cd;
    }
  void CStyleCommand::SetCallback(FunctionPointer f)
    {
    m_Callback = f;
    }
  void CStyleCommand::SetConstCallback(ConstFunctionPointer f)
    {
    m_ConstCallback = f;
    }
  void CStyleCommand::SetClientDataDeleteCallback(DeleteDataFunctionPointer f)
    {
    m_ClientDataDeleteCallback = f;
    }

  void CStyleCommand::Execute(Object *caller, const EventObject & event)
    {
    if ( m_Callback )
      {
      m_Callback(caller, event, m_ClientData);
      }
    }

  void CStyleCommand::Execute(const Object *caller, const EventObject & event)
    {
    if ( m_ConstCallback )
      {
      m_ConstCallback(caller, event, m_ClientData);
      }
    }
}
<commit_msg>STYLE: Use = default for trivial constructors<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#include "itkCommand.h"

namespace itk
{
  Command::Command() = default;

  Command::~Command() = default;

  CStyleCommand::CStyleCommand() = default;

  CStyleCommand::~CStyleCommand()
    {
    if ( m_ClientDataDeleteCallback )
      {
      m_ClientDataDeleteCallback(m_ClientData);
      }
    }

  void CStyleCommand::SetClientData(void *cd)
    {
    m_ClientData = cd;
    }
  void CStyleCommand::SetCallback(FunctionPointer f)
    {
    m_Callback = f;
    }
  void CStyleCommand::SetConstCallback(ConstFunctionPointer f)
    {
    m_ConstCallback = f;
    }
  void CStyleCommand::SetClientDataDeleteCallback(DeleteDataFunctionPointer f)
    {
    m_ClientDataDeleteCallback = f;
    }

  void CStyleCommand::Execute(Object *caller, const EventObject & event)
    {
    if ( m_Callback )
      {
      m_Callback(caller, event, m_ClientData);
      }
    }

  void CStyleCommand::Execute(const Object *caller, const EventObject & event)
    {
    if ( m_ConstCallback )
      {
      m_ConstCallback(caller, event, m_ClientData);
      }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Jari Saukkonen
 *
 * 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 "PowerConsumptionLog.h"

PowerConsumptionLog::PowerConsumptionLog() :
    m_pos(0),
    m_windowPos(0),
    m_overloadThreshold(5000) {
    memset(&m_data[0], 0, 16);
    memset(&m_window[0], 0, 16);
}

void PowerConsumptionLog::measure(unsigned int milliAmps) {
    m_window[m_windowPos++ & 0xF] = milliAmps;
}

void PowerConsumptionLog::appendCurrentMeasurement() {
    unsigned int avg = 0;
    for (int i = 1; i <= 10; i++) {
        avg += m_window[(m_windowPos-i) & 0xF];
    }
    m_data[m_pos++ & 0xF] = avg/10;
}

bool PowerConsumptionLog::isOverload(unsigned int threshold) const {
    for (int i = 1; i <= 5; i++) {
        if (m_data[(m_pos-i) % 0xF] < threshold) {
            return false;
        }
    }
    return true;
}

void PowerConsumptionLog::report(NMEASerial& serial) {
    String message = "POWER,";
    for (int i = 1; i <= 10; i++) {
        message += String(m_data[(m_pos-i) % 0xF]) + ",";
    }
    serial.print(message.substring(0, message.length()-1));
}
<commit_msg>Make overload condition more sensitive<commit_after>/*
 * Copyright (c) 2016 Jari Saukkonen
 *
 * 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 "PowerConsumptionLog.h"

PowerConsumptionLog::PowerConsumptionLog() :
    m_pos(0),
    m_windowPos(0),
    m_overloadThreshold(5000) {
    memset(&m_data[0], 0, 16);
    memset(&m_window[0], 0, 16);
}

void PowerConsumptionLog::measure(unsigned int milliAmps) {
    m_window[m_windowPos++ & 0xF] = milliAmps;
}

void PowerConsumptionLog::appendCurrentMeasurement() {
    unsigned int avg = 0;
    for (int i = 1; i <= 10; i++) {
        avg += m_window[(m_windowPos-i) & 0xF];
    }
    m_data[m_pos++ & 0xF] = avg/10;
}

bool PowerConsumptionLog::isOverload(unsigned int threshold) const {
    for (int i = 1; i <= 3; i++) {
        if (m_data[(m_pos-i) % 0xF] < threshold) {
            return false;
        }
    }
    return true;
}

void PowerConsumptionLog::report(NMEASerial& serial) {
    String message = "POWER,";
    for (int i = 1; i <= 10; i++) {
        message += String(m_data[(m_pos-i) % 0xF]) + ",";
    }
    serial.print(message.substring(0, message.length()-1));
}
<|endoftext|>


<commit_before>#pragma once

#include <DirectXMath.h>
#include <typeinfo>

namespace dx
{
    struct UpdateArgs;
    class Game;
    class ComponentBase;

    inline constexpr std::uint32_t kMaxComponentCount = 8;

    template<typename T>
    struct is_unique_ptr : std::false_type
    {};

    template<typename T, typename D>
    struct is_unique_ptr<std::unique_ptr<T, D>> : std::true_type
    {};

    class Object final
    {
      public:
        template<typename... ComponentsT>
        Object(std::unique_ptr<ComponentsT>... components)
        {
            AddComponents(std::move(components)...);
        }

        template<typename... ComponentsT, typename = std::enable_if_t<std::conjunction_v<
                     std::negation<std::disjunction<is_unique_ptr<ComponentsT>,
                                                    std::is_same<std::decay_t<ComponentsT>, Object>>>...>>>
        Object(ComponentsT&&... components)
        {
            AddComponents(std::make_unique<std::decay_t<ComponentsT>>(std::forward<ComponentsT>(components))...);
        }

        template<typename T>
        T* GetComponent() const
        {
            return dynamic_cast<T*>(GetComponent(typeid(T)));
        }

        ComponentBase* GetComponent(const std::type_info& type) const;

        template<typename T>
        T& AddComponent(std::unique_ptr<T> component)
        {
            auto& ret = *component;
            AddComponentInternal(std::move(component));
            return ret;
        }

        template<typename... Args>
        void AddComponents(std::unique_ptr<Args>... components)
        {
            m_components.reserve(sizeof...(components));
            (AddComponentInternal(std::move(components)), ...);
        }

      private:
        void AddComponentInternal(std::unique_ptr<ComponentBase> component);

        boost::container::static_vector<std::unique_ptr<ComponentBase>, kMaxComponentCount>
            m_components;
    };
}<commit_msg>decay<commit_after>#pragma once

#include <DirectXMath.h>
#include <typeinfo>

namespace dx
{
    struct UpdateArgs;
    class Game;
    class ComponentBase;

    inline constexpr std::uint32_t kMaxComponentCount = 8;

    template<typename T>
    struct is_unique_ptr : std::false_type
    {};

    template<typename T, typename D>
    struct is_unique_ptr<std::unique_ptr<T, D>> : std::true_type
    {};

    class Object final
    {
      public:
        template<typename... ComponentsT>
        Object(std::unique_ptr<ComponentsT>... components)
        {
            AddComponents(std::move(components)...);
        }

        template<typename... ComponentsT, typename = std::enable_if_t<std::conjunction_v<
                     std::negation<std::disjunction<is_unique_ptr<std::decay_t<ComponentsT>>,
                                                    std::is_same<std::decay_t<ComponentsT>, Object>>>...>>>
        Object(ComponentsT&&... components)
        {
            AddComponents(std::make_unique<std::decay_t<ComponentsT>>(std::forward<ComponentsT>(components))...);
        }

        template<typename T>
        T* GetComponent() const
        {
            return dynamic_cast<T*>(GetComponent(typeid(T)));
        }

        ComponentBase* GetComponent(const std::type_info& type) const;

        template<typename T>
        T& AddComponent(std::unique_ptr<T> component)
        {
            auto& ret = *component;
            AddComponentInternal(std::move(component));
            return ret;
        }

        template<typename T, typename... Args,
                 typename =
                     std::enable_if_t <
                         !std::disjunction_v<is_unique_ptr<std::decay_t<Args>>...>>>
        T& AddComponent(Args&&... args)
        {
            return AddComponent<T>(std::make_unique<T>(std::forward<Args>(args)...));
        }

        template<typename... Args>
        void AddComponents(std::unique_ptr<Args>... components)
        {
            m_components.reserve(sizeof...(components));
            (AddComponentInternal(std::move(components)), ...);
        }

      private:
        void AddComponentInternal(std::unique_ptr<ComponentBase> component);

        boost::container::static_vector<std::unique_ptr<ComponentBase>, kMaxComponentCount>
            m_components;
    };
}<|endoftext|>