<commit_before>//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains code to lower PPC MachineInstrs to their corresponding
// MCInst records.
//
//===----------------------------------------------------------------------===//

#include "PPC.h"
#include "MCTargetDesc/PPCMCExpr.h"
#include "PPCSubtarget.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;

static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) {
  return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>();
}

static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
  const TargetMachine &TM = AP.TM;
  Mangler *Mang = AP.Mang;
  const DataLayout *DL = TM.getDataLayout();
  MCContext &Ctx = AP.OutContext;
  bool isDarwin = Triple(TM.getTargetTriple()).isOSDarwin();

  SmallString<128> Name;
  StringRef Suffix;
  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB) {
    if (isDarwin)
      Suffix = "$stub";
  } else if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG)
    Suffix = "$non_lazy_ptr";

  if (!Suffix.empty())
    Name += DL->getPrivateGlobalPrefix();

  unsigned PrefixLen = Name.size();

  if (!MO.isGlobal()) {
    assert(MO.isSymbol() && "Isn't a symbol reference");
    Mang->getNameWithPrefix(Name, MO.getSymbolName());
  } else {
    const GlobalValue *GV = MO.getGlobal();
    TM.getNameWithPrefix(Name, GV, *Mang);
  }

  unsigned OrigLen = Name.size() - PrefixLen;

  Name += Suffix;
  MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
  StringRef OrigName = StringRef(Name).substr(PrefixLen, OrigLen);

  // If the target flags on the operand changes the name of the symbol, do that
  // before we return the symbol.
  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && isDarwin) {
    MachineModuleInfoImpl::StubValueTy &StubSym =
      getMachOMMI(AP).getFnStubEntry(Sym);
    if (StubSym.getPointer())
      return Sym;

    if (MO.isGlobal()) {
      StubSym =
      MachineModuleInfoImpl::
      StubValueTy(AP.getSymbol(MO.getGlobal()),
                  !MO.getGlobal()->hasInternalLinkage());
    } else {
      StubSym =
      MachineModuleInfoImpl::
      StubValueTy(Ctx.GetOrCreateSymbol(OrigName), false);
    }
    return Sym;
  }

  // If the symbol reference is actually to a non_lazy_ptr, not to the symbol,
  // then add the suffix.
  if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) {
    MachineModuleInfoMachO &MachO = getMachOMMI(AP);

    MachineModuleInfoImpl::StubValueTy &StubSym =
      (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ?
         MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym);

    if (!StubSym.getPointer()) {
      assert(MO.isGlobal() && "Extern symbol not handled yet");
      StubSym = MachineModuleInfoImpl::
                   StubValueTy(AP.getSymbol(MO.getGlobal()),
                               !MO.getGlobal()->hasInternalLinkage());
    }
    return Sym;
  }

  return Sym;
}

static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
                              AsmPrinter &Printer, bool isDarwin) {
  MCContext &Ctx = Printer.OutContext;
  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;

  unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;

  switch (access) {
    case PPCII::MO_TPREL_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO;
      break;
    case PPCII::MO_TPREL_HA:
      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA;
      break;
    case PPCII::MO_DTPREL_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO;
      break;
    case PPCII::MO_TLSLD_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO;
      break;
    case PPCII::MO_TOC_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
      break;
    case PPCII::MO_TLS:
      RefKind = MCSymbolRefExpr::VK_PPC_TLS;
      break;
  }

  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && !isDarwin)
    RefKind = MCSymbolRefExpr::VK_PLT;

  const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);

  if (!MO.isJTI() && MO.getOffset())
    Expr = MCBinaryExpr::CreateAdd(Expr,
                                   MCConstantExpr::Create(MO.getOffset(), Ctx),
                                   Ctx);

  // Subtract off the PIC base if required.
  if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) {
    const MachineFunction *MF = MO.getParent()->getParent()->getParent();

    const MCExpr *PB = MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), Ctx);
    Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx);
  }

  // Add ha16() / lo16() markers if required.
  switch (access) {
    case PPCII::MO_LO:
      Expr = PPCMCExpr::CreateLo(Expr, isDarwin, Ctx);
      break;
    case PPCII::MO_HA:
      Expr = PPCMCExpr::CreateHa(Expr, isDarwin, Ctx);
      break;
  }

  return MCOperand::CreateExpr(Expr);
}

void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
                                        AsmPrinter &AP, bool isDarwin) {
  OutMI.setOpcode(MI->getOpcode());

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);

    MCOperand MCOp;
    switch (MO.getType()) {
    default:
      MI->dump();
      llvm_unreachable("unknown operand type");
    case MachineOperand::MO_Register:
      assert(!MO.getSubReg() && "Subregs should be eliminated!");
      MCOp = MCOperand::CreateReg(MO.getReg());
      break;
    case MachineOperand::MO_Immediate:
      MCOp = MCOperand::CreateImm(MO.getImm());
      break;
    case MachineOperand::MO_MachineBasicBlock:
      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
                                      MO.getMBB()->getSymbol(), AP.OutContext));
      break;
    case MachineOperand::MO_GlobalAddress:
    case MachineOperand::MO_ExternalSymbol:
      MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
      break;
    case MachineOperand::MO_JumpTableIndex:
      MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
      break;
    case MachineOperand::MO_ConstantPoolIndex:
      MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
      break;
    case MachineOperand::MO_BlockAddress:
      MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP,
                          isDarwin);
      break;
    case MachineOperand::MO_RegisterMask:
      continue;
    }

    OutMI.addOperand(MCOp);
  }
}
<commit_msg>Add assertion to detect invalid registers in the PowerPC MC instruction lowering.<commit_after>//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains code to lower PPC MachineInstrs to their corresponding
// MCInst records.
//
//===----------------------------------------------------------------------===//

#include "PPC.h"
#include "MCTargetDesc/PPCMCExpr.h"
#include "PPCSubtarget.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;

static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) {
  return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>();
}

static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
  const TargetMachine &TM = AP.TM;
  Mangler *Mang = AP.Mang;
  const DataLayout *DL = TM.getDataLayout();
  MCContext &Ctx = AP.OutContext;
  bool isDarwin = Triple(TM.getTargetTriple()).isOSDarwin();

  SmallString<128> Name;
  StringRef Suffix;
  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB) {
    if (isDarwin)
      Suffix = "$stub";
  } else if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG)
    Suffix = "$non_lazy_ptr";

  if (!Suffix.empty())
    Name += DL->getPrivateGlobalPrefix();

  unsigned PrefixLen = Name.size();

  if (!MO.isGlobal()) {
    assert(MO.isSymbol() && "Isn't a symbol reference");
    Mang->getNameWithPrefix(Name, MO.getSymbolName());
  } else {
    const GlobalValue *GV = MO.getGlobal();
    TM.getNameWithPrefix(Name, GV, *Mang);
  }

  unsigned OrigLen = Name.size() - PrefixLen;

  Name += Suffix;
  MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
  StringRef OrigName = StringRef(Name).substr(PrefixLen, OrigLen);

  // If the target flags on the operand changes the name of the symbol, do that
  // before we return the symbol.
  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && isDarwin) {
    MachineModuleInfoImpl::StubValueTy &StubSym =
      getMachOMMI(AP).getFnStubEntry(Sym);
    if (StubSym.getPointer())
      return Sym;

    if (MO.isGlobal()) {
      StubSym =
      MachineModuleInfoImpl::
      StubValueTy(AP.getSymbol(MO.getGlobal()),
                  !MO.getGlobal()->hasInternalLinkage());
    } else {
      StubSym =
      MachineModuleInfoImpl::
      StubValueTy(Ctx.GetOrCreateSymbol(OrigName), false);
    }
    return Sym;
  }

  // If the symbol reference is actually to a non_lazy_ptr, not to the symbol,
  // then add the suffix.
  if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) {
    MachineModuleInfoMachO &MachO = getMachOMMI(AP);

    MachineModuleInfoImpl::StubValueTy &StubSym =
      (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ?
         MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym);

    if (!StubSym.getPointer()) {
      assert(MO.isGlobal() && "Extern symbol not handled yet");
      StubSym = MachineModuleInfoImpl::
                   StubValueTy(AP.getSymbol(MO.getGlobal()),
                               !MO.getGlobal()->hasInternalLinkage());
    }
    return Sym;
  }

  return Sym;
}

static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
                              AsmPrinter &Printer, bool isDarwin) {
  MCContext &Ctx = Printer.OutContext;
  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;

  unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;

  switch (access) {
    case PPCII::MO_TPREL_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO;
      break;
    case PPCII::MO_TPREL_HA:
      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA;
      break;
    case PPCII::MO_DTPREL_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO;
      break;
    case PPCII::MO_TLSLD_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO;
      break;
    case PPCII::MO_TOC_LO:
      RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
      break;
    case PPCII::MO_TLS:
      RefKind = MCSymbolRefExpr::VK_PPC_TLS;
      break;
  }

  if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && !isDarwin)
    RefKind = MCSymbolRefExpr::VK_PLT;

  const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);

  if (!MO.isJTI() && MO.getOffset())
    Expr = MCBinaryExpr::CreateAdd(Expr,
                                   MCConstantExpr::Create(MO.getOffset(), Ctx),
                                   Ctx);

  // Subtract off the PIC base if required.
  if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) {
    const MachineFunction *MF = MO.getParent()->getParent()->getParent();

    const MCExpr *PB = MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), Ctx);
    Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx);
  }

  // Add ha16() / lo16() markers if required.
  switch (access) {
    case PPCII::MO_LO:
      Expr = PPCMCExpr::CreateLo(Expr, isDarwin, Ctx);
      break;
    case PPCII::MO_HA:
      Expr = PPCMCExpr::CreateHa(Expr, isDarwin, Ctx);
      break;
  }

  return MCOperand::CreateExpr(Expr);
}

void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
                                        AsmPrinter &AP, bool isDarwin) {
  OutMI.setOpcode(MI->getOpcode());

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);

    MCOperand MCOp;
    switch (MO.getType()) {
    default:
      MI->dump();
      llvm_unreachable("unknown operand type");
    case MachineOperand::MO_Register:
      assert(!MO.getSubReg() && "Subregs should be eliminated!");
      assert(MO.getReg() > PPC::NoRegister &&
             MO.getReg() < PPC::NUM_TARGET_REGS &&
             "Invalid register for this target!");
      MCOp = MCOperand::CreateReg(MO.getReg());
      break;
    case MachineOperand::MO_Immediate:
      MCOp = MCOperand::CreateImm(MO.getImm());
      break;
    case MachineOperand::MO_MachineBasicBlock:
      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
                                      MO.getMBB()->getSymbol(), AP.OutContext));
      break;
    case MachineOperand::MO_GlobalAddress:
    case MachineOperand::MO_ExternalSymbol:
      MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
      break;
    case MachineOperand::MO_JumpTableIndex:
      MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
      break;
    case MachineOperand::MO_ConstantPoolIndex:
      MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
      break;
    case MachineOperand::MO_BlockAddress:
      MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP,
                          isDarwin);
      break;
    case MachineOperand::MO_RegisterMask:
      continue;
    }

    OutMI.addOperand(MCOp);
  }
}
<|endoftext|>


<commit_before>/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/
#include "CLWProgram.h"
#include "CLWContext.h"
#include "CLWDevice.h"
#include "CLWExcept.h"
#include "CLWKernel.h"

#include <functional>
#include <cassert>
#include <algorithm>
#include <fstream>

static void load_file_contents(std::string const& name, std::vector<char>& contents, bool binary)
{
    std::ifstream in(name, std::ios::in | (std::ios_base::openmode)(binary?std::ios::binary : 0));

    if (in)
    {
        contents.clear();

        std::streamoff beg = in.tellg();

        in.seekg(0, std::ios::end);

        std::streamoff fileSize = in.tellg() - beg;

        in.seekg(0, std::ios::beg);

        contents.resize(static_cast<unsigned>(fileSize));

        in.read(&contents[0], fileSize);
    }
    else
    {
        throw std::runtime_error("Cannot read the contents of a file");
    }
}

CLWProgram CLWProgram::CreateFromSource(char const* sourcecode, size_t sourcesize, char const* buildopts, CLWContext context)
{
    cl_int status = CL_SUCCESS;

    cl_program program = clCreateProgramWithSource(context, 1, (const char**)&sourcecode, &sourcesize, &status);

    ThrowIf(status != CL_SUCCESS, status, "clCreateProgramWithSource failed");

    std::vector<cl_device_id> deviceIds(context.GetDeviceCount());
    for(unsigned int i = 0; i < context.GetDeviceCount(); ++i)
    {
        deviceIds[i] = context.GetDevice(i);
    }

    status = clBuildProgram(program, context.GetDeviceCount(), &deviceIds[0], buildopts, nullptr, nullptr);

    if(status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    CLWProgram prg(program);

    clReleaseProgram(program);

    return prg;
}

CLWProgram CLWProgram::CreateFromSource(char const* sourcecode,
                                        size_t sourcesize,
                                        char const** headers,
                                        char const** headernames,
                                        size_t* headersizes,
                                        int numheaders,
                                        char const* buildopts,
                                        CLWContext context)
{
    cl_int status = CL_SUCCESS;

    std::vector<cl_device_id> deviceIds(context.GetDeviceCount());
    for(unsigned int i = 0; i < context.GetDeviceCount(); ++i)
    {
        deviceIds[i] = context.GetDevice(i);
    }

    std::vector<cl_program> headerPrograms(numheaders);
    for (int i=0; i<numheaders; ++i)
    {
        size_t sourceSize = headersizes[i];
        char const* tempPtr = headers[i];
        headerPrograms[i] = clCreateProgramWithSource(context, 1, (const char**)&tempPtr, &sourceSize, &status);
        ThrowIf(status != CL_SUCCESS, status, "clCreateProgramWithSource failed");
    }

    cl_program program = clCreateProgramWithSource(context, 1, (const char**)&sourcecode, &sourcesize, &status);

    ThrowIf(status != CL_SUCCESS, status, "clCreateProgramWithSource failed");

    status = clCompileProgram(program, context.GetDeviceCount(), &deviceIds[0], buildopts, numheaders, &headerPrograms[0], headernames, nullptr, nullptr);

    if(status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    status = clBuildProgram(program, context.GetDeviceCount(), &deviceIds[0], buildopts, nullptr, nullptr);

    if(status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    CLWProgram prg(program);

    clReleaseProgram(program);

    return prg;
}

CLWProgram CLWProgram::CreateFromBinary(std::uint8_t** binaries, std::size_t* binary_sizes, CLWContext context)
{
    cl_int status = CL_SUCCESS;

    std::vector<cl_device_id> deviceIds(context.GetDeviceCount());
    for (unsigned int i = 0; i < context.GetDeviceCount(); ++i)
    {
        deviceIds[i] = context.GetDevice(i);
    }

    cl_int binary_status = 0;
    cl_program program = clCreateProgramWithBinary(context, context.GetDeviceCount(), &deviceIds[0], binary_sizes, (const unsigned char**)binaries, &binary_status, &status);

    if (status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    status = clBuildProgram(program, context.GetDeviceCount(), &deviceIds[0], nullptr, nullptr, nullptr);

    if (status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    CLWProgram prg(program);

    clReleaseProgram(program);

    return prg;

}

CLWProgram CLWProgram::CreateFromFile(char const* filename, char const* buildopts, CLWContext context)
{
    std::vector<char> sourcecode;
    load_file_contents(filename, sourcecode, false);
    return CreateFromSource(&sourcecode[0], sourcecode.size(), buildopts, context);
}

CLWProgram CLWProgram::CreateFromFile(char const* filename,
                                      char const** headernames,
                                      int numheaders,
                                      char const* buildopts,
                                      CLWContext context)
{
    std::vector<char> sourcecode;
    load_file_contents(filename, sourcecode, false);

    std::vector<std::vector<char> > headers;
    std::vector<char const*> headerstrs;
    std::vector<size_t> headerssizes;

    if (numheaders > 0)
    {
        for (int i = 0; i < numheaders; ++i)
        {
            std::vector<char> headersource;
            load_file_contents(headernames[i], headersource, false);
            headerssizes.push_back(headersource.size());
            headers.push_back(std::move(headersource));
            headerstrs.push_back(&headers[i][0]);
        }

        return CreateFromSource(&sourcecode[0], sourcecode.size(), &headerstrs[0], headernames, &headerssizes[0], numheaders, buildopts, context);
    }
    else
    {
        return CreateFromSource(&sourcecode[0], sourcecode.size(), buildopts, context);
    }
}

CLWProgram::CLWProgram(cl_program program)
: ReferenceCounter<cl_program, clRetainProgram, clReleaseProgram>(program)
{
    cl_int status = CL_SUCCESS;
    cl_uint numKernels;
    status = clCreateKernelsInProgram(*this, 0, nullptr, &numKernels);
    ThrowIf(numKernels == 0, CL_BUILD_ERROR, "clCreateKernelsInProgram return 0 kernels");

    ThrowIf(status != CL_SUCCESS, status, "clCreateKernelsInProgram failed");

    std::vector<cl_kernel> kernels(numKernels);
    status = clCreateKernelsInProgram(*this, numKernels, &kernels[0], nullptr);

    ThrowIf(status != CL_SUCCESS, status, "clCreateKernelsInProgram failed");

    std::for_each(kernels.begin(), kernels.end(), [this](cl_kernel k)
                  {
                      size_t size = 0;
                      cl_int res;

                      res = clGetKernelInfo(k, CL_KERNEL_FUNCTION_NAME, 0, nullptr, &size);
                      ThrowIf(res != CL_SUCCESS, res, "clGetKernelInfo failed");

                      std::vector<char> temp(size);
                      res = clGetKernelInfo(k, CL_KERNEL_FUNCTION_NAME, size, &temp[0], nullptr);
                      ThrowIf(res != CL_SUCCESS, res, "clGetKernelInfo failed");

                      std::string funcName(temp.begin(), temp.end()-1);
                      kernels_[funcName] = CLWKernel::Create(k);
                  });
}

CLWProgram::~CLWProgram()
{
}

unsigned int CLWProgram::GetKernelCount() const
{
    return static_cast<unsigned int>(kernels_.size());
}

CLWKernel CLWProgram::GetKernel(std::string const& funcName) const
{
    auto iter = kernels_.find(funcName);

    ThrowIf(iter == kernels_.end(), CL_INVALID_KERNEL_NAME, "No such kernel in program");

    return iter->second;
}

void CLWProgram::GetBinaries(int device, std::vector<std::uint8_t>& data) const
{
    std::uint32_t num_devices;
    auto status = clGetProgramInfo(*this, CL_PROGRAM_NUM_DEVICES,
        sizeof(uint32_t),
        &num_devices,
        nullptr);

    std::vector<std::size_t> binary_sizes(num_devices);
    status = clGetProgramInfo(*this, CL_PROGRAM_BINARY_SIZES,
        sizeof(size_t) * num_devices,
        &binary_sizes[0],
        nullptr);

    ThrowIf(status != CL_SUCCESS, status, "clGetProgramInfo failed");

    data.resize(binary_sizes[device]);

    char** temp = new char*[num_devices];

    for (auto i = 0u; i < num_devices; ++i)
    {
        if (i == device)
        {
            temp[i] = (char*)&data[0];
        }
        else
        {
            temp[i] = new char[binary_sizes[i]];
        }
    }

    status = clGetProgramInfo(*this, CL_PROGRAM_BINARIES,
        binary_sizes[0],
        temp,
        nullptr);

    // TODO: fix potential leak here
    ThrowIf(status != CL_SUCCESS, status, "clGetProgramInfo failed");

    for (auto i = 0u; i < num_devices; ++i)
    {
        if (i != device)
        {
            delete temp[i];
        }
    }

    delete [] temp;
}
<commit_msg>Fix binaries generation<commit_after>/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/
#include "CLWProgram.h"
#include "CLWContext.h"
#include "CLWDevice.h"
#include "CLWExcept.h"
#include "CLWKernel.h"

#include <functional>
#include <cassert>
#include <algorithm>
#include <fstream>

static void load_file_contents(std::string const& name, std::vector<char>& contents, bool binary)
{
    std::ifstream in(name, std::ios::in | (std::ios_base::openmode)(binary?std::ios::binary : 0));

    if (in)
    {
        contents.clear();

        std::streamoff beg = in.tellg();

        in.seekg(0, std::ios::end);

        std::streamoff fileSize = in.tellg() - beg;

        in.seekg(0, std::ios::beg);

        contents.resize(static_cast<unsigned>(fileSize));

        in.read(&contents[0], fileSize);
    }
    else
    {
        throw std::runtime_error("Cannot read the contents of a file");
    }
}

CLWProgram CLWProgram::CreateFromSource(char const* sourcecode, size_t sourcesize, char const* buildopts, CLWContext context)
{
    cl_int status = CL_SUCCESS;

    cl_program program = clCreateProgramWithSource(context, 1, (const char**)&sourcecode, &sourcesize, &status);

    ThrowIf(status != CL_SUCCESS, status, "clCreateProgramWithSource failed");

    std::vector<cl_device_id> deviceIds(context.GetDeviceCount());
    for(unsigned int i = 0; i < context.GetDeviceCount(); ++i)
    {
        deviceIds[i] = context.GetDevice(i);
    }

    status = clBuildProgram(program, context.GetDeviceCount(), &deviceIds[0], buildopts, nullptr, nullptr);

    if(status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    CLWProgram prg(program);

    clReleaseProgram(program);

    return prg;
}

CLWProgram CLWProgram::CreateFromSource(char const* sourcecode,
                                        size_t sourcesize,
                                        char const** headers,
                                        char const** headernames,
                                        size_t* headersizes,
                                        int numheaders,
                                        char const* buildopts,
                                        CLWContext context)
{
    cl_int status = CL_SUCCESS;

    std::vector<cl_device_id> deviceIds(context.GetDeviceCount());
    for(unsigned int i = 0; i < context.GetDeviceCount(); ++i)
    {
        deviceIds[i] = context.GetDevice(i);
    }

    std::vector<cl_program> headerPrograms(numheaders);
    for (int i=0; i<numheaders; ++i)
    {
        size_t sourceSize = headersizes[i];
        char const* tempPtr = headers[i];
        headerPrograms[i] = clCreateProgramWithSource(context, 1, (const char**)&tempPtr, &sourceSize, &status);
        ThrowIf(status != CL_SUCCESS, status, "clCreateProgramWithSource failed");
    }

    cl_program program = clCreateProgramWithSource(context, 1, (const char**)&sourcecode, &sourcesize, &status);

    ThrowIf(status != CL_SUCCESS, status, "clCreateProgramWithSource failed");

    status = clCompileProgram(program, context.GetDeviceCount(), &deviceIds[0], buildopts, numheaders, &headerPrograms[0], headernames, nullptr, nullptr);

    if(status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    status = clBuildProgram(program, context.GetDeviceCount(), &deviceIds[0], buildopts, nullptr, nullptr);

    if(status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    CLWProgram prg(program);

    clReleaseProgram(program);

    return prg;
}

CLWProgram CLWProgram::CreateFromBinary(std::uint8_t** binaries, std::size_t* binary_sizes, CLWContext context)
{
    cl_int status = CL_SUCCESS;

    std::vector<cl_device_id> deviceIds(context.GetDeviceCount());
    for (unsigned int i = 0; i < context.GetDeviceCount(); ++i)
    {
        deviceIds[i] = context.GetDevice(i);
    }

    cl_int binary_status = 0;
    cl_program program = clCreateProgramWithBinary(context, context.GetDeviceCount(), &deviceIds[0], binary_sizes, (const unsigned char**)binaries, &binary_status, &status);

    if (status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    status = clBuildProgram(program, context.GetDeviceCount(), &deviceIds[0], nullptr, nullptr, nullptr);

    if (status != CL_SUCCESS)
    {
        std::vector<char> buildLog;
        size_t logSize;
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, 0, nullptr, &logSize);

        buildLog.resize(logSize);
        clGetProgramBuildInfo(program, deviceIds[0], CL_PROGRAM_BUILD_LOG, logSize, &buildLog[0], nullptr);

#ifdef _DEBUG
        std::cout << &buildLog[0] << "\n";
#endif

        throw CLWException(status, std::string(&buildLog[0]));
    }

    CLWProgram prg(program);

    clReleaseProgram(program);

    return prg;

}

CLWProgram CLWProgram::CreateFromFile(char const* filename, char const* buildopts, CLWContext context)
{
    std::vector<char> sourcecode;
    load_file_contents(filename, sourcecode, false);
    return CreateFromSource(&sourcecode[0], sourcecode.size(), buildopts, context);
}

CLWProgram CLWProgram::CreateFromFile(char const* filename,
                                      char const** headernames,
                                      int numheaders,
                                      char const* buildopts,
                                      CLWContext context)
{
    std::vector<char> sourcecode;
    load_file_contents(filename, sourcecode, false);

    std::vector<std::vector<char> > headers;
    std::vector<char const*> headerstrs;
    std::vector<size_t> headerssizes;

    if (numheaders > 0)
    {
        for (int i = 0; i < numheaders; ++i)
        {
            std::vector<char> headersource;
            load_file_contents(headernames[i], headersource, false);
            headerssizes.push_back(headersource.size());
            headers.push_back(std::move(headersource));
            headerstrs.push_back(&headers[i][0]);
        }

        return CreateFromSource(&sourcecode[0], sourcecode.size(), &headerstrs[0], headernames, &headerssizes[0], numheaders, buildopts, context);
    }
    else
    {
        return CreateFromSource(&sourcecode[0], sourcecode.size(), buildopts, context);
    }
}

CLWProgram::CLWProgram(cl_program program)
: ReferenceCounter<cl_program, clRetainProgram, clReleaseProgram>(program)
{
    cl_int status = CL_SUCCESS;
    cl_uint numKernels;
    status = clCreateKernelsInProgram(*this, 0, nullptr, &numKernels);
    ThrowIf(numKernels == 0, CL_BUILD_ERROR, "clCreateKernelsInProgram return 0 kernels");

    ThrowIf(status != CL_SUCCESS, status, "clCreateKernelsInProgram failed");

    std::vector<cl_kernel> kernels(numKernels);
    status = clCreateKernelsInProgram(*this, numKernels, &kernels[0], nullptr);

    ThrowIf(status != CL_SUCCESS, status, "clCreateKernelsInProgram failed");

    std::for_each(kernels.begin(), kernels.end(), [this](cl_kernel k)
                  {
                      size_t size = 0;
                      cl_int res;

                      res = clGetKernelInfo(k, CL_KERNEL_FUNCTION_NAME, 0, nullptr, &size);
                      ThrowIf(res != CL_SUCCESS, res, "clGetKernelInfo failed");

                      std::vector<char> temp(size);
                      res = clGetKernelInfo(k, CL_KERNEL_FUNCTION_NAME, size, &temp[0], nullptr);
                      ThrowIf(res != CL_SUCCESS, res, "clGetKernelInfo failed");

                      std::string funcName(temp.begin(), temp.end()-1);
                      kernels_[funcName] = CLWKernel::Create(k);
                  });
}

CLWProgram::~CLWProgram()
{
}

unsigned int CLWProgram::GetKernelCount() const
{
    return static_cast<unsigned int>(kernels_.size());
}

CLWKernel CLWProgram::GetKernel(std::string const& funcName) const
{
    auto iter = kernels_.find(funcName);

    ThrowIf(iter == kernels_.end(), CL_INVALID_KERNEL_NAME, "No such kernel in program");

    return iter->second;
}

void CLWProgram::GetBinaries(int device, std::vector<std::uint8_t>& data) const
{
    std::uint32_t num_devices;
    auto status = clGetProgramInfo(*this, CL_PROGRAM_NUM_DEVICES,
        sizeof(uint32_t),
        &num_devices,
        nullptr);

    std::vector<std::size_t> binary_sizes(num_devices);
    status = clGetProgramInfo(*this, CL_PROGRAM_BINARY_SIZES,
        sizeof(size_t) * num_devices,
        &binary_sizes[0],
        nullptr);

    ThrowIf(status != CL_SUCCESS, status, "clGetProgramInfo failed");

    data.resize(binary_sizes[device]);

    char** temp = new char*[num_devices];

    for (auto i = 0u; i < num_devices; ++i)
    {
        if (i == device)
        {
            temp[i] = (char*)&data[0];
        }
        else
        {
            temp[i] = new char[binary_sizes[i]];
        }
    }

    status = clGetProgramInfo(*this, CL_PROGRAM_BINARIES,
        sizeof(char*),
        temp,
        nullptr);

    // TODO: fix potential leak here
    ThrowIf(status != CL_SUCCESS, status, "clGetProgramInfo failed");

    for (auto i = 0u; i < num_devices; ++i)
    {
        if (i != device)
        {
            delete temp[i];
        }
    }

    delete [] temp;
}
<|endoftext|>


<commit_before>#include "Config/Config.h"

using namespace std;
namespace po = boost::program_options;

Config::Config() :
  name_("Name"),
  desc_(),
  var_map_(),
  descs_(),
  desc_hidden_(),
  var_map_hidden(),
  descs_hidden_(),
  unrec_options_()
{
  DefineOptions();
  CombineOptions();
}

Config::Config(int argc, char* argv){
  DefineOptions();
  CombineOptions();

  /// \todo{ add a clever way to parse the config file. How to specify what the
  ///        config file is without messing with the program_options objects
  ///        itself too much or requiring anything... }
}

Config::Config(const vector<string>& option_vector){
  DefineOptions();
  CombineOptions();
}

Config::CombineOptions() {
  for (vector<po::options_description>::const_iterator it = descs_.begin(); it < descs_.end(); ++it) {
    desc_.add(*it);
  }

  for (vector<po::options_description>::const_iterator it = descs_hidden_.begin(); it < descs_hidden_.end(); ++it) {
    desc_hidden_.add(*it);
  }
}<commit_msg>typos<commit_after>#include "Config/Config.h"

using namespace std;
namespace po = boost::program_options;

Config::Config() :
  name_("Name"),
  desc_(),
  var_map_(),
  descs_(),
  desc_hidden_(),
  var_map_hidden(),
  descs_hidden_(),
  unrec_options_()
{
  DefineOptions();
  CombineOptions();
}

Config::Config(int argc, char* argv){
  DefineOptions();
  CombineOptions();

  /// \todo Add a clever way to parse the config file. How to specify what the
  ///       config file is without messing with the program_options objects
  ///       itself too much or requiring anything...
}

Config::Config(const vector<string>& option_vector){
  DefineOptions();
  CombineOptions();
}

Config::CombineOptions() {
  for (vector<po::options_description>::const_iterator it = descs_.begin(); it < descs_.end(); ++it) {
    desc_.add(*it);
  }

  for (vector<po::options_description>::const_iterator it = descs_hidden_.begin(); it < descs_hidden_.end(); ++it) {
    desc_hidden_.add(*it);
  }
}<|endoftext|>


<commit_before>
// STL
#include <string>
#include <vector>
#include <iostream>
#include <fstream>

// boost
#include <boost/exception/all.hpp>

#include "Utils/MsgStream.h"
#include "Config/Config.h"

using namespace std;
namespace po = boost::program_options;

boost::program_options::options_description Config::desc_visible_all_;
std::vector<Config*> Config::config_container_;

typedef boost::error_info<struct tag_my_info,std::string> ConfigName;
struct NameDuplicationException: public virtual boost::exception, public virtual std::exception {
  virtual const char* what() const throw() { return "Name duplication"; }
};

Config::Config(const std::string& name) :
  name_(name),
  desc_(),
  var_map_(),
  desc_visible_(),
  descs_visible_(),
  desc_hidden_(),
  descs_hidden_(),
  unrec_options_(),
  config_file_(),
  help_flag_(false)
{
  /// \todo Implement uniqueness check for names
  for (vector<Config*>::const_iterator it = config_container_.begin(); it < config_container_.end(); ++it) {
    if (name_.compare((*it)->name_) == 0) {
      serr << "ERROR in Config::Config(const std::string&): Config object with name " << name_ << " already existing." << endmsg;
      throw NameDuplicationException() << ConfigName(name_);
    }
  }

  config_container_.push_back(this);
}

Config::~Config() {}

void Config::InitializeOptions(int argc, char* argv[]) {
  DefineOptions();
  CombineOptions();

  ParseOptionsAndConfigFile(po::command_line_parser(argc, argv));

  LoadOptions();
}

void Config::InitializeOptions(const Config& previous_config) {
  DefineOptions();
  CombineOptions();

  config_file_ = previous_config.config_file_;
  ParseOptionsAndConfigFile(po::command_line_parser(previous_config.unrec_options()));

  LoadOptions();
}

void Config::PrintAll() const {
  for (vector<Config*>::const_iterator it = config_container_.begin(); it < config_container_.end(); ++it) {
    (*it)->Print();
  }
}

void Config::PrintHelp() const {
  cout << desc_visible_all_ << endl;
}

void Config::CombineOptions() {
  for (vector<po::options_description*>::const_iterator it = descs_visible_.begin(); it < descs_visible_.end(); ++it) {
    desc_visible_.add(**it);
  }

  for (vector<po::options_description*>::const_iterator it = descs_hidden_.begin(); it < descs_hidden_.end(); ++it) {
    desc_hidden_.add(**it);
  }

  desc_.add(desc_visible_).add(desc_hidden_);
  desc_visible_all_.add(desc_visible_);
}

void Config::ParseOptionsAndConfigFile(boost::program_options::command_line_parser parser) {
  try {
    po::parsed_options parsed = parser.options(desc_).allow_unregistered().run();
    po::store(parsed, var_map_);
    po::notify(var_map_);
    unrec_options_ = po::collect_unrecognized(parsed.options, po::exclude_positional);

    if (config_file_.length() > 0) {
      ifstream ifs(config_file_.c_str());
      if (!ifs) {
        cout << "can not open config file: " << config_file_ << "\n";
      } else {
        po::parsed_options parsed = po::parse_config_file(ifs, desc_, true);
        po::store(parsed, var_map_);
        po::notify(var_map_);
      }
    }
  } catch (exception& e) {
    // in case of parsing problems give an error message and throw exception further
    serr << "ERROR in Config::ParseOptionsAndConfigFile(boost::program_options::command_line_parser): Parsing problem in Config " << name_ << ": " << e.what() << endmsg;
    throw e;
  }
}<commit_msg>Config:    * some doxygen comments for exceptions<commit_after>
// STL
#include <string>
#include <vector>
#include <iostream>
#include <fstream>

// boost
#include <boost/exception/all.hpp>

#include "Utils/MsgStream.h"
#include "Config/Config.h"

using namespace std;
namespace po = boost::program_options;

boost::program_options::options_description Config::desc_visible_all_;
std::vector<Config*> Config::config_container_;

/// boost error_info for the name of the config file (see boost::exception for reference)
typedef boost::error_info<struct tag_my_info,std::string> ConfigName;

/** \struct ConfigNameDuplicationException
 *  \brief Exception for name duplication in Config objects.
 */
struct ConfigNameDuplicationException: public virtual boost::exception, public virtual std::exception {
  virtual const char* what() const throw() { return "Name duplication"; }
};

Config::Config(const std::string& name) :
  name_(name),
  desc_(),
  var_map_(),
  desc_visible_(),
  descs_visible_(),
  desc_hidden_(),
  descs_hidden_(),
  unrec_options_(),
  config_file_(),
  help_flag_(false)
{
  /// \todo Implement uniqueness check for names
  for (vector<Config*>::const_iterator it = config_container_.begin(); it < config_container_.end(); ++it) {
    if (name_.compare((*it)->name_) == 0) {
      serr << "ERROR in Config::Config(const std::string&): Config object with name " << name_ << " already existing." << endmsg;
      throw ConfigNameDuplicationException() << ConfigName(name_);
    }
  }

  config_container_.push_back(this);
}

Config::~Config() {}

void Config::InitializeOptions(int argc, char* argv[]) {
  DefineOptions();
  CombineOptions();

  ParseOptionsAndConfigFile(po::command_line_parser(argc, argv));

  LoadOptions();
}

void Config::InitializeOptions(const Config& previous_config) {
  DefineOptions();
  CombineOptions();

  config_file_ = previous_config.config_file_;
  ParseOptionsAndConfigFile(po::command_line_parser(previous_config.unrec_options()));

  LoadOptions();
}

void Config::PrintAll() const {
  for (vector<Config*>::const_iterator it = config_container_.begin(); it < config_container_.end(); ++it) {
    (*it)->Print();
  }
}

void Config::PrintHelp() const {
  cout << desc_visible_all_ << endl;
}

void Config::CombineOptions() {
  for (vector<po::options_description*>::const_iterator it = descs_visible_.begin(); it < descs_visible_.end(); ++it) {
    desc_visible_.add(**it);
  }

  for (vector<po::options_description*>::const_iterator it = descs_hidden_.begin(); it < descs_hidden_.end(); ++it) {
    desc_hidden_.add(**it);
  }

  desc_.add(desc_visible_).add(desc_hidden_);
  desc_visible_all_.add(desc_visible_);
}

void Config::ParseOptionsAndConfigFile(boost::program_options::command_line_parser parser) {
  try {
    po::parsed_options parsed = parser.options(desc_).allow_unregistered().run();
    po::store(parsed, var_map_);
    po::notify(var_map_);
    unrec_options_ = po::collect_unrecognized(parsed.options, po::exclude_positional);

    if (config_file_.length() > 0) {
      ifstream ifs(config_file_.c_str());
      if (!ifs) {
        cout << "can not open config file: " << config_file_ << "\n";
      } else {
        po::parsed_options parsed = po::parse_config_file(ifs, desc_, true);
        po::store(parsed, var_map_);
        po::notify(var_map_);
      }
    }
  } catch (exception& e) {
    // in case of parsing problems give an error message and throw exception further
    serr << "ERROR in Config::ParseOptionsAndConfigFile(boost::program_options::command_line_parser): Parsing problem in Config " << name_ << ": " << e.what() << endmsg;
    throw e;
  }
}<|endoftext|>


<commit_before>#pragma once

namespace despairagus {
	namespace bitnode {
		template <typename A>
		class bitnode {
			template<typename B>
			using conref = const B &;

			using byte = unsigned char;
			using bit = bool;

		public:
			inline explicit bitnode(void) : zero{nullptr}, one{nullptr}, data{nullptr} {}

		private:
			bitnode* zero;
			bitnode* one;

			A* data;
		};
	}
}<commit_msg>make any other constructor delete<commit_after>#pragma once

namespace despairagus {
	namespace bitnode {
		template <typename A>
		class bitnode {
			template<typename B>
			using conref = const B &;

			using byte = unsigned char;
			using bit = bool;

		public:
			inline explicit bitnode(void) : zero{nullptr}, one{nullptr}, data{nullptr} {}

			template <typename... A>
			explicit bitnode(A... a) = delete;

		private:
			bitnode* zero;
			bitnode* one;

			A* data;
		};
	}
}<|endoftext|>


<commit_before>// Copyright (c) 2010 - 2013 Leap Motion. All rights reserved. Proprietary and confidential.
#include "stdafx.h"
#include "CoreThread.h"
#include <Windows.h>

#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO
{
   DWORD dwType; // must be 0x1000
   LPCSTR szName; // pointer to name (in user addr space)
   DWORD dwThreadID; // thread ID (-1=caller thread)
   DWORD dwFlags; // reserved for future use, must be zero
} THREADNAME_INFO;
#pragma pack(pop)

void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
{
  THREADNAME_INFO info;
  info.dwType = 0x1000;
  info.szName = szThreadName;
  info.dwThreadID = dwThreadID;
  info.dwFlags = 0;

  __try
  {
    // Magic exception which informs the OS of this thread's name
    RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info);
  }
  __except(EXCEPTION_CONTINUE_EXECUTION)
  {
  }
}

void CoreThread::SetCurrentThreadName(void) const {
#if IS_INTERNAL_BUILD
  ::SetThreadName(
    GetCurrentThreadId(),
    m_name
  );
#endif
}
<commit_msg>Made some internal build flags more specific.<commit_after>// Copyright (c) 2010 - 2013 Leap Motion. All rights reserved. Proprietary and confidential.
#include "stdafx.h"
#include "CoreThread.h"
#include <Windows.h>

#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO
{
   DWORD dwType; // must be 0x1000
   LPCSTR szName; // pointer to name (in user addr space)
   DWORD dwThreadID; // thread ID (-1=caller thread)
   DWORD dwFlags; // reserved for future use, must be zero
} THREADNAME_INFO;
#pragma pack(pop)

void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
{
  THREADNAME_INFO info;
  info.dwType = 0x1000;
  info.szName = szThreadName;
  info.dwThreadID = dwThreadID;
  info.dwFlags = 0;

  __try
  {
    // Magic exception which informs the OS of this thread's name
    RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info);
  }
  __except(EXCEPTION_CONTINUE_EXECUTION)
  {
  }
}

void CoreThread::SetCurrentThreadName(void) const {
#if IS_INTERNAL_BUILD == 1
  ::SetThreadName(
    GetCurrentThreadId(),
    m_name
  );
#endif
}
<|endoftext|>


<commit_before>/*****************************************************************************
   Copyright 2004-2008 Steve Menard

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*****************************************************************************/
#include <jpype.h>

//AT's on porting:
//  1) the original definition of global static object leads to crashing
//on HP-UX platform. Cause: it is suspected to be an undefined order of initialization of static objects
//
//  2) TODO: in any case, use of static objects may impose problems in multi-threaded environment.
//Therefore, they must be guarded with a mutex.
#ifdef WIN32
	#include "jp_platform_win32.h"
	#define  PLATFORM_ADAPTER Win32PlatformAdapter
#else
	#include "jp_platform_linux.h"
	#define  PLATFORM_ADAPTER LinuxPlatformAdapter
#endif

JPPlatformAdapter* JPJavaEnv::GetAdapter()
{
	static JPPlatformAdapter* adapter = new PLATFORM_ADAPTER();
	return adapter;
}

#define JAVA_CHECK(msg) \
	if (JPEnv::getJava()->ExceptionCheck()) \
	{ \
		RAISE(JavaException, msg); \
	} \

jint (JNICALL *JPJavaEnv::CreateJVM_Method)(JavaVM **pvm, void **penv, void *args);
jint (JNICALL *JPJavaEnv::GetCreatedJVMs_Method)(JavaVM **pvm, jsize size, jsize* nVms);

JNIEnv* JPJavaEnv::getJNIEnv()
{
	JNIEnv* env;
	GetEnv(&env);
	return env;
}

void JPJavaEnv::load(const string& path)
{
	TRACE_IN("JPJavaEnv::load");

	// WIN32
	GetAdapter()->loadLibrary((char*)path.c_str());
	CreateJVM_Method = (jint (JNICALL *)(JavaVM ** ,void ** ,void *))GetAdapter()->getSymbol("JNI_CreateJavaVM");
	GetCreatedJVMs_Method = (jint (JNICALL *)(JavaVM ** , jsize, jsize*))GetAdapter()->getSymbol("JNI_GetCreatedJavaVMs");
	// No idea why I can't find this symbol .... no matter, it does not work anyway.
	//JNI_DestroyJavaVM = (jint (__stdcall *)(struct JavaVM_ *))GetAdapter()->getSymbol("DestroyJavaVM");
TRACE_OUT;
}

void JPJavaEnv::shutdown()
{
	jvm = NULL;
	// unload the jvm library
	GetAdapter()->unloadLibrary();
}

/**
	throw a JPypeException if the JVM is not started
*/
void JPJavaEnv::checkInitialized()
{
	if (! JPEnv::isInitialized())
	{
		RAISE( JPypeException, "Java Subsystem not started");
	}
}

JPJavaEnv* JPJavaEnv::GetCreatedJavaVM()
{
	// TODO: because we're returning NULL, jpype.attach() wont work.
	/*
	TRACE_IN("JPJavaEnv::GetCreatedJavaVM");

	JavaVM* vm = NULL;
	jsize numVms;

	jint ret = GetCreatedJVMs_Method(&vm, 1, &numVms);
	if (ret < 0)
	{
		return NULL;
	}

	return new JPJavaEnv(vm);
	TRACE_OUT;
	*/
	return NULL;
}

JPJavaEnv* JPJavaEnv::CreateJavaVM(void* arg)
{
	TRACE_IN("JPJavaEnv::CreateJavaVM");

	JavaVM* vm = NULL;
	void* env;

	CreateJVM_Method(&vm, &env, arg);
	if (vm == NULL)
	{
		return NULL;
	}

	TRACE1("A");
	return new JPJavaEnv(vm);
	TRACE_OUT;
}

int JPJavaEnv::DestroyJavaVM()
{
	if (jvm != NULL)
	{
		int res = jvm->functions->DestroyJavaVM(jvm);
		if (res == 0)
		{
			jvm = NULL;
		}
	}
	return 0;
}

jint JPJavaEnv::PushLocalFrame(jint i)
{
  JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		return env->functions->PushLocalFrame(env, i);
	}
	return -1;
}

jobject JPJavaEnv::PopLocalFrame(jobject obj)
{
  JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		return env->functions->PopLocalFrame(env, obj);
	}
	return NULL;
}

void JPJavaEnv::DeleteLocalRef(jobject obj)
{
	MTRACE_IN("JPJavaEnv::DeleteLocalRef");
	MTRACE1((long)obj);
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		env->functions->DeleteLocalRef(env, obj);
	}
	MTRACE_OUT;
}

void JPJavaEnv::DeleteGlobalRef(jobject obj)
{
	MTRACE_IN("JPJavaEnv::DeleteGlobalRef");
	MTRACE1((long)obj);
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		env->functions->DeleteGlobalRef(env, obj);
	}
	MTRACE_OUT;
}

jobject JPJavaEnv::NewLocalRef(jobject a0)
{
	MTRACE_IN("JPJavaEnv::NewLocalRef");
	jobject res;
	JNIEnv* env = getJNIEnv();
	res = env->functions->NewLocalRef(env, a0);
	MTRACE3((long)a0, "=>", (long)res); //, JPJni::getClassName(a0).getSimpleName());
	return res;
	MTRACE_OUT;
}

jobject JPJavaEnv::NewGlobalRef(jobject a0)
{
	MTRACE_IN("JPJavaEnv::NewGlobalRef");
	jobject res;
	JNIEnv* env = getJNIEnv();
	res = env->functions->NewGlobalRef(env, a0);
	MTRACE3((long)a0, "=>", (long)res); //, JPJni::getClassName(a0).getSimpleName());
	return res;
	MTRACE_OUT;
}

bool JPJavaEnv::ExceptionCheck()
{
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		return (env->functions->ExceptionCheck(env) ? true : false);
	}
	return false;
}

void JPJavaEnv::ExceptionDescribe()
{
	JNIEnv* env = getJNIEnv();
	env->functions->ExceptionDescribe(env);
}

void JPJavaEnv::ExceptionClear()
{
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		env->functions->ExceptionClear(env);
	}
}

jint JPJavaEnv::AttachCurrentThread()
{
	// TODO find a way to get A JVM once JPJavaEnv is not a singleton anymore ...
	JNIEnv* env;
	jint res = jvm->functions->AttachCurrentThread(jvm, (void**)&env, NULL);
	JAVA_CHECK("AttachCurrentThread");
	return res;
}

jint JPJavaEnv::AttachCurrentThreadAsDaemon()
{
	// TODO find a way to get A JVM once JPJavaEnv is not a singleton anymore ...
	JNIEnv* env;
	jint res = jvm->functions->AttachCurrentThreadAsDaemon(jvm, (void**)&env, NULL);
	JAVA_CHECK("AttachCurrentThreadAsDaemon");
	return res;
}

bool JPJavaEnv::isThreadAttached()
{
	return JPEnv::getJava()->getJNIEnv() != NULL;
}

jint JPJavaEnv::DetachCurrentThread()
{
	return jvm->functions->DetachCurrentThread(jvm);

}

jint JPJavaEnv::GetEnv(JNIEnv** env)
{
	if (jvm == NULL)
	{
		*env = NULL;
		return JNI_EDETACHED;
	}

	// This function must not be put in GOTO_EXTERNAL/RETURN_EXTERNAL because it is called from WITHIN such a block already
	jint res;
	res = jvm->functions->GetEnv(jvm, (void**)env, JNI_VERSION_1_2);
	return res;
}

jint JPJavaEnv::ThrowNew(jclass clazz, const char* msg)
{
	JNIEnv* env = getJNIEnv();
	return env->functions->ThrowNew(env, clazz, msg);
}

jint JPJavaEnv::Throw(jthrowable th)
{
	JNIEnv* env = getJNIEnv();
	return env->functions->Throw(env, th);
}

jthrowable JPJavaEnv::ExceptionOccurred()
{
	jthrowable res;
    JNIEnv* env = getJNIEnv();

	res = env->functions->ExceptionOccurred(env);

    return res;
}

jobject JPJavaEnv::NewDirectByteBuffer(void* address, jlong capacity)
{
	TRACE_IN("JPJavaEnv::NewDirectByteBuffer");
	JNIEnv* env = getJNIEnv();
	jobject res = env->functions->NewDirectByteBuffer(env, address, capacity);
	JAVA_CHECK("NewDirectByteBuffer");
	TRACE1((long)res);
	return res;
	TRACE_OUT;
}

jobject JPJavaEnv::NewObjectA(jclass a0, jmethodID a1, jvalue* a2)
{
	JPLocalFrame frame;
	jobject res;
	JNIEnv* env = getJNIEnv();
	void* _save = JPEnv::getHost()->gotoExternal();

	res = env->functions->AllocObject(env, a0);
	JAVA_CHECK("NewObjectA");

	env->functions->CallVoidMethodA(env, res, a1, a2);

	if (ExceptionCheck())
	{
		res = NULL;
	}

  JPEnv::getHost()->returnExternal(_save);
  JAVA_CHECK("NewObjectA");
  return frame.keep(res);
}

jobject JPJavaEnv::NewObject(jclass a0, jmethodID a1)
{
	JPLocalFrame frame;
	jobject res;
  JNIEnv* env = getJNIEnv();
  void* _save = JPEnv::getHost()->gotoExternal();

	res = env->functions->AllocObject(env, a0);
	JAVA_CHECK("NewObject");

	env->functions->CallVoidMethod(env, res, a1);

	if (ExceptionCheck())
	{
		//DeleteLocalRef(res); // This line does not make sense
	}

  JPEnv::getHost()->returnExternal(_save);
  JAVA_CHECK("NewObject");
  return frame.keep(res);
}

void* JPJavaEnv::GetPrimitiveArrayCritical(jarray array, jboolean *isCopy)
{
    JNIEnv* env = getJNIEnv();
    void* res = env->functions->GetPrimitiveArrayCritical(env, array, isCopy);
    JAVA_CHECK("GetPrimitiveArrayCritical");
    return res;
}

void JPJavaEnv::ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode)
{
    JNIEnv* env = getJNIEnv();
    env->functions->ReleasePrimitiveArrayCritical(env, array,carray,mode);
    JAVA_CHECK("ReleasePrimitiveArrayCritical");
}
<commit_msg>Describe exception when tracing is enabled<commit_after>/*****************************************************************************
   Copyright 2004-2008 Steve Menard

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*****************************************************************************/
#include <jpype.h>

//AT's on porting:
//  1) the original definition of global static object leads to crashing
//on HP-UX platform. Cause: it is suspected to be an undefined order of initialization of static objects
//
//  2) TODO: in any case, use of static objects may impose problems in multi-threaded environment.
//Therefore, they must be guarded with a mutex.
#ifdef WIN32
	#include "jp_platform_win32.h"
	#define  PLATFORM_ADAPTER Win32PlatformAdapter
#else
	#include "jp_platform_linux.h"
	#define  PLATFORM_ADAPTER LinuxPlatformAdapter
#endif

JPPlatformAdapter* JPJavaEnv::GetAdapter()
{
	static JPPlatformAdapter* adapter = new PLATFORM_ADAPTER();
	return adapter;
}

#define JAVA_CHECK(msg) \
	if (JPEnv::getJava()->ExceptionCheck()) \
	{ \
		RAISE(JavaException, msg); \
	} \

jint (JNICALL *JPJavaEnv::CreateJVM_Method)(JavaVM **pvm, void **penv, void *args);
jint (JNICALL *JPJavaEnv::GetCreatedJVMs_Method)(JavaVM **pvm, jsize size, jsize* nVms);

JNIEnv* JPJavaEnv::getJNIEnv()
{
	JNIEnv* env;
	GetEnv(&env);
	return env;
}

void JPJavaEnv::load(const string& path)
{
	TRACE_IN("JPJavaEnv::load");

	// WIN32
	GetAdapter()->loadLibrary((char*)path.c_str());
	CreateJVM_Method = (jint (JNICALL *)(JavaVM ** ,void ** ,void *))GetAdapter()->getSymbol("JNI_CreateJavaVM");
	GetCreatedJVMs_Method = (jint (JNICALL *)(JavaVM ** , jsize, jsize*))GetAdapter()->getSymbol("JNI_GetCreatedJavaVMs");
	// No idea why I can't find this symbol .... no matter, it does not work anyway.
	//JNI_DestroyJavaVM = (jint (__stdcall *)(struct JavaVM_ *))GetAdapter()->getSymbol("DestroyJavaVM");
TRACE_OUT;
}

void JPJavaEnv::shutdown()
{
	jvm = NULL;
	// unload the jvm library
	GetAdapter()->unloadLibrary();
}

/**
	throw a JPypeException if the JVM is not started
*/
void JPJavaEnv::checkInitialized()
{
	if (! JPEnv::isInitialized())
	{
		RAISE( JPypeException, "Java Subsystem not started");
	}
}

JPJavaEnv* JPJavaEnv::GetCreatedJavaVM()
{
	// TODO: because we're returning NULL, jpype.attach() wont work.
	/*
	TRACE_IN("JPJavaEnv::GetCreatedJavaVM");

	JavaVM* vm = NULL;
	jsize numVms;

	jint ret = GetCreatedJVMs_Method(&vm, 1, &numVms);
	if (ret < 0)
	{
		return NULL;
	}

	return new JPJavaEnv(vm);
	TRACE_OUT;
	*/
	return NULL;
}

JPJavaEnv* JPJavaEnv::CreateJavaVM(void* arg)
{
	TRACE_IN("JPJavaEnv::CreateJavaVM");

	JavaVM* vm = NULL;
	void* env;

	CreateJVM_Method(&vm, &env, arg);
	if (vm == NULL)
	{
		return NULL;
	}

	TRACE1("A");
	return new JPJavaEnv(vm);
	TRACE_OUT;
}

int JPJavaEnv::DestroyJavaVM()
{
	if (jvm != NULL)
	{
		int res = jvm->functions->DestroyJavaVM(jvm);
		if (res == 0)
		{
			jvm = NULL;
		}
	}
	return 0;
}

jint JPJavaEnv::PushLocalFrame(jint i)
{
  JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		return env->functions->PushLocalFrame(env, i);
	}
	return -1;
}

jobject JPJavaEnv::PopLocalFrame(jobject obj)
{
  JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		return env->functions->PopLocalFrame(env, obj);
	}
	return NULL;
}

void JPJavaEnv::DeleteLocalRef(jobject obj)
{
	MTRACE_IN("JPJavaEnv::DeleteLocalRef");
	MTRACE1((long)obj);
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		env->functions->DeleteLocalRef(env, obj);
	}
	MTRACE_OUT;
}

void JPJavaEnv::DeleteGlobalRef(jobject obj)
{
	MTRACE_IN("JPJavaEnv::DeleteGlobalRef");
	MTRACE1((long)obj);
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		env->functions->DeleteGlobalRef(env, obj);
	}
	MTRACE_OUT;
}

jobject JPJavaEnv::NewLocalRef(jobject a0)
{
	MTRACE_IN("JPJavaEnv::NewLocalRef");
	jobject res;
	JNIEnv* env = getJNIEnv();
	res = env->functions->NewLocalRef(env, a0);
	MTRACE3((long)a0, "=>", (long)res); //, JPJni::getClassName(a0).getSimpleName());
	return res;
	MTRACE_OUT;
}

jobject JPJavaEnv::NewGlobalRef(jobject a0)
{
	MTRACE_IN("JPJavaEnv::NewGlobalRef");
	jobject res;
	JNIEnv* env = getJNIEnv();
	res = env->functions->NewGlobalRef(env, a0);
	MTRACE3((long)a0, "=>", (long)res); //, JPJni::getClassName(a0).getSimpleName());
	return res;
	MTRACE_OUT;
}

bool JPJavaEnv::ExceptionCheck()
{
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		return (env->functions->ExceptionCheck(env) ? true : false);
	}
	return false;
}

void JPJavaEnv::ExceptionDescribe()
{
	JNIEnv* env = getJNIEnv();
	env->functions->ExceptionDescribe(env);
}

void JPJavaEnv::ExceptionClear()
{
	JNIEnv* env = getJNIEnv();
	if (env != NULL)
	{
		env->functions->ExceptionClear(env);
	}
}

jint JPJavaEnv::AttachCurrentThread()
{
	// TODO find a way to get A JVM once JPJavaEnv is not a singleton anymore ...
	JNIEnv* env;
	jint res = jvm->functions->AttachCurrentThread(jvm, (void**)&env, NULL);
	JAVA_CHECK("AttachCurrentThread");
	return res;
}

jint JPJavaEnv::AttachCurrentThreadAsDaemon()
{
	// TODO find a way to get A JVM once JPJavaEnv is not a singleton anymore ...
	JNIEnv* env;
	jint res = jvm->functions->AttachCurrentThreadAsDaemon(jvm, (void**)&env, NULL);
	JAVA_CHECK("AttachCurrentThreadAsDaemon");
	return res;
}

bool JPJavaEnv::isThreadAttached()
{
	return JPEnv::getJava()->getJNIEnv() != NULL;
}

jint JPJavaEnv::DetachCurrentThread()
{
	return jvm->functions->DetachCurrentThread(jvm);

}

jint JPJavaEnv::GetEnv(JNIEnv** env)
{
	if (jvm == NULL)
	{
		*env = NULL;
		return JNI_EDETACHED;
	}

	// This function must not be put in GOTO_EXTERNAL/RETURN_EXTERNAL because it is called from WITHIN such a block already
	jint res;
	res = jvm->functions->GetEnv(jvm, (void**)env, JNI_VERSION_1_2);
	return res;
}

jint JPJavaEnv::ThrowNew(jclass clazz, const char* msg)
{
	JNIEnv* env = getJNIEnv();
	return env->functions->ThrowNew(env, clazz, msg);
}

jint JPJavaEnv::Throw(jthrowable th)
{
	JNIEnv* env = getJNIEnv();
	return env->functions->Throw(env, th);
}

jthrowable JPJavaEnv::ExceptionOccurred()
{
	jthrowable res;
	JNIEnv* env = getJNIEnv();

	res = env->functions->ExceptionOccurred(env);
#ifdef TRACING
	if(res) {
		env->functions->ExceptionDescribe(env);
	}
#endif
	return res;
}

jobject JPJavaEnv::NewDirectByteBuffer(void* address, jlong capacity)
{
	TRACE_IN("JPJavaEnv::NewDirectByteBuffer");
	JNIEnv* env = getJNIEnv();
	jobject res = env->functions->NewDirectByteBuffer(env, address, capacity);
	JAVA_CHECK("NewDirectByteBuffer");
	TRACE1((long)res);
	return res;
	TRACE_OUT;
}

jobject JPJavaEnv::NewObjectA(jclass a0, jmethodID a1, jvalue* a2)
{
	JPLocalFrame frame;
	jobject res;
	JNIEnv* env = getJNIEnv();
	void* _save = JPEnv::getHost()->gotoExternal();

	res = env->functions->AllocObject(env, a0);
	JAVA_CHECK("NewObjectA");

	env->functions->CallVoidMethodA(env, res, a1, a2);

	if (ExceptionCheck())
	{
		res = NULL;
	}

  JPEnv::getHost()->returnExternal(_save);
  JAVA_CHECK("NewObjectA");
  return frame.keep(res);
}

jobject JPJavaEnv::NewObject(jclass a0, jmethodID a1)
{
	JPLocalFrame frame;
	jobject res;
  JNIEnv* env = getJNIEnv();
  void* _save = JPEnv::getHost()->gotoExternal();

	res = env->functions->AllocObject(env, a0);
	JAVA_CHECK("NewObject");

	env->functions->CallVoidMethod(env, res, a1);

	if (ExceptionCheck())
	{
		//DeleteLocalRef(res); // This line does not make sense
	}

  JPEnv::getHost()->returnExternal(_save);
  JAVA_CHECK("NewObject");
  return frame.keep(res);
}

void* JPJavaEnv::GetPrimitiveArrayCritical(jarray array, jboolean *isCopy)
{
    JNIEnv* env = getJNIEnv();
    void* res = env->functions->GetPrimitiveArrayCritical(env, array, isCopy);
    JAVA_CHECK("GetPrimitiveArrayCritical");
    return res;
}

void JPJavaEnv::ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode)
{
    JNIEnv* env = getJNIEnv();
    env->functions->ReleasePrimitiveArrayCritical(env, array,carray,mode);
    JAVA_CHECK("ReleasePrimitiveArrayCritical");
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: shelljob.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2008-02-12 17:25:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"

//_______________________________________________
// include own header

#include <jobs/shelljob.hxx>
#include <jobs/jobconst.hxx>
#include <threadhelp/readguard.hxx>
#include <services.h>

//_______________________________________________
// include others

#include <osl/file.hxx>
#include <osl/process.h>
#include <vcl/svapp.hxx>
#include <rtl/ustrbuf.hxx>
#include <comphelper/sequenceashashmap.hxx>

//_______________________________________________
// include interfaces

#include <com/sun/star/system/XSystemShellExecute.hpp>
#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
#include <com/sun/star/util/XStringSubstitution.hpp>

//_______________________________________________
// namespace

namespace framework{

//_______________________________________________
// definitions

/** adress job configuration inside argument set provided on method execute(). */
static const ::rtl::OUString PROP_JOBCONFIG = ::rtl::OUString::createFromAscii("JobConfig");

/** adress job configuration property "Command". */
static const ::rtl::OUString PROP_COMMAND = ::rtl::OUString::createFromAscii("Command");

/** adress job configuration property "Arguments". */
static const ::rtl::OUString PROP_ARGUMENTS = ::rtl::OUString::createFromAscii("Arguments");

/** adress job configuration property "DeactivateJobIfDone". */
static const ::rtl::OUString PROP_DEACTIVATEJOBIFDONE = ::rtl::OUString::createFromAscii("DeactivateJobIfDone");

/** adress job configuration property "CheckExitCode". */
static const ::rtl::OUString PROP_CHECKEXITCODE = ::rtl::OUString::createFromAscii("CheckExitCode");

//-----------------------------------------------

DEFINE_XINTERFACE_3(ShellJob                                   ,
                    OWeakObject                                ,
                    DIRECT_INTERFACE(css::lang::XTypeProvider ),
                    DIRECT_INTERFACE(css::lang::XServiceInfo  ),
                    DIRECT_INTERFACE(css::task::XJob          ))

DEFINE_XTYPEPROVIDER_3(ShellJob                 ,
                       css::lang::XTypeProvider ,
                       css::lang::XServiceInfo  ,
                       css::task::XJob          )

DEFINE_XSERVICEINFO_MULTISERVICE(ShellJob                   ,
                                 ::cppu::OWeakObject        ,
                                 SERVICENAME_JOB            ,
                                 IMPLEMENTATIONNAME_SHELLJOB)

DEFINE_INIT_SERVICE(ShellJob,
                    {
                        /*  Attention
                            I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
                            to create a new instance of this class by our own supported service factory.
                            see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
                        */
                    }
                   )

//-----------------------------------------------
ShellJob::ShellJob(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
    : ThreadHelpBase(     )
    , m_xSMGR       (xSMGR)
{
}

//-----------------------------------------------
ShellJob::~ShellJob()
{
}

//-----------------------------------------------
css::uno::Any SAL_CALL ShellJob::execute(const css::uno::Sequence< css::beans::NamedValue >& lJobArguments)
    throw(css::lang::IllegalArgumentException,
          css::uno::Exception                ,
          css::uno::RuntimeException         )
{
    ::comphelper::SequenceAsHashMap lArgs  (lJobArguments);
    ::comphelper::SequenceAsHashMap lOwnCfg(lArgs.getUnpackedValueOrDefault(PROP_JOBCONFIG, css::uno::Sequence< css::beans::NamedValue >()));

    const ::rtl::OUString                       sCommand                   = lOwnCfg.getUnpackedValueOrDefault(PROP_COMMAND                  , ::rtl::OUString());
    const css::uno::Sequence< ::rtl::OUString > lCommandArguments          = lOwnCfg.getUnpackedValueOrDefault(PROP_ARGUMENTS                , css::uno::Sequence< ::rtl::OUString >());
    const ::sal_Bool                            bDeactivateJobIfDone       = lOwnCfg.getUnpackedValueOrDefault(PROP_DEACTIVATEJOBIFDONE      , sal_True         );
    const ::sal_Bool                            bCheckExitCode             = lOwnCfg.getUnpackedValueOrDefault(PROP_CHECKEXITCODE            , sal_True         );

    // replace all might existing place holder.
    ::rtl::OUString sRealCommand = impl_substituteCommandVariables(sCommand);

    // Command is required as minimum.
    // If it does not exists ... we cant do our job.
    // Deactivate such miss configured job silently .-)
    if (sRealCommand.getLength() < 1)
        return ShellJob::impl_generateAnswer4Deactivation();

    // do it
    ::sal_Bool bDone = impl_execute(sRealCommand, lCommandArguments, bCheckExitCode);
    if (! bDone)
        return css::uno::Any();

    // Job was done ... user configured deactivation of this job
    // in such case.
    if (bDeactivateJobIfDone)
        return ShellJob::impl_generateAnswer4Deactivation();

    // There was no decision about deactivation of this job.
    // So we have to return nothing here !
    return css::uno::Any();
}

//-----------------------------------------------
css::uno::Any ShellJob::impl_generateAnswer4Deactivation()
{
    css::uno::Sequence< css::beans::NamedValue > aAnswer(1);
    aAnswer[0].Name  = JobConst::ANSWER_DEACTIVATE_JOB();
    aAnswer[0].Value = css::uno::makeAny(sal_True);

    return css::uno::makeAny(aAnswer);
}

//-----------------------------------------------
::rtl::OUString ShellJob::impl_substituteCommandVariables(const ::rtl::OUString& sCommand)
{
    // SYNCHRONIZED ->
    ReadGuard aReadLock(m_aLock);
    css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
    aReadLock.unlock();
    // <- SYNCHRONIZED

    try
    {
              css::uno::Reference< css::util::XStringSubstitution > xSubst           (  xSMGR->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES), css::uno::UNO_QUERY_THROW);
        const ::sal_Bool                                            bSubstRequired   = sal_True;
        const ::rtl::OUString                                       sCompleteCommand = xSubst->substituteVariables(sCommand, bSubstRequired);

        return sCompleteCommand;
    }
    catch(const css::uno::Exception&)
    {}

    return ::rtl::OUString();
}

//-----------------------------------------------
::sal_Bool ShellJob::impl_execute(const ::rtl::OUString&                       sCommand      ,
                                  const css::uno::Sequence< ::rtl::OUString >& lArguments    ,
                                        ::sal_Bool                             bCheckExitCode)
{
          ::rtl_uString**  pArgs    = NULL;
    const ::sal_Int32      nArgs    = lArguments.getLength ();
          oslProcessOption nOptions = osl_Process_WAIT;
          oslProcess       hProcess(0);

    if (nArgs > 0)
        pArgs = reinterpret_cast< ::rtl_uString** >(const_cast< ::rtl::OUString* >(lArguments.getConstArray()));

    oslProcessError eError = osl_executeProcess(sCommand.pData, pArgs, nArgs, nOptions, NULL, NULL, NULL, 0, &hProcess);

    // executable not found or couldnt be started
    if (eError != osl_Process_E_None)
        return sal_False;

    if (! bCheckExitCode)
        return sal_True;

    // check it's return codes ...
    oslProcessInfo aInfo;
    aInfo.Size = sizeof (oslProcessInfo);
        eError = osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &aInfo);

    if (eError != osl_Process_E_None)
        return sal_False;

    return (aInfo.Code == 0);
}

} // namespace framework
<commit_msg>INTEGRATION: CWS changefileheader (1.4.40); FILE MERGED 2008/03/28 15:35:22 rt 1.4.40.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: shelljob.cxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"

//_______________________________________________
// include own header

#include <jobs/shelljob.hxx>
#include <jobs/jobconst.hxx>
#include <threadhelp/readguard.hxx>
#include <services.h>

//_______________________________________________
// include others

#include <osl/file.hxx>
#include <osl/process.h>
#include <vcl/svapp.hxx>
#include <rtl/ustrbuf.hxx>
#include <comphelper/sequenceashashmap.hxx>

//_______________________________________________
// include interfaces

#include <com/sun/star/system/XSystemShellExecute.hpp>
#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
#include <com/sun/star/util/XStringSubstitution.hpp>

//_______________________________________________
// namespace

namespace framework{

//_______________________________________________
// definitions

/** adress job configuration inside argument set provided on method execute(). */
static const ::rtl::OUString PROP_JOBCONFIG = ::rtl::OUString::createFromAscii("JobConfig");

/** adress job configuration property "Command". */
static const ::rtl::OUString PROP_COMMAND = ::rtl::OUString::createFromAscii("Command");

/** adress job configuration property "Arguments". */
static const ::rtl::OUString PROP_ARGUMENTS = ::rtl::OUString::createFromAscii("Arguments");

/** adress job configuration property "DeactivateJobIfDone". */
static const ::rtl::OUString PROP_DEACTIVATEJOBIFDONE = ::rtl::OUString::createFromAscii("DeactivateJobIfDone");

/** adress job configuration property "CheckExitCode". */
static const ::rtl::OUString PROP_CHECKEXITCODE = ::rtl::OUString::createFromAscii("CheckExitCode");

//-----------------------------------------------

DEFINE_XINTERFACE_3(ShellJob                                   ,
                    OWeakObject                                ,
                    DIRECT_INTERFACE(css::lang::XTypeProvider ),
                    DIRECT_INTERFACE(css::lang::XServiceInfo  ),
                    DIRECT_INTERFACE(css::task::XJob          ))

DEFINE_XTYPEPROVIDER_3(ShellJob                 ,
                       css::lang::XTypeProvider ,
                       css::lang::XServiceInfo  ,
                       css::task::XJob          )

DEFINE_XSERVICEINFO_MULTISERVICE(ShellJob                   ,
                                 ::cppu::OWeakObject        ,
                                 SERVICENAME_JOB            ,
                                 IMPLEMENTATIONNAME_SHELLJOB)

DEFINE_INIT_SERVICE(ShellJob,
                    {
                        /*  Attention
                            I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
                            to create a new instance of this class by our own supported service factory.
                            see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
                        */
                    }
                   )

//-----------------------------------------------
ShellJob::ShellJob(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
    : ThreadHelpBase(     )
    , m_xSMGR       (xSMGR)
{
}

//-----------------------------------------------
ShellJob::~ShellJob()
{
}

//-----------------------------------------------
css::uno::Any SAL_CALL ShellJob::execute(const css::uno::Sequence< css::beans::NamedValue >& lJobArguments)
    throw(css::lang::IllegalArgumentException,
          css::uno::Exception                ,
          css::uno::RuntimeException         )
{
    ::comphelper::SequenceAsHashMap lArgs  (lJobArguments);
    ::comphelper::SequenceAsHashMap lOwnCfg(lArgs.getUnpackedValueOrDefault(PROP_JOBCONFIG, css::uno::Sequence< css::beans::NamedValue >()));

    const ::rtl::OUString                       sCommand                   = lOwnCfg.getUnpackedValueOrDefault(PROP_COMMAND                  , ::rtl::OUString());
    const css::uno::Sequence< ::rtl::OUString > lCommandArguments          = lOwnCfg.getUnpackedValueOrDefault(PROP_ARGUMENTS                , css::uno::Sequence< ::rtl::OUString >());
    const ::sal_Bool                            bDeactivateJobIfDone       = lOwnCfg.getUnpackedValueOrDefault(PROP_DEACTIVATEJOBIFDONE      , sal_True         );
    const ::sal_Bool                            bCheckExitCode             = lOwnCfg.getUnpackedValueOrDefault(PROP_CHECKEXITCODE            , sal_True         );

    // replace all might existing place holder.
    ::rtl::OUString sRealCommand = impl_substituteCommandVariables(sCommand);

    // Command is required as minimum.
    // If it does not exists ... we cant do our job.
    // Deactivate such miss configured job silently .-)
    if (sRealCommand.getLength() < 1)
        return ShellJob::impl_generateAnswer4Deactivation();

    // do it
    ::sal_Bool bDone = impl_execute(sRealCommand, lCommandArguments, bCheckExitCode);
    if (! bDone)
        return css::uno::Any();

    // Job was done ... user configured deactivation of this job
    // in such case.
    if (bDeactivateJobIfDone)
        return ShellJob::impl_generateAnswer4Deactivation();

    // There was no decision about deactivation of this job.
    // So we have to return nothing here !
    return css::uno::Any();
}

//-----------------------------------------------
css::uno::Any ShellJob::impl_generateAnswer4Deactivation()
{
    css::uno::Sequence< css::beans::NamedValue > aAnswer(1);
    aAnswer[0].Name  = JobConst::ANSWER_DEACTIVATE_JOB();
    aAnswer[0].Value = css::uno::makeAny(sal_True);

    return css::uno::makeAny(aAnswer);
}

//-----------------------------------------------
::rtl::OUString ShellJob::impl_substituteCommandVariables(const ::rtl::OUString& sCommand)
{
    // SYNCHRONIZED ->
    ReadGuard aReadLock(m_aLock);
    css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
    aReadLock.unlock();
    // <- SYNCHRONIZED

    try
    {
              css::uno::Reference< css::util::XStringSubstitution > xSubst           (  xSMGR->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES), css::uno::UNO_QUERY_THROW);
        const ::sal_Bool                                            bSubstRequired   = sal_True;
        const ::rtl::OUString                                       sCompleteCommand = xSubst->substituteVariables(sCommand, bSubstRequired);

        return sCompleteCommand;
    }
    catch(const css::uno::Exception&)
    {}

    return ::rtl::OUString();
}

//-----------------------------------------------
::sal_Bool ShellJob::impl_execute(const ::rtl::OUString&                       sCommand      ,
                                  const css::uno::Sequence< ::rtl::OUString >& lArguments    ,
                                        ::sal_Bool                             bCheckExitCode)
{
          ::rtl_uString**  pArgs    = NULL;
    const ::sal_Int32      nArgs    = lArguments.getLength ();
          oslProcessOption nOptions = osl_Process_WAIT;
          oslProcess       hProcess(0);

    if (nArgs > 0)
        pArgs = reinterpret_cast< ::rtl_uString** >(const_cast< ::rtl::OUString* >(lArguments.getConstArray()));

    oslProcessError eError = osl_executeProcess(sCommand.pData, pArgs, nArgs, nOptions, NULL, NULL, NULL, 0, &hProcess);

    // executable not found or couldnt be started
    if (eError != osl_Process_E_None)
        return sal_False;

    if (! bCheckExitCode)
        return sal_True;

    // check it's return codes ...
    oslProcessInfo aInfo;
    aInfo.Size = sizeof (oslProcessInfo);
        eError = osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &aInfo);

    if (eError != osl_Process_E_None)
        return sal_False;

    return (aInfo.Code == 0);
}

} // namespace framework
<|endoftext|>


<commit_before>// Copyright (c) 2007- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

#include <algorithm>
#include <iostream>

#include "TSocketPool.h"

namespace facebook { namespace thrift { namespace transport {

using namespace std;

/**
 * TSocketPoolServer implementation
 *
 * @author Akhil Wable <akhil@facebook.com>
 */
TSocketPoolServer::TSocketPoolServer()
  : host_(""),
    port_(0),
    lastFailTime_(0),
    consecutiveFailures_(0) {}

/**
 * Constructor for TSocketPool server
 */
TSocketPoolServer::TSocketPoolServer(const std::string &host, int port)
  : host_(host),
    port_(port),
    lastFailTime_(0),
    consecutiveFailures_(0) {}

/**
 * TSocketPool implementation.
 *
 * @author Jason Sobel <jsobel@facebook.com>
 */

TSocketPool::TSocketPool(const vector<string> &hosts,
                         const vector<int> &ports) : TSocket(),
  numRetries_(1),
  retryInterval_(60),
  maxConsecutiveFailures_(1),
  randomize_(true),
  alwaysTryLast_(true)
{
  if (hosts.size() != ports.size()) {
    GlobalOutput("TSocketPool::TSocketPool: hosts.size != ports.size");
    throw TTransportException(TTransportException::BAD_ARGS);
  }

  for (unsigned int i = 0; i < hosts.size(); ++i) {
    addServer(hosts[i], ports[i]);
  }
}

TSocketPool::TSocketPool(const vector<pair<string, int> > servers) : TSocket(),
  numRetries_(1),
  retryInterval_(60),
  maxConsecutiveFailures_(1),
  randomize_(true),
  alwaysTryLast_(true)
{
  for (unsigned i = 0; i < servers.size(); ++i) {
    addServer(servers[i].first, servers[i].second);
  }
}

TSocketPool::TSocketPool(const string& host, int port) : TSocket(),
  numRetries_(1),
  retryInterval_(60),
  maxConsecutiveFailures_(1),
  randomize_(true),
  alwaysTryLast_(true)
{
  addServer(host, port);
}

TSocketPool::~TSocketPool() {
  close();
}

void TSocketPool::addServer(const string& host, int port) {
  servers_.push_back(TSocketPoolServer(host, port));
}

void TSocketPool::setNumRetries(int numRetries) {
  numRetries_ = numRetries;
}

void TSocketPool::setRetryInterval(int retryInterval) {
  retryInterval_ = retryInterval;
}

void TSocketPool::setMaxConsecutiveFailures(int maxConsecutiveFailures) {
  maxConsecutiveFailures_ = maxConsecutiveFailures;
}

void TSocketPool::setRandomize(bool randomize) {
  randomize_ = randomize;
}

void TSocketPool::setAlwaysTryLast(bool alwaysTryLast) {
  alwaysTryLast_ = alwaysTryLast;
}

/* TODO: without apc we ignore a lot of functionality from the php version */
void TSocketPool::open() {
  if (randomize_) {
    std::random_shuffle(servers_.begin(), servers_.end());
  }

  unsigned int numServers = servers_.size();
  for (unsigned int i = 0; i < numServers; ++i) {

    TSocketPoolServer &server = servers_[i];
    bool retryIntervalPassed = (server.lastFailTime_ == 0);
    bool isLastServer = alwaysTryLast_ ? (i == (numServers - 1)) : false;

    if (server.lastFailTime_ > 0) {
      // The server was marked as down, so check if enough time has elapsed to retry
      int elapsedTime = time(NULL) - server.lastFailTime_;
      if (elapsedTime > retryInterval_) {
        retryIntervalPassed = true;
      }
    }

    if (retryIntervalPassed || isLastServer) {
      for (int j = 0; j < numRetries_; ++j) {
        try {
          TSocket::open();

          // reset lastFailTime_ is required
          if (server.lastFailTime_) {
            server.lastFailTime_ = 0;
          }

          // success
          return;
        } catch (TException e) {
          // connection failed
        }
      }
    }

    ++server.consecutiveFailures_;
    if (server.consecutiveFailures_ > maxConsecutiveFailures_) {
      // Mark server as down
      server.consecutiveFailures_ = 0;
      server.lastFailTime_ = time(NULL);
    }
  }

  GlobalOutput("TSocketPool::open: all connections failed");
  throw TTransportException(TTransportException::NOT_OPEN);
}

}}} // facebook::thrift::transport
<commit_msg>Bug fix for C++ TSocketPool<commit_after>// Copyright (c) 2007- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

#include <algorithm>
#include <iostream>

#include "TSocketPool.h"

namespace facebook { namespace thrift { namespace transport {

using namespace std;

/**
 * TSocketPoolServer implementation
 *
 * @author Akhil Wable <akhil@facebook.com>
 */
TSocketPoolServer::TSocketPoolServer()
  : host_(""),
    port_(0),
    lastFailTime_(0),
    consecutiveFailures_(0) {}

/**
 * Constructor for TSocketPool server
 */
TSocketPoolServer::TSocketPoolServer(const std::string &host, int port)
  : host_(host),
    port_(port),
    lastFailTime_(0),
    consecutiveFailures_(0) {}

/**
 * TSocketPool implementation.
 *
 * @author Jason Sobel <jsobel@facebook.com>
 */

TSocketPool::TSocketPool(const vector<string> &hosts,
                         const vector<int> &ports) : TSocket(),
  numRetries_(1),
  retryInterval_(60),
  maxConsecutiveFailures_(1),
  randomize_(true),
  alwaysTryLast_(true)
{
  if (hosts.size() != ports.size()) {
    GlobalOutput("TSocketPool::TSocketPool: hosts.size != ports.size");
    throw TTransportException(TTransportException::BAD_ARGS);
  }

  for (unsigned int i = 0; i < hosts.size(); ++i) {
    addServer(hosts[i], ports[i]);
  }
}

TSocketPool::TSocketPool(const vector<pair<string, int> > servers) : TSocket(),
  numRetries_(1),
  retryInterval_(60),
  maxConsecutiveFailures_(1),
  randomize_(true),
  alwaysTryLast_(true)
{
  for (unsigned i = 0; i < servers.size(); ++i) {
    addServer(servers[i].first, servers[i].second);
  }
}

TSocketPool::TSocketPool(const string& host, int port) : TSocket(),
  numRetries_(1),
  retryInterval_(60),
  maxConsecutiveFailures_(1),
  randomize_(true),
  alwaysTryLast_(true)
{
  addServer(host, port);
}

TSocketPool::~TSocketPool() {
  close();
}

void TSocketPool::addServer(const string& host, int port) {
  servers_.push_back(TSocketPoolServer(host, port));
}

void TSocketPool::setNumRetries(int numRetries) {
  numRetries_ = numRetries;
}

void TSocketPool::setRetryInterval(int retryInterval) {
  retryInterval_ = retryInterval;
}

void TSocketPool::setMaxConsecutiveFailures(int maxConsecutiveFailures) {
  maxConsecutiveFailures_ = maxConsecutiveFailures;
}

void TSocketPool::setRandomize(bool randomize) {
  randomize_ = randomize;
}

void TSocketPool::setAlwaysTryLast(bool alwaysTryLast) {
  alwaysTryLast_ = alwaysTryLast;
}

/* TODO: without apc we ignore a lot of functionality from the php version */
void TSocketPool::open() {
  if (randomize_) {
    std::random_shuffle(servers_.begin(), servers_.end());
  }

  unsigned int numServers = servers_.size();
  for (unsigned int i = 0; i < numServers; ++i) {

    TSocketPoolServer &server = servers_[i];
    bool retryIntervalPassed = (server.lastFailTime_ == 0);
    bool isLastServer = alwaysTryLast_ ? (i == (numServers - 1)) : false;

    host_ = server.host_;
    port_ = server.port_;

    if (server.lastFailTime_ > 0) {
      // The server was marked as down, so check if enough time has elapsed to retry
      int elapsedTime = time(NULL) - server.lastFailTime_;
      if (elapsedTime > retryInterval_) {
        retryIntervalPassed = true;
      }
    }

    if (retryIntervalPassed || isLastServer) {
      for (int j = 0; j < numRetries_; ++j) {
        try {
          TSocket::open();

          // reset lastFailTime_ is required
          if (server.lastFailTime_) {
            server.lastFailTime_ = 0;
          }

          // success
          return;
        } catch (TException e) {
          // connection failed
        }
      }
    }

    ++server.consecutiveFailures_;
    if (server.consecutiveFailures_ > maxConsecutiveFailures_) {
      // Mark server as down
      server.consecutiveFailures_ = 0;
      server.lastFailTime_ = time(NULL);
    }
  }

  GlobalOutput("TSocketPool::open: all connections failed");
  throw TTransportException(TTransportException::NOT_OPEN);
}

}}} // facebook::thrift::transport
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#ifndef LIBPORT_XLOCALE_HH
# define LIBPORT_XLOCALE_HH

# include <libport/config.h>
# include <libport/compiler.hh>
# include <libport/export.hh>
# if LIBPORT_HAVE_XLOCALE_H
#  include <xlocale.h>
# endif

namespace libport
{
  /// Wrapper around std::strto*_l with the C locale.
  /// Sets errno to 0 beforehand.
  LIBPORT_API
  float       strtof_c(const char* restrict nptr, char** restrict end = 0);
  LIBPORT_API
  double      strtod_c(const char* restrict nptr, char** restrict end = 0);
  // Warning: does not work on MSVC, as it uses "double" internally.
  LIBPORT_API
  long double strtold_c(const char* restrict nptr, char** restrict end = 0);

  /*------------------------------------------------------.
  | Template version for float, double, and long double.  |
  `------------------------------------------------------*/

  // No way to please GCC and MSVC with the same code.  See also
  // ufloat.hh.
# if defined _MSC_VER
  template <typename T>
  T
  strto_c(const char* restrict nptr, char** restrict end = 0);

#  define DECLARE(Type)							\
  template <>								\
  LIBPORT_API								\
  Type									\
  strto_c<Type>(const char* restrict nptr, char** restrict end = 0)

  DECLARE(float);
  DECLARE(double);
  DECLARE(long double);
#  undef DECLARE

# else // !defined _MSC_VER
  template <typename T>
  T
  strto_c(const char* restrict nptr, char** restrict end = 0);
# endif
}

#endif // !LIBPORT_LOCALE_HH
<commit_msg>Libport.Xlocale: MSVC fixes.<commit_after>/*
 * Copyright (C) 2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#ifndef LIBPORT_XLOCALE_HH
# define LIBPORT_XLOCALE_HH

# include <libport/config.h>
# include <libport/compiler.hh>
# include <libport/export.hh>
# if LIBPORT_HAVE_XLOCALE_H
#  include <xlocale.h>
# endif

namespace libport
{
  /// Wrapper around std::strto*_l with the C locale.
  /// Sets errno to 0 beforehand.
  LIBPORT_API
  float       strtof_c(const char* restrict nptr, char** restrict end = 0);
  LIBPORT_API
  double      strtod_c(const char* restrict nptr, char** restrict end = 0);
  // Warning: does not work on MSVC, as it uses "double" internally.
  LIBPORT_API
  long double strtold_c(const char* restrict nptr, char** restrict end = 0);

  /*------------------------------------------------------.
  | Template version for float, double, and long double.  |
  `------------------------------------------------------*/

  // No way to please GCC and MSVC with the same code.  See also
  // ufloat.hh.
# if defined _MSC_VER
  template <typename T>
  T
  strto_c(const char* restrict nptr, char** restrict end = 0);

#  define DECLARE(Type)							\
  template <>								\
  LIBPORT_API								\
  Type									\
  strto_c<Type>(const char* restrict nptr, char** restrict end)

  DECLARE(float);
  DECLARE(double);
  DECLARE(long double);
#  undef DECLARE

# else // !defined _MSC_VER
  template <typename T>
  T
  strto_c(const char* restrict nptr, char** restrict end = 0);
# endif
}

#endif // !LIBPORT_LOCALE_HH
<|endoftext|>