<commit_before>/*
 * Copyright (C) 2020 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 <algorithm>
#include <limits>
#include <ostream>
#include <utility>

#include "dht/token.hh"
#include "dht/token-sharding.hh"
#include "dht/i_partitioner.hh"

namespace dht {

using uint128_t = unsigned __int128;

inline int64_t long_token(const token& t) {
    if (t.is_minimum() || t.is_maximum()) {
        return std::numeric_limits<int64_t>::min();
    }

    return t._data;
}

static const token min_token{ token::kind::before_all_keys, 0 };
static const token max_token{ token::kind::after_all_keys, 0 };

const token&
minimum_token() {
    return min_token;
}

const token&
maximum_token() {
    return max_token;
}

int tri_compare(const token& t1, const token& t2) {
    if (t1._kind < t2._kind) {
            return -1;
    } else if (t1._kind > t2._kind) {
            return 1;
    } else if (t1._kind == token_kind::key) {
        auto l1 = long_token(t1);
        auto l2 = long_token(t2);
        if (l1 == l2) {
            return 0;
        } else {
            return l1 < l2 ? -1 : 1;
        }
    }
    return 0;
}

std::ostream& operator<<(std::ostream& out, const token& t) {
    if (t._kind == token::kind::after_all_keys) {
        out << "maximum token";
    } else if (t._kind == token::kind::before_all_keys) {
        out << "minimum token";
    } else {
        out << t.to_sstring();
    }
    return out;
}

sstring token::to_sstring() const {
    return seastar::to_sstring<sstring>(long_token(*this));
}

// Assuming that x>=y, return the positive difference x-y.
// The return type is an unsigned type, as the difference may overflow
// a signed type (e.g., consider very positive x and very negative y).
template <typename T>
static std::make_unsigned_t<T> positive_subtract(T x, T y) {
        return std::make_unsigned_t<T>(x) - std::make_unsigned_t<T>(y);
}

token token::midpoint(const token& t1, const token& t2) {
    auto l1 = long_token(t1);
    auto l2 = long_token(t2);
    int64_t mid;
    if (l1 <= l2) {
        // To find the midpoint, we cannot use the trivial formula (l1+l2)/2
        // because the addition can overflow the integer. To avoid this
        // overflow, we first notice that the above formula is equivalent to
        // l1 + (l2-l1)/2. Now, "l2-l1" can still overflow a signed integer
        // (e.g., think of a very positive l2 and very negative l1), but
        // because l1 <= l2 in this branch, we note that l2-l1 is positive
        // and fits an *unsigned* int's range. So,
        mid = l1 + positive_subtract(l2, l1)/2;
    } else {
        // When l2 < l1, we need to switch l1 and and l2 in the above
        // formula, because now l1 - l2 is positive.
        // Additionally, we consider this case is a "wrap around", so we need
        // to behave as if l2 + 2^64 was meant instead of l2, i.e., add 2^63
        // to the average.
        mid = l2 + positive_subtract(l1, l2)/2 + 0x8000'0000'0000'0000;
    }
    return token{kind::key, mid};
}

token token::get_random_token() {
    static thread_local std::default_random_engine re{std::random_device{}()};
    // std::numeric_limits<int64_t>::min() value is reserved and shouldn't
    // be used for regular tokens.
    static thread_local std::uniform_int_distribution<int64_t> dist(
            std::numeric_limits<int64_t>::min() + 1);
    return token(kind::key, dist(re));
}

token token::from_sstring(const sstring& t) {
    auto lp = boost::lexical_cast<long>(t);
    if (lp == std::numeric_limits<long>::min()) {
        return minimum_token();
    } else {
        return token(kind::key, uint64_t(lp));
    }
}

token token::from_bytes(bytes_view bytes) {
    if (bytes.size() != sizeof(int64_t)) {
        throw runtime_exception(format("Invalid token. Should have size {:d}, has size {:d}\n", sizeof(int64_t), bytes.size()));
    }

    int64_t v;
    std::copy_n(bytes.begin(), sizeof(v), reinterpret_cast<int8_t *>(&v));
    auto tok = net::ntoh(v);
    if (tok == std::numeric_limits<int64_t>::min()) {
        return minimum_token();
    } else {
        return dht::token(dht::token::kind::key, tok);
    }
}

static float ratio_helper(int64_t a, int64_t b) {

    uint64_t val = (a > b)? static_cast<uint64_t>(a) - static_cast<uint64_t>(b) : (static_cast<uint64_t>(a) - static_cast<uint64_t>(b) - 1);
    return val/(float)std::numeric_limits<uint64_t>::max();
}

std::map<token, float>
token::describe_ownership(const std::vector<token>& sorted_tokens) {
    std::map<token, float> ownerships;
    auto i = sorted_tokens.begin();

    // 0-case
    if (i == sorted_tokens.end()) {
        throw runtime_exception("No nodes present in the cluster. Has this node finished starting up?");
    }
    // 1-case
    if (sorted_tokens.size() == 1) {
        ownerships[sorted_tokens[0]] = 1.0;
    // n-case
    } else {
        const token& start = sorted_tokens[0];

        int64_t ti = long_token(start);  // The first token and its value
        int64_t start_long = ti;
        int64_t tim1 = ti; // The last token and its value (after loop)
        for (i++; i != sorted_tokens.end(); i++) {
            ti = long_token(*i); // The next token and its value
            ownerships[*i]= ratio_helper(ti, tim1);  // save (T(i) -> %age)
            tim1 = ti;
        }

        // The start token's range extends backward to the last token, which is why both were saved above.
        ownerships[start] = ratio_helper(start_long, ti);
    }

    return ownerships;
}

data_type
token::get_token_validator() {
    return long_type;
}

static uint64_t unbias(const token& t) {
    return uint64_t(long_token(t)) + uint64_t(std::numeric_limits<int64_t>::min());
}

static token bias(uint64_t n) {
    return token(token::kind::key, n - uint64_t(std::numeric_limits<int64_t>::min()));
}

inline
unsigned
zero_based_shard_of(uint64_t token, unsigned shards, unsigned sharding_ignore_msb_bits) {
    // This is the master function, the inverses have to match it wrt. rounding errors.
    token <<= sharding_ignore_msb_bits;
    // Treat "token" as a fraction in the interval [0, 1); compute:
    //    shard = floor((0.token) * shards)
    return (uint128_t(token) * shards) >> 64;
}

std::vector<uint64_t>
init_zero_based_shard_start(unsigned shards, unsigned sharding_ignore_msb_bits) {
    // computes the inverse of zero_based_shard_of(). ret[s] will return the smallest token that belongs to s
    if (shards == 1) {
        // Avoid the while loops below getting confused finding the "edge" between two nonexistent shards
        return std::vector<uint64_t>(1, uint64_t(0));
    }
    auto ret = std::vector<uint64_t>(shards);
    for (auto s : boost::irange<unsigned>(0, shards)) {
        uint64_t token = (uint128_t(s) << 64) / shards;
        token >>= sharding_ignore_msb_bits;   // leftmost bits are ignored by zero_based_shard_of
        // token is the start of the next shard, and can be slightly before due to rounding errors; adjust
        while (zero_based_shard_of(token, shards, sharding_ignore_msb_bits) != s) {
            ++token;
        }
        ret[s] = token;
    }
    return ret;
}

unsigned
shard_of(unsigned shard_count, unsigned sharding_ignore_msb_bits, const token& t) {
    switch (t._kind) {
        case token::kind::before_all_keys:
            return 0;
        case token::kind::after_all_keys:
            return shard_count - 1;
        case token::kind::key:
            uint64_t adjusted = unbias(t);
            return zero_based_shard_of(adjusted, shard_count, sharding_ignore_msb_bits);
    }
    abort();
}

token
token_for_next_shard(const std::vector<uint64_t>& shard_start, unsigned shard_count, unsigned sharding_ignore_msb_bits, const token& t, shard_id shard, unsigned spans) {
    uint64_t n = 0;
    switch (t._kind) {
        case token::kind::before_all_keys:
            break;
        case token::kind::after_all_keys:
            return maximum_token();
        case token::kind::key:
            n = unbias(t);
            break;
    }
    auto s = zero_based_shard_of(n, shard_count, sharding_ignore_msb_bits);

    if (!sharding_ignore_msb_bits) {
        // This ought to be the same as the else branch, but avoids shifts by 64
        n = shard_start[shard];
        if (spans > 1 || shard <= s) {
            return maximum_token();
        }
    } else {
        auto left_part = n >> (64 - sharding_ignore_msb_bits);
        left_part += spans - unsigned(shard > s);
        if (left_part >= (1u << sharding_ignore_msb_bits)) {
            return maximum_token();
        }
        left_part <<= (64 - sharding_ignore_msb_bits);
        auto right_part = shard_start[shard];
        n = left_part | right_part;
    }
    return bias(n);
}

int64_t token::to_int64(token t) {
    return t._data;
}

dht::token token::from_int64(int64_t i) {
    return {kind::key, i};
}

} // namespace dht
<commit_msg>dht: use long_token in token::to_int64<commit_after>/*
 * Copyright (C) 2020 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 <algorithm>
#include <limits>
#include <ostream>
#include <utility>

#include "dht/token.hh"
#include "dht/token-sharding.hh"
#include "dht/i_partitioner.hh"

namespace dht {

using uint128_t = unsigned __int128;

inline int64_t long_token(const token& t) {
    if (t.is_minimum() || t.is_maximum()) {
        return std::numeric_limits<int64_t>::min();
    }

    return t._data;
}

static const token min_token{ token::kind::before_all_keys, 0 };
static const token max_token{ token::kind::after_all_keys, 0 };

const token&
minimum_token() {
    return min_token;
}

const token&
maximum_token() {
    return max_token;
}

int tri_compare(const token& t1, const token& t2) {
    if (t1._kind < t2._kind) {
            return -1;
    } else if (t1._kind > t2._kind) {
            return 1;
    } else if (t1._kind == token_kind::key) {
        auto l1 = long_token(t1);
        auto l2 = long_token(t2);
        if (l1 == l2) {
            return 0;
        } else {
            return l1 < l2 ? -1 : 1;
        }
    }
    return 0;
}

std::ostream& operator<<(std::ostream& out, const token& t) {
    if (t._kind == token::kind::after_all_keys) {
        out << "maximum token";
    } else if (t._kind == token::kind::before_all_keys) {
        out << "minimum token";
    } else {
        out << t.to_sstring();
    }
    return out;
}

sstring token::to_sstring() const {
    return seastar::to_sstring<sstring>(long_token(*this));
}

// Assuming that x>=y, return the positive difference x-y.
// The return type is an unsigned type, as the difference may overflow
// a signed type (e.g., consider very positive x and very negative y).
template <typename T>
static std::make_unsigned_t<T> positive_subtract(T x, T y) {
        return std::make_unsigned_t<T>(x) - std::make_unsigned_t<T>(y);
}

token token::midpoint(const token& t1, const token& t2) {
    auto l1 = long_token(t1);
    auto l2 = long_token(t2);
    int64_t mid;
    if (l1 <= l2) {
        // To find the midpoint, we cannot use the trivial formula (l1+l2)/2
        // because the addition can overflow the integer. To avoid this
        // overflow, we first notice that the above formula is equivalent to
        // l1 + (l2-l1)/2. Now, "l2-l1" can still overflow a signed integer
        // (e.g., think of a very positive l2 and very negative l1), but
        // because l1 <= l2 in this branch, we note that l2-l1 is positive
        // and fits an *unsigned* int's range. So,
        mid = l1 + positive_subtract(l2, l1)/2;
    } else {
        // When l2 < l1, we need to switch l1 and and l2 in the above
        // formula, because now l1 - l2 is positive.
        // Additionally, we consider this case is a "wrap around", so we need
        // to behave as if l2 + 2^64 was meant instead of l2, i.e., add 2^63
        // to the average.
        mid = l2 + positive_subtract(l1, l2)/2 + 0x8000'0000'0000'0000;
    }
    return token{kind::key, mid};
}

token token::get_random_token() {
    static thread_local std::default_random_engine re{std::random_device{}()};
    // std::numeric_limits<int64_t>::min() value is reserved and shouldn't
    // be used for regular tokens.
    static thread_local std::uniform_int_distribution<int64_t> dist(
            std::numeric_limits<int64_t>::min() + 1);
    return token(kind::key, dist(re));
}

token token::from_sstring(const sstring& t) {
    auto lp = boost::lexical_cast<long>(t);
    if (lp == std::numeric_limits<long>::min()) {
        return minimum_token();
    } else {
        return token(kind::key, uint64_t(lp));
    }
}

token token::from_bytes(bytes_view bytes) {
    if (bytes.size() != sizeof(int64_t)) {
        throw runtime_exception(format("Invalid token. Should have size {:d}, has size {:d}\n", sizeof(int64_t), bytes.size()));
    }

    int64_t v;
    std::copy_n(bytes.begin(), sizeof(v), reinterpret_cast<int8_t *>(&v));
    auto tok = net::ntoh(v);
    if (tok == std::numeric_limits<int64_t>::min()) {
        return minimum_token();
    } else {
        return dht::token(dht::token::kind::key, tok);
    }
}

static float ratio_helper(int64_t a, int64_t b) {

    uint64_t val = (a > b)? static_cast<uint64_t>(a) - static_cast<uint64_t>(b) : (static_cast<uint64_t>(a) - static_cast<uint64_t>(b) - 1);
    return val/(float)std::numeric_limits<uint64_t>::max();
}

std::map<token, float>
token::describe_ownership(const std::vector<token>& sorted_tokens) {
    std::map<token, float> ownerships;
    auto i = sorted_tokens.begin();

    // 0-case
    if (i == sorted_tokens.end()) {
        throw runtime_exception("No nodes present in the cluster. Has this node finished starting up?");
    }
    // 1-case
    if (sorted_tokens.size() == 1) {
        ownerships[sorted_tokens[0]] = 1.0;
    // n-case
    } else {
        const token& start = sorted_tokens[0];

        int64_t ti = long_token(start);  // The first token and its value
        int64_t start_long = ti;
        int64_t tim1 = ti; // The last token and its value (after loop)
        for (i++; i != sorted_tokens.end(); i++) {
            ti = long_token(*i); // The next token and its value
            ownerships[*i]= ratio_helper(ti, tim1);  // save (T(i) -> %age)
            tim1 = ti;
        }

        // The start token's range extends backward to the last token, which is why both were saved above.
        ownerships[start] = ratio_helper(start_long, ti);
    }

    return ownerships;
}

data_type
token::get_token_validator() {
    return long_type;
}

static uint64_t unbias(const token& t) {
    return uint64_t(long_token(t)) + uint64_t(std::numeric_limits<int64_t>::min());
}

static token bias(uint64_t n) {
    return token(token::kind::key, n - uint64_t(std::numeric_limits<int64_t>::min()));
}

inline
unsigned
zero_based_shard_of(uint64_t token, unsigned shards, unsigned sharding_ignore_msb_bits) {
    // This is the master function, the inverses have to match it wrt. rounding errors.
    token <<= sharding_ignore_msb_bits;
    // Treat "token" as a fraction in the interval [0, 1); compute:
    //    shard = floor((0.token) * shards)
    return (uint128_t(token) * shards) >> 64;
}

std::vector<uint64_t>
init_zero_based_shard_start(unsigned shards, unsigned sharding_ignore_msb_bits) {
    // computes the inverse of zero_based_shard_of(). ret[s] will return the smallest token that belongs to s
    if (shards == 1) {
        // Avoid the while loops below getting confused finding the "edge" between two nonexistent shards
        return std::vector<uint64_t>(1, uint64_t(0));
    }
    auto ret = std::vector<uint64_t>(shards);
    for (auto s : boost::irange<unsigned>(0, shards)) {
        uint64_t token = (uint128_t(s) << 64) / shards;
        token >>= sharding_ignore_msb_bits;   // leftmost bits are ignored by zero_based_shard_of
        // token is the start of the next shard, and can be slightly before due to rounding errors; adjust
        while (zero_based_shard_of(token, shards, sharding_ignore_msb_bits) != s) {
            ++token;
        }
        ret[s] = token;
    }
    return ret;
}

unsigned
shard_of(unsigned shard_count, unsigned sharding_ignore_msb_bits, const token& t) {
    switch (t._kind) {
        case token::kind::before_all_keys:
            return 0;
        case token::kind::after_all_keys:
            return shard_count - 1;
        case token::kind::key:
            uint64_t adjusted = unbias(t);
            return zero_based_shard_of(adjusted, shard_count, sharding_ignore_msb_bits);
    }
    abort();
}

token
token_for_next_shard(const std::vector<uint64_t>& shard_start, unsigned shard_count, unsigned sharding_ignore_msb_bits, const token& t, shard_id shard, unsigned spans) {
    uint64_t n = 0;
    switch (t._kind) {
        case token::kind::before_all_keys:
            break;
        case token::kind::after_all_keys:
            return maximum_token();
        case token::kind::key:
            n = unbias(t);
            break;
    }
    auto s = zero_based_shard_of(n, shard_count, sharding_ignore_msb_bits);

    if (!sharding_ignore_msb_bits) {
        // This ought to be the same as the else branch, but avoids shifts by 64
        n = shard_start[shard];
        if (spans > 1 || shard <= s) {
            return maximum_token();
        }
    } else {
        auto left_part = n >> (64 - sharding_ignore_msb_bits);
        left_part += spans - unsigned(shard > s);
        if (left_part >= (1u << sharding_ignore_msb_bits)) {
            return maximum_token();
        }
        left_part <<= (64 - sharding_ignore_msb_bits);
        auto right_part = shard_start[shard];
        n = left_part | right_part;
    }
    return bias(n);
}

int64_t token::to_int64(token t) {
    return long_token(t);
}

dht::token token::from_int64(int64_t i) {
    return {kind::key, i};
}

} // namespace dht
<|endoftext|>


<commit_before>#include "alfe/main.h"
#include <mmsystem.h>

class Program : public ProgramBase
{
public:
    DWORD msFromWallClock(int hour, int minute, int second = 0, int ms = 0)
    {
        return (((hour*60) + minute)*60 + second)*1000 + ms;
    }
    void beep()
    {
        PlaySound(L"C:\\t\\timer.wav", NULL, SND_FILENAME);
    }
    void run()
    {
        static const int secondsToWindow = 10;
        static const int stareSeconds = 20;
        do {
            SYSTEMTIME t;
            GetLocalTime(&t);
            DWORD ms = msFromWallClock(t.wHour, t.wMinute, t.wSecond,
                t.wMilliseconds);
            ms -= msFromWallClock(t.wHour, t.wMinute - t.wMinute % 20);
            if (ms > msFromWallClock(0, 15) ||
                ms < msFromWallClock(0, 5)) {
                beep();
                Sleep(secondsToWindow*1000);
                beep();
                Sleep(stareSeconds*1000);
                beep();
                GetLocalTime(&t);
                ms = msFromWallClock(t.wHour, t.wMinute, t.wSecond,
                    t.wMilliseconds);
                if (ms > msFromWallClock(17, 55))
                    ms = msFromWallClock(24 + 9, 0) - ms;
                else {
                    ms -= msFromWallClock(t.wHour, t.wMinute - t.wMinute % 20);
                    if (t.wMinute % 20 < 10)
                        ms = msFromWallClock(0, 10) - ms;
                    else
                        ms = msFromWallClock(0, 30) - ms;
                }
            }
            else {
                beep();
                GetLocalTime(&t);
                ms = msFromWallClock(0, 20) - msFromWallClock(0,
                    t.wMinute % 20, t.wSecond, t.wMilliseconds);
            }
            Sleep(ms);
        } while (true);
    }
};<commit_msg>10 minute timer<commit_after>#include "alfe/main.h"
#include <mmsystem.h>

#define TEN_MINUTE 1

class Program : public ProgramBase
{
public:
    DWORD msFromWallClock(int hour, int minute, int second = 0, int ms = 0)
    {
        return (((hour*60) + minute)*60 + second)*1000 + ms;
    }
    void beep()
    {
        PlaySound(L"C:\\t\\timer.wav", NULL, SND_FILENAME);
    }
    void run()
    {
        static const int secondsToWindow = 10;
        static const int stareSeconds = 20;
        do {
            SYSTEMTIME t;
            DWORD ms;
#ifdef TEN_MINUTE
            GetLocalTime(&t);
            ms = msFromWallClock(t.wHour, t.wMinute, t.wSecond,
                t.wMilliseconds);
            ms -= msFromWallClock(t.wHour, t.wMinute - t.wMinute % 20);
            if (ms > msFromWallClock(0, 15) ||
                ms < msFromWallClock(0, 5)) {
#endif
                beep();
                Sleep(secondsToWindow*1000);
                beep();
                Sleep(stareSeconds*1000);
                beep();
                GetLocalTime(&t);
                ms = msFromWallClock(t.wHour, t.wMinute, t.wSecond,
                    t.wMilliseconds);
                if (ms > msFromWallClock(17, 55))
                    ms = msFromWallClock(24 + 9, 0) - ms;
                else {
                    ms -= msFromWallClock(t.wHour, t.wMinute - t.wMinute % 20);
                    if (t.wMinute % 20 < 10)
#ifdef TEN_MINUTE
                        ms = msFromWallClock(0, 10) - ms;
                    else
                        ms = msFromWallClock(0, 30) - ms;
#else
                        ms = msFromWallClock(0, 20) - ms;
                    else
                        ms = msFromWallClock(0, 40) - ms;
#endif
                }
#ifdef TEN_MINUTE
            }
            else {
                beep();
                GetLocalTime(&t);
                ms = msFromWallClock(0, 20) - msFromWallClock(0,
                    t.wMinute % 20, t.wSecond, t.wMilliseconds);
            }
#endif
            Sleep(ms);
        } while (true);
    }
};<|endoftext|>


<commit_before>//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <libport/unistd.h>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <libport/cstring>

#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <libport/asio.hh>
#include <libport/cli.hh>
#include <libport/debug.hh>
#include <libport/exception.hh>
#include <libport/foreach.hh>
#include <libport/format.hh>
#ifndef NO_OPTION_PARSER
# include <libport/option-parser.hh>
# define IF_OPTION_PARSER(a, b) a
#else
 #define IF_OPTION_PARSER(a, b) b
#endif
#include <libport/package-info.hh>
#include <libport/program-name.hh>
#include <libport/read-stdin.hh>
#include <libport/semaphore.hh>
#include <libport/sys/socket.h>
#include <libport/sysexits.hh>
#include <libport/thread.hh>
#include <libport/utime.hh>
#include <libport/windows.hh>

#include <libltdl/ltdl.h>

// Inclusion order matters for windows. Leave userver.hh after network.hh.
#include <kernel/uqueue.hh>
#include <kernel/userver.hh>
#include <kernel/uconnection.hh>

#include <sched/configuration.hh>
#include <sched/scheduler.hh>

#include <kernel/connection.hh>
#include <kernel/ubanner.hh>
#include <object/symbols.hh>
#include <object/object.hh>
#include <object/float.hh>
#include <object/system.hh>
#include <urbi/export.hh>
#include <urbi/umain.hh>
#include <urbi/uobject.hh>

GD_INIT();
GD_ADD_CATEGORY(URBI);

using libport::program_name;

class ConsoleServer
  : public kernel::UServer
  , public libport::Socket
{
public:
  ConsoleServer(bool fast)
    : kernel::UServer("console")
    , fast(fast)
    , ctime(0)
    , io_(libport::get_io_service(false))
  {}

  virtual ~ConsoleServer()
  {}

  virtual void reset()
  {}

  virtual void reboot()
  {}

  virtual libport::utime_t getTime()
  {
    return fast ? ctime : libport::utime();
  }

  virtual
  UErrorValue
  save_file(const std::string& filename, const std::string& content)
  {
    //! \todo check this code
    std::ofstream os(filename.c_str());
    os << content;
    os.close();
    return os.good() ? USUCCESS : UFAIL;
  }

  virtual
  void effectiveDisplay(const char* t)
  {
    std::cout << t;
  }

  bool fast;
  libport::utime_t ctime;
  boost::asio::io_service& io_;
};

namespace
{
#ifndef NO_OPTION_PARSER
  static
  void
  help(libport::OptionParser& parser)
  {
    std::stringstream output;
    output
      << "usage: " << libport::program_name()
      << " [OPTIONS] [PROGRAM_FILE] [ARGS...]" << std::endl
      << std::endl
      << "  PROGRAM_FILE   Urbi script to load."
      << "  `-' stands for standard input" << std::endl
      << "  ARGS           user arguments passed to PROGRAM_FILE" << std::endl
      << parser;
    throw urbi::Exit(EX_OK, output.str());
  }
#endif
  static
  void
  version()
  {
    throw urbi::Exit(EX_OK, kernel::UServer::package_info().signature());
  }

  static
  void
  forbid_option(const std::string& arg)
  {
    if (arg.size() > 1 && arg[0] == '-')
    {
      boost::format fmt("%s: unrecognized command line option: %s");
      throw urbi::Exit(EX_USAGE, str(fmt % libport::program_name() % arg));
    }
  }
}

namespace urbi
{

  /// Command line options needed in the main loop.
  struct LoopData
  {
    LoopData()
      : interactive(false)
      , fast(false)
      , network(true)
      , server(0)
    {}

    bool interactive;
    bool fast;
    /// Whether network connections are enabled.
    bool network;
    ConsoleServer* server;
  };

  int main_loop(LoopData& l);

  static libport::Socket*
  connectionFactory()
  {
    kernel::Connection* c = new kernel::Connection();
    kernel::urbiserver->connection_add(c);
    return c;
  }

  static
  int
  ltdebug(unsigned verbosity, unsigned level, const char* format, va_list args)
  {
    int errors = 0;
    if (level <= verbosity)
    {
      errors += fprintf(stderr, "%s: ", program_name().c_str()) < 0;
      errors += vfprintf(stderr, format, args) < 0;
    }
    return errors;
  }

  static std::string convert_input_file(const std::string& arg)
  {
    return (arg == "-") ? "/dev/stdin" : arg;
  }

  /// Data to send to the server.
  struct Input
  {
    Input(bool f, const std::string& v)
      : file_p(f), value(v)
    {}
    /// Whether it's a file (or a litteral).
    bool file_p;
    /// File name or litteral value.
    std::string value;
  };

  static int
  init(const libport::cli_args_type& _args, bool errors,
             libport::Semaphore* sem)
  {
    libport::Finally f;
    if (sem)
      f << boost::bind(&libport::Semaphore::operator++, sem);
    if (errors)
    {
      try
      {
        return init(_args, false, sem);
      }
      catch (const urbi::Exit& e)
      {
        std::cerr << program_name() << ": " << e.what() << std::endl;
        return e.error_get();
      }
    }

    GD_CATEGORY(URBI);

    libport::cli_args_type args = _args;

    object::system_set_program_name(args[0]);
    args.erase(args.begin());

    // Input files.
    typedef std::vector<Input> input_type;
    input_type input;
    /// The size of the stacks.
    size_t arg_stack_size = 0;

    // Parse the command line.
    LoopData data;
#ifndef NO_OPTION_PARSER
    libport::OptionFlag
      arg_fast("ignore system time, go as fast as possible",
               "fast", 'F'),
      arg_interactive("read and parse stdin in a nonblocking way",
                      "interactive", 'i'),
      arg_no_net("ignored for backward compatibility", "no-network", 'n');

    libport::OptionValue
      arg_period   ("ignored for backward compatibility", "period", 'P'),
      arg_port_file("write port number to the specified file.",
                    "port-file", 'w', "FILE"),
      arg_stack    ("set the job stack size in KB", "stack-size", 's', "SIZE");

    libport::OptionValues
      arg_exps("run expression", "expression", 'e', "EXP");

    {
      libport::OptionParser parser;
      parser
        << "Options:"
        << arg_fast
        << libport::opts::help
        << libport::opts::version
        << libport::opts::debug
        << arg_period
        << "Tuning:"
        << arg_stack
        << "Networking:"
        << libport::opts::host_l
        << libport::opts::port_l
        << arg_port_file
        << arg_no_net
        << "Execution:"
        << arg_exps
        << libport::opts::files
        << arg_interactive
        ;
      try
      {
        args = parser(args);
      }
      catch (libport::Error& e)
      {
        boost::format fmt("%s: command line error: %s");
        throw Exit(EX_USAGE, str(fmt % libport::program_name() % e.what()));
      }

      if (libport::opts::help.get())
        help(parser);
      if (libport::opts::version.get())
        version();
#endif
      data.interactive = IF_OPTION_PARSER(arg_interactive.get(), true);
      data.fast = IF_OPTION_PARSER(arg_fast.get(), false);

#ifndef NO_OPTION_PARSER
      foreach (const std::string& exp, arg_exps.get())
        input.push_back(Input(false, exp));
      foreach (const std::string& file, libport::opts::files.get())
        input.push_back(Input(true, convert_input_file(file)));
      arg_stack_size = arg_stack.get<size_t>(static_cast<size_t>(0));

      // Unrecognized options. These are a script file, followed by user args.
      if (!args.empty())
      {
        forbid_option(args[0]);
        input.push_back(Input(true, convert_input_file(args[0])));
        // Anything left is user argument
        for (unsigned i = 1; i < args.size(); ++i)
        {
          std::string arg = args[i];
          forbid_option(arg);
          object::system_push_argument(arg);
        }
      }
    }
#endif

    // Libtool traces.
    lt_dladd_log_function((lt_dllog_function*) &ltdebug,
                          (void*) IF_OPTION_PARSER(GD_CURRENT_LEVEL(),0));

    // If not defined in command line, use the envvar.
    if (IF_OPTION_PARSER(!arg_stack.filled() && , )  getenv("URBI_STACK_SIZE"))
      arg_stack_size = libport::convert_envvar<size_t> ("URBI_STACK_SIZE");

    if (arg_stack_size)
    {
      // Make sure the result is a multiple of the page size.  This
      // required at least on OSX (which unfortunately fails with errno
      // = 0).
      arg_stack_size *= 1024;
      size_t pagesize = getpagesize();
      arg_stack_size = ((arg_stack_size + pagesize - 1) / pagesize) * pagesize;
      sched::configuration.default_stack_size = arg_stack_size;
    }

    data.server = new ConsoleServer(data.fast);
    ConsoleServer& s = *data.server;

    /*----------------.
    | --port/--host.  |
    `----------------*/
    int port = -1;
    {
      int desired_port = IF_OPTION_PARSER(libport::opts::port_l.get<int>(-1),
                                          54000);
      if (desired_port != -1)
      {
        std::string host = IF_OPTION_PARSER(libport::opts::host_l.value(""),"");
        s.listen(&connectionFactory, host, desired_port);
        port = s.getLocalPort();
        if (!port)
          throw urbi::Exit
            (EX_UNAVAILABLE,
             libport::format("%s: cannot bind to port %s:%s",
                             program_name(), host, desired_port));
      }
    }
    data.network = 0 < port;
    // In Urbi: System.listenPort = <port>.
    object::system_class->slot_set(SYMBOL(listenPort),
                                   object::to_urbi(port),
                                   true);

    s.initialize(data.interactive);

    /*--------------.
    | --port-file.  |
    `--------------*/
    // Write the port file after initialize returned; that is, after
    // urbi.u is loaded.
    IF_OPTION_PARSER(
    if (arg_port_file.filled())
      std::ofstream(arg_port_file.value().c_str(), std::ios::out)
        << port << std::endl;,
    )

    kernel::UConnection& c = s.ghost_connection_get();
    GD_INFO_TRACE("got ghost connection");

    foreach (const Input& i, input)
    {
      int res = USUCCESS;
      if (i.file_p)
        res = s.load_file(i.value, c.recv_queue_get());
      else
        c.recv_queue_get().push(i.value.c_str());
      if (res != USUCCESS)
      {
        boost::format fmt("%s: failed to process %s");
        throw urbi::Exit(EX_NOINPUT, str(fmt % program_name() % i.value));
      }
    }

    c.received("");
    GD_INFO_TRACE("going to work...");

    if (sem)
      (*sem)++;

    return main_loop(data);

  }

  int
  main_loop(LoopData& data)
  {
    ConsoleServer& s = *data.server;
    libport::utime_t next_time = 0;
    while (true)
    {
      if (data.interactive)
      {
        std::string input;
        try
        {
          input = libport::read_stdin();
        }
        catch (libport::exception::Exception e)
        {
          std::cerr << program_name() << ": "  << e.what() << std::endl;
          data.interactive = false;
        }
        if (!input.empty())
          s.ghost_connection_get().received(input);
      }

      if (data.network)
      {
        libport::utime_t select_time = 0;
        if (!data.fast)
        {
          select_time = std::max(next_time - libport::utime(), select_time);
          if (data.interactive)
            select_time = std::min(100000LL, select_time);
        }
        s.io_.reset();
        s.io_.poll();
      }

      next_time = s.work();
      if (next_time == sched::SCHED_EXIT)
        break;
      s.ctime = std::max(next_time, s.ctime + 1000L);
    }

    return EX_OK;
  }

  int
  main(const libport::cli_args_type& _args, bool block, bool errors)
  {
    if (block)
      return init(_args, errors, 0);
    else
    {
      // The semaphore must survive this block, as init will use it when
      // exiting.
      libport::Semaphore* s = new libport::Semaphore;
      libport::startThread(boost::bind(&init, boost::ref(_args),
                                       errors, s));
      (*s)--;
      return 0;
    }
  }

}
<commit_msg>console-server: fixes.<commit_after>//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <libport/unistd.h>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <libport/cstring>

#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <libport/asio.hh>
#include <libport/cli.hh>
#include <libport/debug.hh>
#include <libport/exception.hh>
#include <libport/foreach.hh>
#include <libport/format.hh>
#ifndef NO_OPTION_PARSER
# include <libport/option-parser.hh>
# define IF_OPTION_PARSER(a, b) a
#else
 #define IF_OPTION_PARSER(a, b) b
#endif
#include <libport/package-info.hh>
#include <libport/program-name.hh>
#include <libport/read-stdin.hh>
#include <libport/semaphore.hh>
#include <libport/sys/socket.h>
#include <libport/sysexits.hh>
#include <libport/thread.hh>
#include <libport/utime.hh>
#include <libport/windows.hh>

#include <libltdl/ltdl.h>

// Inclusion order matters for windows. Leave userver.hh after network.hh.
#include <kernel/uqueue.hh>
#include <kernel/userver.hh>
#include <kernel/uconnection.hh>

#include <sched/configuration.hh>
#include <sched/scheduler.hh>

#include <kernel/connection.hh>
#include <kernel/ubanner.hh>
#include <object/symbols.hh>
#include <object/object.hh>
#include <object/float.hh>
#include <object/system.hh>
#include <urbi/export.hh>
#include <urbi/umain.hh>
#include <urbi/uobject.hh>

GD_INIT();
GD_ADD_CATEGORY(URBI);

using libport::program_name;

class ConsoleServer
  : public kernel::UServer
  , public libport::Socket
{
public:
  ConsoleServer(bool fast)
    : kernel::UServer("console")
    , fast(fast)
    , ctime(0)
    , io_(libport::get_io_service(false))
  {}

  virtual ~ConsoleServer()
  {}

  virtual void reset()
  {}

  virtual void reboot()
  {}

  virtual libport::utime_t getTime()
  {
    return fast ? ctime : libport::utime();
  }

  virtual
  UErrorValue
  save_file(const std::string& filename, const std::string& content)
  {
    //! \todo check this code
    std::ofstream os(filename.c_str());
    os << content;
    os.close();
    return os.good() ? USUCCESS : UFAIL;
  }

  virtual
  void effectiveDisplay(const char* t)
  {
    std::cout << t;
  }

  bool fast;
  libport::utime_t ctime;
  boost::asio::io_service& io_;
};

namespace
{
#ifndef NO_OPTION_PARSER
  static
  void
  help(libport::OptionParser& parser)
  {
    std::stringstream output;
    output
      << "usage: " << libport::program_name()
      << " [OPTIONS] [PROGRAM_FILE] [ARGS...]" << std::endl
      << std::endl
      << "  PROGRAM_FILE   Urbi script to load."
      << "  `-' stands for standard input" << std::endl
      << "  ARGS           user arguments passed to PROGRAM_FILE" << std::endl
      << parser;
    throw urbi::Exit(EX_OK, output.str());
  }
#endif
  static
  void
  version()
  {
    throw urbi::Exit(EX_OK, kernel::UServer::package_info().signature());
  }

  static
  void
  forbid_option(const std::string& arg)
  {
    if (arg.size() > 1 && arg[0] == '-')
    {
      boost::format fmt("%s: unrecognized command line option: %s");
      throw urbi::Exit(EX_USAGE, str(fmt % libport::program_name() % arg));
    }
  }
}

namespace urbi
{

  /// Command line options needed in the main loop.
  struct LoopData
  {
    LoopData()
      : interactive(false)
      , fast(false)
      , network(true)
      , server(0)
    {}

    bool interactive;
    bool fast;
    /// Whether network connections are enabled.
    bool network;
    ConsoleServer* server;
  };

  int main_loop(LoopData& l);

  static libport::Socket*
  connectionFactory()
  {
    kernel::Connection* c = new kernel::Connection();
    kernel::urbiserver->connection_add(c);
    return c;
  }

  static
  int
  ltdebug(unsigned verbosity, unsigned level, const char* format, va_list args)
  {
    int errors = 0;
    if (level <= verbosity)
    {
      errors += fprintf(stderr, "%s: ", program_name().c_str()) < 0;
      errors += vfprintf(stderr, format, args) < 0;
    }
    return errors;
  }

  static std::string convert_input_file(const std::string& arg)
  {
    return (arg == "-") ? "/dev/stdin" : arg;
  }

  /// Data to send to the server.
  struct Input
  {
    Input(bool f, const std::string& v)
      : file_p(f), value(v)
    {}
    /// Whether it's a file (or a litteral).
    bool file_p;
    /// File name or litteral value.
    std::string value;
  };

  static int
  init(const libport::cli_args_type& _args, bool errors,
             libport::Semaphore* sem)
  {
    libport::Finally f;
    if (sem)
      f << boost::bind(&libport::Semaphore::operator++, sem);
    if (errors)
    {
      try
      {
        return init(_args, false, sem);
      }
      catch (const urbi::Exit& e)
      {
        std::cerr << program_name() << ": " << e.what() << std::endl;
        return e.error_get();
      }
    }

    GD_CATEGORY(URBI);

    libport::cli_args_type args = _args;

    object::system_set_program_name(args[0]);
    args.erase(args.begin());

    // Input files.
    typedef std::vector<Input> input_type;
    input_type input;
    /// The size of the stacks.
    size_t arg_stack_size = 0;

    // Parse the command line.
    LoopData data;
#ifndef NO_OPTION_PARSER
    libport::OptionFlag
      arg_fast("ignore system time, go as fast as possible",
               "fast", 'F'),
      arg_interactive("read and parse stdin in a nonblocking way",
                      "interactive", 'i'),
      arg_no_net("ignored for backward compatibility", "no-network", 'n');

    libport::OptionValue
      arg_period   ("ignored for backward compatibility", "period", 'P'),
      arg_port_file("write port number to the specified file.",
                    "port-file", 'w', "FILE"),
      arg_stack    ("set the job stack size in KB", "stack-size", 's', "SIZE");

    libport::OptionValues
      arg_exps("run expression", "expression", 'e', "EXP");

    {
      libport::OptionParser parser;
      parser
        << "Options:"
        << arg_fast
        << libport::opts::help
        << libport::opts::version
        << libport::opts::debug
        << arg_period
        << "Tuning:"
        << arg_stack
        << "Networking:"
        << libport::opts::host_l
        << libport::opts::port_l
        << arg_port_file
        << arg_no_net
        << "Execution:"
        << arg_exps
        << libport::opts::files
        << arg_interactive
        ;
      try
      {
        args = parser(args);
      }
      catch (libport::Error& e)
      {
        boost::format fmt("%s: command line error: %s");
        throw Exit(EX_USAGE, str(fmt % libport::program_name() % e.what()));
      }

      if (libport::opts::help.get())
        help(parser);
      if (libport::opts::version.get())
        version();
#endif
      data.interactive = IF_OPTION_PARSER(arg_interactive.get(), true);
      data.fast = IF_OPTION_PARSER(arg_fast.get(), false);

#ifndef NO_OPTION_PARSER
      foreach (const std::string& exp, arg_exps.get())
        input.push_back(Input(false, exp));
      foreach (const std::string& file, libport::opts::files.get())
        input.push_back(Input(true, convert_input_file(file)));
      arg_stack_size = arg_stack.get<size_t>(static_cast<size_t>(0));

      // Unrecognized options. These are a script file, followed by user args.
      if (!args.empty())
      {
        forbid_option(args[0]);
        input.push_back(Input(true, convert_input_file(args[0])));
        // Anything left is user argument
        for (unsigned i = 1; i < args.size(); ++i)
        {
          std::string arg = args[i];
          forbid_option(arg);
          object::system_push_argument(arg);
        }
      }
    }
#endif

    // Libtool traces.
    lt_dladd_log_function((lt_dllog_function*) &ltdebug,
                          (void*) IF_OPTION_PARSER(GD_CURRENT_LEVEL(),0));

    // If not defined in command line, use the envvar.
    if (IF_OPTION_PARSER(!arg_stack.filled() && , )  getenv("URBI_STACK_SIZE"))
      arg_stack_size = libport::convert_envvar<size_t> ("URBI_STACK_SIZE");

    if (arg_stack_size)
    {
      // Make sure the result is a multiple of the page size.  This
      // required at least on OSX (which unfortunately fails with errno
      // = 0).
      arg_stack_size *= 1024;
      size_t pagesize = getpagesize();
      arg_stack_size = ((arg_stack_size + pagesize - 1) / pagesize) * pagesize;
      sched::configuration.default_stack_size = arg_stack_size;
    }

    data.server = new ConsoleServer(data.fast);
    ConsoleServer& s = *data.server;

    /*----------------.
    | --port/--host.  |
    `----------------*/
    int port = -1;
    {
      int desired_port = IF_OPTION_PARSER(libport::opts::port_l.get<int>(-1),
                                          54000);
      if (desired_port != -1)
      {
        std::string host = IF_OPTION_PARSER(libport::opts::host_l.value(""),"");
        if (boost::system::error_code err =
            s.listen(&connectionFactory, host, desired_port))
          throw urbi::Exit
            (EX_UNAVAILABLE,
             libport::format("%s: cannot listen to port %s:%s: %s",
                             program_name(), host, desired_port,
                             err.message()));
        port = s.getLocalPort();
        if (!port)
          throw urbi::Exit
            (EX_UNAVAILABLE,
             libport::format("%s: cannot bind to port %s:%s",
                             program_name(), host, desired_port));
      }
    }
    data.network = 0 < port;
    // In Urbi: System.listenPort = <port>.
    object::system_class->slot_set(SYMBOL(listenPort),
                                   object::to_urbi(port),
                                   true);

    s.initialize(data.interactive);

    /*--------------.
    | --port-file.  |
    `--------------*/
    // Write the port file after initialize returned; that is, after
    // urbi.u is loaded.
    IF_OPTION_PARSER(
    if (arg_port_file.filled())
      std::ofstream(arg_port_file.value().c_str(), std::ios::out)
        << port << std::endl;,
    )

    kernel::UConnection& c = s.ghost_connection_get();
    GD_INFO_TRACE("got ghost connection");

    foreach (const Input& i, input)
    {
      int res = USUCCESS;
      if (i.file_p)
        res = s.load_file(i.value, c.recv_queue_get());
      else
        c.recv_queue_get().push(i.value.c_str());
      if (res != USUCCESS)
      {
        boost::format fmt("%s: failed to process %s");
        throw urbi::Exit(EX_NOINPUT, str(fmt % program_name() % i.value));
      }
    }

    c.received("");
    GD_INFO_TRACE("going to work...");

    if (sem)
      (*sem)++;

    return main_loop(data);

  }

  int
  main_loop(LoopData& data)
  {
    ConsoleServer& s = *data.server;
    libport::utime_t next_time = 0;
    while (true)
    {
      if (data.interactive)
      {
        std::string input;
        try
        {
          input = libport::read_stdin();
        }
        catch (libport::exception::Exception e)
        {
          std::cerr << program_name() << ": "  << e.what() << std::endl;
          data.interactive = false;
        }
        if (!input.empty())
          s.ghost_connection_get().received(input);
      }

      if (data.network)
      {
        libport::utime_t select_time = 0;
        if (!data.fast)
        {
          select_time = std::max(next_time - libport::utime(), select_time);
          if (data.interactive)
            select_time = std::min(100000LL, select_time);
        }
        if (select_time)
          libport::pollFor(select_time, true);
        else
        {
          s.io_.reset();
          s.io_.poll();
        }
      }

      next_time = s.work();
      if (next_time == sched::SCHED_EXIT)
        break;
      s.ctime = std::max(next_time, s.ctime + 1000L);
    }

    return EX_OK;
  }

  int
  main(const libport::cli_args_type& _args, bool block, bool errors)
  {
    if (block)
      return init(_args, errors, 0);
    else
    {
      // The semaphore must survive this block, as init will use it when
      // exiting.
      libport::Semaphore* s = new libport::Semaphore;
      libport::startThread(boost::bind(&init, boost::ref(_args),
                                       errors, s));
      (*s)--;
      return 0;
    }
  }

}
<|endoftext|>


<commit_before>// Copyright (c) 2019 Matthew J. Smith and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#include "ovk/core/Geometry.hpp"

#include "ovk/core/Array.hpp"
#include "ovk/core/Cart.hpp"
#include "ovk/core/Comm.hpp"
#include "ovk/core/Context.hpp"
#include "ovk/core/Debug.hpp"
#include "ovk/core/Editor.hpp"
#include "ovk/core/Event.hpp"
#include "ovk/core/Field.hpp"
#include "ovk/core/FloatingRef.hpp"
#include "ovk/core/Global.hpp"
#include "ovk/core/Grid.hpp"
#include "ovk/core/Logger.hpp"
#include "ovk/core/Partition.hpp"
#include "ovk/core/Request.hpp"

#include <mpi.h>

#include <memory>
#include <utility>

namespace ovk {

namespace geometry_internal {

geometry_base::geometry_base(std::shared_ptr<context> &&Context, const grid &Grid):
  Context_(std::move(Context)),
  Grid_(&Grid),
  Comm_(Grid.Comm())
{
  MPI_Barrier(Comm_);
}

geometry_base::~geometry_base() noexcept {

  if (Context_) {
    MPI_Barrier(Comm_);
    core::logger &Logger = Context_->core_Logger();
    Logger.LogDebug(Comm_.Rank() == 0, 0, "Destroyed geometry %s.", Grid_->Name());
  }

}

}

geometry::geometry(std::shared_ptr<context> &&Context, const grid &Grid, params &&Params):
  geometry_base(std::move(Context), Grid),
  NumDims_(Grid.Dimension()),
  Type_(Params.Type_),
  PeriodicLength_(Params.PeriodicLength_),
  Coords_({MAX_DIMS})
{

  if (OVK_DEBUG) {
    for (int iDim = NumDims_; iDim < MAX_DIMS; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength_(iDim) == 0., "Periodic length has incorrect dimension.");
    }
  }

  // In 1D, geometry type is always uniform or rectilinear
  if (NumDims_ == 1) {
    switch (Type_) {
    case geometry_type::UNIFORM:
    case geometry_type::ORIENTED_UNIFORM:
      Type_ = geometry_type::UNIFORM;
      break;
    case geometry_type::RECTILINEAR:
    case geometry_type::ORIENTED_RECTILINEAR:
    case geometry_type::CURVILINEAR:
      Type_ = geometry_type::RECTILINEAR;
      break;
    default:
      OVK_DEBUG_ASSERT(false, "Unhandled enum value.");
      break;
    }
  }

  const range &ExtendedRange = Grid.ExtendedRange();

  for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
    Coords_(iDim).Assign(Grid.SharedPartition());
  }

  for (int k = ExtendedRange.Begin(2); k < ExtendedRange.End(2); ++k) {
    for (int j = ExtendedRange.Begin(1); j < ExtendedRange.End(1); ++j) {
      for (int i = ExtendedRange.Begin(0); i < ExtendedRange.End(0); ++i) {
        Coords_(0)(i,j,k) = double(i);
        Coords_(1)(i,j,k) = double(j);
        Coords_(2)(i,j,k) = double(k);
      }
    }
  }

  Volumes_.Assign(Grid.SharedPartition(), 1.);
  CellVolumes_.Assign(Grid.SharedCellPartition(), 1.);

  MPI_Barrier(Comm_);

  core::logger &Logger = Context_->core_Logger();
  Logger.LogDebug(Comm_.Rank() == 0, 0, "Created geometry %s.", Grid.Name());

}

geometry::~geometry() noexcept {

  if (Context_) {
    // Barrier before cleaning up
    MPI_Barrier(Comm_);
  }

}

geometry geometry::internal_Create(std::shared_ptr<context> &&Context, const grid &Grid, params
  &&Params) {

  return {std::move(Context), Grid, std::move(Params)};

}

namespace core {

geometry CreateGeometry(std::shared_ptr<context> Context, const grid &Grid, geometry::params Params)
  {

  OVK_DEBUG_ASSERT(Context, "Invalid context.");

  return geometry::internal_Create(std::move(Context), Grid, std::move(Params));

}

}

void geometry::SetPeriodicLength(const tuple<double> &PeriodicLength) {

  if (OVK_DEBUG) {
    for (int iDim = 0; iDim < NumDims_; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength(iDim) >= 0., "Periodic length must be nonnegative.");
    }
    for (int iDim = NumDims_; iDim < MAX_DIMS; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength(iDim) == 0., "Periodic length has incorrect dimension.");
    }
  }

  PeriodicLength_ = PeriodicLength;

  CoordsEvent_.Trigger();

}

bool geometry::EditingCoords() const {

  return CoordsEditor_.Active();

}

edit_handle<array<distributed_field<double>>> geometry::EditCoords() {

  if (!CoordsEditor_.Active()) {
    MPI_Barrier(Comm_);
    floating_ref<geometry> FloatingRef = FloatingRefGenerator_.Generate(*this);
    auto DeactivateFunc = [FloatingRef] {
      geometry &Geometry = *FloatingRef;
      Geometry.OnCoordsEndEdit_();
      MPI_Barrier(Geometry.Comm_);
    };
    CoordsEditor_.Activate(std::move(DeactivateFunc));
  }

  return CoordsEditor_.Edit(Coords_);

}

void geometry::RestoreCoords() {

  OVK_DEBUG_ASSERT(CoordsEditor_.Active(), "Unable to restore coords; not currently being edited.");

  CoordsEditor_.Restore();

}

void geometry::OnCoordsEndEdit_() {

  const grid &Grid = *Grid_;
  int NumDims = Grid.Dimension();
  const partition &Partition = Grid.Partition();
  const cart &Cart = Grid.Cart();
  const range &GlobalRange = Grid.GlobalRange();
  const range &LocalRange = Grid.LocalRange();
  const range &ExtendedRange = Grid.ExtendedRange();
  const range &CellLocalRange = Grid.CellLocalRange();
  const range &CellExtendedRange = Grid.CellExtendedRange();

  request Requests[MAX_DIMS];

  for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
    Requests[iDim] = Partition.Exchange(Coords_(iDim));
  }

  WaitAll(Requests);

  for (int k = ExtendedRange.Begin(2); k < ExtendedRange.End(2); ++k) {
    for (int j = ExtendedRange.Begin(1); j < ExtendedRange.End(1); ++j) {
      for (int i = ExtendedRange.Begin(0); i < ExtendedRange.End(0); ++i) {
        tuple<int> Point = {i,j,k};
        if (!GlobalRange.Contains(Point)) {
          tuple<int> Period = Cart.GetPeriod(Point);
          for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
            Coords_(iDim)(Point) += double(Period(iDim)) * PeriodicLength_(iDim);
          }
        }
      }
    }
  }

  MPI_Barrier(Comm_);

  CoordsEvent_.Trigger();

  for (int k = CellLocalRange.Begin(2); k < CellLocalRange.End(2); ++k) {
    for (int j = CellLocalRange.Begin(1); j < CellLocalRange.End(1); ++j) {
      for (int i = CellLocalRange.Begin(0); i < CellLocalRange.End(0); ++i) {
        tuple<int> Cell = {i,j,k};
        CellVolumes_(Cell) = core::CellVolume(NumDims, Coords_, Type_, Cell);
      }
    }
  }

  CellVolumes_.Exchange();

  // Compute the volume at each point by averaging the volumes of neighboring cells
  for (int k = LocalRange.Begin(2); k < LocalRange.End(2); ++k) {
    for (int j = LocalRange.Begin(1); j < LocalRange.End(1); ++j) {
      for (int i = LocalRange.Begin(0); i < LocalRange.End(0); ++i) {
        tuple<int> Point = {i,j,k};
        range NeighborCellRange;
        for (int iDim = 0; iDim < NumDims; ++iDim) {
          NeighborCellRange.Begin(iDim) = Point(iDim)-1;
          NeighborCellRange.End(iDim) = Point(iDim)+1;
        }
        for (int iDim = NumDims; iDim < MAX_DIMS; ++iDim) {
          NeighborCellRange.Begin(iDim) = 0;
          NeighborCellRange.End(iDim) = 1;
        }
        NeighborCellRange = IntersectRanges(CellExtendedRange, NeighborCellRange);
        Volumes_(Point) = 0.;
        for (int o = NeighborCellRange.Begin(2); o < NeighborCellRange.End(2); ++o) {
          for (int n = NeighborCellRange.Begin(1); n < NeighborCellRange.End(1); ++n) {
            for (int m = NeighborCellRange.Begin(0); m < NeighborCellRange.End(0); ++m) {
              tuple<int> NeighborCell = {m,n,o};
              Volumes_(Point) += CellVolumes_(NeighborCell);
            }
          }
        }
        Volumes_(Point) /= double(NeighborCellRange.Count());
      }
    }
  }

  Volumes_.Exchange();

  MPI_Barrier(Comm_);

  VolumesEvent_.Trigger();
  CellVolumesEvent_.Trigger();

}

geometry::params &geometry::params::SetType(geometry_type Type) {

  OVK_DEBUG_ASSERT(ValidGeometryType(Type), "Invalid type.");

  Type_ = Type;

  return *this;

}

geometry::params &geometry::params::SetPeriodicLength(const tuple<double> &PeriodicLength) {

  if (OVK_DEBUG) {
    for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength(iDim) >= 0., "Periodic length must be nonnegative.");
    }
  }

  PeriodicLength_ = PeriodicLength;

  return *this;

}

}
<commit_msg>add some logging for cell volume computation<commit_after>// Copyright (c) 2019 Matthew J. Smith and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#include "ovk/core/Geometry.hpp"

#include "ovk/core/Array.hpp"
#include "ovk/core/Cart.hpp"
#include "ovk/core/Comm.hpp"
#include "ovk/core/Context.hpp"
#include "ovk/core/Debug.hpp"
#include "ovk/core/Editor.hpp"
#include "ovk/core/Event.hpp"
#include "ovk/core/Field.hpp"
#include "ovk/core/FloatingRef.hpp"
#include "ovk/core/Global.hpp"
#include "ovk/core/Grid.hpp"
#include "ovk/core/Logger.hpp"
#include "ovk/core/Partition.hpp"
#include "ovk/core/Request.hpp"

#include <mpi.h>

#include <memory>
#include <utility>

namespace ovk {

namespace geometry_internal {

geometry_base::geometry_base(std::shared_ptr<context> &&Context, const grid &Grid):
  Context_(std::move(Context)),
  Grid_(&Grid),
  Comm_(Grid.Comm())
{
  MPI_Barrier(Comm_);
}

geometry_base::~geometry_base() noexcept {

  if (Context_) {
    MPI_Barrier(Comm_);
    core::logger &Logger = Context_->core_Logger();
    Logger.LogDebug(Comm_.Rank() == 0, 0, "Destroyed geometry %s.", Grid_->Name());
  }

}

}

geometry::geometry(std::shared_ptr<context> &&Context, const grid &Grid, params &&Params):
  geometry_base(std::move(Context), Grid),
  NumDims_(Grid.Dimension()),
  Type_(Params.Type_),
  PeriodicLength_(Params.PeriodicLength_),
  Coords_({MAX_DIMS})
{

  if (OVK_DEBUG) {
    for (int iDim = NumDims_; iDim < MAX_DIMS; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength_(iDim) == 0., "Periodic length has incorrect dimension.");
    }
  }

  // In 1D, geometry type is always uniform or rectilinear
  if (NumDims_ == 1) {
    switch (Type_) {
    case geometry_type::UNIFORM:
    case geometry_type::ORIENTED_UNIFORM:
      Type_ = geometry_type::UNIFORM;
      break;
    case geometry_type::RECTILINEAR:
    case geometry_type::ORIENTED_RECTILINEAR:
    case geometry_type::CURVILINEAR:
      Type_ = geometry_type::RECTILINEAR;
      break;
    default:
      OVK_DEBUG_ASSERT(false, "Unhandled enum value.");
      break;
    }
  }

  const range &ExtendedRange = Grid.ExtendedRange();

  for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
    Coords_(iDim).Assign(Grid.SharedPartition());
  }

  for (int k = ExtendedRange.Begin(2); k < ExtendedRange.End(2); ++k) {
    for (int j = ExtendedRange.Begin(1); j < ExtendedRange.End(1); ++j) {
      for (int i = ExtendedRange.Begin(0); i < ExtendedRange.End(0); ++i) {
        Coords_(0)(i,j,k) = double(i);
        Coords_(1)(i,j,k) = double(j);
        Coords_(2)(i,j,k) = double(k);
      }
    }
  }

  Volumes_.Assign(Grid.SharedPartition(), 1.);
  CellVolumes_.Assign(Grid.SharedCellPartition(), 1.);

  MPI_Barrier(Comm_);

  core::logger &Logger = Context_->core_Logger();
  Logger.LogDebug(Comm_.Rank() == 0, 0, "Created geometry %s.", Grid.Name());

}

geometry::~geometry() noexcept {

  if (Context_) {
    // Barrier before cleaning up
    MPI_Barrier(Comm_);
  }

}

geometry geometry::internal_Create(std::shared_ptr<context> &&Context, const grid &Grid, params
  &&Params) {

  return {std::move(Context), Grid, std::move(Params)};

}

namespace core {

geometry CreateGeometry(std::shared_ptr<context> Context, const grid &Grid, geometry::params Params)
  {

  OVK_DEBUG_ASSERT(Context, "Invalid context.");

  return geometry::internal_Create(std::move(Context), Grid, std::move(Params));

}

}

void geometry::SetPeriodicLength(const tuple<double> &PeriodicLength) {

  if (OVK_DEBUG) {
    for (int iDim = 0; iDim < NumDims_; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength(iDim) >= 0., "Periodic length must be nonnegative.");
    }
    for (int iDim = NumDims_; iDim < MAX_DIMS; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength(iDim) == 0., "Periodic length has incorrect dimension.");
    }
  }

  PeriodicLength_ = PeriodicLength;

  CoordsEvent_.Trigger();

}

bool geometry::EditingCoords() const {

  return CoordsEditor_.Active();

}

edit_handle<array<distributed_field<double>>> geometry::EditCoords() {

  if (!CoordsEditor_.Active()) {
    MPI_Barrier(Comm_);
    floating_ref<geometry> FloatingRef = FloatingRefGenerator_.Generate(*this);
    auto DeactivateFunc = [FloatingRef] {
      geometry &Geometry = *FloatingRef;
      Geometry.OnCoordsEndEdit_();
      MPI_Barrier(Geometry.Comm_);
    };
    CoordsEditor_.Activate(std::move(DeactivateFunc));
  }

  return CoordsEditor_.Edit(Coords_);

}

void geometry::RestoreCoords() {

  OVK_DEBUG_ASSERT(CoordsEditor_.Active(), "Unable to restore coords; not currently being edited.");

  CoordsEditor_.Restore();

}

void geometry::OnCoordsEndEdit_() {

  core::logger &Logger = Context_->core_Logger();

  const grid &Grid = *Grid_;
  int NumDims = Grid.Dimension();
  const partition &Partition = Grid.Partition();
  const cart &Cart = Grid.Cart();
  const range &GlobalRange = Grid.GlobalRange();
  const range &LocalRange = Grid.LocalRange();
  const range &ExtendedRange = Grid.ExtendedRange();
  const range &CellLocalRange = Grid.CellLocalRange();
  const range &CellExtendedRange = Grid.CellExtendedRange();

  request Requests[MAX_DIMS];

  for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
    Requests[iDim] = Partition.Exchange(Coords_(iDim));
  }

  WaitAll(Requests);

  for (int k = ExtendedRange.Begin(2); k < ExtendedRange.End(2); ++k) {
    for (int j = ExtendedRange.Begin(1); j < ExtendedRange.End(1); ++j) {
      for (int i = ExtendedRange.Begin(0); i < ExtendedRange.End(0); ++i) {
        tuple<int> Point = {i,j,k};
        if (!GlobalRange.Contains(Point)) {
          tuple<int> Period = Cart.GetPeriod(Point);
          for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
            Coords_(iDim)(Point) += double(Period(iDim)) * PeriodicLength_(iDim);
          }
        }
      }
    }
  }

  MPI_Barrier(Comm_);

  CoordsEvent_.Trigger();

  Logger.LogDebug(Comm_.Rank() == 0, 0, "Updating auxiliary data for geometry %s...", Grid.Name());

  for (int k = CellLocalRange.Begin(2); k < CellLocalRange.End(2); ++k) {
    for (int j = CellLocalRange.Begin(1); j < CellLocalRange.End(1); ++j) {
      for (int i = CellLocalRange.Begin(0); i < CellLocalRange.End(0); ++i) {
        tuple<int> Cell = {i,j,k};
        CellVolumes_(Cell) = core::CellVolume(NumDims, Coords_, Type_, Cell);
      }
    }
  }

  CellVolumes_.Exchange();

  // Compute the volume at each point by averaging the volumes of neighboring cells
  for (int k = LocalRange.Begin(2); k < LocalRange.End(2); ++k) {
    for (int j = LocalRange.Begin(1); j < LocalRange.End(1); ++j) {
      for (int i = LocalRange.Begin(0); i < LocalRange.End(0); ++i) {
        tuple<int> Point = {i,j,k};
        range NeighborCellRange;
        for (int iDim = 0; iDim < NumDims; ++iDim) {
          NeighborCellRange.Begin(iDim) = Point(iDim)-1;
          NeighborCellRange.End(iDim) = Point(iDim)+1;
        }
        for (int iDim = NumDims; iDim < MAX_DIMS; ++iDim) {
          NeighborCellRange.Begin(iDim) = 0;
          NeighborCellRange.End(iDim) = 1;
        }
        NeighborCellRange = IntersectRanges(CellExtendedRange, NeighborCellRange);
        Volumes_(Point) = 0.;
        for (int o = NeighborCellRange.Begin(2); o < NeighborCellRange.End(2); ++o) {
          for (int n = NeighborCellRange.Begin(1); n < NeighborCellRange.End(1); ++n) {
            for (int m = NeighborCellRange.Begin(0); m < NeighborCellRange.End(0); ++m) {
              tuple<int> NeighborCell = {m,n,o};
              Volumes_(Point) += CellVolumes_(NeighborCell);
            }
          }
        }
        Volumes_(Point) /= double(NeighborCellRange.Count());
      }
    }
  }

  Volumes_.Exchange();

  MPI_Barrier(Comm_);

  Logger.LogDebug(Comm_.Rank() == 0, 0, "Done updating auxiliary data for geometry %s.",
    Grid.Name());

  VolumesEvent_.Trigger();
  CellVolumesEvent_.Trigger();

}

geometry::params &geometry::params::SetType(geometry_type Type) {

  OVK_DEBUG_ASSERT(ValidGeometryType(Type), "Invalid type.");

  Type_ = Type;

  return *this;

}

geometry::params &geometry::params::SetPeriodicLength(const tuple<double> &PeriodicLength) {

  if (OVK_DEBUG) {
    for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
      OVK_DEBUG_ASSERT(PeriodicLength(iDim) >= 0., "Periodic length must be nonnegative.");
    }
  }

  PeriodicLength_ = PeriodicLength;

  return *this;

}

}
<|endoftext|>


<commit_before>/* libs/graphics/sgl/SkShader.cpp
**
** Copyright 2006, The Android Open Source Project
**
** 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.
*/

#include "SkShader.h"
#include "SkPaint.h"

SkShader::SkShader() : fLocalMatrix(NULL) {
    SkDEBUGCODE(fInSession = false;)
}

SkShader::SkShader(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer), fLocalMatrix(NULL) {
    if (buffer.readBool()) {
        SkMatrix matrix;
        buffer.read(&matrix, sizeof(matrix));
        setLocalMatrix(matrix);
    }
    SkDEBUGCODE(fInSession = false;)
}

SkShader::~SkShader() {
    SkASSERT(!fInSession);
    sk_free(fLocalMatrix);
}

void SkShader::beginSession() {
    SkASSERT(!fInSession);
    SkDEBUGCODE(fInSession = true;)
}

void SkShader::endSession() {
    SkASSERT(fInSession);
    SkDEBUGCODE(fInSession = false;)
}

void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
    this->INHERITED::flatten(buffer);
    buffer.writeBool(fLocalMatrix != NULL);
    if (fLocalMatrix) {
        buffer.writeMul4(fLocalMatrix, sizeof(SkMatrix));
    }
}

bool SkShader::getLocalMatrix(SkMatrix* localM) const {
    if (fLocalMatrix) {
        if (localM) {
            *localM = *fLocalMatrix;
        }
        return true;
    } else {
        if (localM) {
            localM->reset();
        }
        return false;
    }
}

void SkShader::setLocalMatrix(const SkMatrix& localM) {
    if (localM.isIdentity()) {
        this->resetLocalMatrix();
    } else {
        if (fLocalMatrix == NULL) {
            fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
        }
        *fLocalMatrix = localM;
    }
}

void SkShader::resetLocalMatrix() {
    if (fLocalMatrix) {
        sk_free(fLocalMatrix);
        fLocalMatrix = NULL;
    }
}

bool SkShader::setContext(const SkBitmap& device,
                          const SkPaint& paint,
                          const SkMatrix& matrix) {
    const SkMatrix* m = &matrix;
    SkMatrix        total;

    fDeviceConfig = SkToU8(device.getConfig());
    fPaintAlpha = paint.getAlpha();
    if (fLocalMatrix) {
        total.setConcat(matrix, *fLocalMatrix);
        m = &total;
    }
    if (m->invert(&fTotalInverse)) {
        fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
        return true;
    }
    return false;
}

#include "SkColorPriv.h"

void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
    SkASSERT(span16);
    SkASSERT(count > 0);
    SkASSERT(this->canCallShadeSpan16());

    // basically, if we get here, the subclass screwed up
    SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented");
}

#define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
#define kTempColorCount     (kTempColorQuadCount << 2)

#ifdef SK_CPU_BENDIAN
    #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
#else
    #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
#endif

void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    SkASSERT(count > 0);

    SkPMColor   colors[kTempColorCount];

    while ((count -= kTempColorCount) >= 0) {
        this->shadeSpan(x, y, colors, kTempColorCount);
        x += kTempColorCount;

        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
        int quads = kTempColorQuadCount;
        do {
            U8CPU a0 = srcA[0];
            U8CPU a1 = srcA[4];
            U8CPU a2 = srcA[8];
            U8CPU a3 = srcA[12];
            srcA += 4*4;
            *alpha++ = SkToU8(a0);
            *alpha++ = SkToU8(a1);
            *alpha++ = SkToU8(a2);
            *alpha++ = SkToU8(a3);
        } while (--quads != 0);
    }
    SkASSERT(count < 0);
    SkASSERT(count + kTempColorCount >= 0);
    if (count += kTempColorCount) {
        this->shadeSpan(x, y, colors, count);

        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
        do {
            *alpha++ = *srcA;
            srcA += 4;
        } while (--count != 0);
    }
#if 0
    do {
        int n = count;
        if (n > kTempColorCount)
            n = kTempColorCount;
        SkASSERT(n > 0);

        this->shadeSpan(x, y, colors, n);
        x += n;
        count -= n;

        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
        do {
            *alpha++ = *srcA;
            srcA += 4;
        } while (--n != 0);
    } while (count > 0);
#endif
}

SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
    MatrixClass mc = kLinear_MatrixClass;

    if (mat.getType() & SkMatrix::kPerspective_Mask) {
        if (mat.fixedStepInX(0, NULL, NULL)) {
            mc = kFixedStepInX_MatrixClass;
        } else {
            mc = kPerspective_MatrixClass;
        }
    }
    return mc;
}

//////////////////////////////////////////////////////////////////////////////

bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
    return false;
}

SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy) {
    return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
}

//////////////////////////////////////////////////////////////////////////////

#include "SkColorShader.h"
#include "SkUtils.h"

SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
    fFlags = 0; // computed in setContext
    fInheritColor = b.readU8();
    if (fInheritColor) {
        return;
    }
    fColor = b.readU32();
}

void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
    this->INHERITED::flatten(buffer);
    buffer.write8(fInheritColor);
    if (fInheritColor) {
        return;
    }
    buffer.write32(fColor);
}

uint8_t SkColorShader::getSpan16Alpha() const {
    return SkGetPackedA32(fPMColor);
}

bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
                               const SkMatrix& matrix) {
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    SkColor c;
    unsigned a;

    if (fInheritColor) {
        c = paint.getColor();
        a = SkColorGetA(c);
    } else {
        c = fColor;
        a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
    }

    unsigned r = SkColorGetR(c);
    unsigned g = SkColorGetG(c);
    unsigned b = SkColorGetB(c);

    // we want this before we apply any alpha
    fColor16 = SkPack888ToRGB16(r, g, b);

    if (a != 255) {
        a = SkAlpha255To256(a);
        r = SkAlphaMul(r, a);
        g = SkAlphaMul(g, a);
        b = SkAlphaMul(b, a);
    }
    fPMColor = SkPackARGB32(a, r, g, b);

    fFlags = kHasSpan16_Flag | kConstInY32_Flag;
    if (SkGetPackedA32(fPMColor) == 255) {
        fFlags |= kOpaqueAlpha_Flag;
    }

    return true;
}

void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
    sk_memset32(span, fPMColor, count);
}

void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
    sk_memset16(span, fColor16, count);
}

void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    memset(alpha, SkGetPackedA32(fPMColor), count);
}

<commit_msg>partial fix for http://b/issue?id=2486139 off-by-1 in alpha for colorshader<commit_after>/* libs/graphics/sgl/SkShader.cpp
**
** Copyright 2006, The Android Open Source Project
**
** 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.
*/

#include "SkShader.h"
#include "SkPaint.h"

SkShader::SkShader() : fLocalMatrix(NULL) {
    SkDEBUGCODE(fInSession = false;)
}

SkShader::SkShader(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer), fLocalMatrix(NULL) {
    if (buffer.readBool()) {
        SkMatrix matrix;
        buffer.read(&matrix, sizeof(matrix));
        setLocalMatrix(matrix);
    }
    SkDEBUGCODE(fInSession = false;)
}

SkShader::~SkShader() {
    SkASSERT(!fInSession);
    sk_free(fLocalMatrix);
}

void SkShader::beginSession() {
    SkASSERT(!fInSession);
    SkDEBUGCODE(fInSession = true;)
}

void SkShader::endSession() {
    SkASSERT(fInSession);
    SkDEBUGCODE(fInSession = false;)
}

void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
    this->INHERITED::flatten(buffer);
    buffer.writeBool(fLocalMatrix != NULL);
    if (fLocalMatrix) {
        buffer.writeMul4(fLocalMatrix, sizeof(SkMatrix));
    }
}

bool SkShader::getLocalMatrix(SkMatrix* localM) const {
    if (fLocalMatrix) {
        if (localM) {
            *localM = *fLocalMatrix;
        }
        return true;
    } else {
        if (localM) {
            localM->reset();
        }
        return false;
    }
}

void SkShader::setLocalMatrix(const SkMatrix& localM) {
    if (localM.isIdentity()) {
        this->resetLocalMatrix();
    } else {
        if (fLocalMatrix == NULL) {
            fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
        }
        *fLocalMatrix = localM;
    }
}

void SkShader::resetLocalMatrix() {
    if (fLocalMatrix) {
        sk_free(fLocalMatrix);
        fLocalMatrix = NULL;
    }
}

bool SkShader::setContext(const SkBitmap& device,
                          const SkPaint& paint,
                          const SkMatrix& matrix) {
    const SkMatrix* m = &matrix;
    SkMatrix        total;

    fDeviceConfig = SkToU8(device.getConfig());
    fPaintAlpha = paint.getAlpha();
    if (fLocalMatrix) {
        total.setConcat(matrix, *fLocalMatrix);
        m = &total;
    }
    if (m->invert(&fTotalInverse)) {
        fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
        return true;
    }
    return false;
}

#include "SkColorPriv.h"

void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
    SkASSERT(span16);
    SkASSERT(count > 0);
    SkASSERT(this->canCallShadeSpan16());

    // basically, if we get here, the subclass screwed up
    SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented");
}

#define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
#define kTempColorCount     (kTempColorQuadCount << 2)

#ifdef SK_CPU_BENDIAN
    #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
#else
    #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
#endif

void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    SkASSERT(count > 0);

    SkPMColor   colors[kTempColorCount];

    while ((count -= kTempColorCount) >= 0) {
        this->shadeSpan(x, y, colors, kTempColorCount);
        x += kTempColorCount;

        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
        int quads = kTempColorQuadCount;
        do {
            U8CPU a0 = srcA[0];
            U8CPU a1 = srcA[4];
            U8CPU a2 = srcA[8];
            U8CPU a3 = srcA[12];
            srcA += 4*4;
            *alpha++ = SkToU8(a0);
            *alpha++ = SkToU8(a1);
            *alpha++ = SkToU8(a2);
            *alpha++ = SkToU8(a3);
        } while (--quads != 0);
    }
    SkASSERT(count < 0);
    SkASSERT(count + kTempColorCount >= 0);
    if (count += kTempColorCount) {
        this->shadeSpan(x, y, colors, count);

        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
        do {
            *alpha++ = *srcA;
            srcA += 4;
        } while (--count != 0);
    }
#if 0
    do {
        int n = count;
        if (n > kTempColorCount)
            n = kTempColorCount;
        SkASSERT(n > 0);

        this->shadeSpan(x, y, colors, n);
        x += n;
        count -= n;

        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
        do {
            *alpha++ = *srcA;
            srcA += 4;
        } while (--n != 0);
    } while (count > 0);
#endif
}

SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
    MatrixClass mc = kLinear_MatrixClass;

    if (mat.getType() & SkMatrix::kPerspective_Mask) {
        if (mat.fixedStepInX(0, NULL, NULL)) {
            mc = kFixedStepInX_MatrixClass;
        } else {
            mc = kPerspective_MatrixClass;
        }
    }
    return mc;
}

//////////////////////////////////////////////////////////////////////////////

bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
    return false;
}

SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy) {
    return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
}

//////////////////////////////////////////////////////////////////////////////

#include "SkColorShader.h"
#include "SkUtils.h"

SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
    fFlags = 0; // computed in setContext
    fInheritColor = b.readU8();
    if (fInheritColor) {
        return;
    }
    fColor = b.readU32();
}

void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
    this->INHERITED::flatten(buffer);
    buffer.write8(fInheritColor);
    if (fInheritColor) {
        return;
    }
    buffer.write32(fColor);
}

uint8_t SkColorShader::getSpan16Alpha() const {
    return SkGetPackedA32(fPMColor);
}

bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
                               const SkMatrix& matrix) {
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    SkColor c;
    unsigned a;

    if (fInheritColor) {
        c = paint.getColor();
        a = SkColorGetA(c);
    } else {
        c = fColor;
        a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
    }

    unsigned r = SkColorGetR(c);
    unsigned g = SkColorGetG(c);
    unsigned b = SkColorGetB(c);

    // we want this before we apply any alpha
    fColor16 = SkPack888ToRGB16(r, g, b);

    if (a != 255) {
        r = SkMulDiv255Round(r, a);
        g = SkMulDiv255Round(g, a);
        b = SkMulDiv255Round(b, a);
    }
    fPMColor = SkPackARGB32(a, r, g, b);

    fFlags = kConstInY32_Flag;
    if (paint.isDither() == false) {
        fFlags |= kHasSpan16_Flag;
    }
    if (SkGetPackedA32(fPMColor) == 255) {
        fFlags |= kOpaqueAlpha_Flag;
    }

    return true;
}

void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
    sk_memset32(span, fPMColor, count);
}

void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
    sk_memset16(span, fColor16, count);
}

void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    memset(alpha, SkGetPackedA32(fPMColor), count);
}

<|endoftext|>


<commit_before>#include <QTextStream>

#include "qCTKDCMTK.h"

#include <iostream>
#include <cstdlib>

int qCTKDCMTKTest1(int argc, char** argv) {

  QTextStream out(stdout);
  qCTKDCMTK myCTK;
  if ( myCTK.openDatabase( argv[1]) )
    {
    out << "open db success\n";
    myCTK.initializeDatabase();
    }
  else
    {
    out << "ERROR: " ;
    out << myCTK.GetLastError();
    }
  return EXIT_SUCCESS;
}

<commit_msg>ENH: DICOM db testing<commit_after>#include <QTextStream>
#include <QApplication>

#include "qCTKDCMTK.h"

#include <iostream>
#include <cstdlib>

int qCTKDCMTKTest1(int argc, char** argv) {

  QApplication app(argc, argv);
  QTextStream out(stdout);
  qCTKDCMTK myCTK;
  if ( myCTK.openDatabase( argv[1]) )
    {
    out << "open db success\n";
    myCTK.initializeDatabase();
    }
  else
    {
    out << "ERROR: " ;
    out << myCTK.GetLastError();
    }
  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/**
 * @file sodium.cpp
 * @brief Crypto layer using libsodium.
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega.h"

#ifdef ENABLE_CHAT

namespace mega
{

const std::string EdDSA::TLV_KEY = "prEd255";

EdDSA::EdDSA(unsigned char *keySeed)
{
    initializationOK = false;

    if (sodium_init() == -1)
    {
        LOG_err << "Cannot initialize sodium library.";
        return;
    }

    if (keySeed)    // then use the value
    {
        memcpy(this->keySeed, keySeed, EdDSA::SEED_KEY_LENGTH);
    }
    else    // make the new key seed.
    {
        PrnGen::genblock(this->keySeed, EdDSA::SEED_KEY_LENGTH);
    }

    // derive public and private keys from the seed
    if (crypto_sign_seed_keypair(this->pubKey, this->privKey, this->keySeed) != 0)
    {
        LOG_err << "Error generating an Ed25519 key pair.";
    }

    initializationOK = true;
}

EdDSA::~EdDSA()
{
}

// Computes the signature of a message.
int EdDSA::sign(const unsigned char* msg, const unsigned long long msglen,
                unsigned char* sig)
{
    if (!sig || !msg)
    {
        return 0;
    }

    int result = crypto_sign_detached(sig, NULL, msg, msglen, (const unsigned char*)privKey);

    return (result == 0) ? (crypto_sign_BYTES + msglen) : 0;
}

// Verifies the signature of a message.
int EdDSA::verify(const unsigned char* msg, unsigned long long msglen,
                  const unsigned char* sig, const unsigned char* pubKey)
{
    if (!sig || !msg)
    {
        return 0;
    }

    return !crypto_sign_verify_detached(sig, msg, msglen, pubKey);
}

byte *EdDSA::genFingerprint(bool hexFormat)
{
    HashSHA256 hash;
    string binaryhash;
    hash.add((byte*)&pubKey, PUBLIC_KEY_LENGTH);
    hash.get(&binaryhash);

    size_t size = hexFormat ? 40 : 20;

    byte *result = new byte[size];
    memcpy(result, binaryhash.substr(0, size).data(), size);

    return result;
}

char *EdDSA::genFingerprintHex()
{
    byte *fp = genFingerprint(true);

    static const char hexchars[] = "0123456789abcdef";
    ostringstream oss;
    string fpHex;
    for (size_t i = 0; i < 40; ++i)
    {
        oss.put(hexchars[(fp[i] >> 4) & 0x0F]);
        oss.put(hexchars[fp[i] & 0x0F]);
    }
    fpHex = oss.str();

    delete fp;

    char *result = new char[40 + 1];
    strncpy(result, fpHex.c_str(), 40);
    result[40] = '\0';

    return result;
}

void EdDSA::signKey(const unsigned char *key, const unsigned long long keyLength, string *result, uint64_t ts)
{
    if (!ts)
    {
        ts = (uint64_t) time(NULL);
    }

    string tsstr;
    unsigned char digit;
    for (int i = 0; i < 8; i++)
    {
        digit = ts & 0xFF;
        tsstr.insert(0, 1, digit);
        ts >>= 8;
    }

    string keyString = "keyauth";
    keyString.append(tsstr);
    keyString.append((char*)key, keyLength);

    byte sigBuf[crypto_sign_BYTES];
    sign((unsigned char *)keyString.data(), keyString.size(), sigBuf);

    result->resize(crypto_sign_BYTES + sizeof(ts));  // 8 --> timestamp prefix
    result->assign(tsstr.data(), sizeof(ts));
    result->append((const char*)sigBuf, crypto_sign_BYTES);
}

bool EdDSA::verifyKey(const unsigned char *pubk, const unsigned long long pubkLen, string *sig, const unsigned char* signingPubKey)
{
    if (sig->size() < 72)
    {
        return false;
    }

    uint64_t ts;
    memcpy(&ts, sig->substr(0, 8).data(), sizeof(ts));

    string message = "keyauth";
    message.append(sig->data(), 8);
    message.append((char*)pubk, pubkLen);

    string signature = sig->substr(8);

    return verify((unsigned char*) message.data(), message.length(),
                  (unsigned char*) signature.data(),
                  signingPubKey ? signingPubKey : pubKey);
}

const std::string ECDH::TLV_KEY= "prCu255";

ECDH::ECDH(unsigned char *privKey)
{
    initializationOK = false;

    if (sodium_init() == -1)
    {
        LOG_err << "Cannot initialize sodium library.";
        return;
    }

    if (privKey)    // then use the value
    {
        memcpy(this->privKey, privKey, PRIVATE_KEY_LENGTH);

        // derive public key from privKey
        crypto_scalarmult_base(this->pubKey, this->privKey);
    }
    else
    {
        // no private key specified: create a new key pair
        crypto_box_keypair(this->pubKey, this->privKey);
    }

    initializationOK = true;
}

ECDH::~ECDH()
{
}

int ECDH::encrypt(unsigned char *encmsg, const unsigned char *msg,
                  const unsigned long long msglen, const unsigned char *nonce,
                  const unsigned char *pubKey, const unsigned char *privKey)
{
   return !crypto_box(encmsg, msg, msglen, nonce, pubKey, privKey);
}

int ECDH::decrypt(unsigned char *msg, const unsigned char *encmsg,
                  const unsigned long long encmsglen, const unsigned char *nonce,
                  const unsigned char *pubKey, const unsigned char *privKey)
{
    return !crypto_box_open(msg, encmsg, encmsglen, nonce, pubKey, privKey);
}

} // namespace

#endif  // ENABLE_CHAT
<commit_msg>Use uppercase letters for the own fingerprint like in the webclient<commit_after>/**
 * @file sodium.cpp
 * @brief Crypto layer using libsodium.
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include "mega.h"

#ifdef ENABLE_CHAT

namespace mega
{

const std::string EdDSA::TLV_KEY = "prEd255";

EdDSA::EdDSA(unsigned char *keySeed)
{
    initializationOK = false;

    if (sodium_init() == -1)
    {
        LOG_err << "Cannot initialize sodium library.";
        return;
    }

    if (keySeed)    // then use the value
    {
        memcpy(this->keySeed, keySeed, EdDSA::SEED_KEY_LENGTH);
    }
    else    // make the new key seed.
    {
        PrnGen::genblock(this->keySeed, EdDSA::SEED_KEY_LENGTH);
    }

    // derive public and private keys from the seed
    if (crypto_sign_seed_keypair(this->pubKey, this->privKey, this->keySeed) != 0)
    {
        LOG_err << "Error generating an Ed25519 key pair.";
    }

    initializationOK = true;
}

EdDSA::~EdDSA()
{
}

// Computes the signature of a message.
int EdDSA::sign(const unsigned char* msg, const unsigned long long msglen,
                unsigned char* sig)
{
    if (!sig || !msg)
    {
        return 0;
    }

    int result = crypto_sign_detached(sig, NULL, msg, msglen, (const unsigned char*)privKey);

    return (result == 0) ? (crypto_sign_BYTES + msglen) : 0;
}

// Verifies the signature of a message.
int EdDSA::verify(const unsigned char* msg, unsigned long long msglen,
                  const unsigned char* sig, const unsigned char* pubKey)
{
    if (!sig || !msg)
    {
        return 0;
    }

    return !crypto_sign_verify_detached(sig, msg, msglen, pubKey);
}

byte *EdDSA::genFingerprint(bool hexFormat)
{
    HashSHA256 hash;
    string binaryhash;
    hash.add((byte*)&pubKey, PUBLIC_KEY_LENGTH);
    hash.get(&binaryhash);

    size_t size = hexFormat ? 40 : 20;

    byte *result = new byte[size];
    memcpy(result, binaryhash.substr(0, size).data(), size);

    return result;
}

char *EdDSA::genFingerprintHex()
{
    byte *fp = genFingerprint(true);

    static const char hexchars[] = "0123456789ABCDEF";
    ostringstream oss;
    string fpHex;
    for (size_t i = 0; i < 40; ++i)
    {
        oss.put(hexchars[(fp[i] >> 4) & 0x0F]);
        oss.put(hexchars[fp[i] & 0x0F]);
    }
    fpHex = oss.str();

    delete fp;

    char *result = new char[40 + 1];
    strncpy(result, fpHex.c_str(), 40);
    result[40] = '\0';

    return result;
}

void EdDSA::signKey(const unsigned char *key, const unsigned long long keyLength, string *result, uint64_t ts)
{
    if (!ts)
    {
        ts = (uint64_t) time(NULL);
    }

    string tsstr;
    unsigned char digit;
    for (int i = 0; i < 8; i++)
    {
        digit = ts & 0xFF;
        tsstr.insert(0, 1, digit);
        ts >>= 8;
    }

    string keyString = "keyauth";
    keyString.append(tsstr);
    keyString.append((char*)key, keyLength);

    byte sigBuf[crypto_sign_BYTES];
    sign((unsigned char *)keyString.data(), keyString.size(), sigBuf);

    result->resize(crypto_sign_BYTES + sizeof(ts));  // 8 --> timestamp prefix
    result->assign(tsstr.data(), sizeof(ts));
    result->append((const char*)sigBuf, crypto_sign_BYTES);
}

bool EdDSA::verifyKey(const unsigned char *pubk, const unsigned long long pubkLen, string *sig, const unsigned char* signingPubKey)
{
    if (sig->size() < 72)
    {
        return false;
    }

    uint64_t ts;
    memcpy(&ts, sig->substr(0, 8).data(), sizeof(ts));

    string message = "keyauth";
    message.append(sig->data(), 8);
    message.append((char*)pubk, pubkLen);

    string signature = sig->substr(8);

    return verify((unsigned char*) message.data(), message.length(),
                  (unsigned char*) signature.data(),
                  signingPubKey ? signingPubKey : pubKey);
}

const std::string ECDH::TLV_KEY= "prCu255";

ECDH::ECDH(unsigned char *privKey)
{
    initializationOK = false;

    if (sodium_init() == -1)
    {
        LOG_err << "Cannot initialize sodium library.";
        return;
    }

    if (privKey)    // then use the value
    {
        memcpy(this->privKey, privKey, PRIVATE_KEY_LENGTH);

        // derive public key from privKey
        crypto_scalarmult_base(this->pubKey, this->privKey);
    }
    else
    {
        // no private key specified: create a new key pair
        crypto_box_keypair(this->pubKey, this->privKey);
    }

    initializationOK = true;
}

ECDH::~ECDH()
{
}

int ECDH::encrypt(unsigned char *encmsg, const unsigned char *msg,
                  const unsigned long long msglen, const unsigned char *nonce,
                  const unsigned char *pubKey, const unsigned char *privKey)
{
   return !crypto_box(encmsg, msg, msglen, nonce, pubKey, privKey);
}

int ECDH::decrypt(unsigned char *msg, const unsigned char *encmsg,
                  const unsigned long long encmsglen, const unsigned char *nonce,
                  const unsigned char *pubKey, const unsigned char *privKey)
{
    return !crypto_box_open(msg, encmsg, encmsglen, nonce, pubKey, privKey);
}

} // namespace

#endif  // ENABLE_CHAT
<|endoftext|>


<commit_before>//===------------------------- cxa_exception.hpp --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//
//  This file implements the "Exception Handling APIs"
//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
//
//===----------------------------------------------------------------------===//

#include <exception> // for std::unexpected_handler and std::terminate_handler
#include <cxxabi.h>
#include "unwind.h"

namespace __cxxabiv1 {

    struct __cxa_exception {
#if __LP64__
    // This is a new field to support C++ 0x exception_ptr.
    // For binary compatibility it is at the start of this
    // struct which is prepended to the object thrown in
    // __cxa_allocate_exception.
        size_t referenceCount;
#endif

    //  Manage the exception object itself.
        std::type_info *exceptionType;
        void (*exceptionDestructor)(void *);
        std::unexpected_handler unexpectedHandler;
        std::terminate_handler  terminateHandler;

         __cxa_exception *nextException;

         int handlerCount;

#ifdef __ARM_EABI_UNWINDER__
         __cxa_exception* nextPropagatingException;
         int propagationCount;
#else
         int handlerSwitchValue;
         const unsigned char *actionRecord;
         const unsigned char *languageSpecificData;
         void *catchTemp;
         void *adjustedPtr;
#endif

#if !__LP64__
    // This is a new field to support C++ 0x exception_ptr.
    // For binary compatibility it is placed where the compiler
    // previously adding padded to 64-bit align unwindHeader.
        size_t referenceCount;
#endif

        _Unwind_Exception unwindHeader;
        };

// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html

    struct __cxa_dependent_exception {
#if __LP64__
        void* primaryException;
#endif

    // Unused dummy data (should be set to null)
        std::type_info *exceptionType;
        void (*exceptionDestructor)(void *);

        std::unexpected_handler unexpectedHandler;
        std::terminate_handler terminateHandler;

        __cxa_exception *nextException;

        int handlerCount;

#ifdef __ARM_EABI_UNWINDER__
        __cxa_exception* nextPropagatingException;
        int propagationCount;
#else
        int handlerSwitchValue;
        const unsigned char *actionRecord;
        const unsigned char *languageSpecificData;
        void * catchTemp;
        void *adjustedPtr;
#endif

#if !__LP64__
        void* primaryException;
#endif

        _Unwind_Exception unwindHeader;
        };

    struct __cxa_eh_globals {
        __cxa_exception *   caughtExceptions;
        unsigned int        uncaughtExceptions;
#ifdef __ARM_EABI_UNWINDER__
        __cxa_exception* propagatingExceptions;
#endif
    };

    extern "C" __cxa_eh_globals * __cxa_get_globals      () throw();
    extern "C" __cxa_eh_globals * __cxa_get_globals_fast () throw();

    extern "C" void * __cxa_allocate_dependent_exception () throw();
    extern "C" void __cxa_free_dependent_exception (void * dependent_exception) throw();

}<commit_msg>Correct comment regarding members of __cxa_dependent_exception.  Actually it is useful to disguise a __cxa_dependent_exception as a __cxa_exception by filling in most (not all) of these members at __cxa_dependent_exception construction time.  That way most routines don't have to care which kind of exception they have.<commit_after>//===------------------------- cxa_exception.hpp --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//
//  This file implements the "Exception Handling APIs"
//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
//
//===----------------------------------------------------------------------===//

#include <exception> // for std::unexpected_handler and std::terminate_handler
#include <cxxabi.h>
#include "unwind.h"

namespace __cxxabiv1 {

    struct __cxa_exception {
#if __LP64__
    // This is a new field to support C++ 0x exception_ptr.
    // For binary compatibility it is at the start of this
    // struct which is prepended to the object thrown in
    // __cxa_allocate_exception.
        size_t referenceCount;
#endif

    //  Manage the exception object itself.
        std::type_info *exceptionType;
        void (*exceptionDestructor)(void *);
        std::unexpected_handler unexpectedHandler;
        std::terminate_handler  terminateHandler;

         __cxa_exception *nextException;

         int handlerCount;

#ifdef __ARM_EABI_UNWINDER__
         __cxa_exception* nextPropagatingException;
         int propagationCount;
#else
         int handlerSwitchValue;
         const unsigned char *actionRecord;
         const unsigned char *languageSpecificData;
         void *catchTemp;
         void *adjustedPtr;
#endif

#if !__LP64__
    // This is a new field to support C++ 0x exception_ptr.
    // For binary compatibility it is placed where the compiler
    // previously adding padded to 64-bit align unwindHeader.
        size_t referenceCount;
#endif

        _Unwind_Exception unwindHeader;
        };

// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html

    struct __cxa_dependent_exception {
#if __LP64__
        void* primaryException;
#endif

        std::type_info *exceptionType;
        void (*exceptionDestructor)(void *);
        std::unexpected_handler unexpectedHandler;
        std::terminate_handler terminateHandler;

        __cxa_exception *nextException;

        int handlerCount;

#ifdef __ARM_EABI_UNWINDER__
        __cxa_exception* nextPropagatingException;
        int propagationCount;
#else
        int handlerSwitchValue;
        const unsigned char *actionRecord;
        const unsigned char *languageSpecificData;
        void * catchTemp;
        void *adjustedPtr;
#endif

#if !__LP64__
        void* primaryException;
#endif

        _Unwind_Exception unwindHeader;
        };

    struct __cxa_eh_globals {
        __cxa_exception *   caughtExceptions;
        unsigned int        uncaughtExceptions;
#ifdef __ARM_EABI_UNWINDER__
        __cxa_exception* propagatingExceptions;
#endif
    };

    extern "C" __cxa_eh_globals * __cxa_get_globals      () throw();
    extern "C" __cxa_eh_globals * __cxa_get_globals_fast () throw();

    extern "C" void * __cxa_allocate_dependent_exception () throw();
    extern "C" void __cxa_free_dependent_exception (void * dependent_exception) throw();

}<|endoftext|>


<commit_before>/*
 * Store a URI along with a list of socket addresses.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "address_list.hxx"
#include "shm/dpool.hxx"

AddressList::AddressList(struct dpool &pool, const AddressList &src)
    :sticky_mode(src.sticky_mode)
{
    addresses.clear();

    for (const auto &i : src)
        Add(pool, i);
}

bool
AddressList::Add(struct dpool &pool, const SocketAddress address)
{
    if (addresses.full())
        return false;

    const struct sockaddr *new_address = (const struct sockaddr *)
        d_memdup(pool, address.GetAddress(), address.GetSize());
    addresses.push_back({new_address, address.GetSize()});
    return true;
}

void
AddressList::Free(struct dpool &pool)
{
    for (const auto &i : *this)
        d_free(pool, i.GetAddress());
}
<commit_msg>daddress_list: suppress alignment warnings<commit_after>/*
 * Store a URI along with a list of socket addresses.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "address_list.hxx"
#include "shm/dpool.hxx"

AddressList::AddressList(struct dpool &pool, const AddressList &src)
    :sticky_mode(src.sticky_mode)
{
    addresses.clear();

    for (const auto &i : src)
        Add(pool, i);
}

bool
AddressList::Add(struct dpool &pool, const SocketAddress address)
{
    if (addresses.full())
        return false;

    const struct sockaddr *new_address = (const struct sockaddr *)
        (const void *)
        d_memdup(pool, address.GetAddress(), address.GetSize());
    addresses.push_back({new_address, address.GetSize()});
    return true;
}

void
AddressList::Free(struct dpool &pool)
{
    for (const auto &i : *this)
        d_free(pool, i.GetAddress());
}
<|endoftext|>