<commit_before>// A work-in-progress llvm backend

#include <taichi/common/util.h>
#include <taichi/io/io.h>
#include <set>

#include "cuda_context.h"
#include "../util.h"
#include "codegen_cuda.h"
#include "../program.h"
#include "../ir.h"

#if defined(TLANG_WITH_CUDA)
#include "cuda_runtime.h"
#endif

#if defined(TLANG_WITH_LLVM)

#include "codegen_llvm.h"

#endif

TLANG_NAMESPACE_BEGIN

#if defined(TLANG_WITH_LLVM)

using namespace llvm;

// NVVM IR Spec:
// https://docs.nvidia.com/cuda/archive/10.0/pdf/NVVM_IR_Specification.pdf

class CodeGenLLVMGPU : public CodeGenLLVM {
 public:
  int kernel_grid_dim;
  int kernel_block_dim;

  CodeGenLLVMGPU(CodeGenBase *codegen_base, Kernel *kernel)
      : CodeGenLLVM(codegen_base, kernel) {
  }

  void mark_function_as_cuda_kernel(llvm::Function *func) {
    /*******************************************************************
    Example annotation from llvm PTX doc:

    define void @kernel(float addrspace(1)* %A,
                        float addrspace(1)* %B,
                        float addrspace(1)* %C);

    !nvvm.annotations = !{!0}
    !0 = !{void (float addrspace(1)*,
                 float addrspace(1)*,
                 float addrspace(1)*)* @kernel, !"kernel", i32 1}
    *******************************************************************/

    // Mark kernel function as a CUDA __global__ function
    // Add the nvvm annotation that it is considered a kernel function.

    llvm::Metadata *md_args[] = {
        llvm::ValueAsMetadata::get(func),
        MDString::get(*llvm_context, "kernel"),
        llvm::ValueAsMetadata::get(tlctx->get_constant(1))};

    MDNode *md_node = MDNode::get(*llvm_context, md_args);

    module->getOrInsertNamedMetadata("nvvm.annotations")->addOperand(md_node);
  }

  FunctionType compile_module_to_executable() override {
#if defined(TLANG_WITH_CUDA)
    auto offloaded_local = offloaded_tasks;
    for (auto &task : offloaded_local) {
      llvm::Function *func = module->getFunction(task.name);
      TC_ASSERT(func);
      mark_function_as_cuda_kernel(func);
    }

    auto ptx = compile_module_to_ptx(module);
    auto cuda_module = cuda_context.compile(ptx);

    for (auto &task : offloaded_local) {
      task.cuda_func =
          (void *)cuda_context.get_function(cuda_module, task.name);
    }
    return [offloaded_local](Context context) {
      for (auto task : offloaded_local) {
        cuda_context.launch((CUfunction)task.cuda_func, &context, task.grid_dim,
                            task.block_dim);
      }
    };
#else
    TC_NOT_IMPLEMENTED;
    return nullptr;
#endif
  }

  void visit(PrintStmt *stmt) override {
    TC_ASSERT(stmt->width() == 1);

    auto value_type = tlctx->get_data_type(stmt->stmt->ret_type.data_type);

    std::string format;

    auto value = stmt->stmt->value;

    if (stmt->stmt->ret_type.data_type == DataType::i32) {
      format = "%d";
    } else if (stmt->stmt->ret_type.data_type == DataType::f32) {
      value_type = llvm::Type::getDoubleTy(*llvm_context);
      value = builder->CreateFPExt(value, value_type);
      format = "%f";
    } else if (stmt->stmt->ret_type.data_type == DataType::f64) {
      format = "%f";
    } else {
      TC_NOT_IMPLEMENTED
    }

    std::vector<llvm::Type *> types{value_type};
    auto stype = llvm::StructType::get(*llvm_context, types, false);
    auto values = builder->CreateAlloca(stype);
    auto value_ptr = builder->CreateGEP(
        values, {tlctx->get_constant(0), tlctx->get_constant(0)});
    builder->CreateStore(value, value_ptr);

    auto format_str = "[debug] " + stmt->str + " = " + format + "\n";

    stmt->value = ModuleBuilder::call(
        builder, "vprintf",
        builder->CreateGlobalStringPtr(format_str, "format_string"),
        builder->CreateBitCast(values,
                               llvm::Type::getInt8PtrTy(*llvm_context)));
  }

  void emit_extra_unary(UnaryOpStmt *stmt) override {
    // functions from libdevice
    auto input = stmt->operand->value;
    auto input_taichi_type = stmt->operand->ret_type.data_type;
    auto input_type = input->getType();
    auto op = stmt->op_type;

#define UNARY_STD(x)                                                        \
  else if (op == UnaryOpType::x) {                                          \
    if (input_taichi_type == DataType::f32) {                               \
      stmt->value =                                                         \
          builder->CreateCall(get_runtime_function("__nv_" #x "f"), input); \
    } else if (input_taichi_type == DataType::f64) {                        \
      stmt->value =                                                         \
          builder->CreateCall(get_runtime_function("__nv_" #x), input);     \
    } else if (input_taichi_type == DataType::i32) {                        \
      stmt->value = builder->CreateCall(get_runtime_function(#x), input);   \
    } else {                                                                \
      TC_NOT_IMPLEMENTED                                                    \
    }                                                                       \
  }
    if (op == UnaryOpType::abs) {
      if (input_taichi_type == DataType::f32) {
        stmt->value =
            builder->CreateCall(get_runtime_function("__nv_fabsf"), input);
      } else if (input_taichi_type == DataType::f64) {
        stmt->value =
            builder->CreateCall(get_runtime_function("__nv_fabs"), input);
      } else if (input_taichi_type == DataType::i32) {
        stmt->value =
            builder->CreateCall(get_runtime_function("__nv_abs"), input);
      } else {
        TC_NOT_IMPLEMENTED
      }
    } else if (op == UnaryOpType::logic_not) {
      if (input_taichi_type == DataType::i32) {
        stmt->value =
            builder->CreateCall(get_runtime_function("logic_not_i32"), input);
      } else {
        TC_NOT_IMPLEMENTED
      }
    }
    UNARY_STD(exp)
    UNARY_STD(log)
    UNARY_STD(tan)
    UNARY_STD(tanh)
    UNARY_STD(sgn)
    else {
      TC_P(unary_op_type_name(op));
      TC_NOT_IMPLEMENTED
    }
#undef UNARY_STD
  }

  void visit(RangeForStmt *for_stmt) override {
    create_naive_range_for(for_stmt);
  }

  void create_offload_range_for(OffloadedStmt *stmt) {
    auto loop_var = create_entry_block_alloca(DataType::i32);
    stmt->loop_vars_llvm.push_back(loop_var);
    auto loop_begin = stmt->begin;
    auto loop_end = stmt->end;
    auto loop_block_dim = stmt->block_size;
    if (loop_block_dim == 0) {
      loop_block_dim = default_gpu_block_size;
    }
    kernel_grid_dim =
        (loop_end - loop_begin + loop_block_dim - 1) / loop_block_dim;
    kernel_block_dim = loop_block_dim;
    BasicBlock *body = BasicBlock::Create(*llvm_context, "loop_body", func);
    BasicBlock *after_loop = BasicBlock::Create(*llvm_context, "block", func);

    auto threadIdx =
        builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_tid_x, {}, {});
    auto blockIdx =
        builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_ctaid_x, {}, {});
    auto blockDim =
        builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_ntid_x, {}, {});

    auto loop_id = builder->CreateAdd(
        tlctx->get_constant(stmt->begin),
        builder->CreateAdd(threadIdx, builder->CreateMul(blockIdx, blockDim)));

    builder->CreateStore(loop_id, loop_var);

    auto cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT,
                                    builder->CreateLoad(loop_var),
                                    tlctx->get_constant(stmt->end));

    builder->CreateCondBr(cond, body, after_loop);
    {
      // body cfg
      builder->SetInsertPoint(body);
      stmt->body_block->accept(this);
      builder->CreateBr(after_loop);
    }

    // create_increment(for_stmt->loop_var->value, tlctx->get_constant(1));

    builder->SetInsertPoint(after_loop);

    offloaded = false;
  }

  void visit(OffloadedStmt *stmt) override {
    using Type = OffloadedStmt::TaskType;
    kernel_grid_dim = 1;
    kernel_block_dim = 1;
    init_task_function(stmt);
    if (stmt->task_type == Type::serial) {
      stmt->body_block->accept(this);
    } else if (stmt->task_type == Type::range_for) {
      create_offload_range_for(stmt);
    } else if (stmt->task_type == Type::struct_for) {
      int num_SMs;
      cudaDeviceGetAttribute(&num_SMs, cudaDevAttrMultiProcessorCount, 0);
      kernel_grid_dim = num_SMs * 32;  // each SM can have 16-32 resident blocks
      kernel_block_dim = stmt->block_size;
      if (kernel_block_dim == 0) {
        kernel_block_dim = std::min(1024, 1 << stmt->snode->total_num_bits);
      }
      create_offload_struct_for(stmt, true);
    } else if (stmt->task_type == Type::listgen) {
      emit_list_gen(stmt);
    } else {
      TC_NOT_IMPLEMENTED
    }
    finalize_task_function();
    current_task->grid_dim = kernel_grid_dim;
    current_task->block_dim = kernel_block_dim;
    current_task->end();
    current_task = nullptr;
  }
};

FunctionType GPUCodeGen::codegen_llvm() {
  return CodeGenLLVMGPU(this, kernel).gen();
}

#else

FunctionType GPUCodeGen::codegen_llvm() {
  TC_ERROR("LLVM not found");
}

#endif

TLANG_NAMESPACE_END
<commit_msg>fixed num threads<commit_after>// A work-in-progress llvm backend

#include <taichi/common/util.h>
#include <taichi/io/io.h>
#include <set>

#include "cuda_context.h"
#include "../util.h"
#include "codegen_cuda.h"
#include "../program.h"
#include "../ir.h"

#if defined(TLANG_WITH_CUDA)
#include "cuda_runtime.h"
#endif

#if defined(TLANG_WITH_LLVM)

#include "codegen_llvm.h"

#endif

TLANG_NAMESPACE_BEGIN

#if defined(TLANG_WITH_LLVM)

using namespace llvm;

// NVVM IR Spec:
// https://docs.nvidia.com/cuda/archive/10.0/pdf/NVVM_IR_Specification.pdf

class CodeGenLLVMGPU : public CodeGenLLVM {
 public:
  int kernel_grid_dim;
  int kernel_block_dim;

  CodeGenLLVMGPU(CodeGenBase *codegen_base, Kernel *kernel)
      : CodeGenLLVM(codegen_base, kernel) {
  }

  void mark_function_as_cuda_kernel(llvm::Function *func) {
    /*******************************************************************
    Example annotation from llvm PTX doc:

    define void @kernel(float addrspace(1)* %A,
                        float addrspace(1)* %B,
                        float addrspace(1)* %C);

    !nvvm.annotations = !{!0}
    !0 = !{void (float addrspace(1)*,
                 float addrspace(1)*,
                 float addrspace(1)*)* @kernel, !"kernel", i32 1}
    *******************************************************************/

    // Mark kernel function as a CUDA __global__ function
    // Add the nvvm annotation that it is considered a kernel function.

    llvm::Metadata *md_args[] = {
        llvm::ValueAsMetadata::get(func),
        MDString::get(*llvm_context, "kernel"),
        llvm::ValueAsMetadata::get(tlctx->get_constant(1))};

    MDNode *md_node = MDNode::get(*llvm_context, md_args);

    module->getOrInsertNamedMetadata("nvvm.annotations")->addOperand(md_node);
  }

  FunctionType compile_module_to_executable() override {
#if defined(TLANG_WITH_CUDA)
    auto offloaded_local = offloaded_tasks;
    for (auto &task : offloaded_local) {
      llvm::Function *func = module->getFunction(task.name);
      TC_ASSERT(func);
      mark_function_as_cuda_kernel(func);
    }

    auto ptx = compile_module_to_ptx(module);
    auto cuda_module = cuda_context.compile(ptx);

    for (auto &task : offloaded_local) {
      task.cuda_func =
          (void *)cuda_context.get_function(cuda_module, task.name);
    }
    return [offloaded_local](Context context) {
      for (auto task : offloaded_local) {
        TC_INFO("Launching kernel {}<<<{}, {}>>>", task.name, task.grid_dim,
                task.block_dim);
        cuda_context.launch((CUfunction)task.cuda_func, &context, task.grid_dim,
                            task.block_dim);
      }
    };
#else
    TC_NOT_IMPLEMENTED;
    return nullptr;
#endif
  }

  void visit(PrintStmt *stmt) override {
    TC_ASSERT(stmt->width() == 1);

    auto value_type = tlctx->get_data_type(stmt->stmt->ret_type.data_type);

    std::string format;

    auto value = stmt->stmt->value;

    if (stmt->stmt->ret_type.data_type == DataType::i32) {
      format = "%d";
    } else if (stmt->stmt->ret_type.data_type == DataType::f32) {
      value_type = llvm::Type::getDoubleTy(*llvm_context);
      value = builder->CreateFPExt(value, value_type);
      format = "%f";
    } else if (stmt->stmt->ret_type.data_type == DataType::f64) {
      format = "%f";
    } else {
      TC_NOT_IMPLEMENTED
    }

    std::vector<llvm::Type *> types{value_type};
    auto stype = llvm::StructType::get(*llvm_context, types, false);
    auto values = builder->CreateAlloca(stype);
    auto value_ptr = builder->CreateGEP(
        values, {tlctx->get_constant(0), tlctx->get_constant(0)});
    builder->CreateStore(value, value_ptr);

    auto format_str = "[debug] " + stmt->str + " = " + format + "\n";

    stmt->value = ModuleBuilder::call(
        builder, "vprintf",
        builder->CreateGlobalStringPtr(format_str, "format_string"),
        builder->CreateBitCast(values,
                               llvm::Type::getInt8PtrTy(*llvm_context)));
  }

  void emit_extra_unary(UnaryOpStmt *stmt) override {
    // functions from libdevice
    auto input = stmt->operand->value;
    auto input_taichi_type = stmt->operand->ret_type.data_type;
    auto input_type = input->getType();
    auto op = stmt->op_type;

#define UNARY_STD(x)                                                        \
  else if (op == UnaryOpType::x) {                                          \
    if (input_taichi_type == DataType::f32) {                               \
      stmt->value =                                                         \
          builder->CreateCall(get_runtime_function("__nv_" #x "f"), input); \
    } else if (input_taichi_type == DataType::f64) {                        \
      stmt->value =                                                         \
          builder->CreateCall(get_runtime_function("__nv_" #x), input);     \
    } else if (input_taichi_type == DataType::i32) {                        \
      stmt->value = builder->CreateCall(get_runtime_function(#x), input);   \
    } else {                                                                \
      TC_NOT_IMPLEMENTED                                                    \
    }                                                                       \
  }
    if (op == UnaryOpType::abs) {
      if (input_taichi_type == DataType::f32) {
        stmt->value =
            builder->CreateCall(get_runtime_function("__nv_fabsf"), input);
      } else if (input_taichi_type == DataType::f64) {
        stmt->value =
            builder->CreateCall(get_runtime_function("__nv_fabs"), input);
      } else if (input_taichi_type == DataType::i32) {
        stmt->value =
            builder->CreateCall(get_runtime_function("__nv_abs"), input);
      } else {
        TC_NOT_IMPLEMENTED
      }
    } else if (op == UnaryOpType::logic_not) {
      if (input_taichi_type == DataType::i32) {
        stmt->value =
            builder->CreateCall(get_runtime_function("logic_not_i32"), input);
      } else {
        TC_NOT_IMPLEMENTED
      }
    }
    UNARY_STD(exp)
    UNARY_STD(log)
    UNARY_STD(tan)
    UNARY_STD(tanh)
    UNARY_STD(sgn)
    else {
      TC_P(unary_op_type_name(op));
      TC_NOT_IMPLEMENTED
    }
#undef UNARY_STD
  }

  void visit(RangeForStmt *for_stmt) override {
    create_naive_range_for(for_stmt);
  }

  void create_offload_range_for(OffloadedStmt *stmt) {
    auto loop_var = create_entry_block_alloca(DataType::i32);
    stmt->loop_vars_llvm.push_back(loop_var);
    auto loop_begin = stmt->begin;
    auto loop_end = stmt->end;
    auto loop_block_dim = stmt->block_size;
    if (loop_block_dim == 0) {
      loop_block_dim = default_gpu_block_size;
    }
    kernel_grid_dim =
        (loop_end - loop_begin + loop_block_dim - 1) / loop_block_dim;
    kernel_block_dim = loop_block_dim;
    BasicBlock *body = BasicBlock::Create(*llvm_context, "loop_body", func);
    BasicBlock *after_loop = BasicBlock::Create(*llvm_context, "block", func);

    auto threadIdx =
        builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_tid_x, {}, {});
    auto blockIdx =
        builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_ctaid_x, {}, {});
    auto blockDim =
        builder->CreateIntrinsic(Intrinsic::nvvm_read_ptx_sreg_ntid_x, {}, {});

    auto loop_id = builder->CreateAdd(
        tlctx->get_constant(stmt->begin),
        builder->CreateAdd(threadIdx, builder->CreateMul(blockIdx, blockDim)));

    builder->CreateStore(loop_id, loop_var);

    auto cond = builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_SLT,
                                    builder->CreateLoad(loop_var),
                                    tlctx->get_constant(stmt->end));

    builder->CreateCondBr(cond, body, after_loop);
    {
      // body cfg
      builder->SetInsertPoint(body);
      stmt->body_block->accept(this);
      builder->CreateBr(after_loop);
    }

    // create_increment(for_stmt->loop_var->value, tlctx->get_constant(1));

    builder->SetInsertPoint(after_loop);

    offloaded = false;
  }

  void visit(OffloadedStmt *stmt) override {
    using Type = OffloadedStmt::TaskType;
    kernel_grid_dim = 1;
    kernel_block_dim = 1;
    init_task_function(stmt);
    if (stmt->task_type == Type::serial) {
      stmt->body_block->accept(this);
    } else if (stmt->task_type == Type::range_for) {
      create_offload_range_for(stmt);
    } else if (stmt->task_type == Type::struct_for) {
      int num_SMs;
      cudaDeviceGetAttribute(&num_SMs, cudaDevAttrMultiProcessorCount, 0);
      kernel_grid_dim = num_SMs * 32;  // each SM can have 16-32 resident blocks
      kernel_block_dim = stmt->block_size;
      if (kernel_block_dim == 0) {
        kernel_block_dim = std::min(1024, 1 << stmt->snode->parent->total_num_bits);
      }
      create_offload_struct_for(stmt, true);
    } else if (stmt->task_type == Type::listgen) {
      emit_list_gen(stmt);
    } else {
      TC_NOT_IMPLEMENTED
    }
    finalize_task_function();
    current_task->grid_dim = kernel_grid_dim;
    current_task->block_dim = kernel_block_dim;
    current_task->end();
    current_task = nullptr;
  }
};

FunctionType GPUCodeGen::codegen_llvm() {
  return CodeGenLLVMGPU(this, kernel).gen();
}

#else

FunctionType GPUCodeGen::codegen_llvm() {
  TC_ERROR("LLVM not found");
}

#endif

TLANG_NAMESPACE_END
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef BACKFILL_PROGRESS_HPP_
#define BACKFILL_PROGRESS_HPP_

#include <vector>

#include "errors.hpp"
#include "threading.hpp"

template <class> class scoped_ptr_t;

struct progress_completion_fraction_t {
    progress_completion_fraction_t() : estimate_of_released_nodes(-1), estimate_of_total_nodes(-1) { }

    progress_completion_fraction_t(int _released, int _total) : estimate_of_released_nodes(_released), estimate_of_total_nodes(_total) {
        rassert(0 <= estimate_of_released_nodes && estimate_of_released_nodes <= estimate_of_total_nodes);
    }

    int64_t estimate_of_released_nodes;
    int64_t estimate_of_total_nodes;

    bool invalid() const { return estimate_of_total_nodes == -1; }
};

// TODO: Rename this to traversal_progress_t after it has been pushed
// and merged into rdb_protocol.
class traversal_progress_t : public home_thread_mixin_t {
public:
    traversal_progress_t() { }
    explicit traversal_progress_t(threadnum_t specified_home_thread)
        : home_thread_mixin_t(specified_home_thread) { }

    virtual progress_completion_fraction_t guess_completion() const = 0;

    // This actually gets used, by traversal_progress_combiner_t.
    virtual ~traversal_progress_t() { }
private:
    DISABLE_COPYING(traversal_progress_t);
};

class traversal_progress_combiner_t : public traversal_progress_t {
public:
    explicit traversal_progress_combiner_t(threadnum_t specified_home_thread)
        : traversal_progress_t(specified_home_thread), is_destructing(false) { }
    traversal_progress_combiner_t() : is_destructing(false) { }
    ~traversal_progress_combiner_t();

    // The constituent is welcome to have a different home thread.
    void add_constituent(scoped_ptr_t<traversal_progress_t> *constituent);
    progress_completion_fraction_t guess_completion() const;

private:
    // Used in a pmap by the destructor.
    void destroy_constituent(int i);

    // Used by guess_completion in a pmap call to go to the
    // constituent's home thread.
    void get_constituent_fraction(int i, std::vector<progress_completion_fraction_t> *outputs) const;

    // constituents _owns_ these pointers.
    std::vector<traversal_progress_t *> constituents;

    bool is_destructing;

    DISABLE_COPYING(traversal_progress_combiner_t);
};
#endif  // BACKFILL_PROGRESS_HPP_
<commit_msg>Removed a TODO comment that was TODONE.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef BACKFILL_PROGRESS_HPP_
#define BACKFILL_PROGRESS_HPP_

#include <vector>

#include "errors.hpp"
#include "threading.hpp"

template <class> class scoped_ptr_t;

struct progress_completion_fraction_t {
    progress_completion_fraction_t() : estimate_of_released_nodes(-1), estimate_of_total_nodes(-1) { }

    progress_completion_fraction_t(int _released, int _total) : estimate_of_released_nodes(_released), estimate_of_total_nodes(_total) {
        rassert(0 <= estimate_of_released_nodes && estimate_of_released_nodes <= estimate_of_total_nodes);
    }

    int64_t estimate_of_released_nodes;
    int64_t estimate_of_total_nodes;

    bool invalid() const { return estimate_of_total_nodes == -1; }
};

class traversal_progress_t : public home_thread_mixin_t {
public:
    traversal_progress_t() { }
    explicit traversal_progress_t(threadnum_t specified_home_thread)
        : home_thread_mixin_t(specified_home_thread) { }

    virtual progress_completion_fraction_t guess_completion() const = 0;

    // This actually gets used, by traversal_progress_combiner_t.
    virtual ~traversal_progress_t() { }
private:
    DISABLE_COPYING(traversal_progress_t);
};

class traversal_progress_combiner_t : public traversal_progress_t {
public:
    explicit traversal_progress_combiner_t(threadnum_t specified_home_thread)
        : traversal_progress_t(specified_home_thread), is_destructing(false) { }
    traversal_progress_combiner_t() : is_destructing(false) { }
    ~traversal_progress_combiner_t();

    // The constituent is welcome to have a different home thread.
    void add_constituent(scoped_ptr_t<traversal_progress_t> *constituent);
    progress_completion_fraction_t guess_completion() const;

private:
    // Used in a pmap by the destructor.
    void destroy_constituent(int i);

    // Used by guess_completion in a pmap call to go to the
    // constituent's home thread.
    void get_constituent_fraction(int i, std::vector<progress_completion_fraction_t> *outputs) const;

    // constituents _owns_ these pointers.
    std::vector<traversal_progress_t *> constituents;

    bool is_destructing;

    DISABLE_COPYING(traversal_progress_combiner_t);
};
#endif  // BACKFILL_PROGRESS_HPP_
<|endoftext|>


<commit_before>/*

Copyright (c) 2009-2014, Arvid Norberg
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 the author 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 OWNER 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 "libtorrent/bandwidth_manager.hpp"
#include "libtorrent/time.hpp"

namespace libtorrent
{

	bandwidth_manager::bandwidth_manager(int channel
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
		, bool log
#endif
		)
		: m_queued_bytes(0)
		, m_channel(channel)
		, m_abort(false)
	{
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
		if (log)
			m_log.open("bandwidth_limiter.log", std::ios::trunc);
		m_start = time_now();
#endif
	}

	void bandwidth_manager::close()
	{
		m_abort = true;
		m_queue.clear();
		m_queued_bytes = 0;
	}

#if TORRENT_USE_ASSERTS
	bool bandwidth_manager::is_queued(bandwidth_socket const* peer) const
	{
		for (queue_t::const_iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			if (i->peer.get() == peer) return true;
		}
		return false;
	}
#endif

	int bandwidth_manager::queue_size() const
	{
		return m_queue.size();
	}

	int bandwidth_manager::queued_bytes() const
	{
		return m_queued_bytes;
	}

	// non prioritized means that, if there's a line for bandwidth,
	// others will cut in front of the non-prioritized peers.
	// this is used by web seeds
	int bandwidth_manager::request_bandwidth(boost::intrusive_ptr<bandwidth_socket> const& peer
		, int blk, int priority
		, bandwidth_channel* chan1
		, bandwidth_channel* chan2
		, bandwidth_channel* chan3
		, bandwidth_channel* chan4
		, bandwidth_channel* chan5
		)
	{
		INVARIANT_CHECK;
		if (m_abort) return 0;

		TORRENT_ASSERT(blk > 0);
		TORRENT_ASSERT(priority > 0);
		TORRENT_ASSERT(!is_queued(peer.get()));

		bw_request bwr(peer, blk, priority);
		int i = 0;
		if (chan1 && chan1->throttle() > 0 && chan1->need_queueing(blk))
			bwr.channel[i++] = chan1;
		if (chan2 && chan2->throttle() > 0 && chan2->need_queueing(blk))
			bwr.channel[i++] = chan2;
		if (chan3 && chan3->throttle() > 0 && chan3->need_queueing(blk))
			bwr.channel[i++] = chan3;
		if (chan4 && chan4->throttle() > 0 && chan4->need_queueing(blk))
			bwr.channel[i++] = chan4;
		if (chan5 && chan5->throttle() > 0 && chan5->need_queueing(blk))
			bwr.channel[i++] = chan5;

		if (i == 0)
		{
			// the connection is not rate limited by any of its
			// bandwidth channels, or it doesn't belong to any
			// channels. There's no point in adding it to
			// the queue, just satisfy the request immediately
			return blk;
		}

		m_queued_bytes += blk;
		m_queue.push_back(bwr);
		return 0;
	}

#if TORRENT_USE_INVARIANT_CHECKS
	void bandwidth_manager::check_invariant() const
	{
		boost::int64_t queued = 0;
		for (queue_t::const_iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			queued += i->request_size - i->assigned;
		}
		TORRENT_ASSERT(queued == m_queued_bytes);
	}
#endif

	void bandwidth_manager::update_quotas(time_duration const& dt)
	{
		if (m_abort) return;
		if (m_queue.empty()) return;

		INVARIANT_CHECK;

		int dt_milliseconds = total_milliseconds(dt);
		if (dt_milliseconds > 3000) dt_milliseconds = 3000;

		// for each bandwidth channel, call update_quota(dt)

		std::vector<bandwidth_channel*> channels;

		queue_t tm;

		for (queue_t::iterator i = m_queue.begin();
			i != m_queue.end();)
		{
			if (i->peer->is_disconnecting())
			{
				m_queued_bytes -= i->request_size - i->assigned;

				// return all assigned quota to all the
				// bandwidth channels this peer belongs to
				for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
				{
					bandwidth_channel* bwc = i->channel[j];
					bwc->return_quota(i->assigned);
				}

				i->assigned = 0;
				tm.push_back(*i);
				i = m_queue.erase(i);
				continue;
			}
			for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
			{
				bandwidth_channel* bwc = i->channel[j];
				bwc->tmp = 0;
			}
			++i;
		}

		for (queue_t::iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
			{
				bandwidth_channel* bwc = i->channel[j];
				if (bwc->tmp == 0) channels.push_back(bwc);
				TORRENT_ASSERT(INT_MAX - bwc->tmp > i->priority);
				bwc->tmp += i->priority;
			}
		}

		for (std::vector<bandwidth_channel*>::iterator i = channels.begin()
			, end(channels.end()); i != end; ++i)
		{
			(*i)->update_quota(dt_milliseconds);
		}

		for (queue_t::iterator i = m_queue.begin();
			i != m_queue.end();)
		{
			int a = i->assign_bandwidth();
			if (i->assigned == i->request_size
				|| (i->ttl <= 0 && i->assigned > 0))
			{
				a += i->request_size - i->assigned;
				TORRENT_ASSERT(i->assigned <= i->request_size);
				tm.push_back(*i);
				i = m_queue.erase(i);
			}
			else
			{
				++i;
			}
			m_queued_bytes -= a;
		}

		while (!tm.empty())
		{
			bw_request& bwr = tm.back();
			bwr.peer->assign_bandwidth(m_channel, bwr.assigned);
			tm.pop_back();
		}
	}
}

<commit_msg>back-port shutdown assert fix<commit_after>/*

Copyright (c) 2009-2014, Arvid Norberg
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 the author 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 OWNER 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 "libtorrent/bandwidth_manager.hpp"
#include "libtorrent/time.hpp"

namespace libtorrent
{

	bandwidth_manager::bandwidth_manager(int channel
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
		, bool log
#endif
		)
		: m_queued_bytes(0)
		, m_channel(channel)
		, m_abort(false)
	{
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
		if (log)
			m_log.open("bandwidth_limiter.log", std::ios::trunc);
		m_start = time_now();
#endif
	}

	void bandwidth_manager::close()
	{
		m_abort = true;

		queue_t tm;
		tm.swap(m_queue);
		m_queued_bytes = 0;

		while (!tm.empty())
		{
			bw_request& bwr = tm.back();
			bwr.peer->assign_bandwidth(m_channel, bwr.assigned);
			tm.pop_back();
		}
	}

#if TORRENT_USE_ASSERTS
	bool bandwidth_manager::is_queued(bandwidth_socket const* peer) const
	{
		for (queue_t::const_iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			if (i->peer.get() == peer) return true;
		}
		return false;
	}
#endif

	int bandwidth_manager::queue_size() const
	{
		return m_queue.size();
	}

	int bandwidth_manager::queued_bytes() const
	{
		return m_queued_bytes;
	}

	// non prioritized means that, if there's a line for bandwidth,
	// others will cut in front of the non-prioritized peers.
	// this is used by web seeds
	int bandwidth_manager::request_bandwidth(boost::intrusive_ptr<bandwidth_socket> const& peer
		, int blk, int priority
		, bandwidth_channel* chan1
		, bandwidth_channel* chan2
		, bandwidth_channel* chan3
		, bandwidth_channel* chan4
		, bandwidth_channel* chan5
		)
	{
		INVARIANT_CHECK;
		if (m_abort) return 0;

		TORRENT_ASSERT(blk > 0);
		TORRENT_ASSERT(priority > 0);
		TORRENT_ASSERT(!is_queued(peer.get()));

		bw_request bwr(peer, blk, priority);
		int i = 0;
		if (chan1 && chan1->throttle() > 0 && chan1->need_queueing(blk))
			bwr.channel[i++] = chan1;
		if (chan2 && chan2->throttle() > 0 && chan2->need_queueing(blk))
			bwr.channel[i++] = chan2;
		if (chan3 && chan3->throttle() > 0 && chan3->need_queueing(blk))
			bwr.channel[i++] = chan3;
		if (chan4 && chan4->throttle() > 0 && chan4->need_queueing(blk))
			bwr.channel[i++] = chan4;
		if (chan5 && chan5->throttle() > 0 && chan5->need_queueing(blk))
			bwr.channel[i++] = chan5;

		if (i == 0)
		{
			// the connection is not rate limited by any of its
			// bandwidth channels, or it doesn't belong to any
			// channels. There's no point in adding it to
			// the queue, just satisfy the request immediately
			return blk;
		}

		m_queued_bytes += blk;
		m_queue.push_back(bwr);
		return 0;
	}

#if TORRENT_USE_INVARIANT_CHECKS
	void bandwidth_manager::check_invariant() const
	{
		boost::int64_t queued = 0;
		for (queue_t::const_iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			queued += i->request_size - i->assigned;
		}
		TORRENT_ASSERT(queued == m_queued_bytes);
	}
#endif

	void bandwidth_manager::update_quotas(time_duration const& dt)
	{
		if (m_abort) return;
		if (m_queue.empty()) return;

		INVARIANT_CHECK;

		int dt_milliseconds = total_milliseconds(dt);
		if (dt_milliseconds > 3000) dt_milliseconds = 3000;

		// for each bandwidth channel, call update_quota(dt)

		std::vector<bandwidth_channel*> channels;

		queue_t tm;

		for (queue_t::iterator i = m_queue.begin();
			i != m_queue.end();)
		{
			if (i->peer->is_disconnecting())
			{
				m_queued_bytes -= i->request_size - i->assigned;

				// return all assigned quota to all the
				// bandwidth channels this peer belongs to
				for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
				{
					bandwidth_channel* bwc = i->channel[j];
					bwc->return_quota(i->assigned);
				}

				i->assigned = 0;
				tm.push_back(*i);
				i = m_queue.erase(i);
				continue;
			}
			for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
			{
				bandwidth_channel* bwc = i->channel[j];
				bwc->tmp = 0;
			}
			++i;
		}

		for (queue_t::iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
			{
				bandwidth_channel* bwc = i->channel[j];
				if (bwc->tmp == 0) channels.push_back(bwc);
				TORRENT_ASSERT(INT_MAX - bwc->tmp > i->priority);
				bwc->tmp += i->priority;
			}
		}

		for (std::vector<bandwidth_channel*>::iterator i = channels.begin()
			, end(channels.end()); i != end; ++i)
		{
			(*i)->update_quota(dt_milliseconds);
		}

		for (queue_t::iterator i = m_queue.begin();
			i != m_queue.end();)
		{
			int a = i->assign_bandwidth();
			if (i->assigned == i->request_size
				|| (i->ttl <= 0 && i->assigned > 0))
			{
				a += i->request_size - i->assigned;
				TORRENT_ASSERT(i->assigned <= i->request_size);
				tm.push_back(*i);
				i = m_queue.erase(i);
			}
			else
			{
				++i;
			}
			m_queued_bytes -= a;
		}

		while (!tm.empty())
		{
			bw_request& bwr = tm.back();
			bwr.peer->assign_bandwidth(m_channel, bwr.assigned);
			tm.pop_back();
		}
	}
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008, Willow Garage, Inc.
 * 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 the Willow Garage, Inc. 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 OWNER 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.
 *
 * $Id$
 *
 */

#include "polygonal_map_display.h"
#include "properties/property.h"
#include "properties/property_manager.h"
#include "common.h"

#include "ogre_tools/arrow.h"

#include <ros/node.h>
#include <tf/transform_listener.h>
#include <tf/message_notifier.h>

#include <boost/bind.hpp>

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreManualObject.h>
#include <OGRE/OgreBillboardSet.h>

#include <ogre_tools/point_cloud.h>

namespace rviz
{

PolygonalMapDisplay::PolygonalMapDisplay(const std::string & name,
    VisualizationManager * manager) :
  Display(name, manager), color_(0.1f, 1.0f, 0.0f)
      , render_operation_(polygon_render_ops::PLines)
      , override_color_(false)
      , color_property_(NULL)
      , topic_property_(NULL)
      , override_color_property_(NULL)
      , render_operation_property_(NULL)
      , point_size_property_(NULL)
      , z_position_property_(NULL)
      , alpha_property_(NULL)
{
  scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();

  static int count = 0;
  std::stringstream ss;
  ss << "Polygonal Map" << count++;
  manual_object_ = scene_manager_->createManualObject(ss.str());
  manual_object_->setDynamic(true);
  scene_node_->attachObject(manual_object_);

  cloud_ = new ogre_tools::PointCloud (scene_manager_, scene_node_);
  billboard_line_ = new ogre_tools::BillboardLine (scene_manager_, scene_node_);

  setAlpha (1.0f);
  setPointSize (0.02f);
  setZPosition (0.0f);
  setLineWidth (0.1f);

  notifier_ = new tf::MessageNotifier<robot_msgs::PolygonalMap> (tf_, ros_node_,
                                                                 boost::bind(&PolygonalMapDisplay::incomingMessage, this, _1),
                                                                 "", "", 1);
}

PolygonalMapDisplay::~PolygonalMapDisplay()
{
  unsubscribe();
  clear();

  delete notifier_;

  scene_manager_->destroyManualObject(manual_object_);

  delete cloud_;
  delete billboard_line_;
}

void PolygonalMapDisplay::clear()
{
  manual_object_->clear ();
  cloud_->clear ();
  billboard_line_->clear ();
}

void PolygonalMapDisplay::setTopic(const std::string & topic)
{
  unsubscribe();
  topic_ = topic;
  subscribe();

  if (topic_property_)
    topic_property_->changed();

  causeRender();
}

void PolygonalMapDisplay::setColor(const Color & color)
{
  color_ = color;

  if (color_property_)
    color_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::setOverrideColor(bool override)
{
  override_color_ = override;

  if (override_color_property_)
    override_color_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::setRenderOperation(int op)
{
  render_operation_ = op;

  if (render_operation_property_)
    render_operation_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::setLineWidth (float width)
{
  line_width_ = width;

  if (line_width_property_)
    line_width_property_->changed ();

  message_mutex_.lock ();
  new_message_ = current_message_;
  processMessage ();
  new_message_ = PolygonalMapPtr ();
  message_mutex_.unlock ();
  causeRender ();
}

void PolygonalMapDisplay::setPointSize (float size)
{
  point_size_ = size;

  if (point_size_property_)
    point_size_property_->changed ();

  cloud_->setBillboardDimensions (size, size);
  causeRender ();
}

void PolygonalMapDisplay::setZPosition(float z)
{
  z_position_ = z;

  if (z_position_property_)
    z_position_property_->changed();

  scene_node_->setPosition(0.0f, z, 0.0f);
  causeRender();
}

void PolygonalMapDisplay::setAlpha(float alpha)
{
  alpha_ = alpha;
  cloud_->setAlpha (alpha);

  if (alpha_property_)
    alpha_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::subscribe()
{
  if (!isEnabled())
    return;

  notifier_->setTopic(topic_);
}

void PolygonalMapDisplay::unsubscribe()
{
  notifier_->setTopic("");
}

void PolygonalMapDisplay::onEnable()
{
  scene_node_->setVisible(true);
  subscribe();
}

void PolygonalMapDisplay::onDisable()
{
  unsubscribe();
  clear();
  scene_node_->setVisible(false);
}

void PolygonalMapDisplay::fixedFrameChanged()
{
  notifier_->setTargetFrame( fixed_frame_ );
  clear();
}

void PolygonalMapDisplay::update(float dt)
{
  message_mutex_.lock();
  if (new_message_)
  {
    processMessage();
    current_message_ = new_message_;
    new_message_ = PolygonalMapPtr();
    causeRender();
  }
  message_mutex_.unlock();
}

void PolygonalMapDisplay::processMessage ()
{
  if (!new_message_)
  {
    return;
  }

  clear ();

  tf::Stamped<tf::Pose> pose(btTransform(btQuaternion(0.0f, 0.0f, 0.0f),
      btVector3(0.0f, 0.0f, z_position_)), new_message_->header.stamp,
      new_message_->header.frame_id);

  try
  {
    tf_->transformPose(fixed_frame_, pose, pose);
  }
  catch (tf::TransformException & e)
  {
    ROS_ERROR("Error transforming from frame 'map' to frame '%s'",
        fixed_frame_.c_str());
  }

  Ogre::Vector3 position = Ogre::Vector3(pose.getOrigin().x(),
      pose.getOrigin().y(), pose.getOrigin().z());
  robotToOgre(position);

  btScalar yaw, pitch, roll;
  pose.getBasis().getEulerZYX(yaw, pitch, roll);

  Ogre::Matrix3 orientation(ogreMatrixFromRobotEulers(yaw, pitch, roll));

  Ogre::ColourValue color;

  uint32_t num_polygons = new_message_->get_polygons_size ();
  uint32_t num_total_points = 0;
  for (uint32_t i = 0; i < num_polygons; i++)
    num_total_points += new_message_->polygons[i].points.size ();

  // If we render points, we don't care about the order
  if (render_operation_ == polygon_render_ops::PPoints)
  {
    typedef std::vector<ogre_tools::PointCloud::Point> V_Point;
    V_Point points;
    points.resize (num_total_points);
    uint32_t cnt_total_points = 0;
    for (uint32_t i = 0; i < num_polygons; i++)
    {
      for (uint32_t j = 0; j < new_message_->polygons[i].points.size(); j++)
      {
        ogre_tools::PointCloud::Point &current_point = points[cnt_total_points];

        current_point.x_ = new_message_->polygons[i].points[j].x;
        current_point.y_ = new_message_->polygons[i].points[j].y;
        current_point.z_ = new_message_->polygons[i].points[j].z;
        if (override_color_)
          color = Ogre::ColourValue (color_.r_, color_.g_, color_.b_, alpha_);
        else
          color = Ogre::ColourValue (new_message_->polygons[i].color.r,
                                     new_message_->polygons[i].color.g,
                                     new_message_->polygons[i].color.b, alpha_);
        current_point.r_ = color.r;
        current_point.g_ = color.g;
        current_point.b_ = color.b;
        cnt_total_points++;
      }
    }

    cloud_->clear();

    if (!points.empty())
      cloud_->addPoints(&points.front(), points.size());
  }
  // Lines ?
  else if (render_operation_ == polygon_render_ops::PLines)
  {
    for (uint32_t i = 0; i < num_polygons; i++)
    {
      manual_object_->estimateVertexCount (new_message_->polygons[i].points.size ());
      manual_object_->begin ("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP);
      for (uint32_t j = 0; j < new_message_->polygons[i].points.size (); j++)
      {
        manual_object_->position (new_message_->polygons[i].points[j].x,
                                  new_message_->polygons[i].points[j].y,
                                  new_message_->polygons[i].points[j].z);
        if (override_color_)
          color = Ogre::ColourValue(color_.r_, color_.g_, color_.b_, alpha_);
        else
          color = Ogre::ColourValue (new_message_->polygons[i].color.r,
                                     new_message_->polygons[i].color.g,
                                     new_message_->polygons[i].color.b, alpha_);
        manual_object_->colour (color);
      }
      manual_object_->end ();
    }
  }
  // Line Billboards ?
  else if (render_operation_ == polygon_render_ops::PBillboards)
  {
    billboard_line_->setMaxPointsPerLine (2);
    billboard_line_->setLineWidth (line_width_);
    if (override_color_)
      billboard_line_->setColor (color_.r_, color_.g_, color_.b_, alpha_);

    billboard_line_->setNumLines (num_total_points);

    // Go over all polygons
    for (uint32_t i = 0; i < num_polygons; i++)
    {
      // Create lines connecting the points from the current polygon
      if (new_message_->polygons[i].points.size () == 0)
        continue;
      uint32_t j = 0;
      for (j = 0; j < new_message_->polygons[i].points.size () - 1; j++)
      {
        Ogre::Vector3 p1 (new_message_->polygons[i].points[j].x,
                          new_message_->polygons[i].points[j].y,
                          new_message_->polygons[i].points[j].z);
        Ogre::Vector3 p2 (new_message_->polygons[i].points[j+1].x,
                          new_message_->polygons[i].points[j+1].y,
                          new_message_->polygons[i].points[j+1].z);

        billboard_line_->newLine ();
        billboard_line_->addPoint (p1);
        billboard_line_->addPoint (p2);
      }
      if (!override_color_)
        billboard_line_->setColor (new_message_->polygons[i].color.r, new_message_->polygons[i].color.g, new_message_->polygons[i].color.b, alpha_);
    }
  }

  scene_node_->setPosition(position);
  scene_node_->setOrientation(orientation);
}

void PolygonalMapDisplay::incomingMessage(const PolygonalMapPtr& message)
{
  message_mutex_.lock();
  new_message_ = message;
  message_mutex_.unlock();
}

void PolygonalMapDisplay::reset()
{
  clear();
}

void PolygonalMapDisplay::targetFrameChanged()
{
}

void PolygonalMapDisplay::createProperties()
{
  override_color_property_ = property_manager_->createProperty<BoolProperty> ("Override Color", property_prefix_, boost::bind(&PolygonalMapDisplay::getOverrideColor, this),
                                                                              boost::bind(&PolygonalMapDisplay::setOverrideColor, this, _1), parent_category_, this);
  color_property_ = property_manager_->createProperty<ColorProperty> ("Color", property_prefix_, boost::bind(&PolygonalMapDisplay::getColor, this),
                                                                      boost::bind(&PolygonalMapDisplay::setColor, this, _1), parent_category_, this);
  render_operation_property_ = property_manager_->createProperty<EnumProperty> ("Render Operation", property_prefix_, boost::bind(&PolygonalMapDisplay::getRenderOperation, this),
                                                                                boost::bind(&PolygonalMapDisplay::setRenderOperation, this, _1), parent_category_, this);
  render_operation_property_->addOption("Lines", polygon_render_ops::PLines);
  render_operation_property_->addOption("Points", polygon_render_ops::PPoints);
  render_operation_property_->addOption("Billboard Lines", polygon_render_ops::PBillboards);

  line_width_property_ = property_manager_->createProperty<FloatProperty> ("Line Width", property_prefix_, boost::bind (&PolygonalMapDisplay::getLineWidth, this),
                                                                           boost::bind (&PolygonalMapDisplay::setLineWidth, this, _1 ), parent_category_, this );
  line_width_property_->setMin (0.001);

  point_size_property_ = property_manager_->createProperty<FloatProperty>("Point Size", property_prefix_, boost::bind(&PolygonalMapDisplay::getPointSize, this),
                                                                          boost::bind( &PolygonalMapDisplay::setPointSize, this, _1 ), parent_category_, this);

  z_position_property_ = property_manager_->createProperty<FloatProperty> ("Z Position", property_prefix_, boost::bind(&PolygonalMapDisplay::getZPosition, this),
                                                                           boost::bind(&PolygonalMapDisplay::setZPosition, this, _1), parent_category_, this);
  alpha_property_ = property_manager_->createProperty<FloatProperty> ("Alpha", property_prefix_, boost::bind(&PolygonalMapDisplay::getAlpha, this),
                                                                      boost::bind(&PolygonalMapDisplay::setAlpha, this, _1), parent_category_,this);
  topic_property_ = property_manager_->createProperty<ROSTopicStringProperty> ("Topic", property_prefix_, boost::bind(&PolygonalMapDisplay::getTopic, this),
                                                                               boost::bind(&PolygonalMapDisplay::setTopic, this, _1), parent_category_, this);
  topic_property_->setMessageType(robot_msgs::PolygonalMap::__s_getDataType());

}

const char*
PolygonalMapDisplay::getDescription()
{
  return ("Displays data from a robot_msgs::PolygonalMap message as either points, billboards, or lines.");
}

} // namespace rviz
<commit_msg>removed default<commit_after>/*
 * Copyright (c) 2008, Willow Garage, Inc.
 * 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 the Willow Garage, Inc. 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 OWNER 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.
 *
 * $Id$
 *
 */

#include "polygonal_map_display.h"
#include "properties/property.h"
#include "properties/property_manager.h"
#include "common.h"

#include "ogre_tools/arrow.h"

#include <ros/node.h>
#include <tf/transform_listener.h>
#include <tf/message_notifier.h>

#include <boost/bind.hpp>

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreManualObject.h>
#include <OGRE/OgreBillboardSet.h>

#include <ogre_tools/point_cloud.h>

namespace rviz
{

PolygonalMapDisplay::PolygonalMapDisplay(const std::string & name,
    VisualizationManager * manager) :
  Display(name, manager), color_(0.1f, 1.0f, 0.0f)
      , render_operation_(polygon_render_ops::PLines)
      , override_color_(false)
      , color_property_(NULL)
      , topic_property_(NULL)
      , override_color_property_(NULL)
      , render_operation_property_(NULL)
      , point_size_property_(NULL)
      , z_position_property_(NULL)
      , alpha_property_(NULL)
{
  scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();

  static int count = 0;
  std::stringstream ss;
  ss << "Polygonal Map" << count++;
  manual_object_ = scene_manager_->createManualObject(ss.str());
  manual_object_->setDynamic(true);
  scene_node_->attachObject(manual_object_);

  cloud_ = new ogre_tools::PointCloud (scene_manager_, scene_node_);
  billboard_line_ = new ogre_tools::BillboardLine (scene_manager_, scene_node_);

  setAlpha (1.0f);
  setPointSize (0.02f);
  setZPosition (0.0f);

  notifier_ = new tf::MessageNotifier<robot_msgs::PolygonalMap> (tf_, ros_node_,
                                                                 boost::bind(&PolygonalMapDisplay::incomingMessage, this, _1),
                                                                 "", "", 1);
}

PolygonalMapDisplay::~PolygonalMapDisplay()
{
  unsubscribe();
  clear();

  delete notifier_;

  scene_manager_->destroyManualObject(manual_object_);

  delete cloud_;
  delete billboard_line_;
}

void PolygonalMapDisplay::clear()
{
  manual_object_->clear ();
  cloud_->clear ();
  billboard_line_->clear ();
}

void PolygonalMapDisplay::setTopic(const std::string & topic)
{
  unsubscribe();
  topic_ = topic;
  subscribe();

  if (topic_property_)
    topic_property_->changed();

  causeRender();
}

void PolygonalMapDisplay::setColor(const Color & color)
{
  color_ = color;

  if (color_property_)
    color_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::setOverrideColor(bool override)
{
  override_color_ = override;

  if (override_color_property_)
    override_color_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::setRenderOperation(int op)
{
  render_operation_ = op;

  if (render_operation_property_)
    render_operation_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::setLineWidth (float width)
{
  line_width_ = width;

  if (line_width_property_)
    line_width_property_->changed ();

  message_mutex_.lock ();
  new_message_ = current_message_;
  processMessage ();
  new_message_ = PolygonalMapPtr ();
  message_mutex_.unlock ();
  causeRender ();
}

void PolygonalMapDisplay::setPointSize (float size)
{
  point_size_ = size;

  if (point_size_property_)
    point_size_property_->changed ();

  cloud_->setBillboardDimensions (size, size);
  causeRender ();
}

void PolygonalMapDisplay::setZPosition(float z)
{
  z_position_ = z;

  if (z_position_property_)
    z_position_property_->changed();

  scene_node_->setPosition(0.0f, z, 0.0f);
  causeRender();
}

void PolygonalMapDisplay::setAlpha(float alpha)
{
  alpha_ = alpha;
  cloud_->setAlpha (alpha);

  if (alpha_property_)
    alpha_property_->changed();

  message_mutex_.lock();
  new_message_ = current_message_;
  processMessage();
  new_message_ = PolygonalMapPtr();
  message_mutex_.unlock();
  causeRender();
}

void PolygonalMapDisplay::subscribe()
{
  if (!isEnabled())
    return;

  notifier_->setTopic(topic_);
}

void PolygonalMapDisplay::unsubscribe()
{
  notifier_->setTopic("");
}

void PolygonalMapDisplay::onEnable()
{
  scene_node_->setVisible(true);
  subscribe();
}

void PolygonalMapDisplay::onDisable()
{
  unsubscribe();
  clear();
  scene_node_->setVisible(false);
}

void PolygonalMapDisplay::fixedFrameChanged()
{
  notifier_->setTargetFrame( fixed_frame_ );
  clear();
}

void PolygonalMapDisplay::update(float dt)
{
  message_mutex_.lock();
  if (new_message_)
  {
    processMessage();
    current_message_ = new_message_;
    new_message_ = PolygonalMapPtr();
    causeRender();
  }
  message_mutex_.unlock();
}

void PolygonalMapDisplay::processMessage ()
{
  if (!new_message_)
  {
    return;
  }

  clear ();

  tf::Stamped<tf::Pose> pose(btTransform(btQuaternion(0.0f, 0.0f, 0.0f),
      btVector3(0.0f, 0.0f, z_position_)), new_message_->header.stamp,
      new_message_->header.frame_id);

  try
  {
    tf_->transformPose(fixed_frame_, pose, pose);
  }
  catch (tf::TransformException & e)
  {
    ROS_ERROR("Error transforming from frame 'map' to frame '%s'",
        fixed_frame_.c_str());
  }

  Ogre::Vector3 position = Ogre::Vector3(pose.getOrigin().x(),
      pose.getOrigin().y(), pose.getOrigin().z());
  robotToOgre(position);

  btScalar yaw, pitch, roll;
  pose.getBasis().getEulerZYX(yaw, pitch, roll);

  Ogre::Matrix3 orientation(ogreMatrixFromRobotEulers(yaw, pitch, roll));

  Ogre::ColourValue color;

  uint32_t num_polygons = new_message_->get_polygons_size ();
  uint32_t num_total_points = 0;
  for (uint32_t i = 0; i < num_polygons; i++)
    num_total_points += new_message_->polygons[i].points.size ();

  // If we render points, we don't care about the order
  if (render_operation_ == polygon_render_ops::PPoints)
  {
    typedef std::vector<ogre_tools::PointCloud::Point> V_Point;
    V_Point points;
    points.resize (num_total_points);
    uint32_t cnt_total_points = 0;
    for (uint32_t i = 0; i < num_polygons; i++)
    {
      for (uint32_t j = 0; j < new_message_->polygons[i].points.size(); j++)
      {
        ogre_tools::PointCloud::Point &current_point = points[cnt_total_points];

        current_point.x_ = new_message_->polygons[i].points[j].x;
        current_point.y_ = new_message_->polygons[i].points[j].y;
        current_point.z_ = new_message_->polygons[i].points[j].z;
        if (override_color_)
          color = Ogre::ColourValue (color_.r_, color_.g_, color_.b_, alpha_);
        else
          color = Ogre::ColourValue (new_message_->polygons[i].color.r,
                                     new_message_->polygons[i].color.g,
                                     new_message_->polygons[i].color.b, alpha_);
        current_point.r_ = color.r;
        current_point.g_ = color.g;
        current_point.b_ = color.b;
        cnt_total_points++;
      }
    }

    cloud_->clear();

    if (!points.empty())
      cloud_->addPoints(&points.front(), points.size());
  }
  // Lines ?
  else if (render_operation_ == polygon_render_ops::PLines)
  {
    for (uint32_t i = 0; i < num_polygons; i++)
    {
      manual_object_->estimateVertexCount (new_message_->polygons[i].points.size ());
      manual_object_->begin ("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP);
      for (uint32_t j = 0; j < new_message_->polygons[i].points.size (); j++)
      {
        manual_object_->position (new_message_->polygons[i].points[j].x,
                                  new_message_->polygons[i].points[j].y,
                                  new_message_->polygons[i].points[j].z);
        if (override_color_)
          color = Ogre::ColourValue(color_.r_, color_.g_, color_.b_, alpha_);
        else
          color = Ogre::ColourValue (new_message_->polygons[i].color.r,
                                     new_message_->polygons[i].color.g,
                                     new_message_->polygons[i].color.b, alpha_);
        manual_object_->colour (color);
      }
      manual_object_->end ();
    }
  }
  // Line Billboards ?
  else if (render_operation_ == polygon_render_ops::PBillboards)
  {
    billboard_line_->setMaxPointsPerLine (2);
    billboard_line_->setLineWidth (line_width_);
    if (override_color_)
      billboard_line_->setColor (color_.r_, color_.g_, color_.b_, alpha_);

    billboard_line_->setNumLines (num_total_points);

    // Go over all polygons
    for (uint32_t i = 0; i < num_polygons; i++)
    {
      // Create lines connecting the points from the current polygon
      if (new_message_->polygons[i].points.size () == 0)
        continue;
      uint32_t j = 0;
      for (j = 0; j < new_message_->polygons[i].points.size () - 1; j++)
      {
        Ogre::Vector3 p1 (new_message_->polygons[i].points[j].x,
                          new_message_->polygons[i].points[j].y,
                          new_message_->polygons[i].points[j].z);
        Ogre::Vector3 p2 (new_message_->polygons[i].points[j+1].x,
                          new_message_->polygons[i].points[j+1].y,
                          new_message_->polygons[i].points[j+1].z);

        billboard_line_->newLine ();
        billboard_line_->addPoint (p1);
        billboard_line_->addPoint (p2);
      }
      if (!override_color_)
        billboard_line_->setColor (new_message_->polygons[i].color.r, new_message_->polygons[i].color.g, new_message_->polygons[i].color.b, alpha_);
    }
  }

  scene_node_->setPosition(position);
  scene_node_->setOrientation(orientation);
}

void PolygonalMapDisplay::incomingMessage(const PolygonalMapPtr& message)
{
  message_mutex_.lock();
  new_message_ = message;
  message_mutex_.unlock();
}

void PolygonalMapDisplay::reset()
{
  clear();
}

void PolygonalMapDisplay::targetFrameChanged()
{
}

void PolygonalMapDisplay::createProperties()
{
  override_color_property_ = property_manager_->createProperty<BoolProperty> ("Override Color", property_prefix_, boost::bind(&PolygonalMapDisplay::getOverrideColor, this),
                                                                              boost::bind(&PolygonalMapDisplay::setOverrideColor, this, _1), parent_category_, this);
  color_property_ = property_manager_->createProperty<ColorProperty> ("Color", property_prefix_, boost::bind(&PolygonalMapDisplay::getColor, this),
                                                                      boost::bind(&PolygonalMapDisplay::setColor, this, _1), parent_category_, this);
  render_operation_property_ = property_manager_->createProperty<EnumProperty> ("Render Operation", property_prefix_, boost::bind(&PolygonalMapDisplay::getRenderOperation, this),
                                                                                boost::bind(&PolygonalMapDisplay::setRenderOperation, this, _1), parent_category_, this);
  render_operation_property_->addOption("Lines", polygon_render_ops::PLines);
  render_operation_property_->addOption("Points", polygon_render_ops::PPoints);
  render_operation_property_->addOption("Billboard Lines", polygon_render_ops::PBillboards);

  line_width_property_ = property_manager_->createProperty<FloatProperty> ("Line Width", property_prefix_, boost::bind (&PolygonalMapDisplay::getLineWidth, this),
                                                                           boost::bind (&PolygonalMapDisplay::setLineWidth, this, _1 ), parent_category_, this );
  line_width_property_->setMin (0.001);

  point_size_property_ = property_manager_->createProperty<FloatProperty>("Point Size", property_prefix_, boost::bind(&PolygonalMapDisplay::getPointSize, this),
                                                                          boost::bind( &PolygonalMapDisplay::setPointSize, this, _1 ), parent_category_, this);

  z_position_property_ = property_manager_->createProperty<FloatProperty> ("Z Position", property_prefix_, boost::bind(&PolygonalMapDisplay::getZPosition, this),
                                                                           boost::bind(&PolygonalMapDisplay::setZPosition, this, _1), parent_category_, this);
  alpha_property_ = property_manager_->createProperty<FloatProperty> ("Alpha", property_prefix_, boost::bind(&PolygonalMapDisplay::getAlpha, this),
                                                                      boost::bind(&PolygonalMapDisplay::setAlpha, this, _1), parent_category_,this);
  topic_property_ = property_manager_->createProperty<ROSTopicStringProperty> ("Topic", property_prefix_, boost::bind(&PolygonalMapDisplay::getTopic, this),
                                                                               boost::bind(&PolygonalMapDisplay::setTopic, this, _1), parent_category_, this);
  topic_property_->setMessageType(robot_msgs::PolygonalMap::__s_getDataType());

}

const char*
PolygonalMapDisplay::getDescription()
{
  return ("Displays data from a robot_msgs::PolygonalMap message as either points, billboards, or lines.");
}

} // namespace rviz
<|endoftext|>


<commit_before>#include <QApplication>
#include <QFile>
#include <QMessageBox>
#include <QDebug>
#include "bfgminer.h"

BFGMiner::BFGMiner(QObject *parent) :
    QObject(parent)
{
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    env.insert("PATH", QString(qApp->applicationDirPath() + "/bfgminer;C:/Windows/System32;C:/Windows;"));
    process.setProcessEnvironment(env);
//    process.setWorkingDirectory(qApp->applicationDirPath() + "/bfgminer");
    process.setWorkingDirectory(qApp->applicationDirPath());

    connect(&process, SIGNAL(started()), this, SIGNAL(started()));
    connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SIGNAL(finished(int, QProcess::ExitStatus)));
    connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutput()));
    connect(&process, SIGNAL(readyReadStandardError()), this, SLOT(readStdError()));
    connect(&process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(readError()));
}

BFGMiner::~BFGMiner()
{

}

void BFGMiner::run(bool action)
{
    /* Stop */
    if (!action) {
        process.kill();
        return;
    }

    /* Start */
    QFile bfgFile(QString(qApp->applicationDirPath() + "/bfgminer/bfgminer.exe"));
//    QFile bfgFile(QString(qApp->applicationDirPath() + "/mytest.exe"));
    if (!bfgFile.exists()) {
        QMessageBox messageBox;
        qCritical("ERROR: File not found: %s", QString(bfgFile.fileName()).toLocal8Bit().data());
        messageBox.critical(0, "Error", "File not found: " + bfgFile.fileName());
//        qApp->quit();
        return;
    }
    process.start(bfgFile.fileName(), para);
}

void BFGMiner::confChanged(bfgConf *bfgConfig)
{
    unsigned int i;
    para = QStringList();
    for (i = 0; i < sizeof(bfgConf)/sizeof(poolInfo); i ++) {
        para += QStringList("-o") + QStringList(bfgConfig->info[i].url + QString(":") + QString::number(bfgConfig->info[i].port));
        para += QStringList("-O") + QStringList(bfgConfig->info[i].name + QString(":") + bfgConfig->info[i].pass);
    }
    para += bfgConfig->para;
    para += QStringList("--log-file") + QStringList(bfgConfig->log);
    qDebug() << para;
}

void BFGMiner::readStdOutput()
{
//    qDebug() << process.readAllStandardOutput();
    return;
}

void BFGMiner::readStdError()
{
//    qDebug() << process.readAllStandardError();
    return;
}

void BFGMiner::readError()
{
//    qDebug() << "An Error Occured! Error Code is " + QString::number(process.error());
    return;
}
<commit_msg>Add Linux support, with bfgminer and bfgminer-rpc in the same directory of Windows<commit_after>#include <QApplication>
#include <QFile>
#include <QMessageBox>
#include <QDebug>
#include "bfgminer.h"

BFGMiner::BFGMiner(QObject *parent) :
    QObject(parent)
{
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
#ifdef Q_OS_WIN
    env.insert("PATH", QString(qApp->applicationDirPath() + "/bfgminer;C:/Windows/System32;C:/Windows;"));
#else
    env.insert("LD_LIBRARY_PATH", QString(qApp->applicationDirPath() + "/bfgminer"));
#endif
    process.setProcessEnvironment(env);
//    process.setWorkingDirectory(qApp->applicationDirPath() + "/bfgminer");
    process.setWorkingDirectory(qApp->applicationDirPath());

    connect(&process, SIGNAL(started()), this, SIGNAL(started()));
    connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SIGNAL(finished(int, QProcess::ExitStatus)));
    connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOutput()));
    connect(&process, SIGNAL(readyReadStandardError()), this, SLOT(readStdError()));
    connect(&process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(readError()));
}

BFGMiner::~BFGMiner()
{

}

void BFGMiner::run(bool action)
{
    /* Stop */
    if (!action) {
        process.kill();
        return;
    }

    /* Start */
#ifdef Q_OS_WIN
    QFile bfgFile(QString(qApp->applicationDirPath() + "/bfgminer/bfgminer.exe"));
#else
    QFile bfgFile(QString(qApp->applicationDirPath() + "/bfgminer/bfgminer"));
#endif
    if (!bfgFile.exists()) {
        QMessageBox messageBox;
        qCritical("ERROR: File not found: %s", QString(bfgFile.fileName()).toLocal8Bit().data());
        messageBox.critical(0, "Error", "File not found: " + bfgFile.fileName());
//        qApp->quit();
        return;
    }
    process.start(bfgFile.fileName(), para);
}

void BFGMiner::confChanged(bfgConf *bfgConfig)
{
    unsigned int i;
    para = QStringList();
    for (i = 0; i < sizeof(bfgConf)/sizeof(poolInfo); i ++) {
        para += QStringList("-o") + QStringList(bfgConfig->info[i].url + QString(":") + QString::number(bfgConfig->info[i].port));
        para += QStringList("-O") + QStringList(bfgConfig->info[i].name + QString(":") + bfgConfig->info[i].pass);
    }
    para += bfgConfig->para;
    para += QStringList("--log-file") + QStringList(bfgConfig->log);
    qDebug() << para;
}

void BFGMiner::readStdOutput()
{
//    qDebug() << process.readAllStandardOutput();
    return;
}

void BFGMiner::readStdError()
{
//    qDebug() << process.readAllStandardError();
    return;
}

void BFGMiner::readError()
{
//    qDebug() << "An Error Occured! Error Code is " + QString::number(process.error());
    return;
}
<|endoftext|>


<commit_before>#ifndef UTENSOR_FULLY_CONNECTED_OPS
#define UTENSOR_FULLY_CONNECTED_OPS
#include "uTensor/core/tensor.hpp"
#include "uTensor/core/uTensorBase.hpp"
#include "arm_math.h"
#include "arm_nnfunctions.h"

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename TOut>
void FullyConnectedLayerCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch)
{
    //Throw error if this gets called
}

template<>
void FullyConnectedLayerCmsis<q7_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q7_t* iV_data = iV->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    q7_t* pOut_data = pOut->write(0, sizeof(q7_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q7(iV_data, mW_data, dim_vec, dim_vec,
            num_of_rows, bias_shift, out_shift, pOut_data, scratch_data);
    //Error checking
}
template<>
void FullyConnectedLayerCmsis<q15_t, q15_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* mW_data = mW->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q15(iV_data, mW_data, dim_vec, dim_vec,
            num_of_rows, bias_shift, out_shift, pOut_data, scratch_data);
    //Error checking
}

template<>
void FullyConnectedLayerCmsis<q15_t, q7_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q7_t* mW_data = mW->read<q15_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_mat_q7_vec_q15(iV_data, mW_data, dim_vec, dim_vec,
            num_of_rows, bias_shift, out_shift, pOut_data, scratch_data);
    //Error checking
}

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename TOut>
void FullyConnectedLayerOptCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch)
{
    //Throw error if this gets called
}

template<>
void FullyConnectedLayerOptCmsis<q7_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q7_t* iV_data = iV->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    q7_t* pOut_data = pOut->write(0, sizeof(q7_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q7_opt(iV_data, mW_data, dim_vec, dim_vec,
            num_of_rows, bias_shift, out_shift, pOut_data, scratch_data);
    //Error checking
}
template<>
void FullyConnectedLayerOptCmsis<q15_t, q15_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* mW_data = mW->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q15_opt(iV_data, mW_data, dim_vec, dim_vec,
            num_of_rows, bias_shift, out_shift, pOut_data, scratch_data);
    //Error checking
}

template<>
void FullyConnectedLayerOptCmsis<q15_t, q7_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q7_t* mW_data = mW->read<q15_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_mat_q7_vec_q15_opt(iV_data, mW_data, dim_vec, dim_vec,
            num_of_rows, bias_shift, out_shift, pOut_data, scratch_data);
    //Error checking
}

template <class T1, class T2, class TOut>
class FullyConnectedLayerCmsisOp : public Operator {
  public:
  FullyConnectedLayerCmsisOp() {
    n_inputs = 7;
    n_outputs = 1;
  }
  virtual void compute() override {
    FullyConnectedLayerCmsis<T1, T2, TOut>(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], inputs[5], outputs[0], inputs[6]);
  }
};

template <class T1, class T2, class TOut>
class FullyConnectedLayerOptCmsisOp : public Operator {
  public:
  FullyConnectedLayerOptCmsisOp() {
    n_inputs = 6;
    n_outputs = 3;
  }
  virtual void compute() override {
    FullyConnectedLayerOptCmsis<T1, T2, TOut>(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], inputs[5], outputs[0], inputs[6]);
  }
};

#endif /*UTENSOR_FULLY_CONNECTED_OPS*/
<commit_msg>Actually add bias to matrix mults<commit_after>#ifndef UTENSOR_FULLY_CONNECTED_OPS
#define UTENSOR_FULLY_CONNECTED_OPS
#include "uTensor/core/tensor.hpp"
#include "uTensor/core/uTensorBase.hpp"
#include "arm_math.h"
#include "arm_nnfunctions.h"

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename TOut>
void FullyConnectedLayerCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch)
{
    //Throw error if this gets called
}

template<>
void FullyConnectedLayerCmsis<q7_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q7_t* iV_data = iV->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q7_t* pOut_data = pOut->write(0, sizeof(q7_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q7(iV_data, mW_data, dim_vec, num_of_rows,
            bias_shift, out_shift, bias_data, pOut_data, scratch_data);

    //Error checking
}
template<>
void FullyConnectedLayerCmsis<q15_t, q15_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* mW_data = mW->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* bias_data = b->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q15(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

template<>
void FullyConnectedLayerCmsis<q15_t, q7_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q7_t* mW_data = mW->read<q15_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_mat_q7_vec_q15(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

/***
 * Here we have two types of kernel functions. The basic function implements the function using regular GEMV approach. The opt functions operates with weights in interleaved formats.
 *
 * http://www.keil.com/pack/doc/CMSIS/NN/html/group__FC.html#gae3857bb6375692e81dde8cbd70adec08
 */

/**
 * @param [in] iV input vector
 * @param [in] mW matrix weights
 * @param [in] b bias
 * @param [in] scratch scrath computation space
 * @param [out] pOut output
 */
template<typename T1, typename T2, typename TOut>
void FullyConnectedLayerOptCmsis(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                         S_TENSOR bShift, S_TENSOR oShift,
                         S_TENSOR pOut, S_TENSOR scratch)
{
    //Throw error if this gets called
}

template<>
void FullyConnectedLayerOptCmsis<q7_t, q7_t, q7_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q7_t* iV_data = iV->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* mW_data = mW->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q7_t* pOut_data = pOut->write(0, sizeof(q7_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q7_opt(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}
template<>
void FullyConnectedLayerOptCmsis<q15_t, q15_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* mW_data = mW->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q15_t* bias_data = b->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_q15_opt(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

template<>
void FullyConnectedLayerOptCmsis<q15_t, q7_t, q15_t>(S_TENSOR iV, S_TENSOR mW, S_TENSOR b,
                                           S_TENSOR bShift, S_TENSOR oShift,
                                           S_TENSOR pOut, S_TENSOR scratch)
{
    const q15_t* iV_data = iV->read<q15_t>(0, sizeof(q15_t)); //Read one byte
    const q7_t* mW_data = mW->read<q15_t>(0, sizeof(q7_t)); //Read one byte
    const q7_t* bias_data = b->read<q7_t>(0, sizeof(q7_t)); //Read one byte
    const uint16_t dim_vec = iV->getShape()[0];
    const uint16_t num_of_rows = mW->getShape()[0];
    const uint16_t bias_shift = *(bShift->read<uint16_t>(0,0));
    const uint16_t out_shift = *(oShift->read<uint16_t>(0,0));
    pOut->resize(b->getShape());
    q15_t* pOut_data = pOut->write(0, sizeof(q15_t));
    q15_t* scratch_data = scratch->write(0, sizeof(q15_t));

    arm_fully_connected_mat_q7_vec_q15_opt(iV_data, mW_data, dim_vec, num_of_rows,
                        bias_shift, out_shift, bias_data, pOut_data, scratch_data);
    //Error checking
}

template <class T1, class T2, class TOut>
class FullyConnectedLayerCmsisOp : public Operator {
  public:
  FullyConnectedLayerCmsisOp() {
    n_inputs = 7;
    n_outputs = 1;
  }
  virtual void compute() override {
    FullyConnectedLayerCmsis<T1, T2, TOut>(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], inputs[5], outputs[0], inputs[6]);
  }
};

template <class T1, class T2, class TOut>
class FullyConnectedLayerOptCmsisOp : public Operator {
  public:
  FullyConnectedLayerOptCmsisOp() {
    n_inputs = 6;
    n_outputs = 3;
  }
  virtual void compute() override {
    FullyConnectedLayerOptCmsis<T1, T2, TOut>(inputs[0], inputs[1], inputs[2], inputs[3],
      inputs[4], inputs[5], outputs[0], inputs[6]);
  }
};

#endif /*UTENSOR_FULLY_CONNECTED_OPS*/
<|endoftext|>