<commit_before>//===-- RegisterScavenging.cpp - Machine register scavenging --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the Evan Cheng and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the machine register scavenger. It can provide
// information such as unused register at any point in a machine basic block.
// It also provides a mechanism to make registers availbale by evicting them
// to spill slots.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "reg-scavenging"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;

void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
  const MachineFunction &MF = *mbb->getParent();
  const TargetMachine &TM = MF.getTarget();
  TII = TM.getInstrInfo();
  RegInfo = TM.getRegisterInfo();

  assert((NumPhysRegs == 0 || NumPhysRegs == RegInfo->getNumRegs()) &&
         "Target changed?");

  if (!MBB) {
    NumPhysRegs = RegInfo->getNumRegs();
    RegsAvailable.resize(NumPhysRegs);

    // Create reserved registers bitvector.
    ReservedRegs = RegInfo->getReservedRegs(MF);

    // Create callee-saved registers bitvector.
    CalleeSavedRegs.resize(NumPhysRegs);
    const unsigned *CSRegs = RegInfo->getCalleeSavedRegs();
    if (CSRegs != NULL)
      for (unsigned i = 0; CSRegs[i]; ++i)
        CalleeSavedRegs.set(CSRegs[i]);
  }

  MBB = mbb;
  ScavengedReg = 0;
  ScavengedRC = NULL;

  // All registers started out unused.
  RegsAvailable.set();

  // Reserved registers are always used.
  RegsAvailable ^= ReservedRegs;

  // Live-in registers are in use.
  if (!MBB->livein_empty())
    for (MachineBasicBlock::const_livein_iterator I = MBB->livein_begin(),
           E = MBB->livein_end(); I != E; ++I)
      setUsed(*I);

  Tracking = false;
}

void RegScavenger::restoreScavengedReg() {
  if (!ScavengedReg)
    return;

  RegInfo->loadRegFromStackSlot(*MBB, MBBI, ScavengedReg,
                                ScavengingFrameIndex, ScavengedRC);
  MachineBasicBlock::iterator II = prior(MBBI);
  RegInfo->eliminateFrameIndex(II, this);
  setUsed(ScavengedReg);
  ScavengedReg = 0;
  ScavengedRC = NULL;
}

void RegScavenger::forward() {
  // Move ptr forward.
  if (!Tracking) {
    MBBI = MBB->begin();
    Tracking = true;
  } else {
    assert(MBBI != MBB->end() && "Already at the end of the basic block!");
    MBBI = next(MBBI);
  }

  MachineInstr *MI = MBBI;

  // Reaching a terminator instruction. Restore a scavenged register (which
  // must be life out.
  if (TII->isTerminatorInstr(MI->getOpcode()))
    restoreScavengedReg();

  // Process uses first.
  BitVector ChangedRegs(NumPhysRegs);
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isUse())
      continue;
    unsigned Reg = MO.getReg();
    if (Reg == 0)
      continue;
    if (!isUsed(Reg)) {
      // Register has been scavenged. Restore it!
      if (Reg != ScavengedReg)
        assert(false);
      else
        restoreScavengedReg();
    }
    if (MO.isKill() && !isReserved(Reg))
      ChangedRegs.set(Reg);
  }
  // Change states of all registers after all the uses are processed to guard
  // against multiple uses.
  setUnused(ChangedRegs);

  // Process defs.
  const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isDef())
      continue;
    unsigned Reg = MO.getReg();
    // If it's dead upon def, then it is now free.
    if (MO.isDead()) {
      setUnused(Reg);
      continue;
    }
    // Skip two-address destination operand.
    if (TID->findTiedToSrcOperand(i) != -1) {
      assert(isUsed(Reg));
      continue;
    }
    assert(isUnused(Reg) || isReserved(Reg));
    setUsed(Reg);
  }
}

void RegScavenger::backward() {
  assert(Tracking && "Not tracking states!");
  assert(MBBI != MBB->begin() && "Already at start of basic block!");
  // Move ptr backward.
  MBBI = prior(MBBI);

  MachineInstr *MI = MBBI;
  // Process defs first.
  const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isDef())
      continue;
    // Skip two-address destination operand.
    if (TID->findTiedToSrcOperand(i) != -1)
      continue;
    unsigned Reg = MO.getReg();
    assert(isUsed(Reg));
    if (!isReserved(Reg))
      setUnused(Reg);
  }

  // Process uses.
  BitVector ChangedRegs(NumPhysRegs);
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isUse())
      continue;
    unsigned Reg = MO.getReg();
    if (Reg == 0)
      continue;
    assert(isUnused(Reg) || isReserved(Reg));
    ChangedRegs.set(Reg);
  }
  setUsed(ChangedRegs);
}

void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) {
  if (includeReserved)
    used = ~RegsAvailable;
  else
    used = ~RegsAvailable & ~ReservedRegs;
}

/// CreateRegClassMask - Set the bits that represent the registers in the
/// TargetRegisterClass.
static void CreateRegClassMask(const TargetRegisterClass *RC, BitVector &Mask) {
  for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); I != E;
       ++I)
    Mask.set(*I);
}

unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass,
                                     const BitVector &Candidates) const {
  // Mask off the registers which are not in the TargetRegisterClass.
  BitVector RegsAvailableCopy(NumPhysRegs, false);
  CreateRegClassMask(RegClass, RegsAvailableCopy);
  RegsAvailableCopy &= RegsAvailable;

  // Restrict the search to candidates.
  RegsAvailableCopy &= Candidates;

  // Returns the first unused (bit is set) register, or 0 is none is found.
  int Reg = RegsAvailableCopy.find_first();
  return (Reg == -1) ? 0 : Reg;
}

unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass,
                                     bool ExCalleeSaved) const {
  // Mask off the registers which are not in the TargetRegisterClass.
  BitVector RegsAvailableCopy(NumPhysRegs, false);
  CreateRegClassMask(RegClass, RegsAvailableCopy);
  RegsAvailableCopy &= RegsAvailable;

  // If looking for a non-callee-saved register, mask off all the callee-saved
  // registers.
  if (ExCalleeSaved)
    RegsAvailableCopy &= ~CalleeSavedRegs;

  // Returns the first unused (bit is set) register, or 0 is none is found.
  int Reg = RegsAvailableCopy.find_first();
  return (Reg == -1) ? 0 : Reg;
}

/// calcDistanceToUse - Calculate the distance to the first use of the
/// specified register.
static unsigned calcDistanceToUse(MachineBasicBlock *MBB,
                                  MachineBasicBlock::iterator I, unsigned Reg) {
  unsigned Dist = 0;
  I = next(I);
  while (I != MBB->end()) {
    Dist++;
    if (I->findRegisterUseOperand(Reg))
        return Dist;
    I = next(I);
  }
  return Dist + 1;
}

unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
                                        MachineBasicBlock::iterator I) {
  assert(ScavengingFrameIndex >= 0 &&
         "Cannot scavenge a register without an emergency spill slot!");

  // Mask off the registers which are not in the TargetRegisterClass.
  BitVector Candidates(NumPhysRegs, false);
  CreateRegClassMask(RC, Candidates);
  Candidates ^= ReservedRegs;  // Do not include reserved registers.

  // Exclude all the registers being used by the instruction.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    MachineOperand &MO = I->getOperand(i);
    if (MO.isReg())
      Candidates.reset(MO.getReg());
  }

  // Find the register whose use is furtherest aaway.
  unsigned SReg = 0;
  unsigned MaxDist = 0;
  int Reg = Candidates.find_first();
  while (Reg != -1) {
    unsigned Dist = calcDistanceToUse(MBB, I, Reg);
    if (Dist >= MaxDist) {
      MaxDist = Dist;
      SReg = Reg;
    }
    Reg = Candidates.find_next(Reg);
  }

  if (ScavengedReg != 0) {
    // First restore previously scavenged register.
    RegInfo->loadRegFromStackSlot(*MBB, I, ScavengedReg,
                                  ScavengingFrameIndex, ScavengedRC);
    MachineBasicBlock::iterator II = prior(I);
    RegInfo->eliminateFrameIndex(II, this);
  }

  RegInfo->storeRegToStackSlot(*MBB, I, SReg, ScavengingFrameIndex, RC);
  MachineBasicBlock::iterator II = prior(I);
  RegInfo->eliminateFrameIndex(II, this);
  ScavengedReg = SReg;
  ScavengedRC = RC;

  return SReg;
}
<commit_msg>Bad bad bug. findRegisterUseOperand() returns -1 if a use if not found.<commit_after>//===-- RegisterScavenging.cpp - Machine register scavenging --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the Evan Cheng and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the machine register scavenger. It can provide
// information such as unused register at any point in a machine basic block.
// It also provides a mechanism to make registers availbale by evicting them
// to spill slots.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "reg-scavenging"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;

void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
  const MachineFunction &MF = *mbb->getParent();
  const TargetMachine &TM = MF.getTarget();
  TII = TM.getInstrInfo();
  RegInfo = TM.getRegisterInfo();

  assert((NumPhysRegs == 0 || NumPhysRegs == RegInfo->getNumRegs()) &&
         "Target changed?");

  if (!MBB) {
    NumPhysRegs = RegInfo->getNumRegs();
    RegsAvailable.resize(NumPhysRegs);

    // Create reserved registers bitvector.
    ReservedRegs = RegInfo->getReservedRegs(MF);

    // Create callee-saved registers bitvector.
    CalleeSavedRegs.resize(NumPhysRegs);
    const unsigned *CSRegs = RegInfo->getCalleeSavedRegs();
    if (CSRegs != NULL)
      for (unsigned i = 0; CSRegs[i]; ++i)
        CalleeSavedRegs.set(CSRegs[i]);
  }

  MBB = mbb;
  ScavengedReg = 0;
  ScavengedRC = NULL;

  // All registers started out unused.
  RegsAvailable.set();

  // Reserved registers are always used.
  RegsAvailable ^= ReservedRegs;

  // Live-in registers are in use.
  if (!MBB->livein_empty())
    for (MachineBasicBlock::const_livein_iterator I = MBB->livein_begin(),
           E = MBB->livein_end(); I != E; ++I)
      setUsed(*I);

  Tracking = false;
}

void RegScavenger::restoreScavengedReg() {
  if (!ScavengedReg)
    return;

  RegInfo->loadRegFromStackSlot(*MBB, MBBI, ScavengedReg,
                                ScavengingFrameIndex, ScavengedRC);
  MachineBasicBlock::iterator II = prior(MBBI);
  RegInfo->eliminateFrameIndex(II, this);
  setUsed(ScavengedReg);
  ScavengedReg = 0;
  ScavengedRC = NULL;
}

void RegScavenger::forward() {
  // Move ptr forward.
  if (!Tracking) {
    MBBI = MBB->begin();
    Tracking = true;
  } else {
    assert(MBBI != MBB->end() && "Already at the end of the basic block!");
    MBBI = next(MBBI);
  }

  MachineInstr *MI = MBBI;

  // Reaching a terminator instruction. Restore a scavenged register (which
  // must be life out.
  if (TII->isTerminatorInstr(MI->getOpcode()))
    restoreScavengedReg();

  // Process uses first.
  BitVector ChangedRegs(NumPhysRegs);
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isUse())
      continue;
    unsigned Reg = MO.getReg();
    if (Reg == 0)
      continue;
    if (!isUsed(Reg)) {
      // Register has been scavenged. Restore it!
      if (Reg != ScavengedReg)
        assert(false);
      else
        restoreScavengedReg();
    }
    if (MO.isKill() && !isReserved(Reg))
      ChangedRegs.set(Reg);
  }
  // Change states of all registers after all the uses are processed to guard
  // against multiple uses.
  setUnused(ChangedRegs);

  // Process defs.
  const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isDef())
      continue;
    unsigned Reg = MO.getReg();
    // If it's dead upon def, then it is now free.
    if (MO.isDead()) {
      setUnused(Reg);
      continue;
    }
    // Skip two-address destination operand.
    if (TID->findTiedToSrcOperand(i) != -1) {
      assert(isUsed(Reg));
      continue;
    }
    assert(isUnused(Reg) || isReserved(Reg));
    setUsed(Reg);
  }
}

void RegScavenger::backward() {
  assert(Tracking && "Not tracking states!");
  assert(MBBI != MBB->begin() && "Already at start of basic block!");
  // Move ptr backward.
  MBBI = prior(MBBI);

  MachineInstr *MI = MBBI;
  // Process defs first.
  const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isDef())
      continue;
    // Skip two-address destination operand.
    if (TID->findTiedToSrcOperand(i) != -1)
      continue;
    unsigned Reg = MO.getReg();
    assert(isUsed(Reg));
    if (!isReserved(Reg))
      setUnused(Reg);
  }

  // Process uses.
  BitVector ChangedRegs(NumPhysRegs);
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg() || !MO.isUse())
      continue;
    unsigned Reg = MO.getReg();
    if (Reg == 0)
      continue;
    assert(isUnused(Reg) || isReserved(Reg));
    ChangedRegs.set(Reg);
  }
  setUsed(ChangedRegs);
}

void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) {
  if (includeReserved)
    used = ~RegsAvailable;
  else
    used = ~RegsAvailable & ~ReservedRegs;
}

/// CreateRegClassMask - Set the bits that represent the registers in the
/// TargetRegisterClass.
static void CreateRegClassMask(const TargetRegisterClass *RC, BitVector &Mask) {
  for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); I != E;
       ++I)
    Mask.set(*I);
}

unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass,
                                     const BitVector &Candidates) const {
  // Mask off the registers which are not in the TargetRegisterClass.
  BitVector RegsAvailableCopy(NumPhysRegs, false);
  CreateRegClassMask(RegClass, RegsAvailableCopy);
  RegsAvailableCopy &= RegsAvailable;

  // Restrict the search to candidates.
  RegsAvailableCopy &= Candidates;

  // Returns the first unused (bit is set) register, or 0 is none is found.
  int Reg = RegsAvailableCopy.find_first();
  return (Reg == -1) ? 0 : Reg;
}

unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass,
                                     bool ExCalleeSaved) const {
  // Mask off the registers which are not in the TargetRegisterClass.
  BitVector RegsAvailableCopy(NumPhysRegs, false);
  CreateRegClassMask(RegClass, RegsAvailableCopy);
  RegsAvailableCopy &= RegsAvailable;

  // If looking for a non-callee-saved register, mask off all the callee-saved
  // registers.
  if (ExCalleeSaved)
    RegsAvailableCopy &= ~CalleeSavedRegs;

  // Returns the first unused (bit is set) register, or 0 is none is found.
  int Reg = RegsAvailableCopy.find_first();
  return (Reg == -1) ? 0 : Reg;
}

/// calcDistanceToUse - Calculate the distance to the first use of the
/// specified register.
static unsigned calcDistanceToUse(MachineBasicBlock *MBB,
                                  MachineBasicBlock::iterator I, unsigned Reg) {
  unsigned Dist = 0;
  I = next(I);
  while (I != MBB->end()) {
    Dist++;
    if (I->findRegisterUseOperand(Reg) != -1)
        return Dist;
    I = next(I);
  }
  return Dist + 1;
}

unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
                                        MachineBasicBlock::iterator I) {
  assert(ScavengingFrameIndex >= 0 &&
         "Cannot scavenge a register without an emergency spill slot!");

  // Mask off the registers which are not in the TargetRegisterClass.
  BitVector Candidates(NumPhysRegs, false);
  CreateRegClassMask(RC, Candidates);
  Candidates ^= ReservedRegs;  // Do not include reserved registers.

  // Exclude all the registers being used by the instruction.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    MachineOperand &MO = I->getOperand(i);
    if (MO.isReg())
      Candidates.reset(MO.getReg());
  }

  // Find the register whose use is furtherest aaway.
  unsigned SReg = 0;
  unsigned MaxDist = 0;
  int Reg = Candidates.find_first();
  while (Reg != -1) {
    unsigned Dist = calcDistanceToUse(MBB, I, Reg);
    if (Dist >= MaxDist) {
      MaxDist = Dist;
      SReg = Reg;
    }
    Reg = Candidates.find_next(Reg);
  }

  if (ScavengedReg != 0) {
    // First restore previously scavenged register.
    RegInfo->loadRegFromStackSlot(*MBB, I, ScavengedReg,
                                  ScavengingFrameIndex, ScavengedRC);
    MachineBasicBlock::iterator II = prior(I);
    RegInfo->eliminateFrameIndex(II, this);
  }

  RegInfo->storeRegToStackSlot(*MBB, I, SReg, ScavengingFrameIndex, RC);
  MachineBasicBlock::iterator II = prior(I);
  RegInfo->eliminateFrameIndex(II, this);
  ScavengedReg = SReg;
  ScavengedRC = RC;

  return SReg;
}
<|endoftext|>


<commit_before>#pragma once

#include <distributions/special.hpp>
#include <distributions/random.hpp>
#include <distributions/random_fwd.hpp>

#include <microscopes/common/util.hpp>

#include <vector>
#include <map>
#include <chrono>
#include <cmath>

#include <eigen3/Eigen/Dense>

namespace microscopes{
namespace hmm{

  typedef Eigen::Matrix<size_t, Eigen::Dynamic, Eigen::Dynamic> MatrixXs;
  typedef Eigen::MatrixXf MatrixXf;

  class model_definition {
  public:
    /**
    * N - size of observation vocabulary
    **/
    model_definition(size_t N): N_(N)
    {
      MICROSCOPES_DCHECK(N > 0, "Vocabulary cannot be empty");
    }
    inline size_t N() const { return N_; }
  protected:
    size_t N_;
  };

  // A class that maintains the direct assignment representation for an HDP,
  // similar to Teh et al 2006, except with explicit stick lengths for the
  // lower-level DPs as well.
  // Contains the data along with functions for hyperparameter sampling
  class direct_assignment_representation {
  public:
    inline float alpha() { return alpha0_; }
    inline float gamma() { return gamma_; }
    inline size_t nsticks()   { return K; }
    inline size_t ncontexts() { return J; }

    inline void set_alpha_hypers(float hyper_alpha_a, float hyper_alpha_b) {
      hyper_alpha_a_ = hyper_alpha_a;
      hyper_alpha_b_ = hyper_alpha_b;
    }

    inline void set_gamma_hypers(float hyper_gamma_a, float hyper_gamma_b) {
      hyper_gamma_a_ = hyper_gamma_a;
      hyper_gamma_b_ = hyper_gamma_b;
    }

    inline void set_alpha(float alpha0) { alpha0_ = alpha0; }
    inline void set_gamma(float gamma)  { gamma_  = gamma; }

    float joint_log_likelihood();
    void clear_empty_states();
    void sample_sticks(distributions::rng_t rng);
    void sample_hypers(distributions::rng_t rng, bool alpha_flag, bool gamma_flag, size_t niter);
    void sample_alpha(distributions::rng_t &rng, size_t m, size_t iter);
    void sample_gamma(distributions::rng_t &rng, size_t m, size_t iter);
  protected:
    std::vector<float> beta_; // the stick lengths for the top-level DP draw. Size K+1.

    // The lengths of the lower-level sticks in each context. Each row is one context.
    // There are K+1 columns and each row sums to one (the last column is all unobserved sticks)
    MatrixXf sticks_;

    // The count of how many times a sample from each stick is observed in each context.
    // Each row is one context. There are K columns.
    MatrixXs stick_counts_;

    // hyperparameters
    float gamma_;
    float alpha0_;
    // Base distribution of the HDP. In this case,
    // hyperparameters for a Dirichlet prior over observations.
    // Will generalize this to other observation models later.
    const std::vector<float> base_;

    // parameters for a gamma hyperprior on gamma_ and alpha0_
    float hyper_gamma_a_, hyper_gamma_b_,
          hyper_alpha_a_, hyper_alpha_b_;

    size_t K, J; // The number of states currently instantiated, and number of contexts, respectively
    // Note, for the HDP-HMM these numbers should always be equal
  };

  // Maintains the state of an HDP-HMM using the direct assignment representation for an
  // HDP, along with the auxilliary variables needed for beam sampling as in Van Gael 2008
  class state {
  public:
    state(const model_definition &defn,
          const std::vector<float> &H,
          const std::vector<std::vector<size_t> > &data,
          distributions::rng_t &rng);

    inline void get_pi(float * f)  { Eigen::Map<MatrixXf>(f, K, K+1)       = pi_; }
    inline void get_phi(float * f) { Eigen::Map<MatrixXf>(f, K, defn_.N()) = phi_; }
    inline size_t nstates()        { return K; }
    inline size_t nobs()           { return defn_.N(); }
    inline float alpha()           { return hdp_.alpha(); }
    inline float gamma()           { return hdp_.gamma(); }

    inline void set_alpha_hypers(float hyper_alpha_a, float hyper_alpha_b) {
      alpha0_flag_ = true;
      hdp_.set_alpha_hypers(hyper_alpha_a, hyper_alpha_b);
    }

    inline void set_gamma_hypers(float hyper_gamma_a, float hyper_gamma_b) {
      gamma_flag_ = true;
      hdp_.set_gamma_hypers(hyper_alpha_a, hyper_gamma_b);
    }

    inline void fix_alpha(float alpha0) {
      alpha0_flag_ = false;
      hdp_.set_alpha(alpha0);
    }

    inline void fix_gamma(float gamma) {
      gamma_flag_ = false;
      hdp_.set_gamma(gamma);
    }

    float joint_log_likelihood();

    void sample_aux(distributions::rng_t &rng);
    void sample_state(distributions::rng_t &rng);

    inline void sample_hypers(distributions::rng_t &rng, size_t niter) {
      hdp_.sample_hypers(rng, alpha_flag_, gamma_flag_, niter);
    }

    void clear_empty_states();

    void sample_pi(distributions::rng_t &rng);
    void sample_phi(distributions::rng_t &rng);

  protected:

    // parameters

    // these three all have the same shape as the data
    const model_definition defn_;
    const std::vector<std::vector <size_t> > data_; // XXX: For now, the observation type is just a vector of vectors of ints. Later we can switch over to using recarrays
    std::vector<std::vector<size_t> > s_; // the state sequence
    std::vector<std::vector<float> > u_; // the slice sampling parameter for each time step in the series
    direct_assignment_representation hdp_; // the state of the HDP itself

    // same shape as the transition matrix, or plus one column
    MatrixXs pi_counts_; // the count of how many times a transition occurs between states. Size K x K.
    MatrixXf pi_; // the observed portion of the infinite transition matrix. Size K x K+1.

    // same shape as the observation matrix
    MatrixXs phi_counts_; // count of how many times an observation is seen from a given state. Size K x N.
    MatrixXf phi_; // the emission matrix. Size K x N.

    std::vector<float> beta_; // the stick lengths for the top-level DP draw. Size K+1.
    std::vector<bool> state_visited_; // Size K

    // hyperparameters
    float gamma_;
    float alpha0_;
    const std::vector<float> H_; // hyperparameters for a Dirichlet prior over observations. Will generalize this to other observation models later.

    // If true, resample the hyperparameter in each loop
    bool gamma_flag_, alpha0_flag_;
    // Only assigned values if the corresponding flag is true
    float hyper_gamma_a_, hyper_gamma_b_,
          hyper_alpha_a_, hyper_alpha_b_;

    // helper fields
    // Over all instantiated states, the maximum value of the part of pi_k that belongs to the "unseen" states.
    //Should be smaller than the least value of the auxiliary variable, so all possible states visited by the beam sampler are instantiated
    float max_pi;
    size_t K;

    void sample_pi_row(distributions::rng_t &rng, size_t i);
    void sample_phi_row(distributions::rng_t &rng, size_t k);

    // Resamples the hyperparameter gamma,
    // not to be confused with distributions::sample_gamma,
    // which samples from a Gamma distribution
    void sample_gamma(distributions::rng_t &rng, size_t m, size_t iter);
    void sample_alpha0(distributions::rng_t &rng, size_t m, size_t iter);
  };

} // namespace hmm
} // namespace microscopes
<commit_msg>Removed unnecessary fields from state<commit_after>#pragma once

#include <distributions/special.hpp>
#include <distributions/random.hpp>
#include <distributions/random_fwd.hpp>

#include <microscopes/common/util.hpp>

#include <vector>
#include <map>
#include <chrono>
#include <cmath>

#include <eigen3/Eigen/Dense>

namespace microscopes{
namespace hmm{

  typedef Eigen::Matrix<size_t, Eigen::Dynamic, Eigen::Dynamic> MatrixXs;
  typedef Eigen::MatrixXf MatrixXf;

  class model_definition {
  public:
    /**
    * N - size of observation vocabulary
    **/
    model_definition(size_t N): N_(N)
    {
      MICROSCOPES_DCHECK(N > 0, "Vocabulary cannot be empty");
    }
    inline size_t N() const { return N_; }
  protected:
    size_t N_;
  };

  // A class that maintains the direct assignment representation for an HDP,
  // similar to Teh et al 2006, except with explicit stick lengths for the
  // lower-level DPs as well.
  // Contains the data along with functions for hyperparameter sampling
  class direct_assignment_representation {
  public:
    inline float alpha() { return alpha0_; }
    inline float gamma() { return gamma_; }
    inline size_t nsticks()   { return K; }
    inline size_t ncontexts() { return J; }

    inline void set_alpha_hypers(float hyper_alpha_a, float hyper_alpha_b) {
      hyper_alpha_a_ = hyper_alpha_a;
      hyper_alpha_b_ = hyper_alpha_b;
    }

    inline void set_gamma_hypers(float hyper_gamma_a, float hyper_gamma_b) {
      hyper_gamma_a_ = hyper_gamma_a;
      hyper_gamma_b_ = hyper_gamma_b;
    }

    inline void set_alpha(float alpha0) { alpha0_ = alpha0; }
    inline void set_gamma(float gamma)  { gamma_  = gamma; }

    float joint_log_likelihood();
    void clear_empty_states();
    void sample_sticks(distributions::rng_t rng);
    void sample_hypers(distributions::rng_t rng, bool alpha_flag, bool gamma_flag, size_t niter);
    void sample_alpha(distributions::rng_t &rng, size_t m, size_t iter);
    void sample_gamma(distributions::rng_t &rng, size_t m, size_t iter);
  protected:
    std::vector<float> beta_; // the stick lengths for the top-level DP draw. Size K+1.

    // The lengths of the lower-level sticks in each context. Each row is one context.
    // There are K+1 columns and each row sums to one (the last column is all unobserved sticks)
    MatrixXf sticks_;

    // The count of how many times a sample from each stick is observed in each context.
    // Each row is one context. There are K columns.
    MatrixXs stick_counts_;

    // hyperparameters
    float gamma_;
    float alpha0_;
    // Base distribution of the HDP. In this case,
    // hyperparameters for a Dirichlet prior over observations.
    // Will generalize this to other observation models later.
    const std::vector<float> base_;

    // parameters for a gamma hyperprior on gamma_ and alpha0_
    float hyper_gamma_a_, hyper_gamma_b_,
          hyper_alpha_a_, hyper_alpha_b_;

    size_t K, J; // The number of states currently instantiated, and number of contexts, respectively
    // Note, for the HDP-HMM these numbers should always be equal
  };

  // Maintains the state of an HDP-HMM using the direct assignment representation for an
  // HDP, along with the auxilliary variables needed for beam sampling as in Van Gael 2008
  class state {
  public:
    state(const model_definition &defn,
          const std::vector<float> &H,
          const std::vector<std::vector<size_t> > &data,
          distributions::rng_t &rng);

    inline void get_pi(float * f)  { Eigen::Map<MatrixXf>(f, K, K+1)       = pi_; }
    inline void get_phi(float * f) { Eigen::Map<MatrixXf>(f, K, defn_.N()) = phi_; }
    inline size_t nstates()        { return K; }
    inline size_t nobs()           { return defn_.N(); }
    inline float alpha()           { return hdp_.alpha(); }
    inline float gamma()           { return hdp_.gamma(); }

    inline void set_alpha_hypers(float a, float b) { hdp_.set_alpha_hypers(a, b); }
    inline void set_gamma_hypers(float a, float b) { hdp_.set_gamma_hypers(a, b); }
    inline void set_alpha(float alpha0) { hdp_.set_alpha(alpha0); }
    inline void set_gamma(float gamma)  { hdp_.set_gamma(gamma); }

    float joint_log_likelihood();

    void sample_aux(distributions::rng_t &rng);
    void sample_state(distributions::rng_t &rng);

    inline void sample_hypers(distributions::rng_t &rng, bool alpha_flag, bool gamma_flag, size_t niter) {
      hdp_.sample_hypers(rng, alpha_flag, gamma_flag, niter);
    }

    void clear_empty_states();

    void sample_pi(distributions::rng_t &rng);
    void sample_phi(distributions::rng_t &rng);

  protected:

    // parameters

    // these three all have the same shape as the data
    const model_definition defn_;
    const std::vector<std::vector <size_t> > data_; // XXX: For now, the observation type is just a vector of vectors of ints. Later we can switch over to using recarrays
    std::vector<std::vector<size_t> > s_; // the state sequence
    std::vector<std::vector<float> > u_; // the slice sampling parameter for each time step in the series
    direct_assignment_representation hdp_; // the state of the HDP itself

    // same shape as the transition matrix, or plus one column
    // MatrixXs pi_counts_; // the count of how many times a transition occurs between states. Size K x K.
    // MatrixXf pi_; // the observed portion of the infinite transition matrix. Size K x K+1.

    // same shape as the observation matrix
    MatrixXs phi_counts_; // count of how many times an observation is seen from a given state. Size K x N.
    MatrixXf phi_; // the emission matrix. Size K x N.

    // std::vector<float> beta_; // the stick lengths for the top-level DP draw. Size K+1.
    std::vector<bool> state_visited_; // Size K

    // hyperparameters
    // float gamma_;
    // float alpha0_;
    // const std::vector<float> H_; // hyperparameters for a Dirichlet prior over observations. Will generalize this to other observation models later.

    // helper fields
    // Over all instantiated states, the maximum value of the part of pi_k that belongs to the "unseen" states.
    //Should be smaller than the least value of the auxiliary variable, so all possible states visited by the beam sampler are instantiated
    float max_pi;
    // size_t K;

    void sample_pi_row(distributions::rng_t &rng, size_t i);
    void sample_phi_row(distributions::rng_t &rng, size_t k);

    // Resamples the hyperparameter gamma,
    // not to be confused with distributions::sample_gamma,
    // which samples from a Gamma distribution
    void sample_gamma(distributions::rng_t &rng, size_t m, size_t iter);
    void sample_alpha0(distributions::rng_t &rng, size_t m, size_t iter);
  };

} // namespace hmm
} // namespace microscopes
<|endoftext|>


<commit_before>/* Copyright (c) 2015 Collin Baker
 *
 * This file is licensed under the MIT license
 * http://opensource.org/licenses/MIT
 */

#ifndef _HTTP_REQUEST_HPP_
#define _HTTP_REQUEST_HPP_

#include <map>
#include <string>

#include <boost/variant.hpp>
#include <boost/optional.hpp>

namespace http
{

enum class request_method
{
	GET,
	HEAD,
	POST,
	PUT,
	DELETE,
	CONNECT,
	OPTIONS,
	TRACE
};

struct request_target_origin_form
{
	std::string absolute_path;
	boost::optional<std::string> query;
};

struct request_target_absolute_form
{
	std::string scheme;
	std::string authority;
	request_target_origin_form origin_part;
};

struct request_target_authority_form
{
	std::string authority;
};

struct request_target_asterisk_form
{
	// Just used as a tag
};

using request_target = boost::variant<request_target_origin_form, request_target_absolute_form, request_target_authority_form, request_target_asterisk_form>;

struct request
{
	request_method method;
	request_target target;
	std::map<std::string, std::string> header_fields;
};

}

#endif // _HTTP_REQUEST_HPP_
<commit_msg>Fixed line ending issue<commit_after>/* Copyright (c) 2015 Collin Baker
 *
 * This file is licensed under the MIT license
 * http://opensource.org/licenses/MIT
 */

#ifndef _HTTP_REQUEST_HPP_
#define _HTTP_REQUEST_HPP_

#include <map>
#include <string>

#include <boost/variant.hpp>
#include <boost/optional.hpp>

namespace http
{

enum class request_method
{
	GET,
	HEAD,
	POST,
	PUT,
	DELETE,
	CONNECT,
	OPTIONS,
	TRACE
};

struct request_target_origin_form
{
	std::string absolute_path;
	boost::optional<std::string> query;
};

struct request_target_absolute_form
{
	std::string scheme;
	std::string authority;
	request_target_origin_form origin_part;
};

struct request_target_authority_form
{
	std::string authority;
};

struct request_target_asterisk_form
{
	// Just used as a tag
};

using request_target = boost::variant<request_target_origin_form, request_target_absolute_form, request_target_authority_form, request_target_asterisk_form>;

struct request
{
	request_method method;
	request_target target;
	std::map<std::string, std::string> header_fields;
};

}

#endif // _HTTP_REQUEST_HPP_
<|endoftext|>


<commit_before>#pragma once

#include <distributions/special.hpp>
#include <distributions/random.hpp>
#include <distributions/random_fwd.hpp>

#include <vector>
#include <map>

namespace microscopes{
namespace hmm{

  distributions::rng_t rng;

  // A class for a vector of vectors, useful for representing pretty much everything we need for the beam sampler.
  // For instance, time series data can be stored as a vector of vectors, where each vector is one time series.
  // The transition matrix can also be stored as a vector of vectors, where each transition probability is one vector.

  // Though I realize now, once I am adding-and-removing states, it might make sense to replace this with group_manager.
  template <typename T>
  class meta_vector {
  public:

    meta_vector(): data_() {}

    meta_vector(std::vector<size_t> size) : data_(size.size()) {
      for (int i = 0; i < data_.size(); i++) {
        data_[i] = std::vector<T>(size[i]);
      }
    }

    std::vector<T>& operator[](size_t i) {
      return data_[i];
    }

    std::vector<size_t> size() {
      std::vector<size_t> sizes(data_.size());
      for (std::vector<T> vec: data_) {
        sizes.push_back(vec.size());
      }
      return sizes;
    }

    T sum(size_t i) { // useful for resampling m, the number of tables serving a dish
      T result = (T)0;
      for(T t: data_[i]) {
        result += t;
      }
      return result;
    }
  protected:
    std::vector<std::vector<T> > data_;
  };

// Implementation of the beam sampler for the HDP-HMM, following van Gael 2008
  template <int N>
  class hmm {
  public:
    hmm(float gamma, float alpha0, float *H, meta_vector<size_t> data):
      gamma_(gamma),
      alpha0_(alpha0),
      H_(H),
      data_(data),
      u_(data.size()),
      beta_(),
      memoized_log_stirling_()
    {
    }
  protected:

    // parameters

    // these three all have the same shape as the data
    const meta_vector<size_t> data_; // XXX: For now, the observation type is just a vector of vectors of ints. Later we can switch over to using recarrays
    meta_vector<size_t> s_; // the state sequence
    meta_vector<float> u_; // the slice sampling parameter for each time step in the series

    // these three all have the same shape as the transition matrix
    meta_vector<size_t> m_; // auxilliary variable necessary for sampling beta
    meta_vector<size_t> counts_; // the count of how many times a transition occurs between states
    meta_vector<float> pi_; // the observed portion of the infinite transition matrix

    // shape is the number of states currently instantiated
    std::vector<float> beta_; // the stick lengths for the top-level DP draw

    // hyperparameters
    const float gamma_;
    const float alpha0_;
    const float H_[N]; // hyperparameters for a Dirichlet prior over observations. Will generalize this to other observation models later.

    // helper fields
    std::map<size_t, std::vector<float> > memoized_log_stirling_; // memoize computation of log stirling numbers for speed when sampling m

    // sampling functions. later we can integrate these into microscopes::kernels where appropriate.
    void sample_s() {
      std::vector<size_t> sizes = data_.size();
      for (int i = 0; i < sizes.size(); i++) {
        // Forward-filter
        for (int t = 0; t < size[i]; t++) {

        }

        // Backwards-sample
        for (int t = size[i]-1; t >= 0; t--) {

        }
      }
    }

    void sample_u() {
      size_t prev_state;
      std::uniform_real_distribution<float> sampler (0.0, 1.0);
      std::vector<size_t> sizes = u_.size();
      for (int i = 0; i < sizes.size(); i++) {
        for(int j = 0; j < sizes[i]; j++) {
          if (j == 0) {
            prev_state = 0;
          } else {
            prev_state = s_[i][j-1];
          }
          u_[i][j] = sampler(rng) / (pi_[prev_state][s_[i][j]]); // scale the uniform sample to be between 0 and pi_{s_{t-1}s_t}
        }
      }
    }

    void sample_pi() {
      std::vector<size_t> sizes = u_.size();
      for (int i = 0; i < sizes.size(); i++) {
        float new_pi[sizes[i]+1];
        float alphas[sizes[i]+1];
        for (int j = 0; j < sizes[i]; j++) {
          alphas[j] = counts_[i][j] + alpha0_ * beta_[j];
        }
        alphas[sizes[i]] = alpha0_ * beta_[sizes[i]];
        distributions::sample_dirichlet(rng, sizes[i]+1, alphas, new_pi);
        for (int j = 0; j < sizes[i]; j++) {
          pi_[i][j] = new_pi[i];
        }
      }
    }

    void sample_m() {
      std::vector<size_t> sizes = counts_.size();
      for (int i = 0; i < sizes.size(); i++) {
        for (int j = 0; j < sizes[i]; j++) {
          size_t n_ij = counts_[i][j];
          if (!memoized_log_stirling_.count(n_ij)) {
            memoized_log_stirling_[n_ij] = distributions::log_stirling1_row(n_ij);
          }

          std::vector<float> stirling_row = memoized_log_stirling_[n_ij];

          // there's gotta be a helper function somewhere in distributions that samples from discrete log probabilities efficiently
          std::vector<float> scores(n_ij);
          for (int m = 0; m < n_ij; m++) {
            scores[m] = stirling_row[m+1] + (m+1) * ( log( alpha0_ ) + log( beta_[j] ) );
          }
          m_[i][j] = distributions::sample_from_scores_overwrite(rng, scores) + 1;
        }
      }
    }

    void sample_beta() {
      size_t K = m_.size().size();
      float alphas[K+1];
      float new_beta[K+1];
      for (int k = 0; k < K; k++) {
        alphas[k] = m_.sum(k);
      }
      alphas[K] = gamma_;
      distributions::sample_dirichlet(rng, K+1, alphas, new_beta);
      for (int k = 0; k <= K; k++) {
        beta_[k] = new_beta[k];
      }
    }
  };

} // namespace hmm
} // namespace microscopes<commit_msg>Started sketching forward-filter-backward-sampler for state sequence<commit_after>#pragma once

#include <distributions/special.hpp>
#include <distributions/random.hpp>
#include <distributions/random_fwd.hpp>

#include <vector>
#include <map>

namespace microscopes{
namespace hmm{

  distributions::rng_t rng;

  // A class for a vector of vectors, useful for representing pretty much everything we need for the beam sampler.
  // For instance, time series data can be stored as a vector of vectors, where each vector is one time series.
  // The transition matrix can also be stored as a vector of vectors, where each transition probability is one vector.

  // Though I realize now, once I am adding-and-removing states, it might make sense to replace this with group_manager.
  template <typename T>
  class meta_vector {
  public:

    meta_vector(): data_() {}

    meta_vector(std::vector<size_t> size) : data_(size.size()) {
      for (int i = 0; i < data_.size(); i++) {
        data_[i] = std::vector<T>(size[i]);
      }
    }

    std::vector<T>& operator[](size_t i) {
      return data_[i];
    }

    std::vector<size_t> size() {
      std::vector<size_t> sizes(data_.size());
      for (std::vector<T> vec: data_) {
        sizes.push_back(vec.size());
      }
      return sizes;
    }

    T sum(size_t i) { // useful for resampling m, the number of tables serving a dish
      T result = (T)0;
      for(T t: data_[i]) {
        result += t;
      }
      return result;
    }
  protected:
    std::vector<std::vector<T> > data_;
  };

// Implementation of the beam sampler for the HDP-HMM, following van Gael 2008
  template <int N>
  class hmm {
  public:
    hmm(float gamma, float alpha0, float *H, meta_vector<size_t> data):
      gamma_(gamma),
      alpha0_(alpha0),
      H_(H),
      data_(data),
      u_(data.size()),
      beta_(),
      memoized_log_stirling_(),
      states_()
    {
    }
  protected:

    // parameters

    // these three all have the same shape as the data
    const meta_vector<size_t> data_; // XXX: For now, the observation type is just a vector of vectors of ints. Later we can switch over to using recarrays
    meta_vector<size_t> s_; // the state sequence
    meta_vector<float> u_; // the slice sampling parameter for each time step in the series

    // these three all have the same shape as the transition matrix
    meta_vector<size_t> m_; // auxilliary variable necessary for sampling beta
    meta_vector<size_t> counts_; // the count of how many times a transition occurs between states
    meta_vector<float> pi_; // the observed portion of the infinite transition matrix

    // shape is the number of states currently instantiated
    std::vector<float> beta_; // the stick lengths for the top-level DP draw

    // hyperparameters
    const float gamma_;
    const float alpha0_;
    const float H_[N]; // hyperparameters for a Dirichlet prior over observations. Will generalize this to other observation models later.

    // helper fields
    std::map<size_t, std::vector<float> > memoized_log_stirling_; // memoize computation of log stirling numbers for speed when sampling m
    std::set<size_t> states_;

    // sampling functions. later we can integrate these into microscopes::kernels where appropriate.
    void sample_s() {
      std::vector<size_t> sizes = data_.size();
      counts_();
      for (int i = 0; i < sizes.size(); i++) {
        // Forward-filter
        for (int t = 0; t < size[i]; t++) {

        }

        // Backwards-sample
        for (int t = size[i]-1; t >= 0; t--) {

        }
      }
    }

    void sample_u() {
      size_t prev_state;
      std::uniform_real_distribution<float> sampler (0.0, 1.0);
      std::vector<size_t> sizes = u_.size();
      for (int i = 0; i < sizes.size(); i++) {
        for(int j = 0; j < sizes[i]; j++) {
          if (j == 0) {
            prev_state = 0;
          } else {
            prev_state = s_[i][j-1];
          }
          u_[i][j] = sampler(rng) / (pi_[prev_state][s_[i][j]]); // scale the uniform sample to be between 0 and pi_{s_{t-1}s_t}
        }
      }
    }

    void sample_pi() {
      std::vector<size_t> sizes = u_.size();
      for (int i = 0; i < sizes.size(); i++) {
        float new_pi[sizes[i]+1];
        float alphas[sizes[i]+1];
        for (int j = 0; j < sizes[i]; j++) {
          alphas[j] = counts_[i][j] + alpha0_ * beta_[j];
        }
        alphas[sizes[i]] = alpha0_ * beta_[sizes[i]];
        distributions::sample_dirichlet(rng, sizes[i]+1, alphas, new_pi);
        for (int j = 0; j < sizes[i]; j++) {
          pi_[i][j] = new_pi[i];
        }
      }
    }

    void sample_m() {
      std::vector<size_t> sizes = counts_.size();
      for (int i = 0; i < sizes.size(); i++) {
        for (int j = 0; j < sizes[i]; j++) {
          size_t n_ij = counts_[i][j];
          if (!memoized_log_stirling_.count(n_ij)) {
            memoized_log_stirling_[n_ij] = distributions::log_stirling1_row(n_ij);
          }

          std::vector<float> stirling_row = memoized_log_stirling_[n_ij];

          // there's gotta be a helper function somewhere in distributions that samples from discrete log probabilities efficiently
          std::vector<float> scores(n_ij);
          for (int m = 0; m < n_ij; m++) {
            scores[m] = stirling_row[m+1] + (m+1) * ( log( alpha0_ ) + log( beta_[j] ) );
          }
          m_[i][j] = distributions::sample_from_scores_overwrite(rng, scores) + 1;
        }
      }
    }

    void sample_beta() {
      size_t K = m_.size().size();
      float alphas[K+1];
      float new_beta[K+1];
      for (int k = 0; k < K; k++) {
        alphas[k] = m_.sum(k);
      }
      alphas[K] = gamma_;
      distributions::sample_dirichlet(rng, K+1, alphas, new_beta);
      for (int k = 0; k <= K; k++) {
        beta_[k] = new_beta[k];
      }
    }
  };

} // namespace hmm
} // namespace microscopes<|endoftext|>


<commit_before>//********************************************************************
//*
//* Warning: This file was generated by ecore4CPP Generator
//*
//********************************************************************

#ifndef TYPESFACTORY_HPP
#define TYPESFACTORY_HPP

#include <map>
#include <memory>

#include "ecore/EFactory.hpp"
#include "types/typesPackage.hpp"

namespace types
{
	class typesPackage;
}

namespace types
{
	class typesFactory : virtual public ecore::EFactory
	{
		private:
			typesFactory(typesFactory const&) = delete;
			typesFactory& operator=(typesFactory const&) = delete;
		protected:
			typesFactory(){}

			//Singleton Instance and Getter
			private:
				static std::shared_ptr<typesFactory> instance;
			public:
				static std::shared_ptr<typesFactory> eInstance();

			//Creator functions
			virtual std::shared_ptr<ecore::EObject> create(std::string _className,  std::shared_ptr<ecore::EObject> container=nullptr, const int referenceID = -1) const = 0;
			virtual std::shared_ptr<ecore::EObject> create(const int classID,  std::shared_ptr<ecore::EObject> container = nullptr, const int referenceID = -1) const = 0;
			virtual std::shared_ptr<ecore::EObject> create(std::shared_ptr<ecore::EClass> _class, std::shared_ptr<EObject> _container=nullptr, const int referenceID = -1) const = 0;

	};
}
#endif /* end of include guard: TYPESFACTORY_HPP */
<commit_msg>[types] updated source code<commit_after>//********************************************************************
//*
//* Warning: This file was generated by ecore4CPP Generator
//*
//********************************************************************

#ifndef TYPESFACTORY_HPP
#define TYPESFACTORY_HPP

#include <map>
#include <memory>

#include "ecore/EFactory.hpp"
#include "types/typesPackage.hpp"

namespace types
{
	class typesPackage;
}

namespace types
{
	class typesFactory : virtual public ecore::EFactory
	{
		private:
			typesFactory(typesFactory const&) = delete;
			typesFactory& operator=(typesFactory const&) = delete;
		protected:
			typesFactory(){}

			//Singleton Instance and Getter
			private:
				static std::shared_ptr<typesFactory> instance;
			public:
				static std::shared_ptr<typesFactory> eInstance();

			//Creator functions
			virtual std::shared_ptr<ecore::EObject> create(std::string _className,  std::shared_ptr<ecore::EObject> container=nullptr, const int referenceID = -1) const = 0;
			virtual std::shared_ptr<ecore::EObject> create(const int classID,  std::shared_ptr<ecore::EObject> container = nullptr, const int referenceID = -1) const = 0;
			virtual std::shared_ptr<ecore::EObject> create(std::shared_ptr<ecore::EClass> _class, std::shared_ptr<EObject> _container=nullptr, const int referenceID = -1) const = 0;

	};
}
#endif /* end of include guard: TYPESFACTORY_HPP */
<|endoftext|>


<commit_before>#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/system/error_code.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/construct.hpp>

#include <libport/thread.hh>
#include <libport/lockable.hh>

namespace libport {
namespace netdetail {

  typedef ::libport::Socket::SocketFactory SocketFactory;
  class SocketImplBase: public BaseSocket, private libport::Lockable
  {
    public:
      SocketImplBase(): current_(-1), pending_(false) {}
      /// Start an asynchronous read operation.
      virtual void startReader() = 0;
    protected:
      /// Write double-buffer.
      boost::asio::streambuf buffers_[2];
      /// Read buffer.
      boost::asio::streambuf readBuffer_;
      /// Buffer id currently engaged in an async write, -1 for none
      int current_;
      /// Second buffer has data to write.
      bool pending_;
      friend class Socket;
      template<class Stream> friend class SocketImpl;
  };
  template<class Stream> class SocketImpl
    : public SocketImplBase
  {
    public:
      SocketImpl():base_(0) {}
      ~SocketImpl() { delete base_;}
      void write(const void* data, unsigned int length);
      void close();
      bool isConnected();
      template<typename Acceptor, typename BaseFactory> static void
        onAccept(Stream* s, SocketFactory fact, Acceptor *a, BaseFactory bf);
      template<typename Acceptor, typename BaseFactory> static void
        acceptOne(SocketFactory fact, Acceptor *a, BaseFactory bf);
      static BaseSocket* create(Stream* base);
      void startReader();
    private:
      Stream* base_;
      void continueWrite(DestructionLock lock, boost::system::error_code erc, size_t sz);
      void onReadDemux(DestructionLock lock, boost::system::error_code erc);
      friend class Socket;
    };

#ifndef LIBPORT_NO_SSL
  struct SSLSettings
  {
    boost::asio::ssl::context_base::method context;
    boost::asio::ssl::context::options options;
    std::string privateKeyFile;
    std::string certChainFile;
    std::string tmpDHFile;
    std::string cipherList;
  };
#endif

  // FIXME: use the delete_ptr in boost::lambda.
  template<class T> void deletor(T* ptr)
  {
    delete ptr;
  }

  inline void
  runIoService(boost::asio::io_service* io)
  {
    // Trick to have io->run() never return.
    boost::asio::io_service::work work(*io);
    io->run();
  }

  inline boost::asio::io_service&
  get_io_service()
  {
    static boost::asio::io_service* io = 0;
    if (!io)
    {
      io = new boost::asio::io_service;
      libport::startThread(boost::bind(&runIoService, io));
    }
    return *io;
  }

  template<typename Stream> void
  SocketImpl<Stream>::close()
  {
    base_->lowest_layer().close();
  }

  template<typename Stream> bool
  SocketImpl<Stream>::isConnected()
  {
    return base_->lowest_layer().is_open();
  }

  template<typename Stream> void
  SocketImpl<Stream>::write(const void* buffer, unsigned int length)
  {
    libport::BlockLock bl(this);
    std::ostream stream(&buffers_[current_==-1 ? 0:1-current_]);
    stream.write((const char*)buffer, length);
    pending_ = true;
    if (current_ == -1)
    {
      current_ = 1; // We wrote on 0, continueWrite will swap.
      continueWrite(getDestructionLock(), boost::system::error_code(), 0 );
    }
  }

  template<typename Stream> void
  SocketImpl<Stream>::continueWrite(DestructionLock lock, boost::system::error_code er, size_t sz)
  {
    if (er)
    {
      if (onErrorFunc)
	onErrorFunc(er);
      close();
      return;
    }
    libport::BlockLock bl(this);
    current_ = 1 - current_;
    if (pending_)
      boost::asio::async_write(*base_, buffers_[current_],
	  boost::bind(&SocketImpl<Stream>::continueWrite, this, lock,  _1, _2));
    else
    {
      current_ = -1;
    }
    pending_ = false;
  }

  template<typename Stream> void
  SocketImpl<Stream>::onReadDemux(DestructionLock lock, boost::system::error_code erc)
  {
    if (erc)
    {
      if (onErrorFunc)
	onErrorFunc(erc);
      close();
    }
    else
    {
      if (onReadFunc)
	onReadFunc(readBuffer_);
      if (isConnected())
	boost::asio::async_read(*base_, readBuffer_,  boost::asio::transfer_at_least(1),
	    boost::bind(&SocketImpl<Stream>::onReadDemux,this, lock, _1));
    }
  }

  template<typename Stream> void
  SocketImpl<Stream>::startReader()
  {
    boost::asio::async_read(*base_, readBuffer_,  boost::asio::transfer_at_least(1),
       	boost::bind(&SocketImpl<Stream>::onReadDemux,this, getDestructionLock(), _1));
  }

  template<typename Stream>
  template<typename Acceptor, typename BaseFactory> void
  SocketImpl<Stream>::onAccept(Stream* s, SocketFactory fact, Acceptor *a, BaseFactory bf)
  {
    SocketImplBase* wrapper = dynamic_cast<SocketImplBase*>(bf(s));
    if (!wrapper)
    { // Failure.
      delete s;
    }
    else
    {
      // This is now connected.
      Socket* s = fact();
      s->setBase(wrapper);
      // Start reading.
      wrapper->startReader();
    }
    acceptOne(fact, a, bf);
  }

  template<typename Stream>
  template<typename Acceptor, typename BaseFactory> void
  SocketImpl<Stream>::acceptOne(SocketFactory fact, Acceptor *a, BaseFactory bf)
  {
    Stream* s = new Stream(get_io_service());
    a->async_accept(*s,
	boost::bind(&SocketImpl<Stream>::template onAccept<Acceptor, BaseFactory>
	  , s, fact, a, bf));
  }

  template<typename Stream>BaseSocket*
  SocketImpl<Stream>::create(Stream*s)
  {
    SocketImpl<Stream>* bs = new SocketImpl<Stream>;
    bs->base_ = s;
    return bs;
  }

#ifndef LIBPORT_NO_SSL
  template<typename Stream>
  BaseSocket* SSLLayer(SSLSettings settings, Stream* s)
  {
    using namespace boost::asio;
    boost::system::error_code erc;
    ssl::context context(s->get_io_service(),
	boost::asio::ssl::context::sslv23_server);
    context.set_options(settings.options);
    if (!settings.cipherList.empty())
    {
      SSL_CTX* ctx = context.impl();
      if (!SSL_CTX_set_cipher_list(ctx, settings.cipherList.c_str()))
	throw std::runtime_error("SSL_CTX_set_cipher_list failed");
    }

#define comma ,
#define CHECK_CALL(param, call, args)  do \
    if (!param.empty()) { call(param, args erc); if (erc) throw erc;} while(0)

    CHECK_CALL(settings.tmpDHFile, context.use_tmp_dh_file, );
    CHECK_CALL(settings.certChainFile, context.use_certificate_chain_file, );
    CHECK_CALL(settings.privateKeyFile, context.use_private_key_file,
       	ssl::context_base::pem comma);
#undef CHECK_CALL

    // Create a SSL stream taking its underlying stream by ref.
    typedef boost::asio::ssl::stream<Stream&> SSLStream;
    SSLStream *sslStream = new SSLStream(*s, context);
    sslStream->handshake(sslStream->server, erc);
    if (erc)
    {
      delete sslStream;
      return 0;
    }
    BaseSocket* bs = SocketImpl<SSLStream>::create(sslStream);
    // s ownership is taken: mark for deletion when bs dies.
    bs->deletor << boost::bind(deletor<Stream>, s);
    return bs;
  }
#endif
} //namespace netdetail

inline void
Socket::setBase(BaseSocket* b)
{
  base_ = b;
  base_-> onReadFunc = boost::bind(&Socket::onRead_, this, _1);
  base_->onErrorFunc = boost::bind(&Socket::onError, this, _1);

}

inline bool
Socket::onRead_(boost::asio::streambuf& buf)
{
  // Dump the stream in our linear buffer
  std::istream is(&buf);
  static const int blockSize = 1024;
  while (is.good())
  {
    int oldBufferLength = buffer.length();
    buffer.resize(oldBufferLength + blockSize);
    is.read(&buffer[0] + oldBufferLength, blockSize);
    long len = is.gcount();
    buffer.resize(oldBufferLength + len);
  }
  // Call onRead until it eats 0 characters.
  int r;
  do
  {
    r = onRead(buffer.c_str(), buffer.length());
    if (r)
      buffer = buffer.substr(r, buffer.npos);
  }
  while(r && !buffer.empty());
  return true;
}

template<class Proto, class BaseFactory> boost::system::error_code
Socket::connectProto(const std::string& host, const std::string& port, BaseFactory bf)
{
  using namespace netdetail;
  boost::system::error_code erc;
  typename Proto::resolver::query query(host, port);
  typename Proto::resolver resolver(netdetail::get_io_service());
  typename Proto::resolver::iterator iter = resolver.resolve(query,erc);
  if (erc)
    return erc;
  typename Proto::socket* s = new typename Proto::socket(get_io_service());
  s->connect(*iter, erc);
  if (erc)
    return erc;
  SocketImplBase* newS = dynamic_cast<SocketImplBase*>(bf(s));
  if (!newS)
  {
    delete s;
#if BOOST_VERSION >= 103600
    return boost::system::errc::make_error_code(boost::system::errc::operation_canceled);
#else
    return boost::system::posix_error::make_error_code(boost::system::posix_error::operation_canceled);
#endif
}
  setBase(newS);
  // Start reading.
  newS->startReader();
  return erc;
}

inline boost::system::error_code
Socket::connect(const std::string& host, const std::string& port, bool udp)
{
  assert(!udp);
  /*
  if (udp)
    return connectProto<boost::asio::ip::udp>(host, port,
	&netdetail::SocketImpl<boost::asio::ip::udp::socket>::create);
  else
  */
    return connectProto<boost::asio::ip::tcp>(host, port,
	&netdetail::SocketImpl<boost::asio::ip::tcp::socket>::create);
}

template<typename Proto, typename BaseFactory> boost::system::error_code
Socket::listenProto(SocketFactory f, const std::string& host,
    const std::string& port, BaseFactory bf)
{
  boost::system::error_code erc;
  typename Proto::resolver::query query(host, port);
  typename Proto::resolver resolver(netdetail::get_io_service());
  typename Proto::resolver::iterator iter = resolver.resolve(query, erc);
  if (erc)
    return erc;
  typename Proto::acceptor* a = new typename Proto::acceptor(netdetail::get_io_service(), *iter);
  netdetail::SocketImpl<typename Proto::socket>::acceptOne(f, a, bf);
  return erc;
}

inline Socket::Handle
Socket::listen(SocketFactory f, const std::string& host,
    const std::string& port, boost::system::error_code & erc, bool udp)
{
  assert(!udp);
  erc = Socket::listenProto<boost::asio::ip::tcp>(f, host, port,
      &netdetail::SocketImpl<boost::asio::ip::tcp::socket>::create);
  return Handle();
}

#ifndef LIBPORT_NO_SSL
inline Socket::Handle
Socket::listenSSL(SocketFactory f, const std::string& host, const std::string&  port,
    boost::system::error_code& erc,
    boost::asio::ssl::context_base::method ctx,
    boost::asio::ssl::context::options options,
    const std::string& privateKeyFile,
    const std::string& certChainFile,
    const std::string& tmpDHFile,
    const std::string& cipherList)
{
  netdetail::SSLSettings settings;
  settings.context = ctx;
  settings.options = options;
  settings.privateKeyFile = privateKeyFile;
  settings.certChainFile = certChainFile;
  settings.tmpDHFile = tmpDHFile;
  settings.cipherList = cipherList;
  erc = Socket::listenProto<boost::asio::ip::tcp>(f, host, port,
      (boost::function1<BaseSocket*, boost::asio::ip::tcp::socket*>)boost::bind(&netdetail::SSLLayer<boost::asio::ip::tcp::socket>, settings, _1));
  return Handle();
}
#endif

inline
Socket::~Socket()
{
  close();
  base_->destroy();
  base_->onReadFunc = 0;
  base_->onErrorFunc = 0;
  base_ = 0;
}

inline void
Socket::destroy()
{
  close();
  AsioDestructible::destroy();
}

inline void
AsioDestructible::doDestroy()
{
  netdetail::get_io_service().post(boost::bind(
	netdetail::deletor<AsioDestructible>, this));
}

}
<commit_msg>Fix compilation warnings.<commit_after>#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/system/error_code.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/construct.hpp>

#include <libport/thread.hh>
#include <libport/lockable.hh>

namespace libport {
namespace netdetail {

  typedef ::libport::Socket::SocketFactory SocketFactory;
  class SocketImplBase: public BaseSocket, private libport::Lockable
  {
    public:
      SocketImplBase(): current_(-1), pending_(false) {}
      /// Start an asynchronous read operation.
      virtual void startReader() = 0;
    protected:
      /// Write double-buffer.
      boost::asio::streambuf buffers_[2];
      /// Read buffer.
      boost::asio::streambuf readBuffer_;
      /// Buffer id currently engaged in an async write, -1 for none
      int current_;
      /// Second buffer has data to write.
      bool pending_;
      friend class Socket;
      template<class Stream> friend class SocketImpl;
  };
  template<class Stream> class SocketImpl
    : public SocketImplBase
  {
    public:
      SocketImpl():base_(0) {}
      ~SocketImpl() { delete base_;}
      void write(const void* data, unsigned int length);
      void close();
      bool isConnected();
      template<typename Acceptor, typename BaseFactory> static void
        onAccept(Stream* s, SocketFactory fact, Acceptor *a, BaseFactory bf);
      template<typename Acceptor, typename BaseFactory> static void
        acceptOne(SocketFactory fact, Acceptor *a, BaseFactory bf);
      static BaseSocket* create(Stream* base);
      void startReader();
    private:
      Stream* base_;
      void continueWrite(DestructionLock lock, boost::system::error_code erc, size_t sz);
      void onReadDemux(DestructionLock lock, boost::system::error_code erc);
      friend class Socket;
    };

#ifndef LIBPORT_NO_SSL
  struct SSLSettings
  {
    boost::asio::ssl::context_base::method context;
    boost::asio::ssl::context::options options;
    std::string privateKeyFile;
    std::string certChainFile;
    std::string tmpDHFile;
    std::string cipherList;
  };
#endif

  // FIXME: use the delete_ptr in boost::lambda.
  template<class T> void deletor(T* ptr)
  {
    delete ptr;
  }

  inline void
  runIoService(boost::asio::io_service* io)
  {
    // Trick to have io->run() never return.
    boost::asio::io_service::work work(*io);
    io->run();
  }

  inline boost::asio::io_service&
  get_io_service()
  {
    static boost::asio::io_service* io = 0;
    if (!io)
    {
      io = new boost::asio::io_service;
      libport::startThread(boost::bind(&runIoService, io));
    }
    return *io;
  }

  template<typename Stream> void
  SocketImpl<Stream>::close()
  {
    base_->lowest_layer().close();
  }

  template<typename Stream> bool
  SocketImpl<Stream>::isConnected()
  {
    return base_->lowest_layer().is_open();
  }

  template<typename Stream> void
  SocketImpl<Stream>::write(const void* buffer, unsigned int length)
  {
    libport::BlockLock bl(this);
    std::ostream stream(&buffers_[current_==-1 ? 0:1-current_]);
    stream.write((const char*)buffer, length);
    pending_ = true;
    if (current_ == -1)
    {
      current_ = 1; // We wrote on 0, continueWrite will swap.
      continueWrite(getDestructionLock(), boost::system::error_code(), 0 );
    }
  }

  template<typename Stream> void
  SocketImpl<Stream>::continueWrite(DestructionLock lock, boost::system::error_code er, size_t)
  {
    if (er)
    {
      if (onErrorFunc)
	onErrorFunc(er);
      close();
      return;
    }
    libport::BlockLock bl(this);
    current_ = 1 - current_;
    if (pending_)
      boost::asio::async_write(*base_, buffers_[current_],
	  boost::bind(&SocketImpl<Stream>::continueWrite, this, lock,  _1, _2));
    else
    {
      current_ = -1;
    }
    pending_ = false;
  }

  template<typename Stream> void
  SocketImpl<Stream>::onReadDemux(DestructionLock lock, boost::system::error_code erc)
  {
    if (erc)
    {
      if (onErrorFunc)
	onErrorFunc(erc);
      close();
    }
    else
    {
      if (onReadFunc)
	onReadFunc(readBuffer_);
      if (isConnected())
	boost::asio::async_read(*base_, readBuffer_,  boost::asio::transfer_at_least(1),
	    boost::bind(&SocketImpl<Stream>::onReadDemux,this, lock, _1));
    }
  }

  template<typename Stream> void
  SocketImpl<Stream>::startReader()
  {
    boost::asio::async_read(*base_, readBuffer_,  boost::asio::transfer_at_least(1),
       	boost::bind(&SocketImpl<Stream>::onReadDemux,this, getDestructionLock(), _1));
  }

  template<typename Stream>
  template<typename Acceptor, typename BaseFactory> void
  SocketImpl<Stream>::onAccept(Stream* s, SocketFactory fact, Acceptor *a, BaseFactory bf)
  {
    SocketImplBase* wrapper = dynamic_cast<SocketImplBase*>(bf(s));
    if (!wrapper)
    { // Failure.
      delete s;
    }
    else
    {
      // This is now connected.
      Socket* s = fact();
      s->setBase(wrapper);
      // Start reading.
      wrapper->startReader();
    }
    acceptOne(fact, a, bf);
  }

  template<typename Stream>
  template<typename Acceptor, typename BaseFactory> void
  SocketImpl<Stream>::acceptOne(SocketFactory fact, Acceptor *a, BaseFactory bf)
  {
    Stream* s = new Stream(get_io_service());
    a->async_accept(*s,
	boost::bind(&SocketImpl<Stream>::template onAccept<Acceptor, BaseFactory>
	  , s, fact, a, bf));
  }

  template<typename Stream>BaseSocket*
  SocketImpl<Stream>::create(Stream*s)
  {
    SocketImpl<Stream>* bs = new SocketImpl<Stream>;
    bs->base_ = s;
    return bs;
  }

#ifndef LIBPORT_NO_SSL
  template<typename Stream>
  BaseSocket* SSLLayer(SSLSettings settings, Stream* s)
  {
    using namespace boost::asio;
    boost::system::error_code erc;
    ssl::context context(s->get_io_service(),
	boost::asio::ssl::context::sslv23_server);
    context.set_options(settings.options);
    if (!settings.cipherList.empty())
    {
      SSL_CTX* ctx = context.impl();
      if (!SSL_CTX_set_cipher_list(ctx, settings.cipherList.c_str()))
	throw std::runtime_error("SSL_CTX_set_cipher_list failed");
    }

#define comma ,
#define CHECK_CALL(param, call, args)  do \
    if (!param.empty()) { call(param, args erc); if (erc) throw erc;} while(0)

    CHECK_CALL(settings.tmpDHFile, context.use_tmp_dh_file, );
    CHECK_CALL(settings.certChainFile, context.use_certificate_chain_file, );
    CHECK_CALL(settings.privateKeyFile, context.use_private_key_file,
       	ssl::context_base::pem comma);
#undef CHECK_CALL

    // Create a SSL stream taking its underlying stream by ref.
    typedef boost::asio::ssl::stream<Stream&> SSLStream;
    SSLStream *sslStream = new SSLStream(*s, context);
    sslStream->handshake(sslStream->server, erc);
    if (erc)
    {
      delete sslStream;
      return 0;
    }
    BaseSocket* bs = SocketImpl<SSLStream>::create(sslStream);
    // s ownership is taken: mark for deletion when bs dies.
    bs->deletor << boost::bind(deletor<Stream>, s);
    return bs;
  }
#endif
} //namespace netdetail

inline void
Socket::setBase(BaseSocket* b)
{
  base_ = b;
  base_-> onReadFunc = boost::bind(&Socket::onRead_, this, _1);
  base_->onErrorFunc = boost::bind(&Socket::onError, this, _1);

}

inline bool
Socket::onRead_(boost::asio::streambuf& buf)
{
  // Dump the stream in our linear buffer
  std::istream is(&buf);
  static const int blockSize = 1024;
  while (is.good())
  {
    int oldBufferLength = buffer.length();
    buffer.resize(oldBufferLength + blockSize);
    is.read(&buffer[0] + oldBufferLength, blockSize);
    long len = is.gcount();
    buffer.resize(oldBufferLength + len);
  }
  // Call onRead until it eats 0 characters.
  int r;
  do
  {
    r = onRead(buffer.c_str(), buffer.length());
    if (r)
      buffer = buffer.substr(r, buffer.npos);
  }
  while(r && !buffer.empty());
  return true;
}

template<class Proto, class BaseFactory> boost::system::error_code
Socket::connectProto(const std::string& host, const std::string& port, BaseFactory bf)
{
  using namespace netdetail;
  boost::system::error_code erc;
  typename Proto::resolver::query query(host, port);
  typename Proto::resolver resolver(netdetail::get_io_service());
  typename Proto::resolver::iterator iter = resolver.resolve(query,erc);
  if (erc)
    return erc;
  typename Proto::socket* s = new typename Proto::socket(get_io_service());
  s->connect(*iter, erc);
  if (erc)
    return erc;
  SocketImplBase* newS = dynamic_cast<SocketImplBase*>(bf(s));
  if (!newS)
  {
    delete s;
#if BOOST_VERSION >= 103600
    return boost::system::errc::make_error_code(boost::system::errc::operation_canceled);
#else
    return boost::system::posix_error::make_error_code(boost::system::posix_error::operation_canceled);
#endif
}
  setBase(newS);
  // Start reading.
  newS->startReader();
  return erc;
}

inline boost::system::error_code
Socket::connect(const std::string& host, const std::string& port, bool udp)
{
  (void)udp;
  assert(!udp);
  /*
  if (udp)
    return connectProto<boost::asio::ip::udp>(host, port,
	&netdetail::SocketImpl<boost::asio::ip::udp::socket>::create);
  else
  */
    return connectProto<boost::asio::ip::tcp>(host, port,
	&netdetail::SocketImpl<boost::asio::ip::tcp::socket>::create);
}

template<typename Proto, typename BaseFactory> boost::system::error_code
Socket::listenProto(SocketFactory f, const std::string& host,
    const std::string& port, BaseFactory bf)
{
  boost::system::error_code erc;
  typename Proto::resolver::query query(host, port);
  typename Proto::resolver resolver(netdetail::get_io_service());
  typename Proto::resolver::iterator iter = resolver.resolve(query, erc);
  if (erc)
    return erc;
  typename Proto::acceptor* a = new typename Proto::acceptor(netdetail::get_io_service(), *iter);
  netdetail::SocketImpl<typename Proto::socket>::acceptOne(f, a, bf);
  return erc;
}

inline Socket::Handle
Socket::listen(SocketFactory f, const std::string& host,
    const std::string& port, boost::system::error_code & erc, bool udp)
{
  (void)udp;
  assert(!udp);
  erc = Socket::listenProto<boost::asio::ip::tcp>(f, host, port,
      &netdetail::SocketImpl<boost::asio::ip::tcp::socket>::create);
  return Handle();
}

#ifndef LIBPORT_NO_SSL
inline Socket::Handle
Socket::listenSSL(SocketFactory f, const std::string& host, const std::string&  port,
    boost::system::error_code& erc,
    boost::asio::ssl::context_base::method ctx,
    boost::asio::ssl::context::options options,
    const std::string& privateKeyFile,
    const std::string& certChainFile,
    const std::string& tmpDHFile,
    const std::string& cipherList)
{
  netdetail::SSLSettings settings;
  settings.context = ctx;
  settings.options = options;
  settings.privateKeyFile = privateKeyFile;
  settings.certChainFile = certChainFile;
  settings.tmpDHFile = tmpDHFile;
  settings.cipherList = cipherList;
  erc = Socket::listenProto<boost::asio::ip::tcp>(f, host, port,
      (boost::function1<BaseSocket*, boost::asio::ip::tcp::socket*>)boost::bind(&netdetail::SSLLayer<boost::asio::ip::tcp::socket>, settings, _1));
  return Handle();
}
#endif

inline
Socket::~Socket()
{
  close();
  base_->destroy();
  base_->onReadFunc = 0;
  base_->onErrorFunc = 0;
  base_ = 0;
}

inline void
Socket::destroy()
{
  close();
  AsioDestructible::destroy();
}

inline void
AsioDestructible::doDestroy()
{
  netdetail::get_io_service().post(boost::bind(
	netdetail::deletor<AsioDestructible>, this));
}

}
<|endoftext|>