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

#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/raw_ostream.h"

#include "llvm/ADT/ArrayRef.h"

#include "PrevirtTypes.h"
#include "Specializer.h"

#include <fstream>

using namespace llvm;

namespace previrt
{
  std::string
  specializeName(Function* f, std::vector<std::string>& args)
  {
    args.clear();
    //iam    std::string fn = f->getNameStr();
    std::string fn = f->getName().str();

    int idx = fn.find('(');
    if (idx != -1 && fn[fn.length()-1] == ')') {
      std::string base = fn.substr(0, idx);
      idx++;
      unsigned int st = idx;
      bool in_str = false;
      while (st < fn.length()-1) {
        idx = st;
        while (true) {
          if (fn[idx] == '"') {
            in_str = !in_str;
          } else if (!in_str) {
            if (fn[idx] == ',') {
              args.push_back(fn.substr(st, idx-st));
              break;
            } else if (fn[idx] == ')') {
              args.push_back(fn.substr(st, idx-st));
              break;
            }
          } else {
            if (fn[idx] == '\\') {
              idx += 2;
            }
          }
          idx++;
        }
        st = idx + 1;
      }
      return base;
    } else {
      args.reserve(f->getArgumentList().size());
      for (unsigned int i = 0; i < f->getArgumentList().size(); ++i)
        args.push_back("?");
      //iam      return f->getNameStr();
      return f->getName().str();
    }
  }

  Function*
  specializeFunction(Function *f, Value*const* args)
  // make a copy of f
  // specialize on the arguments, a null means that that argument isn't known
  {
    assert(!f->isDeclaration());
    ValueToValueMapTy vmap;

    unsigned int i = 0;
    unsigned int j = 0;
    std::vector<std::string> argNames;

    std::string baseName = specializeName(f, argNames);

    for (Function::arg_iterator itr = f->arg_begin(); itr != f->arg_end(); itr++, i++) {
      while (argNames[j] != "?") j++;
      if (args[i] != NULL) {
        Value* arg = (Value*) &(*itr);

        assert(arg->getType() == args[i]->getType()
	       && "Specializing argument with concrete value of wrong type!");

        vmap.insert(std::pair<Value*, WeakVH>(arg, args[i]));
        PrevirtType pt = PrevirtType::abstract(args[i]);
        argNames[j] = pt.to_string();
        /*
        if (const ConstantInt* ci = dyn_cast<const ConstantInt> (args[i])) {
          argNames[j] = ci->getValue().toString(10, true);
        } else if (const Constant* c = dyn_cast<const Constant>(args[i])) {
          if (c->isNullValue()) {
            argNames[j] = "null";
          } else {
            assert(false);
          }
        } else if (const )
        } else {
          assert(false);
        }
        */
      }
      j++;
    }
    assert (i == f->getArgumentList().size());

    baseName += "(";
    for (std::vector<std::string>::const_iterator it = argNames.begin(), be = argNames.begin(), en = argNames.end(); it != en; ++it) {
      if (it != be) baseName += ",";
      baseName += *it;
    }
    baseName += ")";

    Function *result = f->getParent()->getFunction(baseName);
    // If specialized function already exists, no reason
    // to create another one. In fact, can cause the process
    // to diverge. XXX This needs to be a more sophisticated
    // check
    if (!result) {
      ClonedCodeInfo info;
      result = llvm::CloneFunction(f, vmap, true, &info);
      result->setName(baseName);
    }

    return result;
  }

  Function*
  specializeFunction(Function *f, const std::vector<Value*>& args)
  {
    assert(!f->isDeclaration());
    assert(f->getArgumentList().size() == args.size());
    Function *nfunc = specializeFunction(f, args.data());

    // Debugging code for detecting some mis-specializations.
    // Requires #include "llvm/Analysis/Verifier.h"
    //errs() << "\nSpecializing " << f->getName() << "...\n";
    //errs() << "Verifying " << nfunc->getName() << "... ";
    //if (llvm::verifyFunction(*nfunc, llvm::ReturnStatusAction)) {
    //	errs() << "ok\n";
    //} else {
    //  errs() << "bad\n";
    //}

    return nfunc;
  }

  /*
   * Specialize a call site and return the new instruction
   */
  Instruction*
  specializeCallSite(Instruction* I,
      llvm::Function* nfunc, const std::vector<unsigned>& perm)
  {
    assert((nfunc->isVarArg() && nfunc->getArgumentList().size() <= perm.size())
        || (!nfunc->isVarArg() && nfunc->getArgumentList().size() == perm.size()));
    const size_t specialized_arg_count = perm.size(); //nfunc->getArgumentList().size();

    Instruction* newInst = NULL;
    if (CallInst* ci = dyn_cast<CallInst>(I)) {

      Value** newOperands = new Value*[specialized_arg_count];
      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands[j] = ci->getArgOperand(perm[j]);
      }

      if (ci->hasName()) {
	newInst = CallInst::Create(nfunc, ArrayRef<Value*>(newOperands, specialized_arg_count), ci->getName());
      } else {
	newInst = CallInst::Create(nfunc, ArrayRef<Value*>(newOperands, specialized_arg_count));
      }
      delete newOperands;

    } else if (InvokeInst* ci = dyn_cast<InvokeInst>(I)) {

      Value** newOperands = new Value*[specialized_arg_count];
      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands[j] = ci->getArgOperand(perm[j]);
      }

      newInst = InvokeInst::Create(nfunc, ci->getNormalDest(),
          ci->getUnwindDest(), ArrayRef<Value*>(newOperands,
          specialized_arg_count), ci->getName());
      delete newOperands;

    } else {
      assert(false && "specializeCallSite got non-callsite");
      return NULL; // Unreachable
    }

    return newInst;
  }

  bool
  canSpecialize(Function* f)
  {
    if (f->isDeclaration())
      return false;
    for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) {
      if (CallInst* ci = dyn_cast<CallInst>(&*I)) {
        if (ci->isInlineAsm()) {
          return false;
        }
      }
    }
    return true;
  }

  GlobalVariable*
  materializeStringLiteral(llvm::Module& m, const char* data)
  {
    Constant* ary = llvm::ConstantDataArray::getString(m.getContext(), data, true);
    GlobalVariable* gv = new GlobalVariable(m, ary->getType(), true, GlobalValue::LinkageTypes::PrivateLinkage, ary, "");
    gv->setConstant(true);

    return gv;
  }

  Constant*
  charStarFromStringConstant(llvm::Module& m, llvm::Constant* v)
  {
    Constant* zero = ConstantInt::getSigned(IntegerType::getInt32Ty(m.getContext()), 0);
    Constant* args[2] = {zero, zero};
    ArrayRef<Constant*> ar_args(args, 2);
    return ConstantExpr::getGetElementPtr(v, ar_args, false);
  }

}
<commit_msg>[FIXED] memory leak. The code was using delete rather than delete[]. The fix does not call delete[] because the dynamic allocation done by new[] was not actually needed.<commit_after>//
// OCCAM
//
// Copyright (c) 2011-2012, SRI International
//
//  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of SRI International nor the names of its contributors may
//   be used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/raw_ostream.h"

#include "llvm/ADT/ArrayRef.h"

#include "PrevirtTypes.h"
#include "Specializer.h"

#include <fstream>

using namespace llvm;

namespace previrt
{
  std::string
  specializeName(Function* f, std::vector<std::string>& args)
  {
    args.clear();
    //iam    std::string fn = f->getNameStr();
    std::string fn = f->getName().str();

    int idx = fn.find('(');
    if (idx != -1 && fn[fn.length()-1] == ')') {
      std::string base = fn.substr(0, idx);
      idx++;
      unsigned int st = idx;
      bool in_str = false;
      while (st < fn.length()-1) {
        idx = st;
        while (true) {
          if (fn[idx] == '"') {
            in_str = !in_str;
          } else if (!in_str) {
            if (fn[idx] == ',') {
              args.push_back(fn.substr(st, idx-st));
              break;
            } else if (fn[idx] == ')') {
              args.push_back(fn.substr(st, idx-st));
              break;
            }
          } else {
            if (fn[idx] == '\\') {
              idx += 2;
            }
          }
          idx++;
        }
        st = idx + 1;
      }
      return base;
    } else {
      args.reserve(f->getArgumentList().size());
      for (unsigned int i = 0; i < f->getArgumentList().size(); ++i)
        args.push_back("?");
      //iam      return f->getNameStr();
      return f->getName().str();
    }
  }

  Function*
  specializeFunction(Function *f, Value*const* args)
  // make a copy of f
  // specialize on the arguments, a null means that that argument isn't known
  {
    assert(!f->isDeclaration());
    ValueToValueMapTy vmap;

    unsigned int i = 0;
    unsigned int j = 0;
    std::vector<std::string> argNames;

    std::string baseName = specializeName(f, argNames);

    for (Function::arg_iterator itr = f->arg_begin(); itr != f->arg_end(); itr++, i++) {
      while (argNames[j] != "?") j++;
      if (args[i] != NULL) {
        Value* arg = (Value*) &(*itr);

        assert(arg->getType() == args[i]->getType()
	       && "Specializing argument with concrete value of wrong type!");

        vmap.insert(std::pair<Value*, WeakVH>(arg, args[i]));
        PrevirtType pt = PrevirtType::abstract(args[i]);
        argNames[j] = pt.to_string();
        /*
        if (const ConstantInt* ci = dyn_cast<const ConstantInt> (args[i])) {
          argNames[j] = ci->getValue().toString(10, true);
        } else if (const Constant* c = dyn_cast<const Constant>(args[i])) {
          if (c->isNullValue()) {
            argNames[j] = "null";
          } else {
            assert(false);
          }
        } else if (const )
        } else {
          assert(false);
        }
        */
      }
      j++;
    }
    assert (i == f->getArgumentList().size());

    baseName += "(";
    for (std::vector<std::string>::const_iterator it = argNames.begin(), be = argNames.begin(), en = argNames.end(); it != en; ++it) {
      if (it != be) baseName += ",";
      baseName += *it;
    }
    baseName += ")";

    Function *result = f->getParent()->getFunction(baseName);
    // If specialized function already exists, no reason
    // to create another one. In fact, can cause the process
    // to diverge. XXX This needs to be a more sophisticated
    // check
    if (!result) {
      ClonedCodeInfo info;
      result = llvm::CloneFunction(f, vmap, true, &info);
      result->setName(baseName);
    }

    return result;
  }

  Function*
  specializeFunction(Function *f, const std::vector<Value*>& args)
  {
    assert(!f->isDeclaration());
    assert(f->getArgumentList().size() == args.size());
    Function *nfunc = specializeFunction(f, args.data());

    // Debugging code for detecting some mis-specializations.
    // Requires #include "llvm/Analysis/Verifier.h"
    //errs() << "\nSpecializing " << f->getName() << "...\n";
    //errs() << "Verifying " << nfunc->getName() << "... ";
    //if (llvm::verifyFunction(*nfunc, llvm::ReturnStatusAction)) {
    //	errs() << "ok\n";
    //} else {
    //  errs() << "bad\n";
    //}

    return nfunc;
  }

  /*
   * Specialize a call site and return the new instruction
   */
  Instruction*
  specializeCallSite(Instruction* I,
      llvm::Function* nfunc, const std::vector<unsigned>& perm)
  {
    assert((nfunc->isVarArg() && nfunc->getArgumentList().size() <= perm.size())
        || (!nfunc->isVarArg() && nfunc->getArgumentList().size() == perm.size()));
    const size_t specialized_arg_count = perm.size(); //nfunc->getArgumentList().size();

    Instruction* newInst = NULL;
    if (CallInst* ci = dyn_cast<CallInst>(I)) {

      std::vector<Value*> newOperands;
      newOperands.reserve (specialized_arg_count);

      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands.push_back (ci->getArgOperand(perm[j]));
      }

      if (ci->hasName()) {
	newInst = CallInst::Create(nfunc, newOperands, ci->getName());
      } else {
	newInst = CallInst::Create(nfunc, newOperands);
      }

    } else if (InvokeInst* ci = dyn_cast<InvokeInst>(I)) {

      std::vector<Value*> newOperands;
      newOperands.reserve(specialized_arg_count);
      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands.push_back(ci->getArgOperand(perm[j]));
      }

      newInst = InvokeInst::Create(nfunc, ci->getNormalDest(),
          ci->getUnwindDest(), newOperands, ci->getName());

    } else {
      assert(false && "specializeCallSite got non-callsite");
      return NULL; // Unreachable
    }

    return newInst;
  }

  bool
  canSpecialize(Function* f)
  {
    if (f->isDeclaration())
      return false;
    for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) {
      if (CallInst* ci = dyn_cast<CallInst>(&*I)) {
        if (ci->isInlineAsm()) {
          return false;
        }
      }
    }
    return true;
  }

  GlobalVariable*
  materializeStringLiteral(llvm::Module& m, const char* data)
  {
    Constant* ary = llvm::ConstantDataArray::getString(m.getContext(), data, true);
    GlobalVariable* gv = new GlobalVariable(m, ary->getType(), true, GlobalValue::LinkageTypes::PrivateLinkage, ary, "");
    gv->setConstant(true);

    return gv;
  }

  Constant*
  charStarFromStringConstant(llvm::Module& m, llvm::Constant* v)
  {
    Constant* zero = ConstantInt::getSigned(IntegerType::getInt32Ty(m.getContext()), 0);
    Constant* args[2] = {zero, zero};
    ArrayRef<Constant*> ar_args(args, 2);
    return ConstantExpr::getGetElementPtr(v, ar_args, false);
  }

}
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XCOMM_HPP
#define XCOMM_HPP

#include <iostream>
#include <string>
#include <functional>
#include <map>
#include <utility>

#include "xguid.hpp"
#include "xmessage.hpp"

namespace xeus
{

    /***********************
     * xtarget declaration *
     ***********************/

    class xcomm;
    class xcomm_manager;

    /**
     * @class xtarget
     * @brief Comm target.
     */
    class XEUS_API xtarget
    {
    public:

        using function_type = std::function<void (const xcomm&, const xmessage&)>;

        xtarget();
        xtarget(const std::string& name, const function_type& callback, xcomm_manager* manager);

        // name accessor
        std::string& name() & noexcept;
        const std::string& name() const & noexcept;
        std::string name() const && noexcept;

        void operator()(const xcomm& comm, const xmessage& request) const;

        void publish_message(const std::string&, xjson, xjson);

        void register_comm(xguid, xcomm*);
        void unregister_comm(xguid);

    private:

        std::string m_name;
        function_type m_callback;
        xcomm_manager* p_manager;
    };

    /*********************
     * xcomm declaration *
     *********************/

    /**
     * @class xcomm
     * @brief Comm object.
     *
     */
    class XEUS_API xcomm
    {
    public:

        using handler_type = std::function<void(const xmessage&)>;

        xcomm() = delete;
        ~xcomm();
        xcomm(xcomm&&);
        xcomm(const xcomm&);
        xcomm(xtarget* target);
        xcomm(xtarget* target, xguid id);

        xcomm& operator=(xcomm&&);
        xcomm& operator=(const xcomm&);

        void open(xjson metadata, xjson data);
        void close(xjson metadata, xjson data);

        xtarget& target() noexcept;
        const xtarget& target() const noexcept;

        void handle_message(const xmessage& request);
        void handle_close(const xmessage& request);

        xguid id() const noexcept;

        template <class T>
        void on_message(T&& handler);
        template <class T>
        void on_close(T&& handler);

    private:

        friend class xcomm_manager;

        /**
         * Send comm message on iopub. Compose iopub message with specified data
         * and rebinds to target's publish_message
         * {
         *    "comm_id": m_id,
         *    "data": data
         * }
         */
        void publish_message(const std::string& msg_type, xjson metadata, xjson data, const std::string&);

        handler_type m_close_handler;
        handler_type m_message_handler;
        xtarget* p_target;
        xguid m_id;
        bool m_moved;
    };

    /*****************************
     * xcomm_manager declaration *
     *****************************/

    class xkernel_core;

    /**
     * @class xcomm_manager
     * @brief Manager and registry for comms and comm targets in the kernel.
     */
    class XEUS_API xcomm_manager
    {
    public:

        xcomm_manager(xkernel_core* kernel = nullptr);

        using target_function_type = xtarget::function_type;

        void register_comm_target(const std::string& target_name, const target_function_type& callback);
        void unregister_comm_target(const std::string& target_name);

        void comm_open(const xmessage& request);
        void comm_close(const xmessage& request);
        void comm_msg(const xmessage& request);

        std::map<xguid, xcomm*>& comms() & noexcept;
        const std::map<xguid, xcomm*>& comms() const & noexcept;
        std::map<xguid, xcomm*> comms() const && noexcept;

        xtarget* target(const std::string& target_name);

        void register_comm(xguid, xcomm*);
        void unregister_comm(xguid);

    private:

        friend class xtarget;

        xjson get_metadata() const;

        std::map<xguid, xcomm*> m_comms;
        std::map<std::string, xtarget> m_targets;
        xkernel_core* p_kernel;
    };

    /**************************
     * xtarget implementation *
     **************************/

    inline xtarget::xtarget()
        : m_name(), m_callback(), p_manager(nullptr)
    {
    }

    inline xtarget::xtarget(const std::string& name, const function_type& callback, xcomm_manager* manager)
        : m_name(name), m_callback(callback), p_manager(manager)
    {
    }

    inline std::string& xtarget::name() & noexcept
    {
        return m_name;
    }

    inline const std::string& xtarget::name() const & noexcept
    {
        return m_name;
    }

    inline std::string xtarget::name() const && noexcept
    {
        return m_name;
    }

    inline void xtarget::operator()(const xcomm& comm, const xmessage& message) const
    {
        return m_callback(comm, message);
    }

    inline void xtarget::register_comm(xguid id, xcomm* comm)
    {
        p_manager->register_comm(id, comm);
    }

    inline void xtarget::unregister_comm(xguid id)
    {
        p_manager->unregister_comm(id);
    }

    /************************
     * xcomm implementation *
     ************************/

    inline xtarget& xcomm::target() noexcept
    {
        return *p_target;
    }

    inline const xtarget& xcomm::target() const noexcept
    {
        return *p_target;
    }

    inline void xcomm::handle_close(const xmessage& message)
    {
        if(m_close_handler)
        {
            m_close_handler(message);
        }
    }

    inline void xcomm::handle_message(const xmessage& message)
    {
        if(m_message_handler)
        {
            m_message_handler(message);
        }
    }

    inline void xcomm::publish_message(const std::string& msg_type, xjson metadata, xjson data,
                                       const std::string& target_name)
    {
        xjson content;
        content["comm_id"] = guid_to_hex(m_id);
        content["target_name"] = target_name;
        content["data"] = std::move(data);
        target().publish_message(msg_type, std::move(metadata), std::move(content));
    }

    inline xcomm::xcomm(xcomm&& comm)
        : m_close_handler(std::move(comm.m_close_handler)),
          m_message_handler(std::move(comm.m_message_handler)),
          p_target(std::move(comm.p_target)),
          m_id(std::move(comm.m_id))
    {
        comm.m_moved = true;
        // Even though `comm` was not unregistered, the pointer in the container has to be changed.
        p_target->register_comm(m_id, this);
    }

    inline xcomm::xcomm(const xcomm& comm)
        : p_target(comm.p_target), m_id()
    {
        p_target->register_comm(m_id, this);
    }

    inline xcomm& xcomm::operator=(xcomm&& comm)
    {
        m_close_handler = std::move(comm.m_close_handler);
        m_message_handler = std::move(comm.m_message_handler);
        p_target = std::move(comm.p_target);
        m_id = std::move(comm.m_id);
        comm.m_moved = true;
        // Even though `comm` was not unregistered, the pointer in the container has to be changed.
        p_target->register_comm(m_id, this);
        return *this;
    }

    inline xcomm& xcomm::operator=(const xcomm& comm)
    {
        p_target = comm.p_target;
        m_id = xguid();
        p_target->register_comm(m_id, this);
        return *this;
    }

    inline xcomm::xcomm(xtarget* target)
        : p_target(target), m_id()
    {
        p_target->register_comm(m_id, this);
    }

    inline xcomm::xcomm(xtarget* target, xguid id)
        : p_target(target), m_id(id)
    {
        p_target->register_comm(m_id, this);
    }

    inline xcomm::~xcomm()
    {
        if (!m_moved)
        {
            p_target->unregister_comm(m_id);
        }
    }

    inline void xcomm::open(xjson metadata, xjson data)
    {
        publish_message("comm_open", std::move(metadata), std::move(data), p_target->name());
    }

    inline void xcomm::close(xjson metadata, xjson data)
    {
        publish_message("comm_close", std::move(metadata), std::move(data), p_target->name());
    }

    inline xguid xcomm::id() const noexcept
    {
        return m_id;
    }

    template <class T>
    inline void xcomm::on_message(T&& handler)
    {
        m_message_handler = std::forward<T>(handler);
    }

    template <class T>
    inline void xcomm::on_close(T&& handler)
    {
        m_close_handler = std::forward<T>(handler);
    }

    /********************************
     * xcomm_manager implementation *
     ********************************/

    inline xtarget* xcomm_manager::target(const std::string& target_name)
    {
        return &m_targets[target_name];
    }

    inline std::map<xguid, xcomm*>& xcomm_manager::comms() & noexcept
    {
        return m_comms;
    }

    inline const std::map<xguid, xcomm*>& xcomm_manager::comms() const & noexcept
    {
        return m_comms;
    }

    inline std::map<xguid, xcomm*> xcomm_manager::comms() const && noexcept
    {
        return m_comms;
    }

}

#endif
<commit_msg>comm registry fixup<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XCOMM_HPP
#define XCOMM_HPP

#include <iostream>
#include <string>
#include <functional>
#include <map>
#include <utility>

#include "xguid.hpp"
#include "xmessage.hpp"

namespace xeus
{

    /***********************
     * xtarget declaration *
     ***********************/

    class xcomm;
    class xcomm_manager;

    /**
     * @class xtarget
     * @brief Comm target.
     */
    class XEUS_API xtarget
    {
    public:

        using function_type = std::function<void (const xcomm&, const xmessage&)>;

        xtarget();
        xtarget(const std::string& name, const function_type& callback, xcomm_manager* manager);

        // name accessor
        std::string& name() & noexcept;
        const std::string& name() const & noexcept;
        std::string name() const && noexcept;

        void operator()(const xcomm& comm, const xmessage& request) const;

        void publish_message(const std::string&, xjson, xjson);

        void register_comm(xguid, xcomm*);
        void unregister_comm(xguid);

    private:

        std::string m_name;
        function_type m_callback;
        xcomm_manager* p_manager;
    };

    /*********************
     * xcomm declaration *
     *********************/

    /**
     * @class xcomm
     * @brief Comm object.
     *
     */
    class XEUS_API xcomm
    {
    public:

        using handler_type = std::function<void(const xmessage&)>;

        xcomm() = delete;
        ~xcomm();
        xcomm(xcomm&&);
        xcomm(const xcomm&);
        xcomm(xtarget* target);
        xcomm(xtarget* target, xguid id);

        xcomm& operator=(xcomm&&);
        xcomm& operator=(const xcomm&);

        void open(xjson metadata, xjson data);
        void close(xjson metadata, xjson data);

        xtarget& target() noexcept;
        const xtarget& target() const noexcept;

        void handle_message(const xmessage& request);
        void handle_close(const xmessage& request);

        xguid id() const noexcept;

        template <class T>
        void on_message(T&& handler);
        template <class T>
        void on_close(T&& handler);

    private:

        friend class xcomm_manager;

        /**
         * Send comm message on iopub. Compose iopub message with specified data
         * and rebinds to target's publish_message
         * {
         *    "comm_id": m_id,
         *    "data": data
         * }
         */
        void publish_message(const std::string& msg_type, xjson metadata, xjson data, const std::string&);

        handler_type m_close_handler;
        handler_type m_message_handler;
        xtarget* p_target;
        xguid m_id;
        bool m_moved;
    };

    /*****************************
     * xcomm_manager declaration *
     *****************************/

    class xkernel_core;

    /**
     * @class xcomm_manager
     * @brief Manager and registry for comms and comm targets in the kernel.
     */
    class XEUS_API xcomm_manager
    {
    public:

        xcomm_manager(xkernel_core* kernel = nullptr);

        using target_function_type = xtarget::function_type;

        void register_comm_target(const std::string& target_name, const target_function_type& callback);
        void unregister_comm_target(const std::string& target_name);

        void comm_open(const xmessage& request);
        void comm_close(const xmessage& request);
        void comm_msg(const xmessage& request);

        std::map<xguid, xcomm*>& comms() & noexcept;
        const std::map<xguid, xcomm*>& comms() const & noexcept;
        std::map<xguid, xcomm*> comms() const && noexcept;

        xtarget* target(const std::string& target_name);

        void register_comm(xguid, xcomm*);
        void unregister_comm(xguid);

    private:

        friend class xtarget;

        xjson get_metadata() const;

        std::map<xguid, xcomm*> m_comms;
        std::map<std::string, xtarget> m_targets;
        xkernel_core* p_kernel;
    };

    /**************************
     * xtarget implementation *
     **************************/

    inline xtarget::xtarget()
        : m_name(), m_callback(), p_manager(nullptr)
    {
    }

    inline xtarget::xtarget(const std::string& name, const function_type& callback, xcomm_manager* manager)
        : m_name(name), m_callback(callback), p_manager(manager)
    {
    }

    inline std::string& xtarget::name() & noexcept
    {
        return m_name;
    }

    inline const std::string& xtarget::name() const & noexcept
    {
        return m_name;
    }

    inline std::string xtarget::name() const && noexcept
    {
        return m_name;
    }

    inline void xtarget::operator()(const xcomm& comm, const xmessage& message) const
    {
        return m_callback(comm, message);
    }

    inline void xtarget::register_comm(xguid id, xcomm* comm)
    {
        p_manager->register_comm(id, comm);
    }

    inline void xtarget::unregister_comm(xguid id)
    {
        p_manager->unregister_comm(id);
    }

    /************************
     * xcomm implementation *
     ************************/

    inline xtarget& xcomm::target() noexcept
    {
        return *p_target;
    }

    inline const xtarget& xcomm::target() const noexcept
    {
        return *p_target;
    }

    inline void xcomm::handle_close(const xmessage& message)
    {
        if(m_close_handler)
        {
            m_close_handler(message);
        }
    }

    inline void xcomm::handle_message(const xmessage& message)
    {
        if(m_message_handler)
        {
            m_message_handler(message);
        }
    }

    inline void xcomm::publish_message(const std::string& msg_type, xjson metadata, xjson data,
                                       const std::string& target_name)
    {
        xjson content;
        content["comm_id"] = guid_to_hex(m_id);
        content["target_name"] = target_name;
        content["data"] = std::move(data);
        target().publish_message(msg_type, std::move(metadata), std::move(content));
    }

    inline xcomm::xcomm(xcomm&& comm)
        : m_close_handler(std::move(comm.m_close_handler)),
          m_message_handler(std::move(comm.m_message_handler)),
          p_target(std::move(comm.p_target)),
          m_id(std::move(comm.m_id))
    {
        comm.m_moved = true;
        p_target->register_comm(m_id, this);
    }

    inline xcomm::xcomm(const xcomm& comm)
        : p_target(comm.p_target), m_id()
    {
        p_target->register_comm(m_id, this);
    }

    inline xcomm& xcomm::operator=(xcomm&& comm)
    {
        m_close_handler = std::move(comm.m_close_handler);
        m_message_handler = std::move(comm.m_message_handler);
        p_target = std::move(comm.p_target);
        p_target->unregister_comm(m_id);
        m_id = std::move(comm.m_id);
        p_target->register_comm(m_id, this);
        comm.m_moved = true;
        return *this;
    }

    inline xcomm& xcomm::operator=(const xcomm& comm)
    {
        p_target = comm.p_target;
        m_id = xguid();
        p_target->register_comm(m_id, this);
        return *this;
    }

    inline xcomm::xcomm(xtarget* target)
        : p_target(target), m_id()
    {
        p_target->register_comm(m_id, this);
    }

    inline xcomm::xcomm(xtarget* target, xguid id)
        : p_target(target), m_id(id)
    {
        p_target->register_comm(m_id, this);
    }

    inline xcomm::~xcomm()
    {
        if (!m_moved)
        {
            p_target->unregister_comm(m_id);
        }
    }

    inline void xcomm::open(xjson metadata, xjson data)
    {
        publish_message("comm_open", std::move(metadata), std::move(data), p_target->name());
    }

    inline void xcomm::close(xjson metadata, xjson data)
    {
        publish_message("comm_close", std::move(metadata), std::move(data), p_target->name());
    }

    inline xguid xcomm::id() const noexcept
    {
        return m_id;
    }

    template <class T>
    inline void xcomm::on_message(T&& handler)
    {
        m_message_handler = std::forward<T>(handler);
    }

    template <class T>
    inline void xcomm::on_close(T&& handler)
    {
        m_close_handler = std::forward<T>(handler);
    }

    /********************************
     * xcomm_manager implementation *
     ********************************/

    inline xtarget* xcomm_manager::target(const std::string& target_name)
    {
        return &m_targets[target_name];
    }

    inline std::map<xguid, xcomm*>& xcomm_manager::comms() & noexcept
    {
        return m_comms;
    }

    inline const std::map<xguid, xcomm*>& xcomm_manager::comms() const & noexcept
    {
        return m_comms;
    }

    inline std::map<xguid, xcomm*> xcomm_manager::comms() const && noexcept
    {
        return m_comms;
    }

}

#endif
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * CompressorFactory.cpp :
 *
 *  Created on: Sep 29, 2021
 *      Author: Jason Wang jason.ruonan.wang@gmail.com
 */

#include "CompressorFactory.h"
#include "adios2/core/Operator.h"
#include "adios2/helper/adiosFunctions.h"
#include "adios2/operator/compress/CompressNull.h"
#include <numeric>

#ifdef ADIOS2_HAVE_BLOSC
#include "adios2/operator/compress/CompressBlosc.h"
#endif

#ifdef ADIOS2_HAVE_BZIP2
#include "adios2/operator/compress/CompressBZIP2.h"
#endif

#ifdef ADIOS2_HAVE_LIBPRESSIO
#include "adios2/operator/compress/CompressLibPressio.h"
#endif

#ifdef ADIOS2_HAVE_MGARD
#include "adios2/operator/compress/CompressMGARD.h"
#endif

#ifdef ADIOS2_HAVE_PNG
#include "adios2/operator/compress/CompressPNG.h"
#endif

#ifdef ADIOS2_HAVE_MHS
#include "adios2/operator/compress/CompressSirius.h"
#endif

#ifdef ADIOS2_HAVE_SZ
#include "adios2/operator/compress/CompressSZ.h"
#endif

#ifdef ADIOS2_HAVE_ZFP
#include "adios2/operator/compress/CompressZFP.h"
#endif

namespace adios2
{
namespace core
{
namespace compress
{

size_t Compress(const char *dataIn, const Dims &blockStart,
                const Dims &blockCount, const DataType dataType,
                char *bufferOut, const Params &parameters,
                const std::string &compressorType)
{
    size_t ret;
    try
    {
        if (compressorType == "blosc")
        {
#ifdef ADIOS2_HAVE_BLOSC
            CompressBlosc c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with BLOSC, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "bzip2")
        {
#ifdef ADIOS2_HAVE_BZIP2
            CompressBZIP2 c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with BZIP2, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "libpressio")
        {
#ifdef ADIOS2_HAVE_LIBPRESSIO
            CompressLibPressio c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with LibPressio, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "mgard")
        {
#ifdef ADIOS2_HAVE_MGARD
            CompressMGARD c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with MGARD, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "png")
        {
#ifdef ADIOS2_HAVE_PNG
            CompressPNG c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't compile with PNG, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        else if (compressorType == "sirius")
        {
#ifdef ADIOS2_HAVE_MHS
            CompressSirius c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't enable MHS, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        else if (compressorType == "sz")
        {
#ifdef ADIOS2_HAVE_SZ
            CompressSZ c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't compile with SZ, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        else if (compressorType == "zfp")
        {
#ifdef ADIOS2_HAVE_ZFP
            CompressZFP c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't compile with ZFP, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        if (ret == 0)
        {
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "compressor " + compressorType +
                    " failed with returned buffer size 0, compression disabled",
                helper::EXCEPTION);
        }
        else if (ret > helper::GetTotalSize(blockCount,
                                            helper::GetDataTypeSize(dataType)))
        {
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "compressor " + compressorType +
                            " produced buffer larger than uncompressed data, "
                            "compression disabled",
                        helper::EXCEPTION);
        }
    }
    catch (std::exception &e)
    {
        helper::Log("Operator", "CompressorFactory", "Compress", e.what(),
                    helper::WARNING);
        CompressNull c({});
        ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                        parameters);
    }
    return ret;
}

size_t Decompress(const char *bufferIn, const size_t sizeIn, char *dataOut)
{
    Operator::OperatorType compressorType;
    std::memcpy(&compressorType, bufferIn, 1);

    if (compressorType == Operator::COMPRESS_BLOSC)
    {
#ifdef ADIOS2_HAVE_BLOSC
        compress::CompressBlosc op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with BLOSC", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_BZIP2)
    {
#ifdef ADIOS2_HAVE_BZIP2
        compress::CompressBZIP2 op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with BZIP2", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_LIBPRESSIO)
    {
#ifdef ADIOS2_HAVE_LIBPRESSIO
        compress::CompressLibPressio op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with LibPressio", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_MGARD)
    {
#ifdef ADIOS2_HAVE_MGARD
        compress::CompressMGARD op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with MGARD", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_PNG)
    {
#ifdef ADIOS2_HAVE_PNG
        compress::CompressPNG op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with PNG", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_SIRIUS)
    {
#ifdef ADIOS2_HAVE_MHS
        compress::CompressSirius op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't enable MHS", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_SZ)
    {
#ifdef ADIOS2_HAVE_SZ
        compress::CompressSZ op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with SZ", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_ZFP)
    {
#ifdef ADIOS2_HAVE_ZFP
        compress::CompressZFP op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with ZFP", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_NULL)
    {
        compress::CompressNull op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
    }

    return 0;
}

} // end namespace compress
} // end namespace core
} // end namespace adios2
<commit_msg>fix warning<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * CompressorFactory.cpp :
 *
 *  Created on: Sep 29, 2021
 *      Author: Jason Wang jason.ruonan.wang@gmail.com
 */

#include "CompressorFactory.h"
#include "adios2/core/Operator.h"
#include "adios2/helper/adiosFunctions.h"
#include "adios2/operator/compress/CompressNull.h"
#include <numeric>

#ifdef ADIOS2_HAVE_BLOSC
#include "adios2/operator/compress/CompressBlosc.h"
#endif

#ifdef ADIOS2_HAVE_BZIP2
#include "adios2/operator/compress/CompressBZIP2.h"
#endif

#ifdef ADIOS2_HAVE_LIBPRESSIO
#include "adios2/operator/compress/CompressLibPressio.h"
#endif

#ifdef ADIOS2_HAVE_MGARD
#include "adios2/operator/compress/CompressMGARD.h"
#endif

#ifdef ADIOS2_HAVE_PNG
#include "adios2/operator/compress/CompressPNG.h"
#endif

#ifdef ADIOS2_HAVE_MHS
#include "adios2/operator/compress/CompressSirius.h"
#endif

#ifdef ADIOS2_HAVE_SZ
#include "adios2/operator/compress/CompressSZ.h"
#endif

#ifdef ADIOS2_HAVE_ZFP
#include "adios2/operator/compress/CompressZFP.h"
#endif

namespace adios2
{
namespace core
{
namespace compress
{

size_t Compress(const char *dataIn, const Dims &blockStart,
                const Dims &blockCount, const DataType dataType,
                char *bufferOut, const Params &parameters,
                const std::string &compressorType)
{
    size_t ret = 0;
    try
    {
        if (compressorType == "blosc")
        {
#ifdef ADIOS2_HAVE_BLOSC
            CompressBlosc c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with BLOSC, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "bzip2")
        {
#ifdef ADIOS2_HAVE_BZIP2
            CompressBZIP2 c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with BZIP2, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "libpressio")
        {
#ifdef ADIOS2_HAVE_LIBPRESSIO
            CompressLibPressio c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with LibPressio, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "mgard")
        {
#ifdef ADIOS2_HAVE_MGARD
            CompressMGARD c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "ADIOS2 didn't compile with MGARD, compression disabled",
                helper::EXCEPTION);
#endif
        }
        else if (compressorType == "png")
        {
#ifdef ADIOS2_HAVE_PNG
            CompressPNG c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't compile with PNG, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        else if (compressorType == "sirius")
        {
#ifdef ADIOS2_HAVE_MHS
            CompressSirius c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't enable MHS, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        else if (compressorType == "sz")
        {
#ifdef ADIOS2_HAVE_SZ
            CompressSZ c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't compile with SZ, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        else if (compressorType == "zfp")
        {
#ifdef ADIOS2_HAVE_ZFP
            CompressZFP c({});
            ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                            parameters);
#else
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "ADIOS2 didn't compile with ZFP, compression disabled",
                        helper::EXCEPTION);
#endif
        }
        if (ret == 0)
        {
            helper::Log(
                "Operator", "CompressorFactory", "Compress",
                "compressor " + compressorType +
                    " failed with returned buffer size 0, compression disabled",
                helper::EXCEPTION);
        }
        else if (ret > helper::GetTotalSize(blockCount,
                                            helper::GetDataTypeSize(dataType)))
        {
            helper::Log("Operator", "CompressorFactory", "Compress",
                        "compressor " + compressorType +
                            " produced buffer larger than uncompressed data, "
                            "compression disabled",
                        helper::EXCEPTION);
        }
    }
    catch (std::exception &e)
    {
        helper::Log("Operator", "CompressorFactory", "Compress", e.what(),
                    helper::WARNING);
        CompressNull c({});
        ret = c.Operate(dataIn, blockStart, blockCount, dataType, bufferOut,
                        parameters);
    }
    return ret;
}

size_t Decompress(const char *bufferIn, const size_t sizeIn, char *dataOut)
{
    Operator::OperatorType compressorType;
    std::memcpy(&compressorType, bufferIn, 1);

    if (compressorType == Operator::COMPRESS_BLOSC)
    {
#ifdef ADIOS2_HAVE_BLOSC
        compress::CompressBlosc op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with BLOSC", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_BZIP2)
    {
#ifdef ADIOS2_HAVE_BZIP2
        compress::CompressBZIP2 op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with BZIP2", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_LIBPRESSIO)
    {
#ifdef ADIOS2_HAVE_LIBPRESSIO
        compress::CompressLibPressio op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with LibPressio", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_MGARD)
    {
#ifdef ADIOS2_HAVE_MGARD
        compress::CompressMGARD op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with MGARD", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_PNG)
    {
#ifdef ADIOS2_HAVE_PNG
        compress::CompressPNG op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with PNG", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_SIRIUS)
    {
#ifdef ADIOS2_HAVE_MHS
        compress::CompressSirius op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't enable MHS", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_SZ)
    {
#ifdef ADIOS2_HAVE_SZ
        compress::CompressSZ op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with SZ", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_ZFP)
    {
#ifdef ADIOS2_HAVE_ZFP
        compress::CompressZFP op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
#else
        helper::Log("Operator", "CompressorFactory", "Compress",
                    "ADIOS2 didn't compile with ZFP", helper::EXCEPTION);
#endif
    }
    else if (compressorType == Operator::COMPRESS_NULL)
    {
        compress::CompressNull op({});
        return op.InverseOperate(bufferIn, sizeIn, dataOut);
    }

    return 0;
}

} // end namespace compress
} // end namespace core
} // end namespace adios2
<|endoftext|>


<commit_before>/*
   Copyright (c) 2019 University of Oregon
   Distributed under the Boost Software License, Version 1.0. (See accompanying
   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#include "tautimer.hpp"
/* If not enabled, macro out all of the code in this file. */
#if defined(TAU_USE_STUBS)

#include <unistd.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
#include <iostream>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <thread>

/* Clean assertion handling */
inline void _tautimer_assert(const char *expression, const char *file, int line)
{
    fprintf(stderr, "Assertion '%s' failed, file '%s' line '%d'.", expression,
            file, line);
    abort();
}

#ifdef NDEBUG
#define TAUTIMER_ASSERT(EXPRESSION) ((void)0)
#else
#define TAUTIMER_ASSERT(EXPRESSION)                                            \
    ((EXPRESSION) ? (void)0 : _tautimer_assert(#EXPRESSION, __FILE__, __LINE__))
#endif

/* some global static variables to check which thread we are on */
pid_t mypid(0);
thread_local uint64_t mytid(0UL);
/* unfortunately, the C++ support just tells us
 * that the ID is "uninitialized thread"
 * on OSX when the library is loaded.  Bummer. */
std::thread::id main_thread_id = std::this_thread::get_id();

/* Make sure that the TauTimer singleton is constructed when the
 * library is loaded.  This will ensure (on linux, anyway) that
 * we can assert that we have initialized it on the main thread. */
static void __attribute__((constructor)) initialize_library(void);

/* Function pointer types */

typedef int (*Tau_init_type)(int argc, char **argv);
typedef int (*Tau_register_thread_type)(void);
typedef int (*Tau_create_top_level_timer_if_necessary_type)(void);
typedef int (*Tau_start_type)(const char *);
typedef int (*Tau_stop_type)(const char *);
typedef int (*Tau_exit_type)(const char *);
typedef int (*Tau_dump_prefix_type)(const char *prefix);
typedef int (*Tau_set_node_type)(int);
typedef int (*Tau_profile_exit_all_threads_type)(void);
typedef int (*Tau_get_thread_type)(void);
typedef int (*Tau_profile_exit_all_tasks_type)(void);
typedef int (*Tau_global_stop_type)(void);
typedef int (*Tau_trigger_context_event_type)(char *, double);
typedef int (*Tau_metadata_type)(const char *, const char *);
typedef void (*Tau_destructor_trigger_type)(void);

/* Function pointers */

int (*my_Tau_init)(int, char **) = NULL;
int (*my_Tau_register_thread)(void) = NULL;
int (*my_Tau_create_top_level_timer_if_necessary)(void) = NULL;
int (*my_Tau_start)(const char *) = NULL;
int (*my_Tau_stop)(const char *) = NULL;
int (*my_Tau_exit)(const char *) = NULL;
int (*my_Tau_set_node)(int) = NULL;
int (*my_Tau_dump_prefix)(const char *prefix) = NULL;
int (*my_Tau_profile_exit_all_threads)(void) = NULL;
int (*my_Tau_get_thread)(void) = NULL;
int (*my_Tau_profile_exit_all_tasks)(void) = NULL;
int (*my_Tau_global_stop)(void) = NULL;
int (*my_Tau_trigger_context_event)(char *, double) = NULL;
int (*my_Tau_metadata)(const char *, const char *) = NULL;
void (*my_Tau_destructor_trigger)(void) = NULL;

static void initialize_library(void)
{
    // initialize the library when it is loaded
    static taustubs::TauTimer &tt = taustubs::TauTimer::get();
}

void open_preload_libraries(void)
{
/* We might be in a static executable.  Get the ld_preload variable */
#if defined(__APPLE__) && defined(__MACH__)
    const char *envvar = "DYLD_PRELOAD";
#else
    const char *envvar = "LD_PRELOAD";
#endif
    const char *preload = getenv(envvar);
    if (preload != NULL)
    {
        // fprintf(stderr, "%s:\n%s\n", envvar, preload);
        /* tokenize it */
        char *token = strtok((char *)preload, ":");
        while (token)
        {
            printf("token: %s\n", token);
            /* then, dlopen() first and re-try the dlsym() call. */
            dlopen(token, RTLD_LAZY);
            token = strtok(NULL, ":");
        }
    }
    // fprintf(stderr, "%s not set!\n", envvar);
}

int assign_function_pointers(void)
{
    my_Tau_init = (Tau_init_type)dlsym(RTLD_DEFAULT, "Tau_init");
    if (my_Tau_init == NULL)
    {
        open_preload_libraries();
        my_Tau_init = (Tau_init_type)dlsym(RTLD_DEFAULT, "Tau_init");
        if (my_Tau_init == NULL)
        {
            /* Optional - print an error message, because TAU wasn't preloaded!
             */
            // fprintf(stderr, "TAU libraries not loaded, TAU support
            // unavailable\n%s\n", dlerror());
            return 1;
        }
    }
    my_Tau_register_thread =
        (Tau_register_thread_type)dlsym(RTLD_DEFAULT, "Tau_register_thread");
    my_Tau_create_top_level_timer_if_necessary =
        (Tau_create_top_level_timer_if_necessary_type)dlsym(
            RTLD_DEFAULT, "Tau_create_top_level_timer_if_necessary");
    my_Tau_start = (Tau_start_type)dlsym(RTLD_DEFAULT, "Tau_start");
    my_Tau_stop = (Tau_stop_type)dlsym(RTLD_DEFAULT, "Tau_stop");
    my_Tau_dump_prefix =
        (Tau_dump_prefix_type)dlsym(RTLD_DEFAULT, "Tau_dump_prefix");
    my_Tau_exit = (Tau_exit_type)dlsym(RTLD_DEFAULT, "Tau_exit");
    my_Tau_set_node = (Tau_set_node_type)dlsym(RTLD_DEFAULT, "Tau_set_node");
    my_Tau_profile_exit_all_threads = (Tau_profile_exit_all_threads_type)dlsym(
        RTLD_DEFAULT, "Tau_profile_exit_all_threads");
    my_Tau_get_thread =
        (Tau_get_thread_type)dlsym(RTLD_DEFAULT, "Tau_get_thread");
    my_Tau_profile_exit_all_tasks = (Tau_profile_exit_all_tasks_type)dlsym(
        RTLD_DEFAULT, "Tau_profile_exit_all_tasks");
    my_Tau_global_stop =
        (Tau_global_stop_type)dlsym(RTLD_DEFAULT, "Tau_global_stop");
    my_Tau_trigger_context_event = (Tau_trigger_context_event_type)dlsym(
        RTLD_DEFAULT, "Tau_trigger_context_event");
    my_Tau_metadata = (Tau_metadata_type)dlsym(RTLD_DEFAULT, "Tau_metadata");
    my_Tau_destructor_trigger = (Tau_destructor_trigger_type)dlsym(
        RTLD_DEFAULT, "Tau_destructor_trigger");
    return 0;
}

int tau_stub_initialize_simple_(void)
{
    if (assign_function_pointers() == 1)
    {
        return 1;
    }
    int _argc = 1;
    const char *_dummy = "";
    char *_argv[1];
    _argv[0] = (char *)(_dummy);
    my_Tau_init(_argc, _argv);
    // Not necessary to set the node id, the TAU MPI_Init wrapper will do that
    my_Tau_create_top_level_timer_if_necessary();
    return 0;
}

void tau_stub_exit(void)
{
    if (my_Tau_destructor_trigger != NULL)
    {
        my_Tau_destructor_trigger();
    }
    if (my_Tau_profile_exit_all_threads != NULL)
    {
        my_Tau_profile_exit_all_threads();
    }
    if (my_Tau_exit != NULL)
    {
        my_Tau_exit("stub exiting");
    }
}

namespace taustubs
{

thread_local bool TauTimer::thread_seen(false);

// constructor
TauTimer::TauTimer(void) : initialized(false)
{
    // Confirm that we are instantializing this singleton on the main thread!
    mypid = getpid();
#if defined(__APPLE__) && defined(__MACH__)
    // why should Apple support gettid? BE DIFFERENT, BABY!
    pthread_threadid_np(NULL, &mytid);
#else
    mytid = (uint64_t)syscall(__NR_gettid);
#endif
    if (tau_stub_initialize_simple_() == 0)
        initialized = true;
    thread_seen = true;
}

// The only way to get an instance of this class
TauTimer &TauTimer::get(void)
{
    static std::unique_ptr<TauTimer> instance(new TauTimer);
    if (!thread_seen && instance.get()->initialized)
    {
        _RegisterThread();
    }
    return *instance;
}

// used internally to the class
inline void TauTimer::_RegisterThread(void)
{
    if (!thread_seen)
    {
// Confirm that we are NOT on the main thread!
#if defined(__APPLE__) && defined(__MACH__)
        // why should Apple support gettid? BE DIFFERENT, BABY!
        pthread_threadid_np(NULL, &mytid);
#else
        mytid = (uint64_t)syscall(__NR_gettid);
#endif
        my_Tau_register_thread();
        my_Tau_create_top_level_timer_if_necessary();
        thread_seen = true;
    }
}

// external API call
void TauTimer::RegisterThread(void)
{
    if (!TauTimer::get().initialized)
        return;
    _RegisterThread();
}

void TauTimer::Start(const char *timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_start(timer_name);
}

void TauTimer::Start(const std::string &timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_start(timer_name.c_str());
}

void TauTimer::Stop(const char *timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_stop(timer_name);
}

void TauTimer::Stop(const std::string &timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_stop(timer_name.c_str());
}

void TauTimer::SampleCounter(const char *name, const double value)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_trigger_context_event(const_cast<char *>(name), value);
}

void TauTimer::MetaData(const char *name, const char *value)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_metadata(name, value);
}

TauTimer::~TauTimer(void) { tau_stub_exit(); }

} // namespace taustubs

/* Expose the API to C and Fortran */

extern "C" {
// C Bindings
void TauTimer_RegisterThread() { taustubs::TauTimer::RegisterThread(); }

void TauTimer_Start(const char *timer_name)
{
    taustubs::TauTimer::Start(timer_name);
}

void TauTimer_Stop(const char *timer_name)
{
    taustubs::TauTimer::Stop(timer_name);
}

void TauTimer_SampleCounter(const char *name, const double value)
{
    taustubs::TauTimer::SampleCounter(name, value);
}

void TauTimer_MetaData(const char *name, const char *value)
{
    taustubs::TauTimer::MetaData(name, value);
}

// Fortran Bindings
void tautimer_registerthread_() { taustubs::TauTimer::RegisterThread(); }

void tautimer_start_(const char *timer_name)
{
    taustubs::TauTimer::Start(timer_name);
}

void tautimer_stop_(const char *timer_name)
{
    taustubs::TauTimer::Stop(timer_name);
}

void tautimer_samplecounter_(const char *name, const double value)
{
    taustubs::TauTimer::SampleCounter(name, value);
}

void tautimer_metadata_(const char *name, const char *value)
{
    taustubs::TauTimer::MetaData(name, value);
}

} // extern "C"

#endif // defined(TAU_USE_STUBS)
<commit_msg>Removing printf statement<commit_after>/*
   Copyright (c) 2019 University of Oregon
   Distributed under the Boost Software License, Version 1.0. (See accompanying
   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#include "tautimer.hpp"
/* If not enabled, macro out all of the code in this file. */
#if defined(TAU_USE_STUBS)

#include <unistd.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
#include <iostream>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <thread>

/* Clean assertion handling */
inline void _tautimer_assert(const char *expression, const char *file, int line)
{
    fprintf(stderr, "Assertion '%s' failed, file '%s' line '%d'.", expression,
            file, line);
    abort();
}

#ifdef NDEBUG
#define TAUTIMER_ASSERT(EXPRESSION) ((void)0)
#else
#define TAUTIMER_ASSERT(EXPRESSION)                                            \
    ((EXPRESSION) ? (void)0 : _tautimer_assert(#EXPRESSION, __FILE__, __LINE__))
#endif

/* some global static variables to check which thread we are on */
pid_t mypid(0);
thread_local uint64_t mytid(0UL);
/* unfortunately, the C++ support just tells us
 * that the ID is "uninitialized thread"
 * on OSX when the library is loaded.  Bummer. */
std::thread::id main_thread_id = std::this_thread::get_id();

/* Make sure that the TauTimer singleton is constructed when the
 * library is loaded.  This will ensure (on linux, anyway) that
 * we can assert that we have initialized it on the main thread. */
static void __attribute__((constructor)) initialize_library(void);

/* Function pointer types */

typedef int (*Tau_init_type)(int argc, char **argv);
typedef int (*Tau_register_thread_type)(void);
typedef int (*Tau_create_top_level_timer_if_necessary_type)(void);
typedef int (*Tau_start_type)(const char *);
typedef int (*Tau_stop_type)(const char *);
typedef int (*Tau_exit_type)(const char *);
typedef int (*Tau_dump_prefix_type)(const char *prefix);
typedef int (*Tau_set_node_type)(int);
typedef int (*Tau_profile_exit_all_threads_type)(void);
typedef int (*Tau_get_thread_type)(void);
typedef int (*Tau_profile_exit_all_tasks_type)(void);
typedef int (*Tau_global_stop_type)(void);
typedef int (*Tau_trigger_context_event_type)(char *, double);
typedef int (*Tau_metadata_type)(const char *, const char *);
typedef void (*Tau_destructor_trigger_type)(void);

/* Function pointers */

int (*my_Tau_init)(int, char **) = NULL;
int (*my_Tau_register_thread)(void) = NULL;
int (*my_Tau_create_top_level_timer_if_necessary)(void) = NULL;
int (*my_Tau_start)(const char *) = NULL;
int (*my_Tau_stop)(const char *) = NULL;
int (*my_Tau_exit)(const char *) = NULL;
int (*my_Tau_set_node)(int) = NULL;
int (*my_Tau_dump_prefix)(const char *prefix) = NULL;
int (*my_Tau_profile_exit_all_threads)(void) = NULL;
int (*my_Tau_get_thread)(void) = NULL;
int (*my_Tau_profile_exit_all_tasks)(void) = NULL;
int (*my_Tau_global_stop)(void) = NULL;
int (*my_Tau_trigger_context_event)(char *, double) = NULL;
int (*my_Tau_metadata)(const char *, const char *) = NULL;
void (*my_Tau_destructor_trigger)(void) = NULL;

static void initialize_library(void)
{
    // initialize the library when it is loaded
    static taustubs::TauTimer &tt = taustubs::TauTimer::get();
}

void open_preload_libraries(void)
{
/* We might be in a static executable.  Get the ld_preload variable */
#if defined(__APPLE__) && defined(__MACH__)
    const char *envvar = "DYLD_PRELOAD";
#else
    const char *envvar = "LD_PRELOAD";
#endif
    const char *preload = getenv(envvar);
    if (preload != NULL)
    {
        // fprintf(stderr, "%s:\n%s\n", envvar, preload);
        /* tokenize it */
        char *token = strtok((char *)preload, ":");
        while (token)
        {
            /* then, dlopen() first and re-try the dlsym() call. */
            dlopen(token, RTLD_LAZY);
            token = strtok(NULL, ":");
        }
    }
    // fprintf(stderr, "%s not set!\n", envvar);
}

int assign_function_pointers(void)
{
    my_Tau_init = (Tau_init_type)dlsym(RTLD_DEFAULT, "Tau_init");
    if (my_Tau_init == NULL)
    {
        open_preload_libraries();
        my_Tau_init = (Tau_init_type)dlsym(RTLD_DEFAULT, "Tau_init");
        if (my_Tau_init == NULL)
        {
            /* Optional - print an error message, because TAU wasn't preloaded!
             */
            // fprintf(stderr, "TAU libraries not loaded, TAU support
            // unavailable\n%s\n", dlerror());
            return 1;
        }
    }
    my_Tau_register_thread =
        (Tau_register_thread_type)dlsym(RTLD_DEFAULT, "Tau_register_thread");
    my_Tau_create_top_level_timer_if_necessary =
        (Tau_create_top_level_timer_if_necessary_type)dlsym(
            RTLD_DEFAULT, "Tau_create_top_level_timer_if_necessary");
    my_Tau_start = (Tau_start_type)dlsym(RTLD_DEFAULT, "Tau_start");
    my_Tau_stop = (Tau_stop_type)dlsym(RTLD_DEFAULT, "Tau_stop");
    my_Tau_dump_prefix =
        (Tau_dump_prefix_type)dlsym(RTLD_DEFAULT, "Tau_dump_prefix");
    my_Tau_exit = (Tau_exit_type)dlsym(RTLD_DEFAULT, "Tau_exit");
    my_Tau_set_node = (Tau_set_node_type)dlsym(RTLD_DEFAULT, "Tau_set_node");
    my_Tau_profile_exit_all_threads = (Tau_profile_exit_all_threads_type)dlsym(
        RTLD_DEFAULT, "Tau_profile_exit_all_threads");
    my_Tau_get_thread =
        (Tau_get_thread_type)dlsym(RTLD_DEFAULT, "Tau_get_thread");
    my_Tau_profile_exit_all_tasks = (Tau_profile_exit_all_tasks_type)dlsym(
        RTLD_DEFAULT, "Tau_profile_exit_all_tasks");
    my_Tau_global_stop =
        (Tau_global_stop_type)dlsym(RTLD_DEFAULT, "Tau_global_stop");
    my_Tau_trigger_context_event = (Tau_trigger_context_event_type)dlsym(
        RTLD_DEFAULT, "Tau_trigger_context_event");
    my_Tau_metadata = (Tau_metadata_type)dlsym(RTLD_DEFAULT, "Tau_metadata");
    my_Tau_destructor_trigger = (Tau_destructor_trigger_type)dlsym(
        RTLD_DEFAULT, "Tau_destructor_trigger");
    return 0;
}

int tau_stub_initialize_simple_(void)
{
    if (assign_function_pointers() == 1)
    {
        return 1;
    }
    int _argc = 1;
    const char *_dummy = "";
    char *_argv[1];
    _argv[0] = (char *)(_dummy);
    my_Tau_init(_argc, _argv);
    // Not necessary to set the node id, the TAU MPI_Init wrapper will do that
    my_Tau_create_top_level_timer_if_necessary();
    return 0;
}

void tau_stub_exit(void)
{
    if (my_Tau_destructor_trigger != NULL)
    {
        my_Tau_destructor_trigger();
    }
    if (my_Tau_profile_exit_all_threads != NULL)
    {
        my_Tau_profile_exit_all_threads();
    }
    if (my_Tau_exit != NULL)
    {
        my_Tau_exit("stub exiting");
    }
}

namespace taustubs
{

thread_local bool TauTimer::thread_seen(false);

// constructor
TauTimer::TauTimer(void) : initialized(false)
{
    // Confirm that we are instantializing this singleton on the main thread!
    mypid = getpid();
#if defined(__APPLE__) && defined(__MACH__)
    // why should Apple support gettid? BE DIFFERENT, BABY!
    pthread_threadid_np(NULL, &mytid);
#else
    mytid = (uint64_t)syscall(__NR_gettid);
#endif
    if (tau_stub_initialize_simple_() == 0)
        initialized = true;
    thread_seen = true;
}

// The only way to get an instance of this class
TauTimer &TauTimer::get(void)
{
    static std::unique_ptr<TauTimer> instance(new TauTimer);
    if (!thread_seen && instance.get()->initialized)
    {
        _RegisterThread();
    }
    return *instance;
}

// used internally to the class
inline void TauTimer::_RegisterThread(void)
{
    if (!thread_seen)
    {
// Confirm that we are NOT on the main thread!
#if defined(__APPLE__) && defined(__MACH__)
        // why should Apple support gettid? BE DIFFERENT, BABY!
        pthread_threadid_np(NULL, &mytid);
#else
        mytid = (uint64_t)syscall(__NR_gettid);
#endif
        my_Tau_register_thread();
        my_Tau_create_top_level_timer_if_necessary();
        thread_seen = true;
    }
}

// external API call
void TauTimer::RegisterThread(void)
{
    if (!TauTimer::get().initialized)
        return;
    _RegisterThread();
}

void TauTimer::Start(const char *timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_start(timer_name);
}

void TauTimer::Start(const std::string &timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_start(timer_name.c_str());
}

void TauTimer::Stop(const char *timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_stop(timer_name);
}

void TauTimer::Stop(const std::string &timer_name)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_stop(timer_name.c_str());
}

void TauTimer::SampleCounter(const char *name, const double value)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_trigger_context_event(const_cast<char *>(name), value);
}

void TauTimer::MetaData(const char *name, const char *value)
{
    if (!TauTimer::get().initialized)
        return;
    my_Tau_metadata(name, value);
}

TauTimer::~TauTimer(void) { tau_stub_exit(); }

} // namespace taustubs

/* Expose the API to C and Fortran */

extern "C" {
// C Bindings
void TauTimer_RegisterThread() { taustubs::TauTimer::RegisterThread(); }

void TauTimer_Start(const char *timer_name)
{
    taustubs::TauTimer::Start(timer_name);
}

void TauTimer_Stop(const char *timer_name)
{
    taustubs::TauTimer::Stop(timer_name);
}

void TauTimer_SampleCounter(const char *name, const double value)
{
    taustubs::TauTimer::SampleCounter(name, value);
}

void TauTimer_MetaData(const char *name, const char *value)
{
    taustubs::TauTimer::MetaData(name, value);
}

// Fortran Bindings
void tautimer_registerthread_() { taustubs::TauTimer::RegisterThread(); }

void tautimer_start_(const char *timer_name)
{
    taustubs::TauTimer::Start(timer_name);
}

void tautimer_stop_(const char *timer_name)
{
    taustubs::TauTimer::Stop(timer_name);
}

void tautimer_samplecounter_(const char *name, const double value)
{
    taustubs::TauTimer::SampleCounter(name, value);
}

void tautimer_metadata_(const char *name, const char *value)
{
    taustubs::TauTimer::MetaData(name, value);
}

} // extern "C"

#endif // defined(TAU_USE_STUBS)
<|endoftext|>


<commit_before>#include "amatrix.h"
#include "checks.h"

std::size_t TestMatrixLUDeterminant3() {
    AMatrix::Matrix<double, 3, 3> a_matrix;

    double value = 0.00;
    for(auto& i_value : a_matrix)
        i_value = value++;

    a_matrix(2,2) = 0.00;

    // double* A[3];

    // value = 0;
    // for(int i = 0 ; i < 3 ; i++){
    //     A[i] = new double[3];
    //     for(int j = 0 ; j < 3 ; j++)
    //         A[i][j] = value++;
    // }

    // int P[4];

    // LUPDecompose(A,3,1e-12,P);

    AMatrix::Matrix<double, 3, 3> U{6,7,8,0,1,2,0,0,0};
    AMatrix::Matrix<double, 3, 3> L{1,0,0,0,1,0,0.5,0.5,1};

    AMatrix::Matrix<double, 3, 3> LU (L * U);

    std::cout << LU << std::endl;

    AMatrix::Matrix<double, 3, 3> result_matrix{3,4,5,
                                               0,1,2,
                                               0,0,-8};
    // for(int i = 0 ; i < 3 ; i++){
    //     for(int j = 0 ; j < 3 ; j++)
    //         a_matrix(i,j) = A[i][j];
    //     delete A[i];
    // }

   AMatrix::LUFactorization< AMatrix::Matrix<double, 3, 3>, AMatrix::Vector<std::size_t, AMatrix::dynamic> > lu_factorization(a_matrix);

    AMATRIX_CHECK_EQUAL(lu_factorization.Determinant(), 24);

    return 0;  // not failed
}

int main() {
    std::size_t number_of_failed_tests = 0;
    number_of_failed_tests += TestMatrixLUDeterminant3();

    std::cout << number_of_failed_tests << "tests failed" << std::endl;

    return number_of_failed_tests;
}
<commit_msg>Adding tests for determinant and inverse<commit_after>#include "amatrix.h"
#include "checks.h"
#include <limits>

std::size_t TestMatrixLUDeterminant3() {
    AMatrix::Matrix<double, 3, 3> a_matrix;

    double value = 0.00;
    for(auto& i_value : a_matrix)
        i_value = value++;

    a_matrix(2,2) = 0.00;

   AMatrix::LUFactorization< AMatrix::Matrix<double, 3, 3>, AMatrix::Vector<std::size_t, AMatrix::dynamic> > lu_factorization(a_matrix);

    AMATRIX_CHECK_EQUAL(lu_factorization.Determinant(), 24);

    return 0;  // not failed
}

std::size_t TestMatrixLUInvert3() {
    AMatrix::Matrix<double, 3, 3> a_matrix;
    AMatrix::Matrix<double, 3, 3> a_inverse;
    AMatrix::Matrix<double, 3, 3> correct_result{-35./24., 7./12., -1./8.,
                                                 5./4., -1./2., 1./4.,
                                                 -1./8., 1./4., -1./8};

    double value = 0.00;
    for(auto& i_value : a_matrix)
        i_value = value++;

    a_matrix(2,2) = 0.00;

    AMatrix::LUFactorization< AMatrix::Matrix<double, 3, 3>, AMatrix::Vector<std::size_t, AMatrix::dynamic> > lu_factorization(a_matrix);
    lu_factorization.Invert(a_inverse);

    std::cout << a_inverse << std::endl;
    std::cout << correct_result << std::endl;

    for(std::size_t i = 0 ; i < a_matrix.size1() ; i++)
        for(std::size_t j = 0 ; j < a_matrix.size2() ; j++)
            AMATRIX_CHECK_ALMOST_EQUAL(a_inverse(i,j), correct_result(i,j));

    return 0;  // not failed
}

int main() {
    std::size_t number_of_failed_tests = 0;
    number_of_failed_tests += TestMatrixLUDeterminant3();
    number_of_failed_tests += TestMatrixLUInvert3();

    std::cout << number_of_failed_tests << "tests failed" << std::endl;

    return number_of_failed_tests;
}
<|endoftext|>