<commit_before>// RUN: %clangxx -frtti -fsanitize=undefined -g %s -O3 -o %t
// RUN: %run %t 2>&1 | FileCheck %s

// REQUIRES: cxxabi

class Base {
public:
  int i;
  virtual void print() {}
};

class Derived : public Base {
public:
  void print() {}
};

int main() {
  Derived *list = (Derived *)new char[sizeof(Derived)];

// CHECK: PR33221.cpp:[[@LINE+2]]:19: runtime error: member access within address {{.*}} which does not point to an object of type 'Base'
// CHECK-NEXT: object has invalid vptr
  int foo = list->i;
  return 0;
}
<commit_msg>Tighten up test to address bot failure. NFC.<commit_after>// RUN: %clangxx -frtti -fsanitize=vptr -g %s -O3 -o %t
// RUN: %run %t 2>&1 | FileCheck %s

// REQUIRES: cxxabi

#include <string.h>

class Base {
public:
  int i;
  virtual void print() {}
};

class Derived : public Base {
public:
  void print() {}
};

int main() {
  char *c = new char[sizeof(Derived)];
  memset((void *)c, 0, sizeof(Derived));
  Derived *list = (Derived *)c;

// CHECK: PR33221.cpp:[[@LINE+2]]:19: runtime error: member access within address {{.*}} which does not point to an object of type 'Base'
// CHECK-NEXT: invalid vptr
  int foo = list->i;
  return 0;
}
<|endoftext|>


<commit_before>//===--------------------------------------------------------------------------------*- C++ -*-===//
//                         _       _
//                        | |     | |
//                    __ _| |_ ___| | __ _ _ __   __ _
//                   / _` | __/ __| |/ _` | '_ \ / _` |
//                  | (_| | || (__| | (_| | | | | (_| |
//                   \__, |\__\___|_|\__,_|_| |_|\__, | - GridTools Clang DSL
//                    __/ |                       __/ |
//                   |___/                       |___/
//
//
//  This file is distributed under the MIT License (MIT).
//  See LICENSE.txt for details.
//
//===------------------------------------------------------------------------------------------===//
#define GRIDTOOLS_CLANG_GENERATED 1
#include <gtest/gtest.h>
#include "test/integration-test/CodeGen/Options.hpp"
#include "gridtools/clang/verify.hpp"
#include "test/integration-test/CodeGen/generated/coriolis_stencil_gridtools.cpp"
#include "test/integration-test/CodeGen/generated/coriolis_stencil_c++-naive.cpp"

using namespace dawn;
TEST(coriolis_stencil, test) {
  domain dom(Options::getInstance().m_size[0], Options::getInstance().m_size[1], Options::getInstance().m_size[2]);
  dom.set_halos(halo::value, halo::value, halo::value, halo::value, 0, 0);
  verifier verif(dom);

  meta_data_t meta_data(dom.isize(), dom.jsize(), dom.ksize());
  storage_t u_tens_gt(meta_data, "u_tens_gt"), u_tens_cxxnaive(meta_data, "u_tens_cxxnaive");
  storage_t v_tens_gt(meta_data, "v_tens_gt"), v_tens_cxxnaive(meta_data, "v_tens_cxxnaive");
  storage_t u_nnow(meta_data, "u_nnow"), v_nnow(meta_data, "v_nnow"), fc(meta_data, "fc");

  verif.fill(-1.0, u_tens_gt, v_tens_gt, fc, u_tens_cxxnaive, v_tens_cxxnaive);
  verif.fillMath(8.0, 2.0, 1.5, 1.5, 2.0, 4.0, u_nnow);
  verif.fillMath(5.0, 1.2, 1.3, 1.7, 2.2, 3.5, v_nnow);

  gridtools::coriolis_stencil coriolis_gt(dom, u_tens_gt, u_nnow, v_tens_gt, v_nnow, fc);
  cxxnaive::coriolis_stencil coriolis_cxxnaive(dom, u_tens_cxxnaive, u_nnow, v_tens_cxxnaive, v_nnow, fc);

  coriolis_gt.run();
  coriolis_cxxnaive.run();

  ASSERT_TRUE(verif.verify(u_tens_gt, u_tens_cxxnaive));
  ASSERT_TRUE(verif.verify(v_tens_gt, v_tens_cxxnaive));
}
<commit_msg>add missing halo define<commit_after>//===--------------------------------------------------------------------------------*- C++ -*-===//
//                         _       _
//                        | |     | |
//                    __ _| |_ ___| | __ _ _ __   __ _
//                   / _` | __/ __| |/ _` | '_ \ / _` |
//                  | (_| | || (__| | (_| | | | | (_| |
//                   \__, |\__\___|_|\__,_|_| |_|\__, | - GridTools Clang DSL
//                    __/ |                       __/ |
//                   |___/                       |___/
//
//
//  This file is distributed under the MIT License (MIT).
//  See LICENSE.txt for details.
//
//===------------------------------------------------------------------------------------------===//
#define GRIDTOOLS_CLANG_GENERATED 1
#define GRIDTOOLS_CLANG_HALO_EXTEND 3

#include <gtest/gtest.h>
#include "test/integration-test/CodeGen/Options.hpp"
#include "gridtools/clang/verify.hpp"
#include "test/integration-test/CodeGen/generated/coriolis_stencil_gridtools.cpp"
#include "test/integration-test/CodeGen/generated/coriolis_stencil_c++-naive.cpp"

using namespace dawn;
TEST(coriolis_stencil, test) {
  domain dom(Options::getInstance().m_size[0], Options::getInstance().m_size[1], Options::getInstance().m_size[2]);
  dom.set_halos(halo::value, halo::value, halo::value, halo::value, 0, 0);
  verifier verif(dom);

  meta_data_t meta_data(dom.isize(), dom.jsize(), dom.ksize());
  storage_t u_tens_gt(meta_data, "u_tens_gt"), u_tens_cxxnaive(meta_data, "u_tens_cxxnaive");
  storage_t v_tens_gt(meta_data, "v_tens_gt"), v_tens_cxxnaive(meta_data, "v_tens_cxxnaive");
  storage_t u_nnow(meta_data, "u_nnow"), v_nnow(meta_data, "v_nnow"), fc(meta_data, "fc");

  verif.fill(-1.0, u_tens_gt, v_tens_gt, fc, u_tens_cxxnaive, v_tens_cxxnaive);
  verif.fillMath(8.0, 2.0, 1.5, 1.5, 2.0, 4.0, u_nnow);
  verif.fillMath(5.0, 1.2, 1.3, 1.7, 2.2, 3.5, v_nnow);

  gridtools::coriolis_stencil coriolis_gt(dom, u_tens_gt, u_nnow, v_tens_gt, v_nnow, fc);
  cxxnaive::coriolis_stencil coriolis_cxxnaive(dom, u_tens_cxxnaive, u_nnow, v_tens_cxxnaive, v_nnow, fc);

  coriolis_gt.run();
  coriolis_cxxnaive.run();

  ASSERT_TRUE(verif.verify(u_tens_gt, u_tens_cxxnaive));
  ASSERT_TRUE(verif.verify(v_tens_gt, v_tens_cxxnaive));
}
<|endoftext|>


<commit_before>#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <time.h>
#include <vector>
#include <string.h>
#include <chrono>

#include "derecho/derecho.h"
#include <mutils-serialization/SerializationSupport.hpp>
#include <persistent/Persistent.hpp>
#include "conf/conf.hpp"
#include <optional>

using std::cout;
using std::endl;
using namespace persistent;
using namespace std::chrono_literals;

// The binary large object for serialized objects.
class Blob : public mutils::ByteRepresentable {
public:
    char * bytes;
    std::size_t size;

    // constructor - we always copy to 'own' the data
    Blob(const char * const b, const decltype(size) s) : bytes(nullptr),size(s) {
        if ( s > 0 ) {
            bytes = new char[s];
            memcpy(bytes, b, s);
        }
    }

    // copy constructor - we always copy to 'own' the data
    Blob(const Blob & other): bytes(nullptr),size(other.size) {
        bytes = nullptr;
        if ( size > 0 ) {
            bytes = new char[size];
            memcpy(bytes, other.bytes, other.size);
        }
    }

    // default constructor - no data at all
    Blob () : bytes(nullptr), size(0) { }

    // destructor
    virtual ~Blob() {
        if (bytes) delete bytes;
    }

    // move evaluator:
    Blob & operator = (Blob &&other) {
        char *swp_bytes = other.bytes;
        std::size_t swp_size = other.size;
        other.bytes = bytes;
        other.size = size;
        bytes = swp_bytes;
        size = swp_size;
        return *this;
    }

    // copy evaluator:
    Blob & operator = (const Blob &other) {
        if(bytes != nullptr) {
            delete bytes;
        }
        size = other.size;
        if(size > 0) {
            bytes = new char[size];
            memcpy(bytes, other.bytes, size);
        } else {
            bytes = nullptr;
        }
        return *this;
    }

    std::size_t to_bytes(char *v) const {
        ((std::size_t *)(v))[0] = size;
        if(size > 0) {
            memcpy(v + sizeof(size), bytes, size);
        }
        return size + sizeof(size);
    }

    std::size_t bytes_size() const {
        return size + sizeof(size);
    }

    void post_object(const std::function<void(char const *const, std::size_t)> &f) const {
        f((char *)&size, sizeof(size));
        f(bytes, size);
    }

    void ensure_registered(mutils::DeserializationManager &) {}

    static std::unique_ptr<Blob> from_bytes(mutils::DeserializationManager *, const char *const v) {
        return std::make_unique<Blob>(v + sizeof(std::size_t), ((std::size_t *)(v))[0]);
    }

    // we disabled from_bytes_noalloc calls for now.
};

class OSObject : public mutils::ByteRepresentable {
public:
#define INVALID_OID	(0xffffffffffffffffLLU)
    const uint64_t oid; // object_id
    Blob blob; // the object

    bool operator == (const OSObject & other) {
      return this->oid == other.oid;
    }
    bool is_valid () const {
      return (oid == INVALID_OID);
    }

    // constructor 0 : normal
    OSObject(uint64_t & _oid, Blob & _blob):
        oid(_oid),
        blob(_blob) {}
    // constructor 1 : raw
    OSObject(const uint64_t _oid, const char * const _b, const std::size_t _s):
        oid(_oid),
        blob(_b,_s) {}
    // constructor 2 : move
    OSObject(OSObject && other):
        oid(other.oid) {
        blob = other.blob;
    }
    // constructor 3 : copy
    OSObject(const OSObject & other):
       oid(other.oid),
       blob(other.blob.bytes,other.blob.size) {}
    // constructor 4 : invalid
    OSObject() : oid(INVALID_OID) {}

    DEFAULT_SERIALIZATION_SUPPORT(OSObject, oid, blob);
};

class ObjStore : public mutils::ByteRepresentable, public derecho::PersistsFields {
public:
    Persistent<std::vector<OSObject>> objects;
    const OSObject inv_obj;

    void put(const OSObject & obj) {
        for (OSObject & o : *objects) {
            if ( o == obj ) {
                Blob tmp(obj.blob); // create
                o.blob = std::move(tmp); // swap.
                return;
            }
        }
        // we didn't find it. insert...
        objects->emplace_back(obj);
    }

    // This get is SUPER inefficient
    // Passing an output buffer??
    const OSObject get(const uint64_t oid) {
        for(OSObject & o : *objects) {
            if ( o.oid == oid ) {
                return o;
            }
        }
        return this->inv_obj;
    }

    enum Functions { PUT_OBJ, GET_OBJ };

    static auto register_functions() {
      return std::make_tuple(
        derecho::rpc::tag<PUT_OBJ>(&ObjStore::put),
        derecho::rpc::tag<GET_OBJ>(&ObjStore::get)
      );
    }

    DEFAULT_SERIALIZATION_SUPPORT(ObjStore, objects);

    // Only for test: persistent registry is null and we make a copy constructor move.
    ObjStore(Persistent<std::vector<OSObject>> & _objects) : objects(std::move(_objects)) {}

    // Working with derecho.
    ObjStore(PersistentRegistry* pr) : objects(nullptr, pr) {}
};

typedef OSObject * POSObject;
OSObject **g_objs = nullptr;
void initialize_objects(uint32_t num_of_objs) {
  uint64_t max_msg_size = derecho::getConfUInt64(CONF_DERECHO_MAX_PAYLOAD_SIZE);
  uint32_t node_id = derecho::getConfUInt32(CONF_DERECHO_LOCAL_ID);
  // We just reserved 128 bytes for the message header and serialization.
#define VALUE_SIZE(x) ((x) - 128)
  char default_value[VALUE_SIZE(max_msg_size)];
  if (g_objs == nullptr) {
    g_objs = new POSObject[num_of_objs];
    uint32_t i;
    for (i = 0; i < num_of_objs; i++) {
      g_objs[i] = new OSObject{
	(((uint64_t)node_id)<<32) + i,
	default_value,VALUE_SIZE(max_msg_size)};
    }
  }
}

int main(int argc, char* argv[]) {
    if(argc < 3) {
        std::cout << "usage:" << argv[0] << " <num_of_nodes> <num_of_objs>" << std::endl;
        return -1;
    }
    derecho::Conf::initialize(argc,argv);
    int num_of_nodes = std::stoi(argv[1]);
    int num_of_objs = std::stoi(argv[2]);

    // create the key-value array
    initialize_objects(num_of_objs);

    uint64_t max_msg_size = derecho::getConfUInt64(CONF_DERECHO_MAX_PAYLOAD_SIZE);
    uint64_t total_num_messages = num_of_nodes * num_of_objs;
    struct timespec t_start,t_end;
    std::atomic<bool> bReady = false;
    uint32_t msg_counter = 0;
    persistent::version_t latest_version = INVALID_VERSION;

    derecho::CallbackSet callback_set{
            [&](derecho::subgroup_id_t subgroup, uint32_t nid, int32_t mid, std::optional<std::pair<char*, long long int>> data, persistent::version_t ver){
                msg_counter ++;
                latest_version = ver;
                if (msg_counter == (total_num_messages + num_of_nodes)) {
                    bReady = true;
                }
            },  // using stability callback to match the version.
            nullptr,  // local persistent frontier
            [&](derecho::subgroup_id_t subgroup, persistent::version_t ver) {
                // std::cout << "in global persistent callback: ver = " << ver << std::endl;
                if( bReady && (latest_version <= ver) ) {
                    clock_gettime(CLOCK_REALTIME, &t_end);
                    int64_t nsec = ((int64_t)t_end.tv_sec - t_start.tv_sec) * 1000000000 + t_end.tv_nsec - t_start.tv_nsec;
                    double msec = (double)nsec / 1000000;
                    double thp_gbps = ((double)num_of_objs * max_msg_size * 8) / nsec;
                    double thp_ops = ((double)num_of_objs * 1000000000) / nsec;
                    std::cout << "(pers)timespan:" << msec << " millisecond." << std::endl;
                    std::cout << "(pers)throughput:" << thp_gbps << "Gbit/s." << std::endl;
                    std::cout << "(pers)throughput:" << thp_ops << "ops." << std::endl;
                    std::cout << std::flush;
                }
            }}; // global persistent frontier

    derecho::SubgroupInfo subgroup_info{
            {{std::type_index(typeid(ObjStore)), [num_of_nodes](const derecho::View& curr_view, int& next_unassigned_rank) {
                  if(curr_view.num_members < num_of_nodes) {
                      std::cout << "not enough members yet:" << curr_view.num_members << " < " << num_of_nodes << std::endl;
                      throw derecho::subgroup_provisioning_exception();
                  }
                  derecho::subgroup_shard_layout_t subgroup_vector(1);

                  std::vector<uint32_t> members(num_of_nodes);
                  std::vector<int> senders(num_of_nodes, 1);
                  for(int i = 0; i < num_of_nodes; i++)
                      members[i] = i;

                  subgroup_vector[0].emplace_back(curr_view.make_subview(members, derecho::Mode::ORDERED, senders));
                  next_unassigned_rank = std::max(next_unassigned_rank, num_of_nodes);
                  return subgroup_vector;
              }}},
            {std::type_index(typeid(ObjStore))}};

    auto store_factory = [](PersistentRegistry* pr) { return std::make_unique<ObjStore>(pr); };

    derecho::Group<ObjStore> group{
                callback_set, subgroup_info,
                std::vector<derecho::view_upcall_t>{},
                store_factory};

    std::cout << "Finished constructing/joining Group" << std::endl;

    uint32_t node_rank = group.get_my_rank();

    std::cout << "my rank is:" << node_rank << ", and I'm sending." << std::endl;

    /* send operation */
    derecho::Replicated<ObjStore> & handle = group.get_subgroup<ObjStore>();
    {
        clock_gettime(CLOCK_REALTIME, &t_start);
        // send
        try {
          for (uint32_t i=0;i<(uint32_t)num_of_objs;i++)
            handle.ordered_send<ObjStore::PUT_OBJ>(*g_objs[i]);
        } catch (uint64_t exp) {
            std::cout << "Exception caught:0x" << std::hex << exp << std::endl;
        }
    }

    /* query operation */
    {
        OSObject obj1;
        uint64_t key = num_of_nodes - node_rank - 1;
        auto results = handle.ordered_send<ObjStore::GET_OBJ>(key);
        decltype(results)::ReplyMap& replies = results.get();
        std::cout<<"Got a reply map!"<<std::endl;
        for (auto& ritr:replies) {
            auto obj = ritr.second.get();
            std::cout << "Reply from node " << ritr.first << " was [" << obj.oid << ":"
                << obj.blob.size << std::endl;
        }
    }

    std::cout << "Reached end of main(), entering infinite loop so program doesn't exit" << std::endl;
    while(true) {
    }
}
<commit_msg>bugfix:objstore message counter. Many thanks to Xinzhe(xy267@cornell.edu)<commit_after>#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <time.h>
#include <vector>
#include <string.h>
#include <chrono>

#include "derecho/derecho.h"
#include <mutils-serialization/SerializationSupport.hpp>
#include <persistent/Persistent.hpp>
#include "conf/conf.hpp"
#include <optional>

using std::cout;
using std::endl;
using namespace persistent;
using namespace std::chrono_literals;

// The binary large object for serialized objects.
class Blob : public mutils::ByteRepresentable {
public:
    char * bytes;
    std::size_t size;

    // constructor - we always copy to 'own' the data
    Blob(const char * const b, const decltype(size) s) : bytes(nullptr),size(s) {
        if ( s > 0 ) {
            bytes = new char[s];
            memcpy(bytes, b, s);
        }
    }

    // copy constructor - we always copy to 'own' the data
    Blob(const Blob & other): bytes(nullptr),size(other.size) {
        bytes = nullptr;
        if ( size > 0 ) {
            bytes = new char[size];
            memcpy(bytes, other.bytes, other.size);
        }
    }

    // default constructor - no data at all
    Blob () : bytes(nullptr), size(0) { }

    // destructor
    virtual ~Blob() {
        if (bytes) delete bytes;
    }

    // move evaluator:
    Blob & operator = (Blob &&other) {
        char *swp_bytes = other.bytes;
        std::size_t swp_size = other.size;
        other.bytes = bytes;
        other.size = size;
        bytes = swp_bytes;
        size = swp_size;
        return *this;
    }

    // copy evaluator:
    Blob & operator = (const Blob &other) {
        if(bytes != nullptr) {
            delete bytes;
        }
        size = other.size;
        if(size > 0) {
            bytes = new char[size];
            memcpy(bytes, other.bytes, size);
        } else {
            bytes = nullptr;
        }
        return *this;
    }

    std::size_t to_bytes(char *v) const {
        ((std::size_t *)(v))[0] = size;
        if(size > 0) {
            memcpy(v + sizeof(size), bytes, size);
        }
        return size + sizeof(size);
    }

    std::size_t bytes_size() const {
        return size + sizeof(size);
    }

    void post_object(const std::function<void(char const *const, std::size_t)> &f) const {
        f((char *)&size, sizeof(size));
        f(bytes, size);
    }

    void ensure_registered(mutils::DeserializationManager &) {}

    static std::unique_ptr<Blob> from_bytes(mutils::DeserializationManager *, const char *const v) {
        return std::make_unique<Blob>(v + sizeof(std::size_t), ((std::size_t *)(v))[0]);
    }

    // we disabled from_bytes_noalloc calls for now.
};

class OSObject : public mutils::ByteRepresentable {
public:
#define INVALID_OID	(0xffffffffffffffffLLU)
    const uint64_t oid; // object_id
    Blob blob; // the object

    bool operator == (const OSObject & other) {
      return this->oid == other.oid;
    }
    bool is_valid () const {
      return (oid == INVALID_OID);
    }

    // constructor 0 : normal
    OSObject(uint64_t & _oid, Blob & _blob):
        oid(_oid),
        blob(_blob) {}
    // constructor 1 : raw
    OSObject(const uint64_t _oid, const char * const _b, const std::size_t _s):
        oid(_oid),
        blob(_b,_s) {}
    // constructor 2 : move
    OSObject(OSObject && other):
        oid(other.oid) {
        blob = other.blob;
    }
    // constructor 3 : copy
    OSObject(const OSObject & other):
       oid(other.oid),
       blob(other.blob.bytes,other.blob.size) {}
    // constructor 4 : invalid
    OSObject() : oid(INVALID_OID) {}

    DEFAULT_SERIALIZATION_SUPPORT(OSObject, oid, blob);
};

class ObjStore : public mutils::ByteRepresentable, public derecho::PersistsFields {
public:
    Persistent<std::vector<OSObject>> objects;
    const OSObject inv_obj;

    void put(const OSObject & obj) {
        for (OSObject & o : *objects) {
            if ( o == obj ) {
                Blob tmp(obj.blob); // create
                o.blob = std::move(tmp); // swap.
                return;
            }
        }
        // we didn't find it. insert...
        objects->emplace_back(obj);
    }

    // This get is SUPER inefficient
    // Passing an output buffer??
    const OSObject get(const uint64_t oid) {
        for(OSObject & o : *objects) {
            if ( o.oid == oid ) {
                return o;
            }
        }
        return this->inv_obj;
    }

    enum Functions { PUT_OBJ, GET_OBJ };

    static auto register_functions() {
      return std::make_tuple(
        derecho::rpc::tag<PUT_OBJ>(&ObjStore::put),
        derecho::rpc::tag<GET_OBJ>(&ObjStore::get)
      );
    }

    DEFAULT_SERIALIZATION_SUPPORT(ObjStore, objects);

    // Only for test: persistent registry is null and we make a copy constructor move.
    ObjStore(Persistent<std::vector<OSObject>> & _objects) : objects(std::move(_objects)) {}

    // Working with derecho.
    ObjStore(PersistentRegistry* pr) : objects(nullptr, pr) {}
};

typedef OSObject * POSObject;
OSObject **g_objs = nullptr;
void initialize_objects(uint32_t num_of_objs) {
  uint64_t max_msg_size = derecho::getConfUInt64(CONF_DERECHO_MAX_PAYLOAD_SIZE);
  uint32_t node_id = derecho::getConfUInt32(CONF_DERECHO_LOCAL_ID);
  // We just reserved 128 bytes for the message header and serialization.
#define VALUE_SIZE(x) ((x) - 128)
  char default_value[VALUE_SIZE(max_msg_size)];
  if (g_objs == nullptr) {
    g_objs = new POSObject[num_of_objs];
    uint32_t i;
    for (i = 0; i < num_of_objs; i++) {
      g_objs[i] = new OSObject{
	(((uint64_t)node_id)<<32) + i,
	default_value,VALUE_SIZE(max_msg_size)};
    }
  }
}

int main(int argc, char* argv[]) {
    if(argc < 3) {
        std::cout << "usage:" << argv[0] << " <num_of_nodes> <num_of_objs>" << std::endl;
        return -1;
    }
    derecho::Conf::initialize(argc,argv);
    int num_of_nodes = std::stoi(argv[1]);
    int num_of_objs = std::stoi(argv[2]);

    // create the key-value array
    initialize_objects(num_of_objs);

    uint64_t max_msg_size = derecho::getConfUInt64(CONF_DERECHO_MAX_PAYLOAD_SIZE);
    uint64_t total_num_messages = num_of_nodes * num_of_objs;
    struct timespec t_start,t_end;
    std::atomic<bool> bReady = false;
    uint32_t msg_counter = 0;
    persistent::version_t latest_version = INVALID_VERSION;

    derecho::CallbackSet callback_set{
            [&](derecho::subgroup_id_t subgroup, uint32_t nid, int32_t mid, std::optional<std::pair<char*, long long int>> data, persistent::version_t ver){
                msg_counter ++;
                latest_version = ver;
                if (msg_counter == (total_num_messages * num_of_nodes)) {
                    bReady = true;
                }
            },  // using stability callback to match the version.
            nullptr,  // local persistent frontier
            [&](derecho::subgroup_id_t subgroup, persistent::version_t ver) {
                // std::cout << "in global persistent callback: ver = " << ver << std::endl;
                if( bReady && (latest_version <= ver) ) {
                    clock_gettime(CLOCK_REALTIME, &t_end);
                    int64_t nsec = ((int64_t)t_end.tv_sec - t_start.tv_sec) * 1000000000 + t_end.tv_nsec - t_start.tv_nsec;
                    double msec = (double)nsec / 1000000;
                    double thp_gbps = ((double)num_of_objs * max_msg_size * 8) / nsec;
                    double thp_ops = ((double)num_of_objs * 1000000000) / nsec;
                    std::cout << "(pers)timespan:" << msec << " millisecond." << std::endl;
                    std::cout << "(pers)throughput:" << thp_gbps << "Gbit/s." << std::endl;
                    std::cout << "(pers)throughput:" << thp_ops << "ops." << std::endl;
                    std::cout << std::flush;
                }
            }}; // global persistent frontier

    derecho::SubgroupInfo subgroup_info{
            {{std::type_index(typeid(ObjStore)), [num_of_nodes](const derecho::View& curr_view, int& next_unassigned_rank) {
                  if(curr_view.num_members < num_of_nodes) {
                      std::cout << "not enough members yet:" << curr_view.num_members << " < " << num_of_nodes << std::endl;
                      throw derecho::subgroup_provisioning_exception();
                  }
                  derecho::subgroup_shard_layout_t subgroup_vector(1);

                  std::vector<uint32_t> members(num_of_nodes);
                  std::vector<int> senders(num_of_nodes, 1);
                  for(int i = 0; i < num_of_nodes; i++)
                      members[i] = i;

                  subgroup_vector[0].emplace_back(curr_view.make_subview(members, derecho::Mode::ORDERED, senders));
                  next_unassigned_rank = std::max(next_unassigned_rank, num_of_nodes);
                  return subgroup_vector;
              }}},
            {std::type_index(typeid(ObjStore))}};

    auto store_factory = [](PersistentRegistry* pr) { return std::make_unique<ObjStore>(pr); };

    derecho::Group<ObjStore> group{
                callback_set, subgroup_info,
                std::vector<derecho::view_upcall_t>{},
                store_factory};

    std::cout << "Finished constructing/joining Group" << std::endl;

    uint32_t node_rank = group.get_my_rank();

    std::cout << "my rank is:" << node_rank << ", and I'm sending." << std::endl;

    /* send operation */
    derecho::Replicated<ObjStore> & handle = group.get_subgroup<ObjStore>();
    {
        clock_gettime(CLOCK_REALTIME, &t_start);
        // send
        try {
          for (uint32_t i=0;i<(uint32_t)num_of_objs;i++)
            handle.ordered_send<ObjStore::PUT_OBJ>(*g_objs[i]);
        } catch (uint64_t exp) {
            std::cout << "Exception caught:0x" << std::hex << exp << std::endl;
        }
    }

    /* query operation */
    {
        OSObject obj1;
        uint64_t key = num_of_nodes - node_rank - 1;
        auto results = handle.ordered_send<ObjStore::GET_OBJ>(key);
        decltype(results)::ReplyMap& replies = results.get();
        std::cout<<"Got a reply map!"<<std::endl;
        for (auto& ritr:replies) {
            auto obj = ritr.second.get();
            std::cout << "Reply from node " << ritr.first << " was [" << obj.oid << ":"
                << obj.blob.size << std::endl;
        }
    }

    std::cout << "Reached end of main(), entering infinite loop so program doesn't exit" << std::endl;
    while(true) {
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: accessibleeventnotifier.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: fs $ $Date: 2002-12-06 12:56:46 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef COMPHELPER_ACCESSIBLE_EVENT_NOTIFIER
#include <comphelper/accessibleeventnotifier.hxx>
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _COMPHELPER_GUARDING_HXX_
#include <comphelper/guarding.hxx>
#endif

//.........................................................................
namespace comphelper
{
//.........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::lang;
    using namespace ::drafts::com::sun::star::accessibility;
    using namespace ::comphelper;

    //=====================================================================
    //= AccessibleEventNotifier
    //=====================================================================
    //---------------------------------------------------------------------
    ::osl::Mutex                AccessibleEventNotifier::s_aMutex;
    AccessibleEventNotifier*    AccessibleEventNotifier::s_pNotifier = NULL;

    //---------------------------------------------------------------------
    AccessibleEventNotifier::AccessibleEventNotifier( )
        :m_bTerminateRequested( sal_False )
    {
        // no events so far
        m_aEventGuard.reset();
    }

    //---------------------------------------------------------------------
    AccessibleEventNotifier::~AccessibleEventNotifier( )
    {
        OSL_ENSURE( m_aClients.empty() && m_aDisposedClients.empty(),
            "AccessibleEventNotifier::~AccessibleEventNotifier: not correctly terminated - resource leak!" );
    }

    //---------------------------------------------------------------------
    namespace
    {
        static void lcl_copyInterfaceContainer( const ::cppu::OInterfaceContainerHelper& _rSource, ::cppu::OInterfaceContainerHelper& _rDest )
        {
            _rDest.clear();
            Sequence< Reference< XInterface > > aInterfaces( _rSource.getElements() );

            const Reference< XInterface >* pInterfaces = aInterfaces.getConstArray();
            const Reference< XInterface >* pInterfacesEnd = pInterfaces + aInterfaces.getLength();
            for ( ; pInterfaces != pInterfacesEnd; ++pInterfaces )
                _rDest.addInterface( *pInterfaces );
        }
    }
    //---------------------------------------------------------------------
    void SAL_CALL AccessibleEventNotifier::run()
    {
        sal_Bool bTerminate = sal_False;

        do
        {
            // notify the events we have in the queue
            // --- <mutex_lock> -------------------------------------------
            {
                ::osl::MutexGuard aGuard( s_aMutex );

                // continue with all events we have so far
                while ( !m_aEvents.empty() )
                {
                    // the first event in the queue
                    ClientEvent aEvent = m_aEvents.front();
                    m_aEvents.pop_front();

                    // special handling for "disposing"
                    if ( aEvent.second.EventId < 0 )
                    {
                        // look up in the map for "disposed clients"
                        ClientMap::iterator aPos = m_aDisposedClients.find( aEvent.first );
                        OSL_ENSURE( m_aDisposedClients.end() != aPos,
                            "AccessibleEventNotifier::run: could not find this client!" );

                        if ( m_aDisposedClients.end() != aPos )
                        {
                            EventObject aDisposalEvent;
                            aDisposalEvent.Source = aEvent.second.Source;

                            // want to call the listeners with a released mutex
                            // thus we have to copy the container, so that we can savely use the copy while
                            // our mutex is released

                            ::cppu::OInterfaceContainerHelper aCopy( s_aMutex );
                            lcl_copyInterfaceContainer( *aPos->second, aCopy );

                            // we do not need the entry in the "disposed clients" map anymore
                            // because the "disposed" event is the _last_ one to be fired for a client
                            delete aPos->second;
                            m_aDisposedClients.erase( aPos );

                            // now do the notification, and do it with the _copy_ after releasing the mutex
                            // --- <mutex_release> ------------------------
                            {
                                MutexRelease aReleaseOnce( s_aMutex );
                                aCopy.disposeAndClear( aDisposalEvent );

                                // clear the aDisposalEvent while our mutex is _not_ acquired
                                // this ensures that we do not - by accident - release the last reference
                                // of the foreign component while our mutex is locked
                                aDisposalEvent.Source.clear();
                            }
                            // --- </mutex_release> -----------------------

                            // cleanup the thread if we do not have clients anymore
                            implCleanupNotifier( );
                        }
                    }
                    else
                    {
                        // look up the client for this event
                        ClientMap::iterator aClientPos;
                        if ( implLookupClient( aEvent.first, aClientPos ) )
                        {
                            // copy the listener sequence. We do _not_ want to call into the listeners
                            // with our mutex locked
                            Sequence< Reference< XInterface > > aListeners( aClientPos->second->getElements() );
                            // default handling: loop through all listeners, and notify them

                            const Reference< XInterface >* pListeners = aListeners.getConstArray();
                            const Reference< XInterface >* pListenersEnd = pListeners + aListeners.getLength();

                            // --- <mutex_release> ------------------------
                            {
                                // release the mutex within this block
                                MutexRelease aReleaseOnce( s_aMutex );

                                while ( pListeners != pListenersEnd )
                                {
                                    try
                                    {
                                        static_cast< XAccessibleEventListener* >( pListeners->get() )->notifyEvent( aEvent.second );
                                    }
                                    catch( const Exception& e )
                                    {
                                        e;
                                        // silent this
                                        // no assertion, because a broken access remote bridge or something like this
                                        // can cause this exception
                                    }
                                    ++pListeners;
                                }
                            }
                            // --- </mutex_release> -----------------------
                        }
                        else
                            OSL_ENSURE( sal_False, "AccessibleEventNotifier::run: invalid client id found for accessible event!" );
                    }

                    // --- <mutex_release> --------------------------------
                    {
                        MutexRelease aReleaseOnce( s_aMutex );
                        // clear the event
                        // do this with our own mutex released, as clearing the event includes releasing the reference
                        // to the css.lang.EventObject.Source - in case this release is non-trivial (i.e. the last
                        // reference to the object), we certainly do _not_ want to do this while our
                        // mutex is locked
                        aEvent = ClientEvent();
                    }
                    // --- </mutex_release> -------------------------------
                }

                // reset the condition - will be set as soon as a new event arrives
                m_aEventGuard.reset();
            }
            // --- </mutex_lock> ------------------------------------------

            // wait (sleep) 'til a new event arrives
            m_aEventGuard.wait();

            // --- <mutex_lock> -------------------------------------------
            {
                ::osl::MutexGuard aGuard( s_aMutex );
                bTerminate = m_bTerminateRequested;
            }
            // --- </mutex_lock> ------------------------------------------
        }
        while ( !bTerminate );
    }

    //---------------------------------------------------------------------
    void SAL_CALL AccessibleEventNotifier::terminate()
    {
        AccessibleEventNotifier_BASE::terminate();
        // base class does not call onTerminated - just in case we want to do any cleanup there ...
        onTerminated();
    }

    //---------------------------------------------------------------------
    void SAL_CALL AccessibleEventNotifier::onTerminated()
    {
        delete this;
    }

    //---------------------------------------------------------------------
    AccessibleEventNotifier::TClientId AccessibleEventNotifier::generateId()
    {
        TClientId nBiggestUsedId = 0;
        TClientId nFreeId = 0;

        // look through all registered clients until we find a "gap" in the ids

        // Note that the following relies on the fact the elements in the map are traveled with
        // ascending keys (aka client ids)

        for (   ClientMap::const_iterator aLookup = m_aClients.begin();
                aLookup != m_aClients.end();
                ++aLookup
            )
        {
            TClientId nCurrent = aLookup->first;
            OSL_ENSURE( nCurrent > nBiggestUsedId, "AccessibleEventNotifier::generateId: map is expected to be sorted ascending!" );

            if ( nCurrent - nBiggestUsedId > 1 )
            {   // found a "gap"
                TClientId nCandidate = nBiggestUsedId + 1;

                // ensure that the id is really free - it's possible that the id is still in the "disposed clients"
                // map
                if ( m_aDisposedClients.end() == m_aDisposedClients.find( nCandidate ) )
                {   // yep, it's really available
                    nFreeId = nCandidate;
                    break;
                }
            }

            nBiggestUsedId = nCurrent;
        }

        if ( !nFreeId )
            nFreeId = nBiggestUsedId + 1;

        OSL_ENSURE( m_aClients.end() == m_aClients.find( nFreeId ),
            "AccessibleEventNotifier::generateId: algorithm broken!" );

        return nFreeId;
    }

    //---------------------------------------------------------------------
    AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient( )
    {
        ::osl::MutexGuard aGuard( s_aMutex );
        if ( !s_pNotifier )
        {   // the first client -> create the thread

            // create the thread object
            s_pNotifier = new AccessibleEventNotifier;

            // run the thread
            s_pNotifier->create();
                // note that the thread will start running, and the first thing it will do is stopping
                // in run, waiting for the mutex
        }

        // generate a new client id
        TClientId nNewClientId = s_pNotifier->generateId( );

        // the event listeners for the new client
        EventListeners* pNewListeners = new EventListeners( s_aMutex );
            // note that we're using our own mutex here, so the listener containers for all
            // our clients share this same mutex.
            // Shouldn't be any problem: the only situation where this is used is when the
            // thread is firing events, and there the mutex is locked, anyway.

        // add the client
        s_pNotifier->m_aClients.insert( ClientMap::value_type( nNewClientId, pNewListeners ) );

        // outta here
        return nNewClientId;
    }

    //---------------------------------------------------------------------
    sal_Bool AccessibleEventNotifier::implLookupClient( const TClientId _nClient, ClientMap::iterator& _rPos )
    {
        OSL_ENSURE( s_pNotifier, "AccessibleEventNotifier::implLookupClient: illegal call: thread not running!" );
        if ( !s_pNotifier )
            return sal_False;

        // look up this client
        _rPos = s_pNotifier->m_aClients.find( _nClient );
        OSL_ENSURE( s_pNotifier->m_aClients.end() != _rPos, "AccessibleEventNotifier::implLookupClient: invalid client id (did you register your client?)!" );

        return ( s_pNotifier->m_aClients.end() != _rPos );
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::implRemoveEventsForClient( const TClientId _nClient,
            ::std::vector< Reference< XInterface > >& _rEnsureAlive )
    {
        OSL_ENSURE( s_pNotifier, "AccessibleEventNotifier::implRemoveEventsForClient: invalid call, save your documents before it crashes!" );

        EventQueue::iterator aEventLoop = s_pNotifier->m_aEvents.begin();
        while ( aEventLoop != s_pNotifier->m_aEvents.end() )
        {
            if ( _nClient == aEventLoop->first )
            {
                // this is an event queued for the same client
                // -> remove it from the queue
                EventQueue::iterator aErasePos( aEventLoop );
                ++aEventLoop;

                // keep the object alive until we can free our own mutex
                _rEnsureAlive.push_back( aErasePos->second.Source );

                // erase the event
                s_pNotifier->m_aEvents.erase( aErasePos );
            }
            else
                ++aEventLoop;
        }
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::implCleanupNotifier( )
    {
        OSL_PRECOND( s_pNotifier, "AccessibleEventNotifier::implCleanupNotifier: invalid call!" );

        if ( s_pNotifier->m_aClients.empty() && s_pNotifier->m_aDisposedClients.empty() )
        {
            // killing me softly ....

            // tell the instance it should terminate
            s_pNotifier->m_bTerminateRequested = sal_True;

            // awake it
            // (it is sleeping currently - if it were not, it would be in the section
            // guarded by s_aMutex (see <method>run</method>), which is impossible as
            // our thread here has this mutex currently ...
            s_pNotifier->m_aEventGuard.set();

            // reset the notifier holder - thus, the thread may continue to run the few microseconds
            // it will need to finally terminate, but if in the meantime new clients
            // are registered, we will not burden this (terminating) notifier with it,
            // but create a new one.
            // Note that the instance will delete itself in onTerminated
            s_pNotifier = NULL;
        }

        OSL_POSTCOND( !s_pNotifier || !s_pNotifier->m_aClients.empty() || !s_pNotifier->m_aDisposedClients.empty(),
            "AccessibleEventNotifier::implCleanupNotifier: post condition violated!" );
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::revokeClient( const TClientId _nClient )
    {
        // below, we will destroy some AccessibleEventObject instances
        // their Source member refers a foreign component (the broadcaster), which we
        // will release with this destruction. In case that is the _last_ release, it
        // would be potentially deadly if we call it while our own mutex is locked.
        // So we ensure that all these objects are alive _until_ our mutex is released.

        ::std::vector< Reference< XInterface > > aEnsureAlive;

        // ----- <mutex_lock> ---------------------------------------------
        {
            ::osl::MutexGuard aGuard( s_aMutex );

            ClientMap::iterator aClientPos;
            if ( !implLookupClient( _nClient, aClientPos ) )
                // already asserted in implLookupClient
                return;

            // remove it from the clients map
            delete aClientPos->second;
            s_pNotifier->m_aClients.erase( aClientPos );

            // remove any other events which are pending for this client
            implRemoveEventsForClient( _nClient, aEnsureAlive );

            // cleanup the thread if we do not have clients anymore
            implCleanupNotifier( );
        }
        // ----- </mutex_lock> ---------------------------------------------

        // here, aEnsureAlive is cleared, and here it doesn't matter anymore if it's the last
        // reference to the contained components, as our mutex is not locked here ....
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient,
            const Reference< XInterface >& _rxEventSource ) SAL_THROW( ( ) )
    {
        ::std::vector< Reference< XInterface > > aEnsureAlive;

        // ----- <mutex_lock> ---------------------------------------------
        {
            ::osl::MutexGuard aGuard( s_aMutex );

            ClientMap::iterator aClientPos;
            if ( !implLookupClient( _nClient, aClientPos ) )
                // already asserted in implLookupClient
                return;

            // move the client from the "regular clients" to the "disposed clients" map
            // from then on, no events for this client will be accepted anymore
        #ifdef _DEBUG
            ::std::pair< ClientMap::iterator, bool > aInsertResult =
        #endif
            s_pNotifier->m_aDisposedClients.insert( ClientMap::value_type( _nClient, aClientPos->second ) );
            OSL_ENSURE( aInsertResult.second, "AccessibleEventNotifier::revokeClientNotifyDisposing: client was already disposed!" );
                // is this asserts, then there already was an entry for _nClient in m_aDisposedClients, which means
                // somebody already called notifyDisposing with this id
            s_pNotifier->m_aClients.erase( aClientPos );

            // before we add the "disposing" event to the queue, we remove all other events for this client
            implRemoveEventsForClient( _nClient, aEnsureAlive );

            // push back a "disposing" event for this client
            AccessibleEventObject aDisposalEvent;
            aDisposalEvent.Source = _rxEventSource;
            aDisposalEvent.EventId = -1;        // this indicates "disposal"

            // add the event to the queue
            implPushBackEvent( _nClient, aDisposalEvent );
        }
        // ----- </mutex_lock> --------------------------------------------

        // here, aEnsureAlive is cleared, and here it doesn't matter anymore if it's the last
        // reference to the contained components, as our mutex is not locked here ....
    }

    //---------------------------------------------------------------------
    sal_Int32 AccessibleEventNotifier::addEventListener(
        const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( !implLookupClient( _nClient, aClientPos ) )
            // already asserted in implLookupClient
            return 0;

        if ( _rxListener.is() )
            aClientPos->second->addInterface( _rxListener );

        return aClientPos->second->getLength();
    }

    //---------------------------------------------------------------------
    sal_Int32 AccessibleEventNotifier::removeEventListener(
        const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( !implLookupClient( _nClient, aClientPos ) )
            // already asserted in implLookupClient
            return 0;

        if ( _rxListener.is() )
            aClientPos->second->removeInterface( _rxListener );

        return aClientPos->second->getLength();
    }

    //---------------------------------------------------------------------
    Sequence< Reference< XInterface > > AccessibleEventNotifier::getEventListeners( const TClientId _nClient ) SAL_THROW( ( ) )
    {
        Sequence< Reference< XInterface > > aListeners;

        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( implLookupClient( _nClient, aClientPos ) )
            aListeners = aClientPos->second->getElements();

        return aListeners;
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) SAL_THROW( ( ) )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( !implLookupClient( _nClient, aClientPos ) )
            // already asserted in implLookupClient
            return;

        // add the event to the queue
        implPushBackEvent( _nClient, _rEvent );
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::implPushBackEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent )
    {
        OSL_PRECOND( s_pNotifier, "AccessibleEventNotifier::implPushBackEvent: invalid call!" );

        // add the event to the queue
        s_pNotifier->m_aEvents.push_back( ClientEvent( _nClient, _rEvent ) );

        // wake up the thread
        s_pNotifier->m_aEventGuard.set();
    }

//.........................................................................
}   // namespace comphelper
//.........................................................................

/*************************************************************************
 * history:
 *  $Log: not supported by cvs2svn $
 *
 *  Revision 1.0 05.12.2002 11:05:26  fs
 ************************************************************************/

<commit_msg>#106337#; make notification synchron<commit_after>/*************************************************************************
 *
 *  $RCSfile: accessibleeventnotifier.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: sab $ $Date: 2003-01-22 15:18:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef COMPHELPER_ACCESSIBLE_EVENT_NOTIFIER
#include <comphelper/accessibleeventnotifier.hxx>
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _COMPHELPER_GUARDING_HXX_
#include <comphelper/guarding.hxx>
#endif

//.........................................................................
namespace comphelper
{
//.........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::lang;
    using namespace ::drafts::com::sun::star::accessibility;
    using namespace ::comphelper;

    //=====================================================================
    //= AccessibleEventNotifier
    //=====================================================================
    //---------------------------------------------------------------------
    ::osl::Mutex                        AccessibleEventNotifier::s_aMutex;
    AccessibleEventNotifier::ClientMap  AccessibleEventNotifier::s_aClients;

    //---------------------------------------------------------------------
    AccessibleEventNotifier::TClientId AccessibleEventNotifier::generateId()
    {
        TClientId nBiggestUsedId = 0;
        TClientId nFreeId = 0;

        // look through all registered clients until we find a "gap" in the ids

        // Note that the following relies on the fact the elements in the map are traveled with
        // ascending keys (aka client ids)

        for (   ClientMap::const_iterator aLookup = s_aClients.begin();
                aLookup != s_aClients.end();
                ++aLookup
            )
        {
            TClientId nCurrent = aLookup->first;
            OSL_ENSURE( nCurrent > nBiggestUsedId, "AccessibleEventNotifier::generateId: map is expected to be sorted ascending!" );

            if ( nCurrent - nBiggestUsedId > 1 )
            {   // found a "gap"
                nFreeId = nBiggestUsedId + 1;
                break;
            }

            nBiggestUsedId = nCurrent;
        }

        if ( !nFreeId )
            nFreeId = nBiggestUsedId + 1;

        OSL_ENSURE( s_aClients.end() == s_aClients.find( nFreeId ),
            "AccessibleEventNotifier::generateId: algorithm broken!" );

        return nFreeId;
    }

    //---------------------------------------------------------------------
    AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient( )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        // generate a new client id
        TClientId nNewClientId = generateId( );

        // the event listeners for the new client
        EventListeners* pNewListeners = new EventListeners( s_aMutex );
            // note that we're using our own mutex here, so the listener containers for all
            // our clients share this same mutex.
            // this is a reminiscense to the days where the notifier was asynchronous. Today this is
            // completely nonsense, and potentially slowing down the Office me thinks ...

        // add the client
        s_aClients.insert( ClientMap::value_type( nNewClientId, pNewListeners ) );

        // outta here
        return nNewClientId;
    }

    //---------------------------------------------------------------------
    sal_Bool AccessibleEventNotifier::implLookupClient( const TClientId _nClient, ClientMap::iterator& _rPos )
    {
        // look up this client
        _rPos = s_aClients.find( _nClient );
        OSL_ENSURE( s_aClients.end() != _rPos, "AccessibleEventNotifier::implLookupClient: invalid client id (did you register your client?)!" );

        return ( s_aClients.end() != _rPos );
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::revokeClient( const TClientId _nClient )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( !implLookupClient( _nClient, aClientPos ) )
            // already asserted in implLookupClient
            return;

        // remove it from the clients map
        delete aClientPos->second;
        s_aClients.erase( aClientPos );
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient,
            const Reference< XInterface >& _rxEventSource ) SAL_THROW( ( ) )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( !implLookupClient( _nClient, aClientPos ) )
            // already asserted in implLookupClient
            return;

        // notify the "disposing" event for this client
        EventObject aDisposalEvent;
        aDisposalEvent.Source = _rxEventSource;

        // now do the notification
        aClientPos->second->disposeAndClear( aDisposalEvent );

        // we do not need the entry in the clients map anymore
        delete aClientPos->second;
        s_aClients.erase( aClientPos );
    }

    //---------------------------------------------------------------------
    sal_Int32 AccessibleEventNotifier::addEventListener(
        const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( !implLookupClient( _nClient, aClientPos ) )
            // already asserted in implLookupClient
            return 0;

        if ( _rxListener.is() )
            aClientPos->second->addInterface( _rxListener );

        return aClientPos->second->getLength();
    }

    //---------------------------------------------------------------------
    sal_Int32 AccessibleEventNotifier::removeEventListener(
        const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) )
    {
        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( !implLookupClient( _nClient, aClientPos ) )
            // already asserted in implLookupClient
            return 0;

        if ( _rxListener.is() )
            aClientPos->second->removeInterface( _rxListener );

        return aClientPos->second->getLength();
    }

    //---------------------------------------------------------------------
    Sequence< Reference< XInterface > > AccessibleEventNotifier::getEventListeners( const TClientId _nClient ) SAL_THROW( ( ) )
    {
        Sequence< Reference< XInterface > > aListeners;

        ::osl::MutexGuard aGuard( s_aMutex );

        ClientMap::iterator aClientPos;
        if ( implLookupClient( _nClient, aClientPos ) )
            aListeners = aClientPos->second->getElements();

        return aListeners;
    }

    //---------------------------------------------------------------------
    void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) SAL_THROW( ( ) )
    {
        Sequence< Reference< XInterface > > aListeners;

        // --- <mutex lock> -------------------------------
        {
            ::osl::MutexGuard aGuard( s_aMutex );

            ClientMap::iterator aClientPos;
            if ( !implLookupClient( _nClient, aClientPos ) )
                // already asserted in implLookupClient
                return;

            // since we're synchronous, again, we want to notify immediately
            aListeners = aClientPos->second->getElements();
        }
        // --- </mutex lock> ------------------------------

            // default handling: loop through all listeners, and notify them
        const Reference< XInterface >* pListeners = aListeners.getConstArray();
        const Reference< XInterface >* pListenersEnd = pListeners + aListeners.getLength();
        while ( pListeners != pListenersEnd )
        {
            try
            {
                static_cast< XAccessibleEventListener* >( pListeners->get() )->notifyEvent( _rEvent );
            }
            catch( const Exception& e )
            {
                e;
                // silent this
                // no assertion, because a broken access remote bridge or something like this
                // can cause this exception
            }
            ++pListeners;
        }
    }

//.........................................................................
}   // namespace comphelper
//.........................................................................
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/*
 * Implementation of track selection in case the analysis runs on AODs
 * For the moment it uses the AliESDtrackCuts and converts AOD tracks to
 * ESD tracks, which might change in the future when an AOD track selection
 * framework becomes available.
 *
 * Author:
 *   Markus Fasel
 */
#include <TClonesArray.h>
#include <TObjArray.h>

#include <AliAODEvent.h>
#include <AliAODTrack.h>
#include <AliESDtrack.h>
#include <AliEMCalPtTaskTrackSelectionAOD.h>

namespace EMCalTriggerPtAnalysis {

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::AliEMCalPtTaskTrackSelectionAOD() :
		AliEMCalPtTaskVTrackSelection(),
		fTrackCuts(NULL),
		fFilterBits(0)
	{
		/*
		 * Main constructor
		 */
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::AliEMCalPtTaskTrackSelectionAOD(AliESDtrackCuts* cuts, UInt_t filterbits):
		AliEMCalPtTaskVTrackSelection(),
		fTrackCuts(cuts),
		fFilterBits(filterbits)
	{
		/*
		 * Main Constructor, initalising also track cuts
		 *
		 * @param cuts: Inital track cut object
		 */
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::AliEMCalPtTaskTrackSelectionAOD(const AliEMCalPtTaskTrackSelectionAOD& ref) :
		AliEMCalPtTaskVTrackSelection(ref),
		fTrackCuts(NULL),
		fFilterBits(ref.fFilterBits)
	{
		/*
		 * copy constructor
		 *
		 * @param ref: AOD track selection as basis for the copy
		 */
		if(ref.fTrackCuts) fTrackCuts = new AliESDtrackCuts(*(ref.fTrackCuts));
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD& AliEMCalPtTaskTrackSelectionAOD::operator=(const AliEMCalPtTaskTrackSelectionAOD& ref) {
		/*
		 * Assignment operator
		 *
		 * @param ref: AOD track selection as basis for the copy
		 * @return: reference to this cut object
		 */
		AliEMCalPtTaskVTrackSelection::operator=(ref);
		if(this != &ref){
			if(fTrackCuts) {
				delete fTrackCuts;
				fTrackCuts = NULL;
			}
			if(ref.fTrackCuts) fTrackCuts = new AliESDtrackCuts(*(ref.fTrackCuts));
		}
		return *this;
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::~AliEMCalPtTaskTrackSelectionAOD() {
		/*
		 * Destructor, removes the track cuts
		 */
		if(fTrackCuts) delete fTrackCuts;
	}

	//______________________________________________________________________________
	TObjArray* AliEMCalPtTaskTrackSelectionAOD::GetAcceptedTracks(const TClonesArray* const tracks) {
		/*
		 * Select tracks from a list (TClonesArray) of tracks. Internally, the tracks are converted
		 * to ESD tracks and processed by the underlying AliESDtrackCut object
		 *
		 * @param tracks: TClonesArray of input tracks, under which we select the appropriate ones
		 * @return: TObjArray of selected tracks
		 */
		if(!fListOfTracks) fListOfTracks = new TObjArray;
		else fListOfTracks->Clear();
		TIter trackIter(tracks);
		AliAODTrack *track(NULL);
		while((track = dynamic_cast<AliAODTrack *>(trackIter()))){
			// First check filter bits
			if(fFilterBits && !track->TestFilterBit(fFilterBits)) continue;
			if(fTrackCuts){
				AliESDtrack copyTrack(track);
				if(fTrackCuts->AcceptTrack(&copyTrack)) fListOfTracks->AddLast(track);
			}
		}
		return fListOfTracks;
	}

	//______________________________________________________________________________
	TObjArray* AliEMCalPtTaskTrackSelectionAOD::GetAcceptedTracks(const AliVEvent* const event) {
		/*
		 * Select tracks from a list (TClonesArray) of tracks. Internally, the tracks are converted
		 * to ESD tracks and processed by the underlying AliESDtrackCut object
		 *
		 * @param tracks: TClonesArray of input tracks, under which we select the appropriate ones
		 * @return: TObjArray of selected tracks
		 */
		if(!fListOfTracks) fListOfTracks = new TObjArray;
		else fListOfTracks->Clear();
		const AliAODEvent *aod = dynamic_cast<const AliAODEvent *>(event);
		if(!aod){
			AliError("Event not of type AliAODEvent");
			return fListOfTracks;
		}
		AliAODTrack *track(NULL);
		for(int itrk = 0; itrk < event->GetNumberOfTracks(); itrk++){
			track = static_cast<AliAODTrack *>(event->GetTrack(itrk));
			// First check filter bits
			if(fFilterBits && !track->TestFilterBit(fFilterBits)) continue;
			if(fTrackCuts){
				AliESDtrack copyTrack(track);
				if(fTrackCuts->AcceptTrack(&copyTrack)) fListOfTracks->AddLast(track);
			}
		}
		return fListOfTracks;
	}

} /* namespace EMCalTriggerPtAnalysis */

<commit_msg>Add classimp<commit_after>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/*
 * Implementation of track selection in case the analysis runs on AODs
 * For the moment it uses the AliESDtrackCuts and converts AOD tracks to
 * ESD tracks, which might change in the future when an AOD track selection
 * framework becomes available.
 *
 * Author:
 *   Markus Fasel
 */
#include <TClonesArray.h>
#include <TObjArray.h>

#include <AliAODEvent.h>
#include <AliAODTrack.h>
#include <AliESDtrack.h>
#include <AliEMCalPtTaskTrackSelectionAOD.h>

ClassImp(EMCalTriggerPtAnalysis::AliEMCalPtTaskTrackSelectionAOD)

namespace EMCalTriggerPtAnalysis {

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::AliEMCalPtTaskTrackSelectionAOD() :
		AliEMCalPtTaskVTrackSelection(),
		fTrackCuts(NULL),
		fFilterBits(0)
	{
		/*
		 * Main constructor
		 */
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::AliEMCalPtTaskTrackSelectionAOD(AliESDtrackCuts* cuts, UInt_t filterbits):
		AliEMCalPtTaskVTrackSelection(),
		fTrackCuts(cuts),
		fFilterBits(filterbits)
	{
		/*
		 * Main Constructor, initalising also track cuts
		 *
		 * @param cuts: Inital track cut object
		 */
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::AliEMCalPtTaskTrackSelectionAOD(const AliEMCalPtTaskTrackSelectionAOD& ref) :
		AliEMCalPtTaskVTrackSelection(ref),
		fTrackCuts(NULL),
		fFilterBits(ref.fFilterBits)
	{
		/*
		 * copy constructor
		 *
		 * @param ref: AOD track selection as basis for the copy
		 */
		if(ref.fTrackCuts) fTrackCuts = new AliESDtrackCuts(*(ref.fTrackCuts));
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD& AliEMCalPtTaskTrackSelectionAOD::operator=(const AliEMCalPtTaskTrackSelectionAOD& ref) {
		/*
		 * Assignment operator
		 *
		 * @param ref: AOD track selection as basis for the copy
		 * @return: reference to this cut object
		 */
		AliEMCalPtTaskVTrackSelection::operator=(ref);
		if(this != &ref){
			if(fTrackCuts) {
				delete fTrackCuts;
				fTrackCuts = NULL;
			}
			if(ref.fTrackCuts) fTrackCuts = new AliESDtrackCuts(*(ref.fTrackCuts));
		}
		return *this;
	}

	//______________________________________________________________________________
	AliEMCalPtTaskTrackSelectionAOD::~AliEMCalPtTaskTrackSelectionAOD() {
		/*
		 * Destructor, removes the track cuts
		 */
		if(fTrackCuts) delete fTrackCuts;
	}

	//______________________________________________________________________________
	TObjArray* AliEMCalPtTaskTrackSelectionAOD::GetAcceptedTracks(const TClonesArray* const tracks) {
		/*
		 * Select tracks from a list (TClonesArray) of tracks. Internally, the tracks are converted
		 * to ESD tracks and processed by the underlying AliESDtrackCut object
		 *
		 * @param tracks: TClonesArray of input tracks, under which we select the appropriate ones
		 * @return: TObjArray of selected tracks
		 */
		if(!fListOfTracks) fListOfTracks = new TObjArray;
		else fListOfTracks->Clear();
		TIter trackIter(tracks);
		AliAODTrack *track(NULL);
		while((track = dynamic_cast<AliAODTrack *>(trackIter()))){
			// First check filter bits
			if(fFilterBits && !track->TestFilterBit(fFilterBits)) continue;
			if(fTrackCuts){
				AliESDtrack copyTrack(track);
				if(fTrackCuts->AcceptTrack(&copyTrack)) fListOfTracks->AddLast(track);
			}
		}
		return fListOfTracks;
	}

	//______________________________________________________________________________
	TObjArray* AliEMCalPtTaskTrackSelectionAOD::GetAcceptedTracks(const AliVEvent* const event) {
		/*
		 * Select tracks from a list (TClonesArray) of tracks. Internally, the tracks are converted
		 * to ESD tracks and processed by the underlying AliESDtrackCut object
		 *
		 * @param tracks: TClonesArray of input tracks, under which we select the appropriate ones
		 * @return: TObjArray of selected tracks
		 */
		if(!fListOfTracks) fListOfTracks = new TObjArray;
		else fListOfTracks->Clear();
		const AliAODEvent *aod = dynamic_cast<const AliAODEvent *>(event);
		if(!aod){
			AliError("Event not of type AliAODEvent");
			return fListOfTracks;
		}
		AliAODTrack *track(NULL);
		for(int itrk = 0; itrk < event->GetNumberOfTracks(); itrk++){
			track = static_cast<AliAODTrack *>(event->GetTrack(itrk));
			// First check filter bits
			if(fFilterBits && !track->TestFilterBit(fFilterBits)) continue;
			if(fTrackCuts){
				AliESDtrack copyTrack(track);
				if(fTrackCuts->AcceptTrack(&copyTrack)) fListOfTracks->AddLast(track);
			}
		}
		return fListOfTracks;
	}

} /* namespace EMCalTriggerPtAnalysis */

<|endoftext|>


<commit_before>#include "IRPrinter.h"
#include "IROperator.h"
#include "IR.h"

#include <iostream>
#include <sstream>

namespace Halide {

using std::ostream;
using std::endl;

ostream &operator<<(ostream &out, Type type) {
    switch (type.t) {
    case Type::Int:
        out << 'i';
        break;
    case Type::UInt:
        out << 'u';
        break;
    case Type::Float:
        out << 'f';
        break;
    default:
        assert(false && "Malformed type");
    }
    out << type.bits;
    if (type.width > 1) out << 'x' << type.width;
    return out;
}

ostream &operator<<(ostream &out, For::ForType type) {
    switch (type) {
    case For::Serial:
        out << "for";
        break;
    case For::Parallel:
        out << "parallel";
        break;
    case For::Unrolled:
        out << "unrolled";
        break;
    case For::Vectorized:
        out << "vectorized";
        break;
    default:
        assert(false && "Malformed for type");
    }
    return out;
}

ostream &operator<<(ostream &stream, Expr ir) {
    if (!ir.defined()) {
        stream << "(undefined)";
    } else {
        Internal::IRPrinter p(stream);
        p.print(ir);
    }
    return stream;
}

ostream &operator<<(ostream &stream, Stmt ir) {
    if (!ir.defined()) {
        stream << "(undefined)" << std::endl;
    } else {
        Internal::IRPrinter p(stream);
        p.print(ir);
    }
    return stream;
}

namespace Internal {

void IRPrinter::test() {
    Type i32 = Int(32);
    Type f32 = Float(32);
    Expr x = new Variable(i32, "x");
    Expr y = new Variable(i32, "y");
    std::ostringstream expr_source;
    expr_source << (x + 3) * (y / 2 + 17);
    assert(expr_source.str() == "((x + 3)*((y/2) + 17))");

    Stmt store = new Store("buf", (x * 17) / (x - 3), y - 1);
    Stmt for_loop = new For("x", -2, y + 2, For::Parallel, store);
    vector<Expr> args(1); args[0] = x % 3;
    Expr call = new Call(i32, "buf", args, Call::Extern, NULL);
    Stmt store2 = new Store("out", call + 1, x);
    Stmt for_loop2 = new For("x", 0, y, For::Vectorized , store2);
    Stmt pipeline = new Pipeline("buf", for_loop, Stmt(), for_loop2);
    Stmt assertion = new AssertStmt(y > 3, "y is greater than 3");
    Stmt block = new Block(assertion, pipeline);
    Stmt let_stmt = new LetStmt("y", 17, block);
    Stmt allocate = new Allocate("buf", f32, 1023, let_stmt);

    std::ostringstream source;
    source << allocate;
    std::string correct_source = \
        "allocate buf[f32 * 1023]\n"
        "let y = 17\n"
        "assert((y > 3), \"y is greater than 3\")\n"
        "produce buf {\n"
        "  parallel (x, -2, (y + 2)) {\n"
        "    buf[(y - 1)] = ((x*17)/(x - 3))\n"
        "  }\n"
        "} consume {\n"
        "  vectorized (x, 0, y) {\n"
        "    out[x] = (buf((x % 3)) + 1)\n"
        "  }\n"
        "}\n"
        "free buf\n";

    if (source.str() != correct_source) {
        std::cout << "Correct output:" << std::endl << correct_source;
        std::cout << "Actual output:" << std::endl << source.str();
        assert(false);
    }
    std::cout << "IRPrinter test passed" << std::endl;
}

IRPrinter::IRPrinter(ostream &s) : stream(s), indent(0) {}

void IRPrinter::print(Expr ir) {
    ir.accept(this);
}

void IRPrinter::print(Stmt ir) {
    ir.accept(this);
}

void IRPrinter::do_indent() {
    for (int i = 0; i < indent; i++) stream << ' ';
}

void IRPrinter::visit(const IntImm *op) {
    stream << op->value;
}

void IRPrinter::visit(const FloatImm *op) {
    stream << op->value;
}

void IRPrinter::visit(const Cast *op) {
    stream << op->type << '(';
    print(op->value);
    stream << ')';
}

void IRPrinter::visit(const Variable *op) {
    // omit the type
    stream << op->name;
}

void IRPrinter::visit(const Add *op) {
    stream << '(';
    print(op->a);
    stream << " + ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Sub *op) {
    stream << '(';
    print(op->a);
    stream << " - ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Mul *op) {
    stream << '(';
    print(op->a);
    stream << "*";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Div *op) {
    stream << '(';
    print(op->a);
    stream << "/";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Mod *op) {
    stream << '(';
    print(op->a);
    stream << " % ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Min *op) {
    stream << "min(";
    print(op->a);
    stream << ", ";
    print(op->b);
    stream << ")";
}

void IRPrinter::visit(const Max *op) {
    stream << "max(";
    print(op->a);
    stream << ", ";
    print(op->b);
    stream << ")";
}

void IRPrinter::visit(const EQ *op) {
    stream << '(';
    print(op->a);
    stream << " == ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const NE *op) {
    stream << '(';
    print(op->a);
    stream << " != ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const LT *op) {
    stream << '(';
    print(op->a);
    stream << " < ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const LE *op) {
    stream << '(';
    print(op->a);
    stream << " <= ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const GT *op) {
    stream << '(';
    print(op->a);
    stream << " > ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const GE *op) {
    stream << '(';
    print(op->a);
    stream << " >= ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const And *op) {
    stream << '(';
    print(op->a);
    stream << " && ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Or *op) {
    stream << '(';
    print(op->a);
    stream << " || ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Not *op) {
    stream << '!';
    print(op->a);
}

void IRPrinter::visit(const Select *op) {
    stream << "select(";
    print(op->condition);
    stream << ", ";
    print(op->true_value);
    stream << ", ";
    print(op->false_value);
    stream << ")";
}

void IRPrinter::visit(const Load *op) {
    stream << op->buffer << "[";
    print(op->index);
    stream << "]";
}

void IRPrinter::visit(const Ramp *op) {
    stream << "ramp(";
    print(op->base);
    stream << ", ";
    print(op->stride);
    stream << ", " << op->width << ")";
}

void IRPrinter::visit(const Broadcast *op) {
    stream << "broadcast(";
    print(op->value);
    stream << ", " << op->width << ")";
}

void IRPrinter::visit(const Call *op) {
    stream << op->name << "(";
    for (size_t i = 0; i < op->args.size(); i++) {
        print(op->args[i]);
        if (i < op->args.size() - 1) {
            stream << ", ";
        }
    }
    stream << ")";
}

void IRPrinter::visit(const Let *op) {
    stream << "(let " << op->name << " = ";
    print(op->value);
    stream << " in ";
    print(op->body);
    stream << ")";
}

void IRPrinter::visit(const LetStmt *op) {
    do_indent();
    stream << "let " << op->name << " = ";
    print(op->value);
    stream << endl;

    do_indent();
    print(op->body);
}

void IRPrinter::visit(const PrintStmt *op) {
    do_indent();
    stream << "print(" << op->prefix;
    for (size_t i = 0; i < op->args.size(); i++) {
        stream << ", ";
        print(op->args[i]);
    }
    stream << ")" << endl;
}

void IRPrinter::visit(const AssertStmt *op) {
    do_indent();
    stream << "assert(";
    print(op->condition);
    stream << ", \"" << op->message << "\")" << endl;
}

void IRPrinter::visit(const Pipeline *op) {

    do_indent();
    stream << "produce " << op->buffer << " {" << endl;
    indent += 2;
    print(op->produce);
    indent -= 2;

    if (op->update.defined()) {
        do_indent();
        stream << "} update {" << endl;
        indent += 2;
        print(op->update);
        indent -= 2;
    }

    do_indent();
    stream << "} consume {" << endl;
    indent += 2;
    print(op->consume);
    indent -= 2;

    do_indent();
    stream << "}" << endl;
}

void IRPrinter::visit(const For *op) {

    do_indent();
    stream << op->for_type << " (" << op->name << ", ";
    print(op->min);
    stream << ", ";
    print(op->extent);
    stream << ") {" << endl;

    indent += 2;
    print(op->body);
    indent -= 2;

    do_indent();
    stream << "}" << endl;
}

void IRPrinter::visit(const Store *op) {
    do_indent();
    stream << op->buffer << "[";
    print(op->index);
    stream << "] = ";
    print(op->value);
    stream << endl;
}

void IRPrinter::visit(const Provide *op) {
    do_indent();
    stream << op->buffer << "(";
    for (size_t i = 0; i < op->args.size(); i++) {
        print(op->args[i]);
        if (i < op->args.size() - 1) stream << ", ";
    }
    stream << ") = ";
    print(op->value);
    stream << endl;
}

void IRPrinter::visit(const Allocate *op) {
    do_indent();
    stream << "allocate " << op->buffer << "[" << op->type << " * ";
    print(op->size);
    stream << "]" << endl;
    print(op->body);

    do_indent();
    stream << "free " << op->buffer << endl;
}

void IRPrinter::visit(const Realize *op) {
    do_indent();
    stream << "realize " << op->buffer << "(";
    for (size_t i = 0; i < op->bounds.size(); i++) {
        stream << "[";
        print(op->bounds[i].first);
        stream << ", ";
        print(op->bounds[i].second);
        stream << "]";
        if (i < op->bounds.size() - 1) stream << ", ";
    }
    stream << ") {" << endl;

    indent += 2;
    print(op->body);
    indent -= 2;

    do_indent();
    stream << "}" << endl;
}

void IRPrinter::visit(const Block *op) {
    print(op->first);
    if (op->rest.defined()) print(op->rest);
}

}}
<commit_msg>Fixed bug in IRPrinter<commit_after>#include "IRPrinter.h"
#include "IROperator.h"
#include "IR.h"

#include <iostream>
#include <sstream>

namespace Halide {

using std::ostream;
using std::endl;

ostream &operator<<(ostream &out, Type type) {
    switch (type.t) {
    case Type::Int:
        out << 'i';
        break;
    case Type::UInt:
        out << 'u';
        break;
    case Type::Float:
        out << 'f';
        break;
    default:
        assert(false && "Malformed type");
    }
    out << type.bits;
    if (type.width > 1) out << 'x' << type.width;
    return out;
}

ostream &operator<<(ostream &out, For::ForType type) {
    switch (type) {
    case For::Serial:
        out << "for";
        break;
    case For::Parallel:
        out << "parallel";
        break;
    case For::Unrolled:
        out << "unrolled";
        break;
    case For::Vectorized:
        out << "vectorized";
        break;
    default:
        assert(false && "Malformed for type");
    }
    return out;
}

ostream &operator<<(ostream &stream, Expr ir) {
    if (!ir.defined()) {
        stream << "(undefined)";
    } else {
        Internal::IRPrinter p(stream);
        p.print(ir);
    }
    return stream;
}

ostream &operator<<(ostream &stream, Stmt ir) {
    if (!ir.defined()) {
        stream << "(undefined)" << std::endl;
    } else {
        Internal::IRPrinter p(stream);
        p.print(ir);
    }
    return stream;
}

namespace Internal {

void IRPrinter::test() {
    Type i32 = Int(32);
    Type f32 = Float(32);
    Expr x = new Variable(i32, "x");
    Expr y = new Variable(i32, "y");
    std::ostringstream expr_source;
    expr_source << (x + 3) * (y / 2 + 17);
    assert(expr_source.str() == "((x + 3)*((y/2) + 17))");

    Stmt store = new Store("buf", (x * 17) / (x - 3), y - 1);
    Stmt for_loop = new For("x", -2, y + 2, For::Parallel, store);
    vector<Expr> args(1); args[0] = x % 3;
    Expr call = new Call(i32, "buf", args, Call::Extern, NULL);
    Stmt store2 = new Store("out", call + 1, x);
    Stmt for_loop2 = new For("x", 0, y, For::Vectorized , store2);
    Stmt pipeline = new Pipeline("buf", for_loop, Stmt(), for_loop2);
    Stmt assertion = new AssertStmt(y > 3, "y is greater than 3");
    Stmt block = new Block(assertion, pipeline);
    Stmt let_stmt = new LetStmt("y", 17, block);
    Stmt allocate = new Allocate("buf", f32, 1023, let_stmt);

    std::ostringstream source;
    source << allocate;
    std::string correct_source = \
        "allocate buf[f32 * 1023]\n"
        "let y = 17\n"
        "assert((y > 3), \"y is greater than 3\")\n"
        "produce buf {\n"
        "  parallel (x, -2, (y + 2)) {\n"
        "    buf[(y - 1)] = ((x*17)/(x - 3))\n"
        "  }\n"
        "} consume {\n"
        "  vectorized (x, 0, y) {\n"
        "    out[x] = (buf((x % 3)) + 1)\n"
        "  }\n"
        "}\n"
        "free buf\n";

    if (source.str() != correct_source) {
        std::cout << "Correct output:" << std::endl << correct_source;
        std::cout << "Actual output:" << std::endl << source.str();
        assert(false);
    }
    std::cout << "IRPrinter test passed" << std::endl;
}

IRPrinter::IRPrinter(ostream &s) : stream(s), indent(0) {}

void IRPrinter::print(Expr ir) {
    ir.accept(this);
}

void IRPrinter::print(Stmt ir) {
    ir.accept(this);
}

void IRPrinter::do_indent() {
    for (int i = 0; i < indent; i++) stream << ' ';
}

void IRPrinter::visit(const IntImm *op) {
    stream << op->value;
}

void IRPrinter::visit(const FloatImm *op) {
    stream << op->value;
}

void IRPrinter::visit(const Cast *op) {
    stream << op->type << '(';
    print(op->value);
    stream << ')';
}

void IRPrinter::visit(const Variable *op) {
    // omit the type
    stream << op->name;
}

void IRPrinter::visit(const Add *op) {
    stream << '(';
    print(op->a);
    stream << " + ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Sub *op) {
    stream << '(';
    print(op->a);
    stream << " - ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Mul *op) {
    stream << '(';
    print(op->a);
    stream << "*";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Div *op) {
    stream << '(';
    print(op->a);
    stream << "/";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Mod *op) {
    stream << '(';
    print(op->a);
    stream << " % ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Min *op) {
    stream << "min(";
    print(op->a);
    stream << ", ";
    print(op->b);
    stream << ")";
}

void IRPrinter::visit(const Max *op) {
    stream << "max(";
    print(op->a);
    stream << ", ";
    print(op->b);
    stream << ")";
}

void IRPrinter::visit(const EQ *op) {
    stream << '(';
    print(op->a);
    stream << " == ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const NE *op) {
    stream << '(';
    print(op->a);
    stream << " != ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const LT *op) {
    stream << '(';
    print(op->a);
    stream << " < ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const LE *op) {
    stream << '(';
    print(op->a);
    stream << " <= ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const GT *op) {
    stream << '(';
    print(op->a);
    stream << " > ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const GE *op) {
    stream << '(';
    print(op->a);
    stream << " >= ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const And *op) {
    stream << '(';
    print(op->a);
    stream << " && ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Or *op) {
    stream << '(';
    print(op->a);
    stream << " || ";
    print(op->b);
    stream << ')';
}

void IRPrinter::visit(const Not *op) {
    stream << '!';
    print(op->a);
}

void IRPrinter::visit(const Select *op) {
    stream << "select(";
    print(op->condition);
    stream << ", ";
    print(op->true_value);
    stream << ", ";
    print(op->false_value);
    stream << ")";
}

void IRPrinter::visit(const Load *op) {
    stream << op->buffer << "[";
    print(op->index);
    stream << "]";
}

void IRPrinter::visit(const Ramp *op) {
    stream << "ramp(";
    print(op->base);
    stream << ", ";
    print(op->stride);
    stream << ", " << op->width << ")";
}

void IRPrinter::visit(const Broadcast *op) {
    stream << "broadcast(";
    print(op->value);
    stream << ", " << op->width << ")";
}

void IRPrinter::visit(const Call *op) {
    stream << op->name << "(";
    for (size_t i = 0; i < op->args.size(); i++) {
        print(op->args[i]);
        if (i < op->args.size() - 1) {
            stream << ", ";
        }
    }
    stream << ")";
}

void IRPrinter::visit(const Let *op) {
    stream << "(let " << op->name << " = ";
    print(op->value);
    stream << " in ";
    print(op->body);
    stream << ")";
}

void IRPrinter::visit(const LetStmt *op) {
    do_indent();
    stream << "let " << op->name << " = ";
    print(op->value);
    stream << endl;

    print(op->body);
}

void IRPrinter::visit(const PrintStmt *op) {
    do_indent();
    stream << "print(" << op->prefix;
    for (size_t i = 0; i < op->args.size(); i++) {
        stream << ", ";
        print(op->args[i]);
    }
    stream << ")" << endl;
}

void IRPrinter::visit(const AssertStmt *op) {
    do_indent();
    stream << "assert(";
    print(op->condition);
    stream << ", \"" << op->message << "\")" << endl;
}

void IRPrinter::visit(const Pipeline *op) {

    do_indent();
    stream << "produce " << op->buffer << " {" << endl;
    indent += 2;
    print(op->produce);
    indent -= 2;

    if (op->update.defined()) {
        do_indent();
        stream << "} update {" << endl;
        indent += 2;
        print(op->update);
        indent -= 2;
    }

    do_indent();
    stream << "} consume {" << endl;
    indent += 2;
    print(op->consume);
    indent -= 2;

    do_indent();
    stream << "}" << endl;
}

void IRPrinter::visit(const For *op) {

    do_indent();
    stream << op->for_type << " (" << op->name << ", ";
    print(op->min);
    stream << ", ";
    print(op->extent);
    stream << ") {" << endl;

    indent += 2;
    print(op->body);
    indent -= 2;

    do_indent();
    stream << "}" << endl;
}

void IRPrinter::visit(const Store *op) {
    do_indent();
    stream << op->buffer << "[";
    print(op->index);
    stream << "] = ";
    print(op->value);
    stream << endl;
}

void IRPrinter::visit(const Provide *op) {
    do_indent();
    stream << op->buffer << "(";
    for (size_t i = 0; i < op->args.size(); i++) {
        print(op->args[i]);
        if (i < op->args.size() - 1) stream << ", ";
    }
    stream << ") = ";
    print(op->value);
    stream << endl;
}

void IRPrinter::visit(const Allocate *op) {
    do_indent();
    stream << "allocate " << op->buffer << "[" << op->type << " * ";
    print(op->size);
    stream << "]" << endl;
    print(op->body);

    do_indent();
    stream << "free " << op->buffer << endl;
}

void IRPrinter::visit(const Realize *op) {
    do_indent();
    stream << "realize " << op->buffer << "(";
    for (size_t i = 0; i < op->bounds.size(); i++) {
        stream << "[";
        print(op->bounds[i].first);
        stream << ", ";
        print(op->bounds[i].second);
        stream << "]";
        if (i < op->bounds.size() - 1) stream << ", ";
    }
    stream << ") {" << endl;

    indent += 2;
    print(op->body);
    indent -= 2;

    do_indent();
    stream << "}" << endl;
}

void IRPrinter::visit(const Block *op) {
    print(op->first);
    if (op->rest.defined()) print(op->rest);
}

}}
<|endoftext|>


<commit_before>AliAnalysisTaskExtractCascadePbPbRun2 *AddTaskExtractCascade( const TString lMasterJobSessionFlag = "")
{
// Creates, configures and attaches to the train a cascades check task.
   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskExtractCascade", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskExtractCascade", "This task requires an input event handler");
      return NULL;
   }
   TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"

   // Create and configure the task
	 AliAnalysisTaskExtractCascadePbPbRun2 *taskextract = new AliAnalysisTaskExtractCascadePbPbRun2("taskextract");

   mgr->AddTask(taskextract);

   TString outputFileName = AliAnalysisManager::GetCommonFileName();

   outputFileName += ":PWGLFExtractCascade";
   //if (lSwitchIsNuclear) outputFileName += "_AA";
   outputFileName += "_PP";
   if (mgr->GetMCtruthEventHandler()) outputFileName += "_MC";
   //if(lMasterJobSessionFlag.Length()) outputFileName += lMasterJobSessionFlag.Data();

   Printf("Set OutputFileName : \n %s\n", outputFileName.Data() );

   AliAnalysisDataContainer *coutputList = mgr->CreateContainer("clist",
							     TList::Class(),
							     AliAnalysisManager::kOutputContainer,
							     outputFileName );
   AliAnalysisDataContainer *coutputTreeCascade = mgr->CreateContainer("cTreeCascade",
							     TTree::Class(),
							     AliAnalysisManager::kOutputContainer,
							     outputFileName );

   //This one you should merge in file-resident ways...
   coutputTreeCascade->SetSpecialOutput();

   //Recommendation: Tree as a single output slot
   mgr->ConnectInput( taskextract, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(taskextract, 1, coutputList);
   mgr->ConnectOutput(taskextract, 2, coutputTreeCascade);

   return taskextract;
}
<commit_msg>Bug fix in AddTask Macro<commit_after>AliAnalysisTaskExtractCascadePbPbRun2 *AddTaskExtractCascadePbPbRun2( const TString lMasterJobSessionFlag = "")
{
// Creates, configures and attaches to the train a cascades check task.
   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskExtractCascade", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskExtractCascade", "This task requires an input event handler");
      return NULL;
   }
   TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"

   // Create and configure the task
	 AliAnalysisTaskExtractCascadePbPbRun2 *taskextract = new AliAnalysisTaskExtractCascadePbPbRun2("taskextract");

   mgr->AddTask(taskextract);

   TString outputFileName = AliAnalysisManager::GetCommonFileName();

   outputFileName += ":PWGLFExtractCascade";
   //if (lSwitchIsNuclear) outputFileName += "_AA";
   outputFileName += "_PP";
   if (mgr->GetMCtruthEventHandler()) outputFileName += "_MC";
   //if(lMasterJobSessionFlag.Length()) outputFileName += lMasterJobSessionFlag.Data();

   Printf("Set OutputFileName : \n %s\n", outputFileName.Data() );

   AliAnalysisDataContainer *coutputList = mgr->CreateContainer("clist",
							     TList::Class(),
							     AliAnalysisManager::kOutputContainer,
							     outputFileName );
   AliAnalysisDataContainer *coutputTreeCascade = mgr->CreateContainer("cTreeCascade",
							     TTree::Class(),
							     AliAnalysisManager::kOutputContainer,
							     outputFileName );

   //This one you should merge in file-resident ways...
   coutputTreeCascade->SetSpecialOutput();

   //Recommendation: Tree as a single output slot
   mgr->ConnectInput( taskextract, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(taskextract, 1, coutputList);
   mgr->ConnectOutput(taskextract, 2, coutputTreeCascade);

   return taskextract;
}
<|endoftext|>