<commit_before>void loopdir() {
   // example of script to loop on all the objects of a ROOT file directory
   // and print on Postscript all TH1 derived objects
   // This script uses the file generated by tutorial hsimple.C
   //Author: Rene Brun

   TString dir = gSystem->UnixPathName(gInterpreter->GetCurrentMacroName());
   dir.ReplaceAll("loopdir.C","../hsimple.C");
   dir.ReplaceAll("/./","/");
   if (!gInterpreter->IsLoaded(dir.Data())) gInterpreter->LoadMacro(dir.Data());
   TFile *f1 = (TFile*)gROOT->ProcessLineFast("hsimple(1)");
   TIter next(f1->GetListOfKeys());
   TKey *key;
   TCanvas c1;
   c1.Print("hsimple.ps[");
   while ((key = (TKey*)next())) {
      TClass *cl = gROOT->GetClass(key->GetClassName());
      if (!cl->InheritsFrom("TH1")) continue;
      TH1 *h = (TH1*)key->ReadObj();
      h->Draw();
      c1.Print("hsimple.ps");
   }
   c1.Print("hsimple.ps]");
}

<commit_msg>Do not trigger the creation of hsimple.root, which may create clashes when running in parallel.<commit_after>void loopdir() {
   // example of script to loop on all the objects of a ROOT file directory
   // and print on Postscript all TH1 derived objects
   // This script uses the file generated by tutorial hsimple.C
   //Author: Rene Brun

   TFile *f1 = TFile::Open("hsimple.root");
   TIter next(f1->GetListOfKeys());
   TKey *key;
   TCanvas c1;
   c1.Print("hsimple.ps[");
   while ((key = (TKey*)next())) {
      TClass *cl = gROOT->GetClass(key->GetClassName());
      if (!cl->InheritsFrom("TH1")) continue;
      TH1 *h = (TH1*)key->ReadObj();
      h->Draw();
      c1.Print("hsimple.ps");
   }
   c1.Print("hsimple.ps]");
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 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 "mutation.hh"
#include "query-result-writer.hh"

mutation::data::data(dht::decorated_key&& key, schema_ptr&& schema)
    : _schema(std::move(schema))
    , _dk(std::move(key))
    , _p(_schema)
{ }

mutation::data::data(partition_key&& key_, schema_ptr&& schema)
    : _schema(std::move(schema))
    , _dk(dht::global_partitioner().decorate_key(*_schema, std::move(key_)))
    , _p(_schema)
{ }

mutation::data::data(schema_ptr&& schema, dht::decorated_key&& key, const mutation_partition& mp)
    : _schema(std::move(schema))
    , _dk(std::move(key))
    , _p(mp)
{ }

mutation::data::data(schema_ptr&& schema, dht::decorated_key&& key, mutation_partition&& mp)
    : _schema(std::move(schema))
    , _dk(std::move(key))
    , _p(std::move(mp))
{ }

void mutation::set_static_cell(const column_definition& def, atomic_cell_or_collection&& value) {
    partition().static_row().apply(def, std::move(value));
}

void mutation::set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl) {
    auto column_def = schema()->get_column_definition(name);
    if (!column_def) {
        throw std::runtime_error(sprint("no column definition found for '%s'", name));
    }
    if (!column_def->is_static()) {
        throw std::runtime_error(sprint("column '%s' is not static", name));
    }
    partition().static_row().apply(*column_def, atomic_cell::make_live(timestamp, column_def->type->decompose(value), ttl));
}

void mutation::set_clustered_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value) {
    auto& row = partition().clustered_row(clustering_key::from_clustering_prefix(*schema(), prefix)).cells();
    row.apply(def, std::move(value));
}

void mutation::set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value,
        api::timestamp_type timestamp, ttl_opt ttl) {
    auto column_def = schema()->get_column_definition(name);
    if (!column_def) {
        throw std::runtime_error(sprint("no column definition found for '%s'", name));
    }
    return set_clustered_cell(key, *column_def, atomic_cell::make_live(timestamp, column_def->type->decompose(value), ttl));
}

void mutation::set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection&& value) {
    auto& row = partition().clustered_row(key).cells();
    row.apply(def, std::move(value));
}

void mutation::set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const data_value& value,
        api::timestamp_type timestamp, ttl_opt ttl) {
    auto column_def = schema()->get_column_definition(name);
    if (!column_def) {
        throw std::runtime_error(sprint("no column definition found for '%s'", name));
    }
    return set_cell(prefix, *column_def, atomic_cell::make_live(timestamp, column_def->type->decompose(value), ttl));
}

void mutation::set_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value) {
    if (def.is_static()) {
        set_static_cell(def, std::move(value));
    } else if (def.is_regular()) {
        set_clustered_cell(prefix, def, std::move(value));
    } else {
        throw std::runtime_error("attemting to store into a key cell");
    }
}

std::experimental::optional<atomic_cell_or_collection>
mutation::get_cell(const clustering_key& rkey, const column_definition& def) const {
    if (def.is_static()) {
        const atomic_cell_or_collection* cell = partition().static_row().find_cell(def.id);
        if (!cell) {
            return {};
        }
        return { *cell };
    } else {
        const row* r = partition().find_row(rkey);
        if (!r) {
            return {};
        }
        const atomic_cell_or_collection* cell = r->find_cell(def.id);
        return { *cell };
    }
}

bool mutation::operator==(const mutation& m) const {
    return decorated_key().equal(*schema(), m.decorated_key())
           && partition().equal(*schema(), m.partition(), *m.schema());
}

bool mutation::operator!=(const mutation& m) const {
    return !(*this == m);
}

void
mutation::query(query::result::builder& builder,
    const query::partition_slice& slice,
    gc_clock::time_point now,
    uint32_t row_limit) &&
{
    auto pb = builder.add_partition(*schema(), key());
    auto is_reversed = slice.options.contains<query::partition_slice::option::reversed>();
    mutation_partition& p = partition();
    auto limit = std::min(row_limit, slice.partition_row_limit());
    p.compact_for_query(*schema(), now, slice.row_ranges(*schema(), key()), is_reversed, limit);
    p.query_compacted(pb, *schema(), limit);
}

query::result
mutation::query(const query::partition_slice& slice,
    query::result_request request,
    gc_clock::time_point now, uint32_t row_limit) &&
{
    query::result::builder builder(slice, request);
    std::move(*this).query(builder, slice, now, row_limit);
    return builder.build();
}

query::result
mutation::query(const query::partition_slice& slice,
    query::result_request request,
    gc_clock::time_point now, uint32_t row_limit) const&
{
    return mutation(*this).query(slice, request, now, row_limit);
}

size_t
mutation::live_row_count(gc_clock::time_point query_time) const {
    return partition().live_row_count(*schema(), query_time);
}

bool
mutation_decorated_key_less_comparator::operator()(const mutation& m1, const mutation& m2) const {
    return m1.decorated_key().less_compare(*m1.schema(), m2.decorated_key());
}

boost::iterator_range<std::vector<mutation>::const_iterator>
slice(const std::vector<mutation>& partitions, const query::partition_range& r) {
    struct cmp {
        bool operator()(const dht::ring_position& pos, const mutation& m) const {
            return m.decorated_key().tri_compare(*m.schema(), pos) > 0;
        };
        bool operator()(const mutation& m, const dht::ring_position& pos) const {
            return m.decorated_key().tri_compare(*m.schema(), pos) < 0;
        };
    };

    return boost::make_iterator_range(
        r.start()
            ? (r.start()->is_inclusive()
                ? std::lower_bound(partitions.begin(), partitions.end(), r.start()->value(), cmp())
                : std::upper_bound(partitions.begin(), partitions.end(), r.start()->value(), cmp()))
            : partitions.cbegin(),
        r.end()
            ? (r.end()->is_inclusive()
              ? std::upper_bound(partitions.begin(), partitions.end(), r.end()->value(), cmp())
              : std::lower_bound(partitions.begin(), partitions.end(), r.end()->value(), cmp()))
            : partitions.cend());
}

void
mutation::upgrade(const schema_ptr& new_schema) {
    if (_ptr->_schema != new_schema) {
        schema_ptr s = new_schema;
        partition().upgrade(*schema(), *new_schema);
        _ptr->_schema = std::move(s);
    }
}

void mutation::apply(mutation&& m) {
    partition().apply(*schema(), std::move(m.partition()), *m.schema());
}

void mutation::apply(const mutation& m) {
    partition().apply(*schema(), m.partition(), *m.schema());
}

mutation& mutation::operator=(const mutation& m) {
    return *this = mutation(m);
}

mutation mutation::operator+(const mutation& other) const {
    auto m = *this;
    m.apply(other);
    return m;
}

mutation& mutation::operator+=(const mutation& other) {
    apply(other);
    return *this;
}

mutation& mutation::operator+=(mutation&& other) {
    apply(std::move(other));
    return *this;
}

enum class limit_mutation_size { yes, no };

template <limit_mutation_size with_limit>
class mutation_rebuilder {
    mutation _m;
    streamed_mutation& _sm;
    size_t _remaining_limit;

    template <typename T> bool check_remaining_limit(const T& e) {
        if (with_limit == limit_mutation_size::no) {
            return true;
        }
        size_t size = sizeof(e) + e.external_memory_usage();
        if (_remaining_limit <= size) {
            _remaining_limit = 0;
        } else {
            _remaining_limit -= size;
        }
        return _remaining_limit > 0;
    }
public:
    mutation_rebuilder(streamed_mutation& sm)
        : _m(sm.decorated_key(), sm.schema()), _sm(sm), _remaining_limit(0) {
        static_assert(with_limit == limit_mutation_size::no,
                     "This constructor should be used only for mutation_rebuildeer with no limit");
    }
    mutation_rebuilder(streamed_mutation& sm, size_t limit)
        : _m(sm.decorated_key(), sm.schema()), _sm(sm), _remaining_limit(limit) {
        static_assert(with_limit == limit_mutation_size::yes,
                      "This constructor should be used only for mutation_rebuildeer with limit");
        check_remaining_limit(_m.key());
    }

    stop_iteration consume(tombstone t) {
        _m.partition().apply(t);
        return stop_iteration::no;
    }

    stop_iteration consume(range_tombstone&& rt) {
        if (!check_remaining_limit(rt)) {
            return stop_iteration::yes;
        }
        _m.partition().apply_row_tombstone(*_m.schema(), std::move(rt));
        return stop_iteration::no;
    }

    stop_iteration consume(static_row&& sr) {
        if (!check_remaining_limit(sr)) {
            return stop_iteration::yes;
        }
        _m.partition().static_row().apply(*_m.schema(), column_kind::static_column, std::move(sr.cells()));
        return stop_iteration::no;
    }

    stop_iteration consume(clustering_row&& cr) {
        if (!check_remaining_limit(cr)) {
            return stop_iteration::yes;
        }
        auto& dr = _m.partition().clustered_row(std::move(cr.key()));
        dr.apply(cr.tomb());
        dr.apply(cr.marker());
        dr.cells().apply(*_m.schema(), column_kind::regular_column, std::move(cr.cells()));
        return stop_iteration::no;
    }

    mutation_opt consume_end_of_stream() {
        return with_limit == limit_mutation_size::yes && _remaining_limit == 0 ? mutation_opt()
                                                                               : mutation_opt(std::move(_m));
    }
};

future<mutation_opt>
mutation_from_streamed_mutation_with_limit(streamed_mutation sm, size_t limit) {
    return do_with(std::move(sm), [limit] (auto& sm) {
        return consume(sm, mutation_rebuilder<limit_mutation_size::yes>(sm, limit));
    });
}

future<mutation_opt> mutation_from_streamed_mutation(streamed_mutation_opt sm) {
    if (!sm) {
        return make_ready_future<mutation_opt>();
    }
    return do_with(std::move(*sm), [] (auto& sm) {
        return consume(sm, mutation_rebuilder<limit_mutation_size::no>(sm));
    });
}

<commit_msg>mutation_rebuilder: use memory_usage()<commit_after>/*
 * Copyright (C) 2014 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 "mutation.hh"
#include "query-result-writer.hh"

mutation::data::data(dht::decorated_key&& key, schema_ptr&& schema)
    : _schema(std::move(schema))
    , _dk(std::move(key))
    , _p(_schema)
{ }

mutation::data::data(partition_key&& key_, schema_ptr&& schema)
    : _schema(std::move(schema))
    , _dk(dht::global_partitioner().decorate_key(*_schema, std::move(key_)))
    , _p(_schema)
{ }

mutation::data::data(schema_ptr&& schema, dht::decorated_key&& key, const mutation_partition& mp)
    : _schema(std::move(schema))
    , _dk(std::move(key))
    , _p(mp)
{ }

mutation::data::data(schema_ptr&& schema, dht::decorated_key&& key, mutation_partition&& mp)
    : _schema(std::move(schema))
    , _dk(std::move(key))
    , _p(std::move(mp))
{ }

void mutation::set_static_cell(const column_definition& def, atomic_cell_or_collection&& value) {
    partition().static_row().apply(def, std::move(value));
}

void mutation::set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl) {
    auto column_def = schema()->get_column_definition(name);
    if (!column_def) {
        throw std::runtime_error(sprint("no column definition found for '%s'", name));
    }
    if (!column_def->is_static()) {
        throw std::runtime_error(sprint("column '%s' is not static", name));
    }
    partition().static_row().apply(*column_def, atomic_cell::make_live(timestamp, column_def->type->decompose(value), ttl));
}

void mutation::set_clustered_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value) {
    auto& row = partition().clustered_row(clustering_key::from_clustering_prefix(*schema(), prefix)).cells();
    row.apply(def, std::move(value));
}

void mutation::set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value,
        api::timestamp_type timestamp, ttl_opt ttl) {
    auto column_def = schema()->get_column_definition(name);
    if (!column_def) {
        throw std::runtime_error(sprint("no column definition found for '%s'", name));
    }
    return set_clustered_cell(key, *column_def, atomic_cell::make_live(timestamp, column_def->type->decompose(value), ttl));
}

void mutation::set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection&& value) {
    auto& row = partition().clustered_row(key).cells();
    row.apply(def, std::move(value));
}

void mutation::set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const data_value& value,
        api::timestamp_type timestamp, ttl_opt ttl) {
    auto column_def = schema()->get_column_definition(name);
    if (!column_def) {
        throw std::runtime_error(sprint("no column definition found for '%s'", name));
    }
    return set_cell(prefix, *column_def, atomic_cell::make_live(timestamp, column_def->type->decompose(value), ttl));
}

void mutation::set_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value) {
    if (def.is_static()) {
        set_static_cell(def, std::move(value));
    } else if (def.is_regular()) {
        set_clustered_cell(prefix, def, std::move(value));
    } else {
        throw std::runtime_error("attemting to store into a key cell");
    }
}

std::experimental::optional<atomic_cell_or_collection>
mutation::get_cell(const clustering_key& rkey, const column_definition& def) const {
    if (def.is_static()) {
        const atomic_cell_or_collection* cell = partition().static_row().find_cell(def.id);
        if (!cell) {
            return {};
        }
        return { *cell };
    } else {
        const row* r = partition().find_row(rkey);
        if (!r) {
            return {};
        }
        const atomic_cell_or_collection* cell = r->find_cell(def.id);
        return { *cell };
    }
}

bool mutation::operator==(const mutation& m) const {
    return decorated_key().equal(*schema(), m.decorated_key())
           && partition().equal(*schema(), m.partition(), *m.schema());
}

bool mutation::operator!=(const mutation& m) const {
    return !(*this == m);
}

void
mutation::query(query::result::builder& builder,
    const query::partition_slice& slice,
    gc_clock::time_point now,
    uint32_t row_limit) &&
{
    auto pb = builder.add_partition(*schema(), key());
    auto is_reversed = slice.options.contains<query::partition_slice::option::reversed>();
    mutation_partition& p = partition();
    auto limit = std::min(row_limit, slice.partition_row_limit());
    p.compact_for_query(*schema(), now, slice.row_ranges(*schema(), key()), is_reversed, limit);
    p.query_compacted(pb, *schema(), limit);
}

query::result
mutation::query(const query::partition_slice& slice,
    query::result_request request,
    gc_clock::time_point now, uint32_t row_limit) &&
{
    query::result::builder builder(slice, request);
    std::move(*this).query(builder, slice, now, row_limit);
    return builder.build();
}

query::result
mutation::query(const query::partition_slice& slice,
    query::result_request request,
    gc_clock::time_point now, uint32_t row_limit) const&
{
    return mutation(*this).query(slice, request, now, row_limit);
}

size_t
mutation::live_row_count(gc_clock::time_point query_time) const {
    return partition().live_row_count(*schema(), query_time);
}

bool
mutation_decorated_key_less_comparator::operator()(const mutation& m1, const mutation& m2) const {
    return m1.decorated_key().less_compare(*m1.schema(), m2.decorated_key());
}

boost::iterator_range<std::vector<mutation>::const_iterator>
slice(const std::vector<mutation>& partitions, const query::partition_range& r) {
    struct cmp {
        bool operator()(const dht::ring_position& pos, const mutation& m) const {
            return m.decorated_key().tri_compare(*m.schema(), pos) > 0;
        };
        bool operator()(const mutation& m, const dht::ring_position& pos) const {
            return m.decorated_key().tri_compare(*m.schema(), pos) < 0;
        };
    };

    return boost::make_iterator_range(
        r.start()
            ? (r.start()->is_inclusive()
                ? std::lower_bound(partitions.begin(), partitions.end(), r.start()->value(), cmp())
                : std::upper_bound(partitions.begin(), partitions.end(), r.start()->value(), cmp()))
            : partitions.cbegin(),
        r.end()
            ? (r.end()->is_inclusive()
              ? std::upper_bound(partitions.begin(), partitions.end(), r.end()->value(), cmp())
              : std::lower_bound(partitions.begin(), partitions.end(), r.end()->value(), cmp()))
            : partitions.cend());
}

void
mutation::upgrade(const schema_ptr& new_schema) {
    if (_ptr->_schema != new_schema) {
        schema_ptr s = new_schema;
        partition().upgrade(*schema(), *new_schema);
        _ptr->_schema = std::move(s);
    }
}

void mutation::apply(mutation&& m) {
    partition().apply(*schema(), std::move(m.partition()), *m.schema());
}

void mutation::apply(const mutation& m) {
    partition().apply(*schema(), m.partition(), *m.schema());
}

mutation& mutation::operator=(const mutation& m) {
    return *this = mutation(m);
}

mutation mutation::operator+(const mutation& other) const {
    auto m = *this;
    m.apply(other);
    return m;
}

mutation& mutation::operator+=(const mutation& other) {
    apply(other);
    return *this;
}

mutation& mutation::operator+=(mutation&& other) {
    apply(std::move(other));
    return *this;
}

enum class limit_mutation_size { yes, no };

template <limit_mutation_size with_limit>
class mutation_rebuilder {
    mutation _m;
    streamed_mutation& _sm;
    size_t _remaining_limit;

    template <typename T> bool check_remaining_limit(const T& e) {
        if (with_limit == limit_mutation_size::no) {
            return true;
        }
        size_t size = e.memory_usage();
        if (_remaining_limit <= size) {
            _remaining_limit = 0;
        } else {
            _remaining_limit -= size;
        }
        return _remaining_limit > 0;
    }
public:
    mutation_rebuilder(streamed_mutation& sm)
        : _m(sm.decorated_key(), sm.schema()), _sm(sm), _remaining_limit(0) {
        static_assert(with_limit == limit_mutation_size::no,
                     "This constructor should be used only for mutation_rebuildeer with no limit");
    }
    mutation_rebuilder(streamed_mutation& sm, size_t limit)
        : _m(sm.decorated_key(), sm.schema()), _sm(sm), _remaining_limit(limit) {
        static_assert(with_limit == limit_mutation_size::yes,
                      "This constructor should be used only for mutation_rebuildeer with limit");
        check_remaining_limit(_m.key());
    }

    stop_iteration consume(tombstone t) {
        _m.partition().apply(t);
        return stop_iteration::no;
    }

    stop_iteration consume(range_tombstone&& rt) {
        if (!check_remaining_limit(rt)) {
            return stop_iteration::yes;
        }
        _m.partition().apply_row_tombstone(*_m.schema(), std::move(rt));
        return stop_iteration::no;
    }

    stop_iteration consume(static_row&& sr) {
        if (!check_remaining_limit(sr)) {
            return stop_iteration::yes;
        }
        _m.partition().static_row().apply(*_m.schema(), column_kind::static_column, std::move(sr.cells()));
        return stop_iteration::no;
    }

    stop_iteration consume(clustering_row&& cr) {
        if (!check_remaining_limit(cr)) {
            return stop_iteration::yes;
        }
        auto& dr = _m.partition().clustered_row(std::move(cr.key()));
        dr.apply(cr.tomb());
        dr.apply(cr.marker());
        dr.cells().apply(*_m.schema(), column_kind::regular_column, std::move(cr.cells()));
        return stop_iteration::no;
    }

    mutation_opt consume_end_of_stream() {
        return with_limit == limit_mutation_size::yes && _remaining_limit == 0 ? mutation_opt()
                                                                               : mutation_opt(std::move(_m));
    }
};

future<mutation_opt>
mutation_from_streamed_mutation_with_limit(streamed_mutation sm, size_t limit) {
    return do_with(std::move(sm), [limit] (auto& sm) {
        return consume(sm, mutation_rebuilder<limit_mutation_size::yes>(sm, limit));
    });
}

future<mutation_opt> mutation_from_streamed_mutation(streamed_mutation_opt sm) {
    if (!sm) {
        return make_ready_future<mutation_opt>();
    }
    return do_with(std::move(*sm), [] (auto& sm) {
        return consume(sm, mutation_rebuilder<limit_mutation_size::no>(sm));
    });
}

<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <iostream>
#include <fstream>
#include <ctime>
#include <iomanip>

#include <minizinc/model.hh>
#include <minizinc/parser.hh>
#include <minizinc/prettyprinter.hh>
#include <minizinc/typecheck.hh>
#include <minizinc/exception.hh>

#include <minizinc/flatten.hh>
#include <minizinc/optimize.hh>
#include <minizinc/builtins.hh>

using namespace MiniZinc;
using namespace std;

std::string stoptime(clock_t& start) {
  std::ostringstream oss;
  clock_t now = clock();
  oss << std::setprecision(0) << std::fixed << ((static_cast<double>(now-start) / CLOCKS_PER_SEC) * 1000.0) << " ms";
  start = now;
  return oss.str();
}

int main(int argc, char** argv) {
  int i=1;
  string filename;
  vector<string> datafiles;
  vector<string> includePaths;
  bool flag_ignoreStdlib = false;
  bool flag_typecheck = true;
  bool flag_eval = true;
  bool flag_verbose = false;
  bool flag_newfzn = false;
  bool flag_optimize = true;

  clock_t starttime = std::clock();
  clock_t lasttime = std::clock();

  string std_lib_dir;
  if (char* MZNSTDLIBDIR = getenv("MZN_STDLIB_DIR")) {
    std_lib_dir = string(MZNSTDLIBDIR);
  }
  string globals_dir;

  bool flag_no_output_ozn = false;
  string flag_output_base;
  string flag_output_fzn;
  string flag_output_ozn;
  bool flag_output_fzn_stdout = false;
  bool flag_output_ozn_stdout = false;
  FlatteningOptions fopts;

  if (argc < 2)
    goto error;

  GC::init();

  for (;;) {
    if (string(argv[i])==string("-h") || string(argv[i])==string("--help"))
        goto error;
    if (string(argv[i])==string("--version")) {
      std::cout << "NICTA MiniZinc to FlatZinc converter, version "
        << MZN_VERSION_MAJOR << "." << MZN_VERSION_MINOR << "." << MZN_VERSION_PATCH << std::endl;
      std::cout << "Copyright (C) 2014 Monash University and NICTA" << std::endl;
      std::exit(EXIT_SUCCESS);
    }
    if (string(argv[i])==string("-I")) {
      i++;
      if (i==argc) {
        goto error;
      }
      includePaths.push_back(argv[i]+string("/"));
    } else if (string(argv[i])==string("--ignore-stdlib")) {
      flag_ignoreStdlib = true;
    } else if (string(argv[i])==string("--no-typecheck")) {
      flag_typecheck = false; flag_eval=false;
    } else if (string(argv[i])==string("--no-eval")) {
      flag_eval = false;
    } else if (string(argv[i])==string("--verbose")) {
      flag_verbose = true;
    } else if (string(argv[i])==string("--newfzn")) {
      flag_newfzn = true;
    } else if (string(argv[i])==string("--no-optimize")) {
      flag_optimize = false;
    } else if (string(argv[i])==string("--no-output-ozn") ||
               string(argv[i])==string("-O-")) {
      flag_no_output_ozn = false;
    } else if (string(argv[i])=="--output-base") {
      i++;
      if (i==argc)
        goto error;
      flag_output_base = argv[i];
    } else if (string(argv[i])=="-o" || string(argv[i])=="--output-to-file" ||
               string(argv[i])=="--output-fzn-to-file") {
      i++;
      if (i==argc)
        goto error;
      flag_output_fzn = argv[i];
    } else if (string(argv[i])=="--output-ozn-to-file") {
      i++;
      if (i==argc)
        goto error;
      flag_output_ozn = argv[i];
    } else if (string(argv[i])=="--output-to-stdout" ||
               string(argv[i])=="--output-fzn-to-stdout") {
      flag_output_fzn_stdout = true;
    } else if (string(argv[i])=="--output-ozn-to-stdout") {
      flag_output_ozn_stdout = true;
    } else if (string(argv[i])=="--stdlib-dir") {
      i++;
      if (i==argc)
        goto error;
      std_lib_dir = argv[i];
    } else if (string(argv[i])=="-G" ||
               string(argv[i])=="--globals-dir" ||
               string(argv[i])=="--mzn-globals-dir") {
      i++;
      if (i==argc)
        goto error;
      globals_dir = argv[i];
    } else if (string(argv[i])=="--only-range-domains") {
      fopts.onlyRangeDomains = true;
    } else {
      break;
    }
    i++;
  }

  if (std_lib_dir=="") {
    std::cerr << "Error: unknown minizinc standard library directory.\n"
              << "Specify --stdlib-dir on the command line or set the\n"
              << "MZN_STDLIB_DIR environment variable.\n";
    std::exit(EXIT_FAILURE);
  }

  if (globals_dir!="") {
    includePaths.push_back(std_lib_dir+"/"+globals_dir+"/");
  }
  includePaths.push_back(std_lib_dir+"/std/");

  if (i==argc) {
    goto error;
  }
  filename = argv[i++];
  if (filename.length()<=4 ||
      filename.substr(filename.length()-4,string::npos) != ".mzn")
    goto error;

  if (flag_output_base == "") {
    flag_output_base = filename.substr(0,filename.length()-4);
  }
  if (flag_output_fzn == "") {
    flag_output_fzn = flag_output_base+".fzn";
  }
  if (flag_output_ozn == "") {
    flag_output_ozn = flag_output_base+".ozn";
  }

  while (i<argc) {
    std::string datafile = argv[i++];
    if (datafile.length()<=4 ||
        datafile.substr(datafile.length()-4,string::npos) != ".dzn")
      goto error;
    datafiles.push_back(datafile);
  }

  {
    std::stringstream errstream;
    if (flag_verbose)
      std::cerr << "Parsing '" << filename << "' ...";
    if (Model* m = parse(filename, datafiles, includePaths, flag_ignoreStdlib,
                         errstream)) {
      try {
        if (flag_typecheck) {
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          if (flag_verbose)
            std::cerr << "Typechecking ...";
          MiniZinc::typecheck(m);
          MiniZinc::registerBuiltins(m);
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;

          if (flag_verbose)
            std::cerr << "Flattening ...";
          Env env(m);
          try {
            flatten(env,fopts);
          } catch (LocationException& e) {
            if (flag_verbose)
              std::cerr << std::endl;
            std::cerr << e.what() << ": " << e.msg() << std::endl;
            std::cerr << e.loc() << std::endl;
            env.dumpErrorStack(std::cerr);
            exit(EXIT_FAILURE);
          }
          Model* flat = env.flat();
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;

          if (flag_optimize) {
            if (flag_verbose)
              std::cerr << "Optimizing ...";
            optimize(env);
            if (flag_verbose)
              std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          }

          if (!flag_newfzn) {
            if (flag_verbose)
              std::cerr << "Converting to old FlatZinc ...";
            oldflatzinc(env);
            if (flag_verbose)
              std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          }

          if (flag_verbose)
            std::cerr << "Printing FlatZinc ...";
          if (flag_output_fzn_stdout) {
            Printer p(std::cout,0);
            p.print(flat);
          } else {
            std::ofstream os;
            os.open(flag_output_fzn.c_str(), ios::out);
            Printer p(os,0);
            p.print(flat);
            os.close();
          }
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          if (!flag_no_output_ozn) {
            if (flag_verbose)
              std::cerr << "Printing .ozn ...";
            if (flag_output_ozn_stdout) {
              Printer p(std::cout,0);
              p.print(env.output());
            } else {
              std::ofstream os;
              os.open(flag_output_ozn.c_str(), ios::out);
              Printer p(os,0);
              p.print(env.output());
              os.close();
            }
            if (flag_verbose)
              std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          }
        } else { // !flag_typecheck
          Printer p(std::cout);
          p.print(m);
        }
      } catch (LocationException& e) {
        if (flag_verbose)
          std::cerr << std::endl;
        std::cerr << e.what() << ": " << e.msg() << std::endl;
        std::cerr << e.loc() << std::endl;
        exit(EXIT_FAILURE);
      } catch (Exception& e) {
        if (flag_verbose)
          std::cerr << std::endl;
        std::cerr << e.what() << ": " << e.msg() << std::endl;
        exit(EXIT_FAILURE);
      }
      delete m;
    } else {
      if (flag_verbose)
        std::cerr << std::endl;
      std::copy(istreambuf_iterator<char>(errstream),istreambuf_iterator<char>(),ostreambuf_iterator<char>(std::cerr));
    }
  }

  if (flag_verbose)
    std::cerr << "Done (overall time " << stoptime(starttime) << ")." << std::endl;
  return 0;

error:
  std::cerr << "Usage: "<< argv[0]
            << " [<options>] [-I <include path>] <model>.mzn [<data>.dzn ...]" << std::endl
            << std::endl
            << "Options:" << std::endl
            << "  --help, -h\n    Print this help message" << std::endl
            << "  --version\n    Print version information" << std::endl
            << "  --ignore-stdlib\n    Ignore the standard libraries stdlib.mzn and builtins.mzn" << std::endl
            << "  --newfzn\n    Output in the new FlatZinc format" << std::endl
            << "  --verbose\n    Print progress statements" << std::endl
            << "  --no-typecheck\n    Do not typecheck (implies --no-eval)" << std::endl
            << "  --no-eval\n    Do not evaluate" << std::endl
            << "  --no-optimize\n    Do not optimize the FlatZinc (may speed up large instances)" << std::endl
            << "  --no-output-ozn, -O-\n    Do not output ozn file" << std::endl
            << "  --output-base <name>\n    Base name for output files" << std::endl
            << "  -o <file>, --output-to-file <file>, --output-fzn-to-file <file>\n    Filename for generated FlatZinc output" << std::endl
            << "  --output-ozn-to-file <file>\n    Filename for model output specification" << std::endl
            << "  --output-to-stdout, --output-fzn-to-stdout\n    Print generated FlatZinc to standard output" << std::endl
            << "  --output-ozn-to-stdout\n    Print model output specification to standard output" << std::endl
            << "  --stdlib-dir <dir>\n    Path to MiniZinc standard library directory" << std::endl
            << "  -G --globals-dir --mzn-globals-dir\n    Search for included files in <stdlib>/<dir>." << std::endl
  ;

  exit(EXIT_FAILURE);
}
<commit_msg>Support short command line arguments (like -Gg12_fd)<commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <iostream>
#include <fstream>
#include <ctime>
#include <iomanip>

#include <minizinc/model.hh>
#include <minizinc/parser.hh>
#include <minizinc/prettyprinter.hh>
#include <minizinc/typecheck.hh>
#include <minizinc/exception.hh>

#include <minizinc/flatten.hh>
#include <minizinc/optimize.hh>
#include <minizinc/builtins.hh>

using namespace MiniZinc;
using namespace std;

std::string stoptime(clock_t& start) {
  std::ostringstream oss;
  clock_t now = clock();
  oss << std::setprecision(0) << std::fixed << ((static_cast<double>(now-start) / CLOCKS_PER_SEC) * 1000.0) << " ms";
  start = now;
  return oss.str();
}

bool beginswith(string s, string t) {
  return s.compare(0, t.length(), t)==0;
}

int main(int argc, char** argv) {
  int i=1;
  string filename;
  vector<string> datafiles;
  vector<string> includePaths;
  bool flag_ignoreStdlib = false;
  bool flag_typecheck = true;
  bool flag_eval = true;
  bool flag_verbose = false;
  bool flag_newfzn = false;
  bool flag_optimize = true;

  clock_t starttime = std::clock();
  clock_t lasttime = std::clock();

  string std_lib_dir;
  if (char* MZNSTDLIBDIR = getenv("MZN_STDLIB_DIR")) {
    std_lib_dir = string(MZNSTDLIBDIR);
  }
  string globals_dir;

  bool flag_no_output_ozn = false;
  string flag_output_base;
  string flag_output_fzn;
  string flag_output_ozn;
  bool flag_output_fzn_stdout = false;
  bool flag_output_ozn_stdout = false;
  FlatteningOptions fopts;

  if (argc < 2)
    goto error;

  GC::init();

  for (;;) {
    if (string(argv[i])==string("-h") || string(argv[i])==string("--help"))
        goto error;
    if (string(argv[i])==string("--version")) {
      std::cout << "NICTA MiniZinc to FlatZinc converter, version "
        << MZN_VERSION_MAJOR << "." << MZN_VERSION_MINOR << "." << MZN_VERSION_PATCH << std::endl;
      std::cout << "Copyright (C) 2014 Monash University and NICTA" << std::endl;
      std::exit(EXIT_SUCCESS);
    }
    if (beginswith(string(argv[i]),"-I")) {
      string include(argv[i]);
      if (include.length() > 2) {
        includePaths.push_back(include.substr(2)+string("/"));
      } else {
        i++;
        if (i==argc) {
          goto error;
        }
        includePaths.push_back(argv[i]+string("/"));
      }
    } else if (string(argv[i])==string("--ignore-stdlib")) {
      flag_ignoreStdlib = true;
    } else if (string(argv[i])==string("--no-typecheck")) {
      flag_typecheck = false; flag_eval=false;
    } else if (string(argv[i])==string("--no-eval")) {
      flag_eval = false;
    } else if (string(argv[i])==string("--verbose")) {
      flag_verbose = true;
    } else if (string(argv[i])==string("--newfzn")) {
      flag_newfzn = true;
    } else if (string(argv[i])==string("--no-optimize")) {
      flag_optimize = false;
    } else if (string(argv[i])==string("--no-output-ozn") ||
               string(argv[i])==string("-O-")) {
      flag_no_output_ozn = false;
    } else if (string(argv[i])=="--output-base") {
      i++;
      if (i==argc)
        goto error;
      flag_output_base = argv[i];
    } else if (beginswith(string(argv[i]),"-o")) {
        string filename(argv[i]);
        if (filename.length() > 2) {
          flag_output_fzn = filename.substr(2);
        } else {
          i++;
          if (i==argc) {
            goto error;
          }
          flag_output_fzn = argv[i];
        }
    } else if (string(argv[i])=="--output-to-file" ||
               string(argv[i])=="--output-fzn-to-file") {
      i++;
      if (i==argc)
        goto error;
      flag_output_fzn = argv[i];
    } else if (string(argv[i])=="--output-ozn-to-file") {
      i++;
      if (i==argc)
        goto error;
      flag_output_ozn = argv[i];
    } else if (string(argv[i])=="--output-to-stdout" ||
               string(argv[i])=="--output-fzn-to-stdout") {
      flag_output_fzn_stdout = true;
    } else if (string(argv[i])=="--output-ozn-to-stdout") {
      flag_output_ozn_stdout = true;
    } else if (string(argv[i])=="--stdlib-dir") {
      i++;
      if (i==argc)
        goto error;
      std_lib_dir = argv[i];
    } else if (beginswith(string(argv[i]),"-G")) {
      string filename(argv[i]);
      if (filename.length() > 2) {
        globals_dir = filename.substr(2);
      } else {
        i++;
        if (i==argc) {
          goto error;
        }
        globals_dir = argv[i];
      }
    } else if (string(argv[i])=="--globals-dir" ||
               string(argv[i])=="--mzn-globals-dir") {
      i++;
      if (i==argc)
        goto error;
      globals_dir = argv[i];
    } else if (string(argv[i])=="--only-range-domains") {
      fopts.onlyRangeDomains = true;
    } else {
      break;
    }
    i++;
    if (i==argc)
      goto error;
  }

  if (std_lib_dir=="") {
    std::cerr << "Error: unknown minizinc standard library directory.\n"
              << "Specify --stdlib-dir on the command line or set the\n"
              << "MZN_STDLIB_DIR environment variable.\n";
    std::exit(EXIT_FAILURE);
  }

  if (globals_dir!="") {
    includePaths.push_back(std_lib_dir+"/"+globals_dir+"/");
  }
  includePaths.push_back(std_lib_dir+"/std/");

  if (i==argc) {
    goto error;
  }
  filename = argv[i++];
  if (filename.length()<=4 ||
      filename.substr(filename.length()-4,string::npos) != ".mzn")
    goto error;

  if (flag_output_base == "") {
    flag_output_base = filename.substr(0,filename.length()-4);
  }
  if (flag_output_fzn == "") {
    flag_output_fzn = flag_output_base+".fzn";
  }
  if (flag_output_ozn == "") {
    flag_output_ozn = flag_output_base+".ozn";
  }

  while (i<argc) {
    std::string datafile = argv[i++];
    if (datafile.length()<=4 ||
        datafile.substr(datafile.length()-4,string::npos) != ".dzn")
      goto error;
    datafiles.push_back(datafile);
  }

  {
    std::stringstream errstream;
    if (flag_verbose)
      std::cerr << "Parsing '" << filename << "' ...";
    if (Model* m = parse(filename, datafiles, includePaths, flag_ignoreStdlib,
                         errstream)) {
      try {
        if (flag_typecheck) {
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          if (flag_verbose)
            std::cerr << "Typechecking ...";
          MiniZinc::typecheck(m);
          MiniZinc::registerBuiltins(m);
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;

          if (flag_verbose)
            std::cerr << "Flattening ...";
          Env env(m);
          try {
            flatten(env,fopts);
          } catch (LocationException& e) {
            if (flag_verbose)
              std::cerr << std::endl;
            std::cerr << e.what() << ": " << e.msg() << std::endl;
            std::cerr << e.loc() << std::endl;
            env.dumpErrorStack(std::cerr);
            exit(EXIT_FAILURE);
          }
          Model* flat = env.flat();
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;

          if (flag_optimize) {
            if (flag_verbose)
              std::cerr << "Optimizing ...";
            optimize(env);
            if (flag_verbose)
              std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          }

          if (!flag_newfzn) {
            if (flag_verbose)
              std::cerr << "Converting to old FlatZinc ...";
            oldflatzinc(env);
            if (flag_verbose)
              std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          }

          if (flag_verbose)
            std::cerr << "Printing FlatZinc ...";
          if (flag_output_fzn_stdout) {
            Printer p(std::cout,0);
            p.print(flat);
          } else {
            std::ofstream os;
            os.open(flag_output_fzn.c_str(), ios::out);
            Printer p(os,0);
            p.print(flat);
            os.close();
          }
          if (flag_verbose)
            std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          if (!flag_no_output_ozn) {
            if (flag_verbose)
              std::cerr << "Printing .ozn ...";
            if (flag_output_ozn_stdout) {
              Printer p(std::cout,0);
              p.print(env.output());
            } else {
              std::ofstream os;
              os.open(flag_output_ozn.c_str(), ios::out);
              Printer p(os,0);
              p.print(env.output());
              os.close();
            }
            if (flag_verbose)
              std::cerr << " done (" << stoptime(lasttime) << ")" << std::endl;
          }
        } else { // !flag_typecheck
          Printer p(std::cout);
          p.print(m);
        }
      } catch (LocationException& e) {
        if (flag_verbose)
          std::cerr << std::endl;
        std::cerr << e.what() << ": " << e.msg() << std::endl;
        std::cerr << e.loc() << std::endl;
        exit(EXIT_FAILURE);
      } catch (Exception& e) {
        if (flag_verbose)
          std::cerr << std::endl;
        std::cerr << e.what() << ": " << e.msg() << std::endl;
        exit(EXIT_FAILURE);
      }
      delete m;
    } else {
      if (flag_verbose)
        std::cerr << std::endl;
      std::copy(istreambuf_iterator<char>(errstream),istreambuf_iterator<char>(),ostreambuf_iterator<char>(std::cerr));
    }
  }

  if (flag_verbose)
    std::cerr << "Done (overall time " << stoptime(starttime) << ")." << std::endl;
  return 0;

error:
  std::cerr << "Usage: "<< argv[0]
            << " [<options>] [-I <include path>] <model>.mzn [<data>.dzn ...]" << std::endl
            << std::endl
            << "Options:" << std::endl
            << "  --help, -h\n    Print this help message" << std::endl
            << "  --version\n    Print version information" << std::endl
            << "  --ignore-stdlib\n    Ignore the standard libraries stdlib.mzn and builtins.mzn" << std::endl
            << "  --newfzn\n    Output in the new FlatZinc format" << std::endl
            << "  --verbose\n    Print progress statements" << std::endl
            << "  --no-typecheck\n    Do not typecheck (implies --no-eval)" << std::endl
            << "  --no-eval\n    Do not evaluate" << std::endl
            << "  --no-optimize\n    Do not optimize the FlatZinc (may speed up large instances)" << std::endl
            << "  --no-output-ozn, -O-\n    Do not output ozn file" << std::endl
            << "  --output-base <name>\n    Base name for output files" << std::endl
            << "  -o <file>, --output-to-file <file>, --output-fzn-to-file <file>\n    Filename for generated FlatZinc output" << std::endl
            << "  --output-ozn-to-file <file>\n    Filename for model output specification" << std::endl
            << "  --output-to-stdout, --output-fzn-to-stdout\n    Print generated FlatZinc to standard output" << std::endl
            << "  --output-ozn-to-stdout\n    Print model output specification to standard output" << std::endl
            << "  --stdlib-dir <dir>\n    Path to MiniZinc standard library directory" << std::endl
            << "  -G --globals-dir --mzn-globals-dir\n    Search for included files in <stdlib>/<dir>." << std::endl
  ;

  exit(EXIT_FAILURE);
}
<|endoftext|>


<commit_before>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program 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
 * any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

initialiseSingleton( TaxiMgr );

/************************
 *	   TaxiPath	   *
 ************************/

void TaxiPath::ComputeLen()
{
	m_length1 = m_length1 = 0;
	m_map1 = m_map2 = 0;
	float * curptr = &m_length1;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float x = itr->second->x;
	float y = itr->second->y;
	float z = itr->second->z;
	uint32 curmap = itr->second->mapid;
	m_map1 = curmap;

	itr++;

	while (itr != m_pathNodes.end())
	{
		if( itr->second->mapid != curmap )
		{
			curptr = &m_length2;
			m_map2 = itr->second->mapid;
			curmap = itr->second->mapid;
		}

		*curptr += sqrt((itr->second->x - x)*(itr->second->x - x) +
			(itr->second->y - y)*(itr->second->y - y) +
			(itr->second->z - z)*(itr->second->z - z));

		x = itr->second->x;
		y = itr->second->y;
		z = itr->second->z;
		itr++;
	}
}

void TaxiPath::SetPosForTime(float &x, float &y, float &z, uint32 time, uint32 *last_node, uint32 mapid)
{
	if (!time)
		return;

	float length;
	if( mapid == m_map1 )
		length = m_length1;
	else
		length = m_length2;

	float traveled_len = (time/(length * TAXI_TRAVEL_SPEED))*length;
	uint32 len = 0;

	x = 0;
	y = 0;
	z = 0;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float nx,ny,nz = 0.0f;
	bool set = false;
	uint32 nodecounter = 0;

	while (itr != m_pathNodes.end())
	{
		if( itr->second->mapid != mapid )
		{
			itr++;
			nodecounter++;
			continue;
		}

		if(!set)
		{
			nx = itr->second->x;
			ny = itr->second->y;
			nz = itr->second->z;
			set = true;
			continue;
		}

		len = (uint32)sqrt((itr->second->x - nx)*(itr->second->x - nx) +
			(itr->second->y - ny)*(itr->second->y - ny) +
			(itr->second->z - nz)*(itr->second->z - nz));

		if (len >= traveled_len)
		{
			x = (itr->second->x - nx)*(traveled_len/len) + nx;
			y = (itr->second->y - ny)*(traveled_len/len) + ny;
			z = (itr->second->z - nz)*(traveled_len/len) + nz;
			*last_node = nodecounter;
			return;
		}
		else
		{
			traveled_len -= len;
		}

		nx = itr->second->x;
		ny = itr->second->y;
		nz = itr->second->z;
		itr++;
		nodecounter++;
	}

	x = nx;
	y = ny;
	z = nz;
}

TaxiPathNode* TaxiPath::GetPathNode(uint32 i)
{
	if (m_pathNodes.find(i) == m_pathNodes.end())
		return NULL;
	else
		return m_pathNodes.find(i)->second;
}

void TaxiPath::SendMoveForTime(Player *riding, Player *to, uint32 time)
{
	if (!time)
		return;

	float length;
	uint32 mapid = riding->GetMapId();
	if( mapid == m_map1 )
		length = m_length1;
	else
		length = m_length2;

	float traveled_len = (time/(length * TAXI_TRAVEL_SPEED))*length;
	uint32 len = 0;
	float x = 0,y = 0,z = 0;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float nx,ny,nz = 0.0f;
	bool set = false;
	uint32 nodecounter = 1;

	while (itr != m_pathNodes.end())
	{
		if( itr->second->mapid != mapid )
		{
			itr++;
			nodecounter++;
			continue;
		}

		if(!set)
		{
			nx = itr->second->x;
			ny = itr->second->y;
			nz = itr->second->z;
			set = true;
			continue;
		}

		len = (uint32)sqrt((itr->second->x - nx)*(itr->second->x - nx) +
			(itr->second->y - ny)*(itr->second->y - ny) +
			(itr->second->z - nz)*(itr->second->z - nz));

		if (len >= traveled_len)
		{
			x = (itr->second->x - nx)*(traveled_len/len) + nx;
			y = (itr->second->y - ny)*(traveled_len/len) + ny;
			z = (itr->second->z - nz)*(traveled_len/len) + nz;
			break;
		}
		else
		{
			traveled_len -= len;
		}

		nx = itr->second->x;
		ny = itr->second->y;
		nz = itr->second->z;
		itr++;
	}

	if (itr == m_pathNodes.end())
		return;

	WorldPacket * data = new WorldPacket(SMSG_MONSTER_MOVE, 2000);
	size_t pos;

	*data << riding->GetNewGUID();
	*data << riding->GetPositionX( ) << riding->GetPositionY( ) << riding->GetPositionZ( );
	*data << getMSTime();
	*data << uint8( 0 );
	*data << uint32( 0x00000300 );
	*data << uint32( uint32((length * TAXI_TRAVEL_SPEED) - time));
	*data << uint32( nodecounter );
	pos = data->wpos();
	*data << nx << ny << nz;

	while (itr != m_pathNodes.end())
	{
		TaxiPathNode *pn = itr->second;
		if( pn->mapid != mapid )
			break;

		*data << pn->x << pn->y << pn->z;
		++itr;
		++nodecounter;
	}

	*(uint32*)&(data->contents()[pos]) = nodecounter;
	to->delayedPackets.add(data);
/*	if (!time)
		return;

	float traveled_len = (time/(getLength() * TAXI_TRAVEL_SPEED))*getLength();;
	uint32 len = 0, count = 0;
	float x = 0,y = 0,z = 0;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float nx = itr->second->x;
	float ny = itr->second->y;
	float nz = itr->second->z;
	itr++;

	while (itr != m_pathNodes.end())
	{
		len = (uint32)sqrt((itr->second->x - nx)*(itr->second->x - nx) +
			(itr->second->y - ny)*(itr->second->y - ny) +
			(itr->second->z - nz)*(itr->second->z - nz));

		if (len > traveled_len)
		{
			x = (itr->second->x - nx)*(traveled_len/len) + nx;
			y = (itr->second->y - ny)*(traveled_len/len) + ny;
			z = (itr->second->z - nz)*(traveled_len/len) + nz;
			break;
		}
		else
		{
			traveled_len -= len;
		}

		nx = itr->second->x;
		ny = itr->second->y;
		nz = itr->second->z;
		itr++;
		count++;
	}

	if (itr == m_pathNodes.end())
		return;

	WorldPacket * data = new WorldPacket(SMSG_MONSTER_MOVE, 2000);

	*data << riding->GetNewGUID();
	*data << riding->GetPositionX( ) << riding->GetPositionY( ) << riding->GetPositionZ( );
	*data << getMSTime();
	*data << uint8( 0 );
	*data << uint32( 0x00000300 );
	*data << uint32( uint32((getLength() * TAXI_TRAVEL_SPEED) - time));
	*data << uint32( GetNodeCount() - count );
	*data << nx << ny << nz;
	while (itr != m_pathNodes.end())
	{
		TaxiPathNode *pn = itr->second;
		*data << pn->x << pn->y << pn->z;
		itr++;
	}
	//to->GetSession()->SendPacket(&data);
	to->delayedPackets.add(data);*/
}

/***********************
 *	   TaxiMgr	   *
 ***********************/

void TaxiMgr::_LoadTaxiNodes()
{
	uint32 i;

	for(i = 0; i < dbcTaxiNode.GetNumRows(); i++)
	{
		DBCTaxiNode *node = dbcTaxiNode.LookupRow(i);
		if (node)
		{
			TaxiNode *n = new TaxiNode;
			n->id = node->id;
			n->mapid = node->mapid;
			n->alliance_mount = node->alliance_mount;
			n->horde_mount = node->horde_mount;
			n->x = node->x;
			n->y = node->y;
			n->z = node->z;

			this->m_taxiNodes.insert(std::map<uint32, TaxiNode*>::value_type(n->id, n));
		}
	}

	//todo: load mounts
}

void TaxiMgr::_LoadTaxiPaths()
{
	uint32 i, j;

	for(i = 0; i < dbcTaxiPath.GetNumRows(); i++)
	{
		DBCTaxiPath *path = dbcTaxiPath.LookupRow(i);

		if (path)
		{
			TaxiPath *p = new TaxiPath;
			p->from = path->from;
			p->to = path->to;
			p->id = path->id;
			p->price = path->price;

			//Load Nodes
			for(j = 0; j < dbcTaxiPathNode.GetNumRows(); j++)
			{
				DBCTaxiPathNode *pathnode = dbcTaxiPathNode.LookupRow(j);

				if (pathnode)
				{
					if (pathnode->path == p->id)
					{
						TaxiPathNode *pn = new TaxiPathNode;
						pn->x = pathnode->x;
						pn->y = pathnode->y;
						pn->z = pathnode->z;
						pn->mapid = pathnode->mapid;
						p->AddPathNode(pathnode->seq, pn);
					}
				}
			}

			p->ComputeLen();
			this->m_taxiPaths.insert(std::map<uint32, TaxiPath*>::value_type(p->id, p));
		}
	}
}

TaxiPath* TaxiMgr::GetTaxiPath(uint32 path)
{
	HM_NAMESPACE::hash_map<uint32, TaxiPath*>::iterator itr;

	itr = this->m_taxiPaths.find(path);

	if (itr == m_taxiPaths.end())
		return NULL;
	else
		return itr->second;
}

TaxiPath* TaxiMgr::GetTaxiPath(uint32 from, uint32 to)
{
	HM_NAMESPACE::hash_map<uint32, TaxiPath*>::iterator itr;

	for (itr = m_taxiPaths.begin(); itr != m_taxiPaths.end(); itr++)
		if ((itr->second->to == to) && (itr->second->from == from))
			return itr->second;

	return NULL;
}

TaxiNode* TaxiMgr::GetTaxiNode(uint32 node)
{
	HM_NAMESPACE::hash_map<uint32, TaxiNode*>::iterator itr;

	itr = this->m_taxiNodes.find(node);

	if (itr == m_taxiNodes.end())
		return NULL;
	else
		return itr->second;
}

uint32 TaxiMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid )
{
	uint32 nearest = 0;
	float distance = -1;
	float nx, ny, nz, nd;

	HM_NAMESPACE::hash_map<uint32, TaxiNode*>::iterator itr;

	for (itr = m_taxiNodes.begin(); itr != m_taxiNodes.end(); itr++)
	{
		if (itr->second->mapid == mapid)
		{
			nx = itr->second->x - x;
			ny = itr->second->y - y;
			nz = itr->second->z - z;
			nd = nx * nx + ny * ny + nz * nz;
			if( nd < distance || distance < 0 )
			{
				distance = nd;
				nearest = itr->second->id;
			}
		}
	}

	return nearest;
}

bool TaxiMgr::GetGlobalTaxiNodeMask( uint32 curloc, uint32 *Mask )
{
	HM_NAMESPACE::hash_map<uint32, TaxiPath*>::iterator itr;
	uint8 field;

	for (itr = m_taxiPaths.begin(); itr != m_taxiPaths.end(); itr++)
	{
		/*if( itr->second->from == curloc )
		{*/
			field = (uint8)((itr->second->to - 1) / 32);
			Mask[field] |= 1 << ( (itr->second->to - 1 ) % 32 );
		//}
	}

	return true;
}
<commit_msg>Fixes a client crash when clicking on a flight path Seem to only affect some servers http://arcemu.org/forums/index.php?showtopic=8885&st=0&p=41293&#<commit_after>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program 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
 * any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

initialiseSingleton( TaxiMgr );

/************************
 *	   TaxiPath	   *
 ************************/

void TaxiPath::ComputeLen()
{
	m_length1 = m_length1 = 0;
	m_map1 = m_map2 = 0;
	float * curptr = &m_length1;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float x = itr->second->x;
	float y = itr->second->y;
	float z = itr->second->z;
	uint32 curmap = itr->second->mapid;
	m_map1 = curmap;

	itr++;

	while (itr != m_pathNodes.end())
	{
		if( itr->second->mapid != curmap )
		{
			curptr = &m_length2;
			m_map2 = itr->second->mapid;
			curmap = itr->second->mapid;
		}

		*curptr += sqrt((itr->second->x - x)*(itr->second->x - x) +
			(itr->second->y - y)*(itr->second->y - y) +
			(itr->second->z - z)*(itr->second->z - z));

		x = itr->second->x;
		y = itr->second->y;
		z = itr->second->z;
		itr++;
	}
}

void TaxiPath::SetPosForTime(float &x, float &y, float &z, uint32 time, uint32 *last_node, uint32 mapid)
{
	if (!time)
		return;

	float length;
	if( mapid == m_map1 )
		length = m_length1;
	else
		length = m_length2;

	float traveled_len = (time/(length * TAXI_TRAVEL_SPEED))*length;
	uint32 len = 0;

	x = 0;
	y = 0;
	z = 0;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float nx,ny,nz = 0.0f;
	bool set = false;
	uint32 nodecounter = 0;

	while (itr != m_pathNodes.end())
	{
		if( itr->second->mapid != mapid )
		{
			itr++;
			nodecounter++;
			continue;
		}

		if(!set)
		{
			nx = itr->second->x;
			ny = itr->second->y;
			nz = itr->second->z;
			set = true;
			continue;
		}

		len = (uint32)sqrt((itr->second->x - nx)*(itr->second->x - nx) +
			(itr->second->y - ny)*(itr->second->y - ny) +
			(itr->second->z - nz)*(itr->second->z - nz));

		if (len >= traveled_len)
		{
			x = (itr->second->x - nx)*(traveled_len/len) + nx;
			y = (itr->second->y - ny)*(traveled_len/len) + ny;
			z = (itr->second->z - nz)*(traveled_len/len) + nz;
			*last_node = nodecounter;
			return;
		}
		else
		{
			traveled_len -= len;
		}

		nx = itr->second->x;
		ny = itr->second->y;
		nz = itr->second->z;
		itr++;
		nodecounter++;
	}

	x = nx;
	y = ny;
	z = nz;
}

TaxiPathNode* TaxiPath::GetPathNode(uint32 i)
{
	if (m_pathNodes.find(i) == m_pathNodes.end())
		return NULL;
	else
		return m_pathNodes.find(i)->second;
}

void TaxiPath::SendMoveForTime(Player *riding, Player *to, uint32 time)
{
	if (!time)
		return;

	float length;
	uint32 mapid = riding->GetMapId();
	if( mapid == m_map1 )
		length = m_length1;
	else
		length = m_length2;

	float traveled_len = (time/(length * TAXI_TRAVEL_SPEED))*length;
	uint32 len = 0;
	float x = 0,y = 0,z = 0;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float nx,ny,nz = 0.0f;
	bool set = false;
	uint32 nodecounter = 1;

	while (itr != m_pathNodes.end())
	{
		if( itr->second->mapid != mapid )
		{
			itr++;
			nodecounter++;
			continue;
		}

		if(!set)
		{
			nx = itr->second->x;
			ny = itr->second->y;
			nz = itr->second->z;
			set = true;
			continue;
		}

		len = (uint32)sqrt((itr->second->x - nx)*(itr->second->x - nx) +
			(itr->second->y - ny)*(itr->second->y - ny) +
			(itr->second->z - nz)*(itr->second->z - nz));

		if (len >= traveled_len)
		{
			x = (itr->second->x - nx)*(traveled_len/len) + nx;
			y = (itr->second->y - ny)*(traveled_len/len) + ny;
			z = (itr->second->z - nz)*(traveled_len/len) + nz;
			break;
		}
		else
		{
			traveled_len -= len;
		}

		nx = itr->second->x;
		ny = itr->second->y;
		nz = itr->second->z;
		itr++;
	}

	if (itr == m_pathNodes.end())
		return;

	WorldPacket * data = new WorldPacket(SMSG_MONSTER_MOVE, 2000);
	size_t pos;

	*data << riding->GetNewGUID();
	*data << riding->GetPositionX( ) << riding->GetPositionY( ) << riding->GetPositionZ( );
	*data << getMSTime();
	*data << uint8( 0 );
	*data << uint32( 0x00000300 );
	*data << uint32( uint32((length * TAXI_TRAVEL_SPEED) - time));
	*data << uint32( nodecounter );
	pos = data->wpos();
	*data << nx << ny << nz;

	while (itr != m_pathNodes.end())
	{
		TaxiPathNode *pn = itr->second;
		if( pn->mapid != mapid )
			break;

		*data << pn->x << pn->y << pn->z;
		++itr;
		++nodecounter;
	}

	*(uint32*)&(data->contents()[pos]) = nodecounter;
	to->delayedPackets.add(data);
/*	if (!time)
		return;

	float traveled_len = (time/(getLength() * TAXI_TRAVEL_SPEED))*getLength();;
	uint32 len = 0, count = 0;
	float x = 0,y = 0,z = 0;

	if (!m_pathNodes.size())
		return;

	std::map<uint32, TaxiPathNode*>::iterator itr;
	itr = m_pathNodes.begin();

	float nx = itr->second->x;
	float ny = itr->second->y;
	float nz = itr->second->z;
	itr++;

	while (itr != m_pathNodes.end())
	{
		len = (uint32)sqrt((itr->second->x - nx)*(itr->second->x - nx) +
			(itr->second->y - ny)*(itr->second->y - ny) +
			(itr->second->z - nz)*(itr->second->z - nz));

		if (len > traveled_len)
		{
			x = (itr->second->x - nx)*(traveled_len/len) + nx;
			y = (itr->second->y - ny)*(traveled_len/len) + ny;
			z = (itr->second->z - nz)*(traveled_len/len) + nz;
			break;
		}
		else
		{
			traveled_len -= len;
		}

		nx = itr->second->x;
		ny = itr->second->y;
		nz = itr->second->z;
		itr++;
		count++;
	}

	if (itr == m_pathNodes.end())
		return;

	WorldPacket * data = new WorldPacket(SMSG_MONSTER_MOVE, 2000);

	*data << riding->GetNewGUID();
	*data << riding->GetPositionX( ) << riding->GetPositionY( ) << riding->GetPositionZ( );
	*data << getMSTime();
	*data << uint8( 0 );
	*data << uint32( 0x00000300 );
	*data << uint32( uint32((getLength() * TAXI_TRAVEL_SPEED) - time));
	*data << uint32( GetNodeCount() - count );
	*data << nx << ny << nz;
	while (itr != m_pathNodes.end())
	{
		TaxiPathNode *pn = itr->second;
		*data << pn->x << pn->y << pn->z;
		itr++;
	}
	//to->GetSession()->SendPacket(&data);
	to->delayedPackets.add(data);*/
}

/***********************
 *	   TaxiMgr	   *
 ***********************/

void TaxiMgr::_LoadTaxiNodes()
{
	uint32 i;

	for(i = 0; i < dbcTaxiNode.GetNumRows(); i++)
	{
		DBCTaxiNode *node = dbcTaxiNode.LookupRow(i);
		if (node)
		{
			TaxiNode *n = new TaxiNode;
			n->id = node->id;
			n->mapid = node->mapid;
			n->alliance_mount = node->alliance_mount;
			n->horde_mount = node->horde_mount;
			n->x = node->x;
			n->y = node->y;
			n->z = node->z;

			this->m_taxiNodes.insert(std::map<uint32, TaxiNode*>::value_type(n->id, n));
		}
	}

	//todo: load mounts
}

void TaxiMgr::_LoadTaxiPaths()
{
	uint32 i, j;

	for(i = 0; i < dbcTaxiPath.GetNumRows(); i++)
	{
		DBCTaxiPath *path = dbcTaxiPath.LookupRow(i);

		if (path)
		{
			TaxiPath *p = new TaxiPath;
			p->from = path->from;
			p->to = path->to;
			p->id = path->id;
			p->price = path->price;

			//Load Nodes
			for(j = 0; j < dbcTaxiPathNode.GetNumRows(); j++)
			{
				DBCTaxiPathNode *pathnode = dbcTaxiPathNode.LookupRow(j);

				if (pathnode)
				{
					if (pathnode->path == p->id)
					{
						TaxiPathNode *pn = new TaxiPathNode;
						pn->x = pathnode->x;
						pn->y = pathnode->y;
						pn->z = pathnode->z;
						pn->mapid = pathnode->mapid;
						p->AddPathNode(pathnode->seq, pn);
					}
				}
			}

			p->ComputeLen();
			this->m_taxiPaths.insert(std::map<uint32, TaxiPath*>::value_type(p->id, p));
		}
	}
}

TaxiPath* TaxiMgr::GetTaxiPath(uint32 path)
{
	HM_NAMESPACE::hash_map<uint32, TaxiPath*>::iterator itr;

	itr = this->m_taxiPaths.find(path);

	if (itr == m_taxiPaths.end())
		return NULL;
	else
		return itr->second;
}

TaxiPath* TaxiMgr::GetTaxiPath(uint32 from, uint32 to)
{
	HM_NAMESPACE::hash_map<uint32, TaxiPath*>::iterator itr;

	for (itr = m_taxiPaths.begin(); itr != m_taxiPaths.end(); itr++)
		if ((itr->second->to == to) && (itr->second->from == from))
			return itr->second;

	return NULL;
}

TaxiNode* TaxiMgr::GetTaxiNode(uint32 node)
{
	HM_NAMESPACE::hash_map<uint32, TaxiNode*>::iterator itr;

	itr = this->m_taxiNodes.find(node);

	if (itr == m_taxiNodes.end())
		return NULL;
	else
		return itr->second;
}

uint32 TaxiMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid )
{
	uint32 nearest = 0;
	float distance = -1;
	float nx, ny, nz, nd;

	HM_NAMESPACE::hash_map<uint32, TaxiNode*>::iterator itr;

	for (itr = m_taxiNodes.begin(); itr != m_taxiNodes.end(); itr++)
	{
		if (itr->second->mapid == mapid)
		{
			nx = itr->second->x - x;
			ny = itr->second->y - y;
			nz = itr->second->z - z;
			nd = nx * nx + ny * ny + nz * nz;
			if( nd < distance || distance < 0 )
			{
				distance = nd;
				nearest = itr->second->id;
			}
		}
	}

	return nearest;
}

bool TaxiMgr::GetGlobalTaxiNodeMask( uint32 curloc, uint32 *Mask )
{
	HM_NAMESPACE::hash_map<uint32, TaxiPath*>::iterator itr;
	uint8 field;

	for (itr = m_taxiPaths.begin(); itr != m_taxiPaths.end(); itr++)
	{
		if( itr->second->from == curloc )
		{
			field = (uint8)((itr->second->to - 1) / 32);
			Mask[field] |= 1 << ( (itr->second->to - 1 ) % 32 );
		}
	}

	return true;
}
<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/Context.h"
#include "cinder/gl/Texture.h"
#include "cinder/Xml.h"
#include "cinder/Timeline.h"
#include "cinder/ImageIo.h"
#include "cinder/Thread.h"
#include "cinder/ConcurrentCircularBuffer.h"

/*	The heart of this sample is to show how to create a background thread that interacts with OpenGL.
	It launches a secondary thread which pulls down images from a Flickr group and puts them in a thread-safe buffer.
	We can allocate a gl::Context which shares resources (specifically Textures) with the primary gl::Context.
	Note that this Context should be created in the primary thread and passed as a parameter to the secondary thread.
*/

using namespace ci;
using namespace ci::app;
using namespace std;

class FlickrTestMTApp : public App {
  public:
	void setup();
	void update();
	void draw();
	void shutdown();
	void loadImagesThreadFn( gl::ContextRef sharedGlContext );

	ConcurrentCircularBuffer<gl::TextureRef>	*mImages;

	bool					mShouldQuit;
	shared_ptr<thread>		mThread;
	gl::TextureRef			mTexture, mLastTexture;
	Anim<float>				mFade;
	double					mLastTime;
};

void FlickrTestMTApp::setup()
{
	mShouldQuit = false;
	mImages = new ConcurrentCircularBuffer<gl::TextureRef>( 5 ); // room for 5 images
	// create and launch the thread with a new gl::Context just for that thread
	gl::ContextRef backgroundCtx = gl::Context::create( gl::context() );
	mThread = shared_ptr<thread>( new thread( bind( &FlickrTestMTApp::loadImagesThreadFn, this, backgroundCtx ) ) );
	mLastTime = getElapsedSeconds() - 10; // force an initial update by make it "ten seconds ago"

	gl::enableAlphaBlending();
}

void FlickrTestMTApp::loadImagesThreadFn( gl::ContextRef context )
{
	ci::ThreadSetup threadSetup; // instantiate this if you're talking to Cinder from a secondary thread
	// we received as a parameter a gl::Context we can use safely that shares resources with the primary Context
	context->makeCurrent();
	vector<Url>	urls;

	// parse the image URLS from the XML feed and push them into 'urls'
	const Url sunFlickrGroup = Url( "http://api.flickr.com/services/feeds/groups_pool.gne?id=52242317293@N01&format=rss_200" );
	const XmlTree xml( loadUrl( sunFlickrGroup ) );
	for( auto item = xml.begin( "rss/channel/item" ); item != xml.end(); ++item ) {
		const XmlTree &urlXml = ( ( *item / "media:content" ) );
		urls.push_back( Url( urlXml["url"] ) );
	}

	// load images as Textures into our ConcurrentCircularBuffer
	// don't create gl::Textures on a background thread
	while( ( ! mShouldQuit ) && ( ! urls.empty() ) ) {
		try {
			mImages->pushFront( gl::Texture::create( loadImage( loadUrl( urls.back() ) ) ) );
			urls.pop_back();
		}
		catch( ci::Exception &exc ) {
			console() << "failed to create texture, what: " << exc.what() << std::endl;
		}
	}
}

void FlickrTestMTApp::update()
{
	double timeSinceLastImage = getElapsedSeconds() - mLastTime;
	if( ( timeSinceLastImage > 2.5 ) && mImages->isNotEmpty() ) {
		mLastTexture = mTexture; // the "last" texture is now the current text

		mImages->popBack( &mTexture );

		mLastTime = getElapsedSeconds();
		// blend from 0 to 1 over 1.5sec
		timeline().apply( &mFade, 0.0f, 1.0f, 1.5f );
	}
}

void FlickrTestMTApp::draw()
{
	gl::clear( Color( 0.1f, 0.1f, 0.2f ) );

	if( mLastTexture ) {
		gl::color( 1, 1, 1, 1.0f - mFade );
		Rectf textureBounds = mLastTexture->getBounds();
		Rectf drawBounds = textureBounds.getCenteredFit( getWindowBounds(), true );
		gl::draw( mLastTexture, drawBounds );
	}
	if( mTexture ) {
		gl::color( 1, 1, 1, mFade );
		Rectf textureBounds = mTexture->getBounds();
		Rectf drawBounds = textureBounds.getCenteredFit( getWindowBounds(), true );
		gl::draw( mTexture, drawBounds );
	}
}

void FlickrTestMTApp::shutdown()
{
	mShouldQuit = true;
	mImages->cancel();
	mThread->join();
}

CINDER_APP( FlickrTestMTApp, RendererGl )<commit_msg>Updates to MTFlickr sample for app_refactor<commit_after>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/Context.h"
#include "cinder/gl/Texture.h"
#include "cinder/gl/Sync.h"
#include "cinder/Xml.h"
#include "cinder/Timeline.h"
#include "cinder/ImageIo.h"
#include "cinder/Thread.h"
#include "cinder/ConcurrentCircularBuffer.h"

/*	The heart of this sample is to show how to create a background thread that interacts with OpenGL.
	It launches a secondary thread which pulls down images from a Flickr group and puts them in a thread-safe buffer.
	We can allocate a gl::Context which shares resources (specifically Textures) with the primary gl::Context.
	Note that this Context should be created in the primary thread and passed as a parameter to the secondary thread.
*/

using namespace ci;
using namespace ci::app;
using namespace std;

class FlickrTestMTApp : public App {
  public:
	~FlickrTestMTApp();

	void setup() override;
	void update() override;
	void draw() override;
	void loadImagesThreadFn( gl::ContextRef sharedGlContext );

	ConcurrentCircularBuffer<gl::TextureRef>	*mImages;

	bool					mShouldQuit;
	shared_ptr<thread>		mThread;
	gl::TextureRef			mTexture, mLastTexture;
	Anim<float>				mFade;
	double					mLastTime;
};

void FlickrTestMTApp::setup()
{
	mShouldQuit = false;
	mImages = new ConcurrentCircularBuffer<gl::TextureRef>( 5 ); // room for 5 images
	// create and launch the thread with a new gl::Context just for that thread
	gl::ContextRef backgroundCtx = gl::Context::create( gl::context() );
	mThread = shared_ptr<thread>( new thread( bind( &FlickrTestMTApp::loadImagesThreadFn, this, backgroundCtx ) ) );
	mLastTime = getElapsedSeconds() - 10; // force an initial update by make it "ten seconds ago"

	gl::enableAlphaBlending();
}

void FlickrTestMTApp::loadImagesThreadFn( gl::ContextRef context )
{
	ci::ThreadSetup threadSetup; // instantiate this if you're talking to Cinder from a secondary thread
	// we received as a parameter a gl::Context we can use safely that shares resources with the primary Context
	context->makeCurrent();
	vector<Url>	urls;

	// parse the image URLS from the XML feed and push them into 'urls'
	const Url sunFlickrGroup = Url( "http://api.flickr.com/services/feeds/groups_pool.gne?id=52242317293@N01&format=rss_200" );
	const XmlTree xml( loadUrl( sunFlickrGroup ) );
	for( auto item = xml.begin( "rss/channel/item" ); item != xml.end(); ++item ) {
		const XmlTree &urlXml = ( ( *item / "media:content" ) );
		urls.push_back( Url( urlXml["url"] ) );
	}

	// load images as Textures into our ConcurrentCircularBuffer
	while( ( ! mShouldQuit ) && ( ! urls.empty() ) ) {
		try {
			// we need to wait on a fence before alerting the primary thread that the Texture is ready
			auto fence = gl::Sync::create();
			auto tex = gl::Texture::create( loadImage( loadUrl( urls.back() ) ) );
			// wait on the fence
			fence->clientWaitSync();
			mImages->pushFront( tex );
			urls.pop_back();
		}
		catch( ci::Exception &exc ) {
			console() << "failed to create texture, what: " << exc.what() << std::endl;
		}
	}
}

void FlickrTestMTApp::update()
{
	double timeSinceLastImage = getElapsedSeconds() - mLastTime;
	if( ( timeSinceLastImage > 2.5 ) && mImages->isNotEmpty() ) {
		mLastTexture = mTexture; // the "last" texture is now the current text

		mImages->popBack( &mTexture );

		mLastTime = getElapsedSeconds();
		// blend from 0 to 1 over 1.5sec
		timeline().apply( &mFade, 0.0f, 1.0f, 1.5f );
	}
}

void FlickrTestMTApp::draw()
{
	gl::clear( Color( 0.1f, 0.1f, 0.2f ) );

	if( mLastTexture ) {
		gl::color( 1, 1, 1, 1.0f - mFade );
		Rectf textureBounds = mLastTexture->getBounds();
		Rectf drawBounds = textureBounds.getCenteredFit( getWindowBounds(), true );
		gl::draw( mLastTexture, drawBounds );
	}
	if( mTexture ) {
		gl::color( 1, 1, 1, mFade );
		Rectf textureBounds = mTexture->getBounds();
		Rectf drawBounds = textureBounds.getCenteredFit( getWindowBounds(), true );
		gl::draw( mTexture, drawBounds );
	}
}

FlickrTestMTApp::~FlickrTestMTApp()
{
	mShouldQuit = true;
	mImages->cancel();
	mThread->join();
}

CINDER_APP( FlickrTestMTApp, RendererGl )<|endoftext|>


<commit_before>/*
 * CLDevice.cpp
 *
 *  Created on: Oct 24, 2009
 *      Author: rasmussn
 */

#include "CLDevice.hpp"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#ifdef PV_USE_OPENCL

namespace PV {

static char * load_program_source(const char *filename);

CLDevice::CLDevice(int device)
{
   this->device = device;
   initialize(device);
}

CLDevice::~CLDevice()
{
}

int CLDevice::initialize(int device)
{
   int status = 0;

   // get number of devices available
   //
   status = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_ALL, MAX_DEVICES, device_ids, &num_devices);
   if (status != CL_SUCCESS) {
      printf("Error: Failed to find a device group!\n");
      print_error_code(status);
      exit(status);
   }

   // create a compute context
   //
   context = clCreateContext(0, 1, &device_ids[device], NULL, NULL, &status);
   if (!context)
   {
       printf("Error: Failed to create a compute context for device %d!\n", device);
       exit(PVCL_CREATE_CONTEXT_FAILURE);
   }

   // create a command queue
   //
   commands = clCreateCommandQueue(context, device_ids[device], 0, &status);
   if (!commands)
   {
       printf("Error: Failed to create a command commands!\n");
       return PVCL_CREATE_CMD_QUEUE_FAILURE;
   }

   // turn on profiling
   //
   elapsed = 0;
   profiling = true;
   status = clSetCommandQueueProperty(commands, CL_QUEUE_PROFILING_ENABLE, CL_TRUE, NULL);
   if (status != CL_SUCCESS) {
      print_error_code(status);
      exit(status);
   }

   return status;
}

int CLDevice::run(size_t global_work_size)
{
   size_t local_work_size;
   int status = 0;

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device_ids[device], CL_KERNEL_WORK_GROUP_SIZE,
						             sizeof(size_t), &local_work_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! %d\n", status);
      print_error_code(status);
      exit(status);
   } else {
      printf("run: local_work_size==%ld global_work_size==%ld\n", local_work_size, global_work_size);
   }
   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 1, NULL,
								   &global_work_size, &local_work_size, 0, NULL, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel!\n");
      print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

   return status;
}

int CLDevice::run(size_t gWorkSizeX, size_t gWorkSizeY, size_t lWorkSizeX, size_t lWorkSizeY)
{
   size_t local_work_size[2];
   size_t global_work_size[2];
   size_t max_local_size;
   int status = 0;

   global_work_size[0] = gWorkSizeX;
   global_work_size[1] = gWorkSizeY;

   local_work_size[0] = lWorkSizeX;
   local_work_size[1] = lWorkSizeY;

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device_ids[device], CL_KERNEL_WORK_GROUP_SIZE,
								     sizeof(size_t), &max_local_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! (status==%d)\n", status);
      print_error_code(status);
      exit(status);
   } else {
      printf("run: local_work_size==(%ld,%ld) global_work_size==(%ld,%ld)\n",
             local_work_size[0], local_work_size[1], global_work_size[0], global_work_size[1]);
   }

   if (device == 1) {
      // Apple's CPU device has only one thread per group
	  local_work_size[0] = 1;
      local_work_size[1] = 1;
   }

   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 2, NULL,
                                   global_work_size, local_work_size, 0, NULL, &event);
   if (status) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel! (status==%d)\n", status);
      fprintf(stderr, "CLDevice::run(): max_local_work_size==%ld\n", max_local_size);
      print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

   // get profiling information
   //
   if (profiling) {
      size_t param_size;
      cl_ulong start, end;
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START,
                                       sizeof(start), &start, &param_size);
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END,
                                       sizeof(end), &end, &param_size);
      if (status == 0) {
         elapsed = (end - start) / 1000;  // microseconds
      }
   }

   return status;
}

int CLDevice::createKernel(const char * filename, const char * name)
{
   int status = 0;

   // Create the compute program from the source buffer
   //
   char * source = load_program_source(filename);
   program = clCreateProgramWithSource(context, 1, (const char **) &source, NULL, &status);
   if (!program || status != CL_SUCCESS)
   {
       printf("Error: Failed to create compute program!\n");
       print_error_code(status);
       exit(status);
   }

   // Build the program executable
   //
   status = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
   if (status != CL_SUCCESS)
   {
       size_t len;
       char buffer[2048];

       printf("Error: Failed to build program executable!\n");
       clGetProgramBuildInfo(program, device_ids[device], CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
       printf("%s\n", buffer);
       print_error_code(status);
       exit(status);
   }

   // Create the compute kernel in the program we wish to run
   //
   kernel = clCreateKernel(program, name, &status);
   if (!kernel || status != CL_SUCCESS)
   {
       fprintf(stderr, "Error: Failed to create compute kernel!\n");
       print_error_code(status);
       exit(status);
   }

   return status;
}

CLBuffer * CLDevice::createBuffer(cl_mem_flags flags, size_t size, void * host_ptr)
{
   return new CLBuffer(context, commands, flags, size, host_ptr);
}

int CLDevice::addKernelArg(int argid, int arg)
{
   int status = 0;

   status = clSetKernelArg(kernel, argid, sizeof(int), &arg);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      print_error_code(status);
      exit(status);
   }

   return status;
}

int CLDevice::addKernelArg(int argid, CLBuffer * buf)
{
   int status = 0;

   cl_mem mobj = buf->clMemObject();

   status = clSetKernelArg(kernel, argid, sizeof(cl_mem), &mobj);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      print_error_code(status);
      exit(status);
   }

   return status;
}

int CLDevice::addLocalArg(int argid, size_t size)
{
   int status = 0;

   status = clSetKernelArg(kernel, argid, size, 0);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addLocalArg: Failed to set kernel argument! %d\n", status);
      print_error_code(status);
      exit(status);
   }

   return status;
}

int CLDevice::query_device_info()
{
   // query and print information about the devices found
   //
   printf("\n");
   printf("Number of OpenCL devices found: %d\n", num_devices);
   printf("\n");

   for (unsigned int i = 0; i < num_devices; i++) {
      query_device_info(i, device_ids[i]);
   }
   return 0;
}

int CLDevice::query_device_info(int id, cl_device_id device)
{
   const int str_size = 64;
   const int vals_len = MAX_WORK_ITEM_DIMENSIONS;

   long long val;
   size_t vals[vals_len];
   unsigned int max_dims;

   int    status;
   char   param_value[str_size];
   size_t param_value_size;

   status = clGetDeviceInfo(device, CL_DEVICE_NAME, str_size, param_value, &param_value_size);
   param_value[str_size-1] = '\0';

   printf("OpenCL Device # %d == %s\n", id, param_value);

   status = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(val), &val, NULL);

   if (status == CL_SUCCESS) {
      printf("\tdevice[%p]: Type: ", device);

      if (val & CL_DEVICE_TYPE_DEFAULT) {
         val &= ~CL_DEVICE_TYPE_DEFAULT;
         printf("Default ");
      }

      if (val & CL_DEVICE_TYPE_CPU) {
         val &= ~CL_DEVICE_TYPE_CPU;
         printf("CPU ");
      }

      if (val & CL_DEVICE_TYPE_GPU) {
         val &= ~CL_DEVICE_TYPE_GPU;
         printf("GPU ");
      }

      if (val & CL_DEVICE_TYPE_ACCELERATOR) {
         val &= ~CL_DEVICE_TYPE_ACCELERATOR;
         printf("Accelerator ");
      }

      if (val != 0) {
         printf("Unknown (0x%llx) ", val);
      }
   }
   else {
      printf("\tdevice[%p]: Unable to get TYPE: %s!\n", device, "CLErrString(status)");
      print_error_code(status);
      exit(status);
   }

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(val), &val, &param_value_size);
   printf("with %u units/cores", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(val), &val, &param_value_size);
   printf(" at %u MHz\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(val), &val, &param_value_size);
   printf("\tfloat vector width == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tMaximum work group size == %lu\n", (size_t) val);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(max_dims), &max_dims, &param_value_size);
   printf("\tMaximum work item dimensions == %u\n", max_dims);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, vals_len*sizeof(size_t), vals, &param_value_size);
   printf("\tMaximum work item sizes == (");
   for (int i = 0; i < max_dims; i++) printf(" %ld", vals[i]);
   printf(" )\n");

   status = clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tLocal mem size == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tGlobal mem size == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tGlobal mem cache size == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tGlobal mem cache line size == %u\n", (unsigned int) val);

   printf("\n");

   return status;
}

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

void
print_error_code(int code)
{
   char msg[256];

   switch (code) {
      case CL_INVALID_WORK_GROUP_SIZE:
         sprintf(msg, "%s (%d)", "CL_INVALID_WORK_GROUP_SIZE", code);
         break;
      case CL_INVALID_COMMAND_QUEUE:
         sprintf(msg, "%s (%d)", "CL_INVALID_COMMAND_QUEUE", code);
         break;
      case CL_INVALID_KERNEL_ARGS:
         sprintf(msg, "%s (%d)", "CL_INVALID_KERNEL_ARGS", code);
         break;

      default:
         sprintf(msg, "%s (%d)\n", "UNKNOWN_CODE", code);
         break;
   }
   printf("ERROR_CODE==%s\n", msg);
}

static char *
load_program_source(const char *filename)
{
    struct stat statbuf;
    FILE        *fh;
    char        *source;

    fh = fopen(filename, "r");
    if (fh == 0)
        return 0;

    stat(filename, &statbuf);
    source = (char *) malloc(statbuf.st_size + 1);
    fread(source, statbuf.st_size, 1, fh);
    source[statbuf.st_size] = '\0';

    return source;
}

} // namespace PV

#else
void cldevice_noop() { ; }
#endif // PV_USE_OPENCL
<commit_msg>Reworked #ifdefs to provide a little more null functionality with not using OpenCL.<commit_after>/*
 * CLDevice.cpp
 *
 *  Created on: Oct 24, 2009
 *      Author: rasmussn
 */

#include "CLDevice.hpp"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

namespace PV {

CLDevice::CLDevice(int device)
{
   this->device = device;
   initialize(device);
}

int CLDevice::initialize(int device)
{
   int status = 0;

#ifdef PV_USE_OPENCL
   // get number of devices available
   //
   status = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_ALL, MAX_DEVICES, device_ids, &num_devices);
   if (status != CL_SUCCESS) {
      printf("Error: Failed to find a device group!\n");
      print_error_code(status);
      exit(status);
   }

   // create a compute context
   //
   context = clCreateContext(0, 1, &device_ids[device], NULL, NULL, &status);
   if (!context)
   {
       printf("Error: Failed to create a compute context for device %d!\n", device);
       exit(PVCL_CREATE_CONTEXT_FAILURE);
   }

   // create a command queue
   //
   commands = clCreateCommandQueue(context, device_ids[device], 0, &status);
   if (!commands)
   {
       printf("Error: Failed to create a command commands!\n");
       return PVCL_CREATE_CMD_QUEUE_FAILURE;
   }

   // turn on profiling
   //
   elapsed = 0;
   profiling = true;
   status = clSetCommandQueueProperty(commands, CL_QUEUE_PROFILING_ENABLE, CL_TRUE, NULL);
   if (status != CL_SUCCESS) {
      print_error_code(status);
      exit(status);
   }
#endif PV_USE_OPENCL

   return status;
}

#ifdef PV_USE_OPENCL

static char * load_program_source(const char *filename);

int CLDevice::run(size_t global_work_size)
{
   size_t local_work_size;
   int status = 0;

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device_ids[device], CL_KERNEL_WORK_GROUP_SIZE,
						             sizeof(size_t), &local_work_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! %d\n", status);
      print_error_code(status);
      exit(status);
   } else {
      printf("run: local_work_size==%ld global_work_size==%ld\n", local_work_size, global_work_size);
   }
   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 1, NULL,
								   &global_work_size, &local_work_size, 0, NULL, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel!\n");
      print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

   return status;
}

int CLDevice::run(size_t gWorkSizeX, size_t gWorkSizeY, size_t lWorkSizeX, size_t lWorkSizeY)
{
   size_t local_work_size[2];
   size_t global_work_size[2];
   size_t max_local_size;
   int status = 0;

   global_work_size[0] = gWorkSizeX;
   global_work_size[1] = gWorkSizeY;

   local_work_size[0] = lWorkSizeX;
   local_work_size[1] = lWorkSizeY;

   // get the maximum work group size for executing the kernel on the device
   //
   status = clGetKernelWorkGroupInfo(kernel, device_ids[device], CL_KERNEL_WORK_GROUP_SIZE,
								     sizeof(size_t), &max_local_size, NULL);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "Error: Failed to retrieve kernel work group info! (status==%d)\n", status);
      print_error_code(status);
      exit(status);
   } else {
      printf("run: local_work_size==(%ld,%ld) global_work_size==(%ld,%ld)\n",
             local_work_size[0], local_work_size[1], global_work_size[0], global_work_size[1]);
   }

   if (device == 1) {
      // Apple's CPU device has only one thread per group
	  local_work_size[0] = 1;
      local_work_size[1] = 1;
   }

   // execute the kernel over the entire range of our 1d input data set
   // using the maximum number of work group items for this device
   //
   status = clEnqueueNDRangeKernel(commands, kernel, 2, NULL,
                                   global_work_size, local_work_size, 0, NULL, &event);
   if (status) {
      fprintf(stderr, "CLDevice::run(): Failed to execute kernel! (status==%d)\n", status);
      fprintf(stderr, "CLDevice::run(): max_local_work_size==%ld\n", max_local_size);
      print_error_code(status);
      exit(status);
   }

   // wait for the command commands to get serviced before reading back results
   //
   clFinish(commands);

   // get profiling information
   //
   if (profiling) {
      size_t param_size;
      cl_ulong start, end;
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START,
                                       sizeof(start), &start, &param_size);
      status = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END,
                                       sizeof(end), &end, &param_size);
      if (status == 0) {
         elapsed = (end - start) / 1000;  // microseconds
      }
   }

   return status;
}

int CLDevice::createKernel(const char * filename, const char * name)
{
   int status = 0;

   // Create the compute program from the source buffer
   //
   char * source = load_program_source(filename);
   program = clCreateProgramWithSource(context, 1, (const char **) &source, NULL, &status);
   if (!program || status != CL_SUCCESS)
   {
       printf("Error: Failed to create compute program!\n");
       print_error_code(status);
       exit(status);
   }

   // Build the program executable
   //
   status = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
   if (status != CL_SUCCESS)
   {
       size_t len;
       char buffer[2048];

       printf("Error: Failed to build program executable!\n");
       clGetProgramBuildInfo(program, device_ids[device], CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
       printf("%s\n", buffer);
       print_error_code(status);
       exit(status);
   }

   // Create the compute kernel in the program we wish to run
   //
   kernel = clCreateKernel(program, name, &status);
   if (!kernel || status != CL_SUCCESS)
   {
       fprintf(stderr, "Error: Failed to create compute kernel!\n");
       print_error_code(status);
       exit(status);
   }

   return status;
}
#endif // PV_USE_OPENCL

CLBuffer * CLDevice::createBuffer(cl_mem_flags flags, size_t size, void * host_ptr)
{
#ifdef PV_USE_OPENCL
   return new CLBuffer(context, commands, flags, size, host_ptr);
#else
   return new CLBuffer();
#endif
}

#ifdef PV_USE_OPENCL

int CLDevice::addKernelArg(int argid, int arg)
{
   int status = 0;

   status = clSetKernelArg(kernel, argid, sizeof(int), &arg);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      print_error_code(status);
      exit(status);
   }

   return status;
}

int CLDevice::addKernelArg(int argid, CLBuffer * buf)
{
   int status = 0;

   cl_mem mobj = buf->clMemObject();

   status = clSetKernelArg(kernel, argid, sizeof(cl_mem), &mobj);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addKernelArg: Failed to set kernel argument! %d\n", status);
      print_error_code(status);
      exit(status);
   }

   return status;
}

int CLDevice::addLocalArg(int argid, size_t size)
{
   int status = 0;

   status = clSetKernelArg(kernel, argid, size, 0);
   if (status != CL_SUCCESS) {
      fprintf(stderr, "CLDevice::addLocalArg: Failed to set kernel argument! %d\n", status);
      print_error_code(status);
      exit(status);
   }

   return status;
}

int CLDevice::query_device_info()
{
   // query and print information about the devices found
   //
   printf("\n");
   printf("Number of OpenCL devices found: %d\n", num_devices);
   printf("\n");

   for (unsigned int i = 0; i < num_devices; i++) {
      query_device_info(i, device_ids[i]);
   }
   return 0;
}

int CLDevice::query_device_info(int id, cl_device_id device)
{
   const int str_size = 64;
   const int vals_len = MAX_WORK_ITEM_DIMENSIONS;

   long long val;
   size_t vals[vals_len];
   unsigned int max_dims;

   int    status;
   char   param_value[str_size];
   size_t param_value_size;

   status = clGetDeviceInfo(device, CL_DEVICE_NAME, str_size, param_value, &param_value_size);
   param_value[str_size-1] = '\0';

   printf("OpenCL Device # %d == %s\n", id, param_value);

   status = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(val), &val, NULL);

   if (status == CL_SUCCESS) {
      printf("\tdevice[%p]: Type: ", device);

      if (val & CL_DEVICE_TYPE_DEFAULT) {
         val &= ~CL_DEVICE_TYPE_DEFAULT;
         printf("Default ");
      }

      if (val & CL_DEVICE_TYPE_CPU) {
         val &= ~CL_DEVICE_TYPE_CPU;
         printf("CPU ");
      }

      if (val & CL_DEVICE_TYPE_GPU) {
         val &= ~CL_DEVICE_TYPE_GPU;
         printf("GPU ");
      }

      if (val & CL_DEVICE_TYPE_ACCELERATOR) {
         val &= ~CL_DEVICE_TYPE_ACCELERATOR;
         printf("Accelerator ");
      }

      if (val != 0) {
         printf("Unknown (0x%llx) ", val);
      }
   }
   else {
      printf("\tdevice[%p]: Unable to get TYPE: %s!\n", device, "CLErrString(status)");
      print_error_code(status);
      exit(status);
   }

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(val), &val, &param_value_size);
   printf("with %u units/cores", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(val), &val, &param_value_size);
   printf(" at %u MHz\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(val), &val, &param_value_size);
   printf("\tfloat vector width == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tMaximum work group size == %lu\n", (size_t) val);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(max_dims), &max_dims, &param_value_size);
   printf("\tMaximum work item dimensions == %u\n", max_dims);

   status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, vals_len*sizeof(size_t), vals, &param_value_size);
   printf("\tMaximum work item sizes == (");
   for (int i = 0; i < max_dims; i++) printf(" %ld", vals[i]);
   printf(" )\n");

   status = clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tLocal mem size == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tGlobal mem size == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tGlobal mem cache size == %u\n", (unsigned int) val);

   status = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, sizeof(val), &val, &param_value_size);
   printf("\tGlobal mem cache line size == %u\n", (unsigned int) val);

   printf("\n");

   return status;
}

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

void
print_error_code(int code)
{
   char msg[256];

   switch (code) {
      case CL_INVALID_WORK_GROUP_SIZE:
         sprintf(msg, "%s (%d)", "CL_INVALID_WORK_GROUP_SIZE", code);
         break;
      case CL_INVALID_COMMAND_QUEUE:
         sprintf(msg, "%s (%d)", "CL_INVALID_COMMAND_QUEUE", code);
         break;
      case CL_INVALID_KERNEL_ARGS:
         sprintf(msg, "%s (%d)", "CL_INVALID_KERNEL_ARGS", code);
         break;

      default:
         sprintf(msg, "%s (%d)\n", "UNKNOWN_CODE", code);
         break;
   }
   printf("ERROR_CODE==%s\n", msg);
}

static char *
load_program_source(const char *filename)
{
    struct stat statbuf;
    FILE        *fh;
    char        *source;

    fh = fopen(filename, "r");
    if (fh == 0)
        return 0;

    stat(filename, &statbuf);
    source = (char *) malloc(statbuf.st_size + 1);
    fread(source, statbuf.st_size, 1, fh);
    source[statbuf.st_size] = '\0';

    return source;
}

#endif // PV_USE_OPENCL

} // namespace PV

<|endoftext|>