<commit_before>/*
*/

#include "lidar_fake_perception.h"

LidarFakePerception::LidarFakePerception() : nh_(), private_nh_("~")
{
  private_nh_.param<bool>("publish_object", publish_object_, true);
  private_nh_.param<bool>("publish_points", publish_points_, true);
  private_nh_.param<double>("publish_rate", publish_rate_, 10.0);

  private_nh_.param<double>("object_length", object_length_, 5.0);
  private_nh_.param<double>("object_width", object_width_, 2.0);
  private_nh_.param<double>("object_height", object_height_, 2.0);
  private_nh_.param<double>("object_z_offset", object_z_offset_, 0.0);

  private_nh_.param<bool>("use_fake_twist", use_fake_twist_, false);
  private_nh_.param<double>("object_velocity", object_velocity_, 3.0);
  private_nh_.param<double>("object_angular_velocity", object_angular_velocity_, 0.0);

  private_nh_.param<double>("object_intensity", object_intensity_, 100.0);
  private_nh_.param<double>("object_lifetime", object_lifetime_, -1);
  private_nh_.param<double>("object_points_space", object_points_space_, 0.2);

  private_nh_.param<std::string>("object_label", object_label_, "Stable");
  private_nh_.param<std::string>("object_frame", object_frame_, "velodyne");

  object_initial_pose_sub_ = nh_.subscribe("/move_base_simple/goal", 1, &LidarFakePerception::objectInitialPoseCallback, this);
  real_objects_sub_ = nh_.subscribe("/detected_objects", 1, &LidarFakePerception::objectsCallback, this);
  real_points_sub_ = nh_.subscribe("/points_raw", 1, &LidarFakePerception::pointsCallback, this);
  fake_twist_sub_ = nh_.subscribe("/fake_twist", 1, &LidarFakePerception::twistCallback, this);

  fake_objects_pub_ = nh_.advertise<autoware_msgs::DetectedObjectArray>("/fake_objects", 1);
  fake_points_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("/fake_points", 1);

  fake_object_id_ = 0;  // overwritten by real object ids
  global_frame_ = "world";  // overwritten by object initial pose

  fake_object_pose_initialized_ = false;
}

LidarFakePerception::~LidarFakePerception()
{
}

void LidarFakePerception::run()
{
  ros::Rate rate(publish_rate_);

  while (ros::ok())
  {
    ros::spinOnce();
    updateFakes();
    publishFakes();
    rate.sleep();
  }
}

void LidarFakePerception::objectInitialPoseCallback(const geometry_msgs::PoseStampedConstPtr& msg)
{
  global_frame_ = msg->header.frame_id;
  fake_object_initial_time_ = msg->header.stamp;

  tf::poseMsgToTF(msg->pose, fake_object_pose_);

  fake_object_pose_initialized_ = true;
}

void LidarFakePerception::objectsCallback(const autoware_msgs::DetectedObjectArray& msg)
{
  real_objects_ = msg;
}

void LidarFakePerception::pointsCallback(const sensor_msgs::PointCloud2& msg)
{
  pcl::fromROSMsg(msg, real_points_);
}

void LidarFakePerception::twistCallback(const geometry_msgs::Twist& msg)
{
  fake_object_twist_ = msg;
}

void LidarFakePerception::updateFakes()
{
  // update objects
  fake_objects_.objects.clear();
  fake_points_.clear();

  if (real_objects_.objects.size() != 0)
  {
    fake_objects_.objects.resize(real_objects_.objects.size());
    std::copy(real_objects_.objects.begin(), real_objects_.objects.end(), fake_objects_.objects.begin());
    fake_object_id_ = (real_objects_.objects.end()-1)->id + 1;  // using incremented id
  }

  if (real_points_.size() != 0)
  {
    fake_points_.resize(real_points_.size());
    std::copy(real_points_.begin(), real_points_.end(), fake_points_.begin());
  }

  if (fake_object_pose_initialized_)
  {
    if (updateFakeObject())
    {
      updateFakePoints();
    }
  }
}

bool LidarFakePerception::updateFakeObject()
{
  // check lifetime
  if (object_lifetime_ > 0)
  {
    if ((ros::Time::now() - fake_object_initial_time_).toSec() > object_lifetime_)
    {
      return false;
    }
  }

  // world -> sensor frame
  tf::StampedTransform global2local;
  try
  {
    tf_listener_.waitForTransform(global_frame_, object_frame_, ros::Time(0), ros::Duration(1.0));
    tf_listener_.lookupTransform(global_frame_, object_frame_, ros::Time(0), global2local);
  }
  catch (tf::TransformException ex)
  {
    ROS_ERROR("%s", ex.what());
    return false;
  }

  // update pose
  if (use_fake_twist_)
  {
    // update pose by subscribed twist
    updatePose(1./publish_rate_, fake_object_twist_, fake_object_pose_);
  }
  else
  {
    // update pose by rosparam
    geometry_msgs::Twist twist;
    twist.linear.x = object_velocity_;
    twist.angular.z = object_angular_velocity_;
    updatePose(1./publish_rate_, twist, fake_object_pose_);
  }

  // fix height
  tf::Vector3 objpos = fake_object_pose_.getOrigin();
  fake_object_pose_.setOrigin(tf::Vector3(objpos.x(), objpos.y(), object_z_offset_+ object_height_/2.));

  // update msg
  fake_object_.header.stamp = ros::Time::now();
  fake_object_.header.frame_id = object_frame_;
  fake_object_.id = fake_object_id_;
  fake_object_.label = object_label_;
  fake_object_.dimensions.x = object_length_;
  fake_object_.dimensions.y = object_width_;
  fake_object_.dimensions.z = object_height_;
  fake_object_.velocity.linear.x = object_velocity_;
  fake_object_.velocity.angular.z = object_angular_velocity_;
  tf::poseTFToMsg(global2local.inverse() * fake_object_pose_, fake_object_.pose); // local
  fake_objects_.objects.push_back(fake_object_);

  // debug
  double r, p, y;
  (global2local.inverse()*fake_object_pose_).getBasis().getRPY(r, p, y);
  fake_object_.velocity.linear.y = y;

  return true;
}

void LidarFakePerception::updatePose(const double& dt, const geometry_msgs::Twist& twist, tf::Transform& tf)
{
  // update pose by constant velocity model
  tf::Transform dpose;
  tf::Quaternion dquat;
  dpose.setOrigin(tf::Vector3(twist.linear.x*dt, twist.linear.y*dt, twist.linear.z*dt));
  dquat.setRPY(twist.angular.x*dt, twist.angular.y*dt, twist.angular.z*dt);
  dpose.setRotation(dquat);
  fake_object_pose_ *= dpose; // transform
}

void LidarFakePerception::updateFakePoints()
{
  PointCloudT points;
  convertObjectToPoints(fake_object_, points);
  fake_points_ += points;
  fake_points_.header = pcl_conversions::toPCL(fake_object_.header);
}

void LidarFakePerception::convertObjectToPoints(const autoware_msgs::DetectedObject& obj, PointCloudT& points)
{
  points.clear();

  double hl = object_length_ / 2.0;
  double hw = object_width_ / 2.0;
  double hh = object_height_ / 2.0;

  for (double x = -hl; x <= hl; x += object_points_space_)
  {
    for (double y = -hw; y <= hw; y += object_points_space_)
    {
      for (double z = -hh; z <= hh; z += object_points_space_)
      {
        PointT point;
        point.x = x;
        point.y = y;
        point.z = z;
        point.intensity = object_intensity_;
        points.push_back(point);
      }
    }
  }

  tf::Transform trans_tf;
  Eigen::Affine3d trans_eigen;
  tf::poseMsgToTF(obj.pose, trans_tf);
  tf::poseTFToEigen(trans_tf, trans_eigen);
  pcl::transformPointCloud(points, points, trans_eigen);
}

void LidarFakePerception::publishFakes()
{
  if (fake_objects_.objects.size() == 0)  // publish empty
  {
    fake_objects_.header.frame_id = global_frame_;
    fake_objects_.header.stamp = ros::Time::now();
  }

  if (fake_points_.size() != 0)  // publish empty
  {
    fake_points_.header = pcl_conversions::toPCL(fake_object_.header);
  }

  if (publish_object_)
  {
    fake_objects_pub_.publish(fake_objects_);
  }

  if (publish_points_)
  {
    fake_points_pub_.publish(fake_points_);
  }
}
<commit_msg>Fix object velocity/acceleration, pointcloud<commit_after>/*
*/

#include "lidar_fake_perception.h"

LidarFakePerception::LidarFakePerception() : nh_(), private_nh_("~")
{
  private_nh_.param<bool>("publish_object", publish_object_, true);
  private_nh_.param<bool>("publish_points", publish_points_, true);
  private_nh_.param<double>("publish_rate", publish_rate_, 10.0);

  private_nh_.param<double>("object_length", object_length_, 5.0);
  private_nh_.param<double>("object_width", object_width_, 2.0);
  private_nh_.param<double>("object_height", object_height_, 2.0);
  private_nh_.param<double>("object_z_offset", object_z_offset_, 0.0);

  private_nh_.param<bool>("use_fake_twist", use_fake_twist_, false);
  private_nh_.param<double>("object_velocity", object_velocity_, 3.0);
  private_nh_.param<double>("object_angular_velocity", object_angular_velocity_, 0.0);

  private_nh_.param<double>("object_intensity", object_intensity_, 100.0);
  private_nh_.param<double>("object_lifetime", object_lifetime_, -1);
  private_nh_.param<double>("object_points_space", object_points_space_, 0.2);

  private_nh_.param<std::string>("object_label", object_label_, "Stable");
  private_nh_.param<std::string>("object_frame", object_frame_, "velodyne");

  object_initial_pose_sub_ = nh_.subscribe("/move_base_simple/goal", 1, &LidarFakePerception::objectInitialPoseCallback, this);
  real_objects_sub_ = nh_.subscribe("/detected_objects", 1, &LidarFakePerception::objectsCallback, this);
  real_points_sub_ = nh_.subscribe("/points_raw", 1, &LidarFakePerception::pointsCallback, this);
  fake_twist_sub_ = nh_.subscribe("/fake_twist", 1, &LidarFakePerception::twistCallback, this);

  fake_objects_pub_ = nh_.advertise<autoware_msgs::DetectedObjectArray>("/fake_objects", 1);
  fake_points_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("/fake_points", 1);

  fake_object_id_ = 0;  // overwritten by real object ids
  global_frame_ = "world";  // overwritten by object initial pose

  fake_object_pose_initialized_ = false;
}

LidarFakePerception::~LidarFakePerception()
{
}

void LidarFakePerception::run()
{
  ros::Rate rate(publish_rate_);

  while (ros::ok())
  {
    ros::spinOnce();
    updateFakes();
    publishFakes();
    rate.sleep();
  }
}

void LidarFakePerception::objectInitialPoseCallback(const geometry_msgs::PoseStampedConstPtr& msg)
{
  global_frame_ = msg->header.frame_id;
  fake_object_initial_time_ = msg->header.stamp;

  tf::poseMsgToTF(msg->pose, fake_object_pose_);

  fake_object_pose_initialized_ = true;
}

void LidarFakePerception::objectsCallback(const autoware_msgs::DetectedObjectArray& msg)
{
  real_objects_ = msg;
}

void LidarFakePerception::pointsCallback(const sensor_msgs::PointCloud2& msg)
{
  pcl::fromROSMsg(msg, real_points_);
}

void LidarFakePerception::twistCallback(const geometry_msgs::Twist& msg)
{
  fake_object_twist_ = msg;
}

void LidarFakePerception::updateFakes()
{
  // update objects
  fake_objects_.objects.clear();
  fake_points_.clear();

  if (real_objects_.objects.size() != 0)
  {
    fake_objects_.objects.resize(real_objects_.objects.size());
    std::copy(real_objects_.objects.begin(), real_objects_.objects.end(), fake_objects_.objects.begin());
    fake_object_id_ = (real_objects_.objects.end()-1)->id + 1;  // using incremented id
  }

  if (real_points_.size() != 0)
  {
    fake_points_.resize(real_points_.size());
    std::copy(real_points_.begin(), real_points_.end(), fake_points_.begin());
  }

  if (fake_object_pose_initialized_)
  {
    if (updateFakeObject())
    {
      updateFakePoints();
      fake_objects_.objects.push_back(fake_object_);
    }
  }
}

bool LidarFakePerception::updateFakeObject()
{
  // check lifetime
  if (object_lifetime_ > 0)
  {
    if ((ros::Time::now() - fake_object_initial_time_).toSec() > object_lifetime_)
    {
      return false;
    }
  }

  // obtain world -> sensor frame
  tf::StampedTransform global2local;
  try
  {
    tf_listener_.waitForTransform(global_frame_, object_frame_, ros::Time(0), ros::Duration(1.0));
    tf_listener_.lookupTransform(global_frame_, object_frame_, ros::Time(0), global2local);
  }
  catch (tf::TransformException ex)
  {
    ROS_ERROR("%s", ex.what());
    return false;
  }

  // update pose
  geometry_msgs::Twist twist;
  if (use_fake_twist_)
  {
    // update pose by subscribed twist
    twist = fake_object_twist_;
  }
  else
  {
    // update pose by rosparam
    twist.linear.x = object_velocity_;
    twist.angular.z = object_angular_velocity_;

  }
  updatePose(1./publish_rate_, twist, fake_object_pose_);

  // fix height
  tf::Vector3 objpos = fake_object_pose_.getOrigin();
  fake_object_pose_.setOrigin(tf::Vector3(objpos.x(), objpos.y(), object_z_offset_+ object_height_/2.));

  // update msg
  fake_object_.header.stamp = ros::Time::now();
  fake_object_.header.frame_id = object_frame_;
  fake_object_.id = fake_object_id_;
  fake_object_.label = object_label_;
  fake_object_.dimensions.x = object_length_;
  fake_object_.dimensions.y = object_width_;
  fake_object_.dimensions.z = object_height_;
  fake_object_.velocity = twist;
  fake_object_.acceleration = geometry_msgs::Twist();  // NOTE: by constant velocity model
  tf::poseTFToMsg(global2local.inverse() * fake_object_pose_, fake_object_.pose); // local

  // debug
  double r, p, y;
  (global2local.inverse()*fake_object_pose_).getBasis().getRPY(r, p, y);
  fake_object_.velocity.linear.y = y;

  return true;
}

void LidarFakePerception::updatePose(const double& dt, const geometry_msgs::Twist& twist, tf::Transform& tf)
{
  // update pose by constant velocity model
  tf::Transform dpose;
  tf::Quaternion dquat;
  dpose.setOrigin(tf::Vector3(twist.linear.x*dt, twist.linear.y*dt, twist.linear.z*dt));
  dquat.setRPY(twist.angular.x*dt, twist.angular.y*dt, twist.angular.z*dt);
  dpose.setRotation(dquat);
  fake_object_pose_ *= dpose; // transform
}

void LidarFakePerception::updateFakePoints()
{
  PointCloudT points;
  convertObjectToPoints(fake_object_, points);
  fake_points_ += points;
  fake_points_.header = pcl_conversions::toPCL(fake_object_.header);
  pcl::toROSMsg(fake_points_, fake_object_.pointcloud);
}

void LidarFakePerception::convertObjectToPoints(const autoware_msgs::DetectedObject& obj, PointCloudT& points)
{
  points.clear();

  double hl = object_length_ / 2.0;
  double hw = object_width_ / 2.0;
  double hh = object_height_ / 2.0;

  for (double x = -hl; x <= hl; x += object_points_space_)
  {
    for (double y = -hw; y <= hw; y += object_points_space_)
    {
      for (double z = -hh; z <= hh; z += object_points_space_)
      {
        PointT point;
        point.x = x;
        point.y = y;
        point.z = z;
        point.intensity = object_intensity_;
        points.push_back(point);
      }
    }
  }

  tf::Transform trans_tf;
  Eigen::Affine3d trans_eigen;
  tf::poseMsgToTF(obj.pose, trans_tf);
  tf::poseTFToEigen(trans_tf, trans_eigen);
  pcl::transformPointCloud(points, points, trans_eigen);
}

void LidarFakePerception::publishFakes()
{
  if (fake_objects_.objects.size() == 0)  // publish empty
  {
    fake_objects_.header.frame_id = global_frame_;
    fake_objects_.header.stamp = ros::Time::now();
  }

  if (fake_points_.size() != 0)  // publish empty
  {
    fake_points_.header = pcl_conversions::toPCL(fake_object_.header);
  }

  if (publish_object_)
  {
    fake_objects_pub_.publish(fake_objects_);
  }

  if (publish_points_)
  {
    fake_points_pub_.publish(fake_points_);
  }
}
<|endoftext|>


<commit_before>/*
* This example solves an axial bar extension problem. It is based on the
* example of the same name in the MAST source repository.
* (examples/structural/bar_extension).
*/

// C/C++ includes.
#include <iostream>

// libMesh includes.
#include <libmesh/libmesh.h>
#include <libmesh/replicated_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/equation_systems.h>
#include <libmesh/fe_type.h>
#include <libmesh/numeric_vector.h>

// MAST includes.
#include "base/nonlinear_system.h"
#include "elasticity/structural_system_initialization.h"
#include "base/physics_discipline_base.h"
#include "boundary_condition/dirichlet_boundary_condition.h"
#include "base/parameter.h"
#include "base/constant_field_function.h"
#include "property_cards/isotropic_material_property_card.h"
#include "property_cards/solid_1d_section_element_property_card.h"
#include "base/nonlinear_implicit_assembly.h"
#include "elasticity/structural_nonlinear_assembly.h"

int main(int argc, const char** argv)
{
    // Initialize libMesh library.
    libMesh::LibMeshInit init(argc, argv);

    // Create Mesh object on default MPI communicator and generate a line mesh (5 elements, 10 units long).
    //   Note that in libMesh, all meshes are parallel by default in the sense that the equations on the mesh are solved in parallel by PETSc.
    //   A "ReplicatedMesh" is one where all MPI processes have the full mesh in memory, as compared to a "DistributedMesh" where the mesh is
    //   "chunked" up and distributed across processes, each having their own piece.
    libMesh::ReplicatedMesh mesh(init.comm());
    libMesh::MeshTools::Generation::build_line(mesh, 5, 0.0, 10.0);
    mesh.print_info();
    mesh.boundary_info->print_info();

    // Create EquationSystems object, which is a container for multiple systems of equations that are defined on a given mesh.
    libMesh::EquationSystems equation_systems(mesh);

    // Add system of type MAST::NonlinearSystem (which wraps libMesh::NonlinearImplicitSystem) to the EquationSystems container.
    //   We name the system "structural" and also get a reference to the system so we can easily reference it later.
    MAST::NonlinearSystem & system = equation_systems.add_system<MAST::NonlinearSystem>("structural");

    // Create a finite element type for the system. Here we use first order
    // Lagrangian-type finite elements.
    libMesh::FEType fetype(libMesh::FIRST, libMesh::LAGRANGE);

    // Initialize the system to the correct set of variables for a structural
    // analysis. In libMesh this is analogous to adding variables (each with
    // specific finite element type/order to the system for a particular
    // system of equations.
    MAST::StructuralSystemInitialization structural_system(system,
                                                           system.name(),
                                                           fetype);

    // Initialize a new structural discipline using equation_systems.
    MAST::PhysicsDisciplineBase discipline(equation_systems);

    // Create and add boundary conditions to the structural system. A Dirichlet BC fixes the left end of the bar.
    // This definition uses the numbering created by the libMesh mesh generation function.
    MAST::DirichletBoundaryCondition dirichlet_bc;
    dirichlet_bc.init(0, structural_system.vars());
    discipline.add_dirichlet_bc(0, dirichlet_bc);
    discipline.init_system_dirichlet_bc(system);

// Initialize the equation system since we now know the size of our
    // system matrices (based on mesh, element type, variables in the
    // structural_system) as well as the setup of dirichlet boundary conditions.
    // This initialization process is basically a pre-processing step to
    // preallocate storage and spread it across processors.
    equation_systems.init();
    equation_systems.print_info();

    // Create parameters.
    MAST::Parameter thickness_y("thy", 0.06);
    MAST::Parameter thickness_z("thz", 0.02);
    MAST::Parameter E("E", 72.0e9);
    MAST::Parameter nu("nu", 0.33);
    MAST::Parameter zero("zero", 0.0);
    MAST::Parameter pressure("p", 2.0e4);

    // Create ConstantFieldFunctions used to spread parameters throughout the model.
    MAST::ConstantFieldFunction thy_f("hy", thickness_y);
    MAST::ConstantFieldFunction thz_f("hz", thickness_z);
    MAST::ConstantFieldFunction E_f("E", E);
    MAST::ConstantFieldFunction nu_f("nu", nu);
    MAST::ConstantFieldFunction hyoff_f("hy_off", zero);
    MAST::ConstantFieldFunction hzoff_f("hz_off", zero);
    MAST::ConstantFieldFunction pressure_f("pressure", pressure);

    // Initialize load.
    // TODO - Switch this to a concentrated/point load on the right end of the bar.
    MAST::BoundaryConditionBase right_end_pressure(MAST::SURFACE_PRESSURE);
    right_end_pressure.add(pressure_f);
    discipline.add_side_load(1, right_end_pressure);

    // Create the material property card ("card" is NASTRAN lingo) and the relevant parameters to it. An isotropic
    // material needs elastic modulus (E) and Poisson ratio (nu) to describe its behavior.
    MAST::IsotropicMaterialPropertyCard material;
    material.add(E_f);
    material.add(nu_f);

    // Create the section property card. Attach all property values.
    MAST::Solid1DSectionElementPropertyCard section;
    section.add(thy_f);
    section.add(thz_f);
    section.add(hyoff_f);
    section.add(hzoff_f);

    // Specify a section orientation point and add it to the section.
    libMesh::Point orientation;
    orientation(1) = 1.0;
    section.y_vector() = orientation;

    // Attach material to the card.
    section.set_material(material);

    // Initialize the section and specify the subdomain in the mesh that it applies to.
    section.init();
    discipline.set_property_for_subdomain(0, section);

    // Create nonlinear assembly object and set the discipline and
    // structural_system. Create reference to system.

    MAST::NonlinearImplicitAssembly assembly;
    MAST::StructuralNonlinearAssemblyElemOperations elem_ops;
    assembly.set_discipline_and_system(discipline, structural_system);
    elem_ops.set_discipline_and_system(discipline, structural_system);
    MAST::NonlinearSystem& nonlinear_system = assembly.system();

    // Zero the solution before solving.
    nonlinear_system.solution->zero();

    // Solve the system and print displacement degrees-of-freedom to screen.
    nonlinear_system.solve(elem_ops, assembly);
    nonlinear_system.solution->print_global();

    return 0;
}<commit_msg>Typo in comments in intro_ex1.<commit_after>/*
* This example solves an axial bar extension problem. It is based on the
* example of the same name in the MAST source repository.
* (examples/structural/bar_extension).
*/

// C/C++ includes.
#include <iostream>

// libMesh includes.
#include <libmesh/libmesh.h>
#include <libmesh/replicated_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/equation_systems.h>
#include <libmesh/fe_type.h>
#include <libmesh/numeric_vector.h>

// MAST includes.
#include "base/nonlinear_system.h"
#include "elasticity/structural_system_initialization.h"
#include "base/physics_discipline_base.h"
#include "boundary_condition/dirichlet_boundary_condition.h"
#include "base/parameter.h"
#include "base/constant_field_function.h"
#include "property_cards/isotropic_material_property_card.h"
#include "property_cards/solid_1d_section_element_property_card.h"
#include "base/nonlinear_implicit_assembly.h"
#include "elasticity/structural_nonlinear_assembly.h"

int main(int argc, const char** argv)
{
    // Initialize libMesh library.
    libMesh::LibMeshInit init(argc, argv);

    // Create Mesh object on default MPI communicator and generate a line mesh (5 elements, 10 units long).
    //   Note that in libMesh, all meshes are parallel by default in the sense that the equations on the mesh are solved in parallel by PETSc.
    //   A "ReplicatedMesh" is one where all MPI processes have the full mesh in memory, as compared to a "DistributedMesh" where the mesh is
    //   "chunked" up and distributed across processes, each having their own piece.
    libMesh::ReplicatedMesh mesh(init.comm());
    libMesh::MeshTools::Generation::build_line(mesh, 5, 0.0, 10.0);
    mesh.print_info();
    mesh.boundary_info->print_info();

    // Create EquationSystems object, which is a container for multiple systems of equations that are defined on a given mesh.
    libMesh::EquationSystems equation_systems(mesh);

    // Add system of type MAST::NonlinearSystem (which wraps libMesh::NonlinearImplicitSystem) to the EquationSystems container.
    //   We name the system "structural" and also get a reference to the system so we can easily reference it later.
    MAST::NonlinearSystem & system = equation_systems.add_system<MAST::NonlinearSystem>("structural");

    // Create a finite element type for the system. Here we use first order
    // Lagrangian-type finite elements.
    libMesh::FEType fetype(libMesh::FIRST, libMesh::LAGRANGE);

    // Initialize the system to the correct set of variables for a structural
    // analysis. In libMesh this is analogous to adding variables (each with
    // specific finite element type/order to the system for a particular
    // system of equations.
    MAST::StructuralSystemInitialization structural_system(system,
                                                           system.name(),
                                                           fetype);

    // Initialize a new structural discipline using equation_systems.
    MAST::PhysicsDisciplineBase discipline(equation_systems);

    // Create and add boundary conditions to the structural system. A Dirichlet BC fixes the left end of the bar.
    // This definition uses the numbering created by the libMesh mesh generation function.
    MAST::DirichletBoundaryCondition dirichlet_bc;
    dirichlet_bc.init(0, structural_system.vars());
    discipline.add_dirichlet_bc(0, dirichlet_bc);
    discipline.init_system_dirichlet_bc(system);

    // Initialize the equation system since we now know the size of our
    // system matrices (based on mesh, element type, variables in the
    // structural_system) as well as the setup of dirichlet boundary conditions.
    // This initialization process is basically a pre-processing step to
    // preallocate storage and spread it across processors.
    equation_systems.init();
    equation_systems.print_info();

    // Create parameters.
    MAST::Parameter thickness_y("thy", 0.06);
    MAST::Parameter thickness_z("thz", 0.02);
    MAST::Parameter E("E", 72.0e9);
    MAST::Parameter nu("nu", 0.33);
    MAST::Parameter zero("zero", 0.0);
    MAST::Parameter pressure("p", 2.0e4);

    // Create ConstantFieldFunctions used to spread parameters throughout the model.
    MAST::ConstantFieldFunction thy_f("hy", thickness_y);
    MAST::ConstantFieldFunction thz_f("hz", thickness_z);
    MAST::ConstantFieldFunction E_f("E", E);
    MAST::ConstantFieldFunction nu_f("nu", nu);
    MAST::ConstantFieldFunction hyoff_f("hy_off", zero);
    MAST::ConstantFieldFunction hzoff_f("hz_off", zero);
    MAST::ConstantFieldFunction pressure_f("pressure", pressure);

    // Initialize load.
    // TODO - Switch this to a concentrated/point load on the right end of the bar.
    MAST::BoundaryConditionBase right_end_pressure(MAST::SURFACE_PRESSURE);
    right_end_pressure.add(pressure_f);
    discipline.add_side_load(1, right_end_pressure);

    // Create the material property card ("card" is NASTRAN lingo) and the relevant parameters to it. An isotropic
    // material needs elastic modulus (E) and Poisson ratio (nu) to describe its behavior.
    MAST::IsotropicMaterialPropertyCard material;
    material.add(E_f);
    material.add(nu_f);

    // Create the section property card. Attach all property values.
    MAST::Solid1DSectionElementPropertyCard section;
    section.add(thy_f);
    section.add(thz_f);
    section.add(hyoff_f);
    section.add(hzoff_f);

    // Specify a section orientation point and add it to the section.
    libMesh::Point orientation;
    orientation(1) = 1.0;
    section.y_vector() = orientation;

    // Attach material to the card.
    section.set_material(material);

    // Initialize the section and specify the subdomain in the mesh that it applies to.
    section.init();
    discipline.set_property_for_subdomain(0, section);

    // Create nonlinear assembly object and set the discipline and
    // structural_system. Create reference to system.

    MAST::NonlinearImplicitAssembly assembly;
    MAST::StructuralNonlinearAssemblyElemOperations elem_ops;
    assembly.set_discipline_and_system(discipline, structural_system);
    elem_ops.set_discipline_and_system(discipline, structural_system);
    MAST::NonlinearSystem& nonlinear_system = assembly.system();

    // Zero the solution before solving.
    nonlinear_system.solution->zero();

    // Solve the system and print displacement degrees-of-freedom to screen.
    nonlinear_system.solve(elem_ops, assembly);
    nonlinear_system.solution->print_global();

    return 0;
}<|endoftext|>


<commit_before>#include <nan.h>

using namespace v8;

NAN_METHOD(Print) {
  Nan::MaybeLocal<String> maybeStr = Nan::To<String>(info[0]);
  v8::Local<String> str;
  if(maybeStr.ToLocal(&str)) {
    Nan::ThrowError("Error converting first argument to string");
  }
  printf("%s\n", *String::Utf8Value(str));
}

NAN_MODULE_INIT(Init) {
  Nan::Set(target, Nan::New("print").ToLocalChecked(),
      Nan::GetFunction(Nan::New<FunctionTemplate>(Print)).ToLocalChecked());
}

NODE_MODULE(myaddon, Init)
<commit_msg>Fixed the string conversion check<commit_after>#include <nan.h>

using namespace v8;

NAN_METHOD(Print) {
  Nan::MaybeLocal<String> maybeStr = Nan::To<String>(info[0]);
  v8::Local<String> str;
  if(maybeStr.ToLocal(&str) == false) {
    Nan::ThrowError("Error converting first argument to string");
  }
  printf("%s\n", *String::Utf8Value(str));
}

NAN_MODULE_INIT(Init) {
  Nan::Set(target, Nan::New("print").ToLocalChecked(),
      Nan::GetFunction(Nan::New<FunctionTemplate>(Print)).ToLocalChecked());
}

NODE_MODULE(myaddon, Init)
<|endoftext|>


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

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

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

#ifndef _ASYNCEVENTNOTIFIER_HXX_
#include "asynceventnotifier.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif

#ifndef _COM_SUN_STAR_UI_DIALOGS_XFILEPICKERLISTENER_HPP_
#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp>
#endif

#include <process.h>
#include <memory>

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

using namespace com::sun::star;
using ::com::sun::star::ui::dialogs::XFilePickerListener;

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

CAsyncEventNotifier::CAsyncEventNotifier(cppu::OBroadcastHelper& rBroadcastHelper) :
    m_hThread(0),
    m_bRun(false),
    m_ThreadId(0),
    m_rBroadcastHelper(rBroadcastHelper),
    m_NotifyEvent(m_hEvents[0]),
    m_ResumeNotifying(m_hEvents[1])
{
    // m_NotifyEvent
    m_hEvents[0] = CreateEvent(0,       /* no security */
                               true,    /* manual reset */
                               false,   /* initial state not signaled */
                               0);      /* automatic name */

    // m_ResumeNotifying
    m_hEvents[1] = CreateEvent(0,       /* no security */
                               true,    /* manual reset */
                               false,   /* initial state not signaled */
                               0);      /* automatic name */
}

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

CAsyncEventNotifier::~CAsyncEventNotifier()
{
    OSL_ENSURE(0 == m_hThread,"Thread not stopped, destroying this instance leads to desaster");

    CloseHandle(m_hEvents[0]);
    CloseHandle(m_hEvents[1]);
}

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

bool SAL_CALL CAsyncEventNotifier::startup(bool bCreateSuspended)
{
    osl::MutexGuard aGuard(m_Mutex);

    // m_bRun may already be false because of a
    // call to stop but the thread did not yet
    // terminate so m_hEventNotifierThread is
    // yet a valid thread handle that should
    // not be overwritten
    if (!m_bRun)
    {
        if (!bCreateSuspended)
            SetEvent(m_ResumeNotifying);

        m_hThread = (HANDLE)_beginthreadex(
            NULL, 0, CAsyncEventNotifier::ThreadProc, this, 0, &m_ThreadId);

        OSL_ASSERT(0 != m_hThread);

        if (m_hThread)
            m_bRun = true;
    }

    OSL_POSTCOND(m_bRun,"Could not start event notifier!");

    return m_bRun;
}

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

void SAL_CALL CAsyncEventNotifier::shutdown()
{
    OSL_PRECOND(GetCurrentThreadId() != m_ThreadId, "Method called in wrong thread context!");

    osl::ResettableMutexGuard aGuard(m_Mutex);

    OSL_PRECOND(m_bRun,"Event notifier does not run!");

    m_bRun = false;
    m_EventList.clear();

    // awake the the notifier thread
    SetEvent(m_ResumeNotifying);
    SetEvent(m_NotifyEvent);

    // releas the mutex here because the event
    // notifier thread may need it to finish
    aGuard.clear();

    // we are waiting infinite, so error will
    // be better detected in form of deadlocks
    sal_uInt32 dwResult = WaitForSingleObject(m_hThread, INFINITE);

    OSL_ENSURE(WAIT_FAILED != dwResult, "Waiting for thread termination failed!");

    // lock mutex again to reset m_hThread
    // and prevent a race with start()
    aGuard.reset();

    CloseHandle(m_hThread);
    m_hThread = 0;
}

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

void CAsyncEventNotifier::suspend()
{
    ResetEvent(m_ResumeNotifying);
}

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

void CAsyncEventNotifier::resume()
{
    SetEvent(m_ResumeNotifying);
}

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

void SAL_CALL CAsyncEventNotifier::notifyEvent(CEventNotification* EventNotification)
{
    osl::MutexGuard aGuard(m_Mutex);

    OSL_ENSURE(m_bRun,"Event notifier is not running!");

    if (m_bRun)
    {
        m_EventList.push_back(EventNotification);
        SetEvent(m_NotifyEvent);
    }
}

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

size_t SAL_CALL CAsyncEventNotifier::getEventListSize()
{
    osl::MutexGuard aGuard(m_Mutex);
    return m_EventList.size();
}

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

void SAL_CALL CAsyncEventNotifier::resetNotifyEvent()
{
    osl::MutexGuard aGuard(m_Mutex);
    if (0 == m_EventList.size())
        ResetEvent(m_NotifyEvent);
}

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

CEventNotification* SAL_CALL CAsyncEventNotifier::getNextEventRecord()
{
    osl::MutexGuard aGuard(m_Mutex);
    return m_EventList.front();
}

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

void SAL_CALL CAsyncEventNotifier::removeNextEventRecord()
{
    osl::MutexGuard aGuard(m_Mutex);
    m_EventList.pop_front();
}

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

void SAL_CALL CAsyncEventNotifier::run()
{
    while (m_bRun)
    {
        WaitForMultipleObjects(2, m_hEvents, true, INFINITE);

        if (m_bRun)
        {
            while (getEventListSize() > 0)
            {
                std::auto_ptr<CEventNotification> EventNotification(getNextEventRecord());
                removeNextEventRecord();

                ::cppu::OInterfaceContainerHelper* pICHelper =
                    m_rBroadcastHelper.getContainer(getCppuType((uno::Reference<XFilePickerListener>*)0));

                if (pICHelper)
                {
                    ::cppu::OInterfaceIteratorHelper iter(*pICHelper);

                    while(iter.hasMoreElements())
                    {
                        try
                        {
                            EventNotification->notifyEventListener(iter.next());
                        }
                        catch(uno::RuntimeException&)
                        {
                            OSL_ENSURE(sal_False,"RuntimeException during event dispatching");
                        }
                    }
                }

            } // while(getEventListSize() > 0)

            resetNotifyEvent();

        } // if (m_bRun)

    } // while(m_bRun)
}

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

unsigned int WINAPI CAsyncEventNotifier::ThreadProc(LPVOID pParam)
{
    CAsyncEventNotifier* pInst = reinterpret_cast< CAsyncEventNotifier* >(pParam);
    OSL_ASSERT(pInst);

    pInst->run();

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

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

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

#ifndef _ASYNCEVENTNOTIFIER_HXX_
#include "asynceventnotifier.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif

#ifndef _COM_SUN_STAR_UI_DIALOGS_XFILEPICKERLISTENER_HPP_
#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp>
#endif

#include <process.h>
#include <memory>

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

using namespace com::sun::star;
using ::com::sun::star::ui::dialogs::XFilePickerListener;

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

CAsyncEventNotifier::CAsyncEventNotifier(cppu::OBroadcastHelper& rBroadcastHelper) :
    m_hThread(0),
    m_bRun(false),
    m_ThreadId(0),
    m_rBroadcastHelper(rBroadcastHelper),
    m_NotifyEvent(m_hEvents[0]),
    m_ResumeNotifying(m_hEvents[1])
{
    // m_NotifyEvent
    m_hEvents[0] = CreateEvent(0,       /* no security */
                               true,    /* manual reset */
                               false,   /* initial state not signaled */
                               0);      /* automatic name */

    // m_ResumeNotifying
    m_hEvents[1] = CreateEvent(0,       /* no security */
                               true,    /* manual reset */
                               false,   /* initial state not signaled */
                               0);      /* automatic name */
}

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

CAsyncEventNotifier::~CAsyncEventNotifier()
{
    OSL_ENSURE(0 == m_hThread,"Thread not stopped, destroying this instance leads to desaster");

    CloseHandle(m_hEvents[0]);
    CloseHandle(m_hEvents[1]);
}

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

bool SAL_CALL CAsyncEventNotifier::startup(bool bCreateSuspended)
{
    osl::MutexGuard aGuard(m_Mutex);

    // m_bRun may already be false because of a
    // call to stop but the thread did not yet
    // terminate so m_hEventNotifierThread is
    // yet a valid thread handle that should
    // not be overwritten
    if (!m_bRun)
    {
        if (!bCreateSuspended)
            SetEvent(m_ResumeNotifying);

        m_hThread = (HANDLE)_beginthreadex(
            NULL, 0, CAsyncEventNotifier::ThreadProc, this, 0, &m_ThreadId);

        OSL_ASSERT(0 != m_hThread);

        if (m_hThread)
            m_bRun = true;
    }

    OSL_POSTCOND(m_bRun,"Could not start event notifier!");

    return m_bRun;
}

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

void SAL_CALL CAsyncEventNotifier::shutdown()
{
    OSL_PRECOND(GetCurrentThreadId() != m_ThreadId, "Method called in wrong thread context!");

    osl::ResettableMutexGuard aGuard(m_Mutex);

    OSL_PRECOND(m_bRun,"Event notifier does not run!");

    m_bRun = false;
    m_EventList.clear();

    // awake the the notifier thread
    SetEvent(m_ResumeNotifying);
    SetEvent(m_NotifyEvent);

    // releas the mutex here because the event
    // notifier thread may need it to finish
    aGuard.clear();

    // we are waiting infinite, so error will
    // be better detected in form of deadlocks
    sal_uInt32 dwResult = WaitForSingleObject(m_hThread, INFINITE);

    OSL_ENSURE(WAIT_FAILED != dwResult, "Waiting for thread termination failed!");

    // lock mutex again to reset m_hThread
    // and prevent a race with start()
    aGuard.reset();

    CloseHandle(m_hThread);
    m_hThread = 0;
}

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

void CAsyncEventNotifier::suspend()
{
    ResetEvent(m_ResumeNotifying);
}

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

void CAsyncEventNotifier::resume()
{
    SetEvent(m_ResumeNotifying);
}

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

void SAL_CALL CAsyncEventNotifier::notifyEvent(CEventNotification* EventNotification)
{
    osl::MutexGuard aGuard(m_Mutex);

    OSL_ENSURE(m_bRun,"Event notifier is not running!");

    if (m_bRun)
    {
        m_EventList.push_back(EventNotification);
        SetEvent(m_NotifyEvent);
    }
}

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

size_t SAL_CALL CAsyncEventNotifier::getEventListSize()
{
    osl::MutexGuard aGuard(m_Mutex);
    return m_EventList.size();
}

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

void SAL_CALL CAsyncEventNotifier::resetNotifyEvent()
{
    osl::MutexGuard aGuard(m_Mutex);
    if (0 == m_EventList.size())
        ResetEvent(m_NotifyEvent);
}

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

CEventNotification* SAL_CALL CAsyncEventNotifier::getNextEventRecord()
{
    osl::MutexGuard aGuard(m_Mutex);
    return m_EventList.front();
}

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

void SAL_CALL CAsyncEventNotifier::removeNextEventRecord()
{
    osl::MutexGuard aGuard(m_Mutex);
    m_EventList.pop_front();
}

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

void SAL_CALL CAsyncEventNotifier::run()
{
    while (m_bRun)
    {
        WaitForMultipleObjects(2, m_hEvents, true, INFINITE);

        if (m_bRun)
        {
            while (getEventListSize() > 0)
            {
                std::auto_ptr<CEventNotification> EventNotification(getNextEventRecord());
                removeNextEventRecord();

                ::cppu::OInterfaceContainerHelper* pICHelper =
                    m_rBroadcastHelper.getContainer(getCppuType((uno::Reference<XFilePickerListener>*)0));

                if (pICHelper)
                {
                    ::cppu::OInterfaceIteratorHelper iter(*pICHelper);

                    while(iter.hasMoreElements())
                    {
                        try
                        {
                            EventNotification->notifyEventListener(iter.next());
                        }
                        catch(uno::RuntimeException&)
                        {
                            OSL_ENSURE(sal_False,"RuntimeException during event dispatching");
                        }
                    }
                }

            } // while(getEventListSize() > 0)

            resetNotifyEvent();

        } // if (m_bRun)

    } // while(m_bRun)
}

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

unsigned int WINAPI CAsyncEventNotifier::ThreadProc(LPVOID pParam)
{
    CAsyncEventNotifier* pInst = reinterpret_cast< CAsyncEventNotifier* >(pParam);
    OSL_ASSERT(pInst);

    pInst->run();

    return 0;
}
<|endoftext|>


<commit_before>tags::h2(text("How to choose an integer type")) + compile(R"(
(created 2017-04-05, updated 2017-04-05)

Prefer portable types like `std::uint32_t` over the types without an
explicit range. Use `int`, `long`, `long long`
only if you have a reason to use exactly these and not the portable
ones. C++ is different from Java and C#: `int` etc are not the same size
and range on every platform. This makes
them hard to use even for C++ experts. They are neither necessary nor
sufficient for most practical situations.

In most cases you already know the expected range of values. So why
not use the right integer type for this instead instead of
cargo-culting it?

If you know that you are dealing with 64-bit file sizes, document
this assumption in an unambiguous way. There is no reason for
using `int` or `long long` in this case. Using the wrong type leads
to unportable code and misunderstandings.)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-0.cpp")) +
    compile(
        R"(One of the few valid use cases for the built-in types is overloading a function for all integer types that exist:)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-1.cpp")) +
    compile(R"(This kind of code should be fairly uncommon though.

The other major kind of integer types are the pointery ones: `std::size_t`, `std::ptrdiff_t` and `std::uintptr_t`.
They are used when dealing with memory on the current machine. `int` cannot store the sizes of objects on most contemporary
machines. `size_t` can. Use `size_t`. `ptrdiff_t` is for differences between memory addresses. It is signed because a
difference can be negative. `uintptr_t` is for manipulating pointers on the bit level. If you did not know about `uintptr_t`
before reading this article, chances are you won't need this type any soon. `size_t` and `ptrdiff_t` are two of the most
important types in C++ you have to know and make use of. This is a very small function how it would be written by someone w
ho does not waste a single thought on choosing the right type.)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-2.cpp")) +
    compile(
        R"(These are my thoughts when I read this function. I tried to mark the WTF moments so that you can calculate the WTFs per line metric as a take-home exercise if you like.)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-3.cpp")) +
    compile(
        R"(I only have to change one little thing to make all these WTFs go away:)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-4.cpp")) +
    compile(
        R"(Much better, isn't it? Is it really too much to ask for using the right integer types?)")<commit_msg>Fixed typo in article<commit_after>tags::h2(text("How to choose an integer type")) + compile(R"(
(created 2017-04-05, updated 2017-04-05)

Prefer portable types like `std::uint32_t` over the types without an
explicit range. Use `int`, `long`, `long long`
only if you have a reason to use exactly these and not the portable
ones. C++ is different from Java and C#: `int` etc are not the same size
and range on every platform. This makes
them hard to use even for C++ experts. They are neither necessary nor
sufficient for most practical situations.

In most cases you already know the expected range of values. So why
not use the right integer type for this instead instead of
cargo-culting it?

If you know that you are dealing with 64-bit file sizes, document
this assumption in an unambiguous way. There is no reason for
using `int` or `long long` in this case. Using the wrong type leads
to unportable code and misunderstandings.)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-0.cpp")) +
    compile(
        R"(One of the few valid use cases for the built-in types is overloading a function for all integer types that exist:)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-1.cpp")) +
    compile(R"(This kind of code should be fairly uncommon though.

The other major kind of integer types are the pointery ones: `std::size_t`, `std::ptrdiff_t` and `std::uintptr_t`.
They are used when dealing with memory on the current machine. `int` cannot store the sizes of objects on most contemporary
machines. `size_t` can. Use `size_t`. `ptrdiff_t` is for differences between memory addresses. It is signed because a
difference can be negative. `uintptr_t` is for manipulating pointers on the bit level. If you did not know about `uintptr_t`
before reading this article, chances are you won't need this type any soon. `size_t` and `ptrdiff_t` are two of the most
important types in C++ you have to know and make use of. This is a very small function how it would be written by someone
who does not waste a single thought on choosing the right type.)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-2.cpp")) +
    compile(
        R"(These are my thoughts when I read this function. I tried to mark the WTF moments so that you can calculate the WTFs per line metric as a take-home exercise if you like.)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-3.cpp")) +
    compile(
        R"(I only have to change one little thing to make all these WTFs go away:)") +
    snippet_from_file(
        snippets_source_code,
        ventura::relative_path("how-to-choose-an-integer-type-4.cpp")) +
    compile(
        R"(Much better, isn't it? Is it really too much to ask for using the right integer types?)")<|endoftext|>


<commit_before>#include <iostream>

template<class INFERENCE>
class EmptyVisitor{
public:
	EmptyVisitor(){
	}
	void begin(INFERENCE & inf){
	}
	bool operator()(INFERENCE & inf){
		return true;
	}
	void end(INFERENCE & inf){
	}
};

template<class INFERENCE>
class VerboseVisitor{
public:
	VerboseVisitor(){
	}
	void begin(INFERENCE & inf){
		std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
	}
	bool operator()(INFERENCE & inf){
		std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
		return true;
	}
	void end(INFERENCE & inf){
		std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
	}
};

template<class INFERENCE>
class TimingVisitor{
public:
	typedef typename  INFERENCE::ValueType ValueType;

	TimingVisitor()
	:
		iteration_(0)
		times_(),
		values_(),
		bounds_(),
		iterations_(),
		timer_()
	{
		timer_.tic();
	}

	void begin(INFERENCE & inf){
		// stop timer
		timer_.toc();
		// store values
		const ValueType val=inf.value();
		const ValueType bound=inf.bound();
        times_.push_back(timer_.elapsedTime());
        values_.push_back(values_);
        bounds_.push_back(bounds_);

        std::cout<<"value "<<val<<" bound "<<bound<<"\n";

        ++iteration_;
		// restart timer
		timer_.tic():
	}

	bool operator()(INFERENCE & inf){
		// stop timer
		timer_.toc();
		// store values
		const ValueType val=inf.value();
		const ValueType bound=inf.bound();
        times_.push_back(timer_.elapsedTime());
        values_.push_back(values_);
        bounds_.push_back(bounds_);

        std::cout<<"value "<<val<<" bound "<<bound<<"\n";

        ++iteration_;
		// restart timer
		timer_.tic():
		return true;
	}

	void end(INFERENCE & inf){
		// stop timer
		timer_.toc();
		// store values
		const ValueType val=inf.value();
		const ValueType bound=inf.bound();
        times_.push_back(timer_.elapsedTime());
        values_.push_back(values_);
        bounds_.push_back(bounds_);

        std::cout<<"value "<<val<<" bound "<<bound<<"\n";

	}
private:
	iteration_;
	std::vector<float  > times_;
	std::vector<float  > values_;
	std::vector<float  > bounds_;
	std::vector<size_t > iterations_;
	opengm::Timer timer_;
};
<commit_msg>implemented new visitors<commit_after>#ifndef OPENGM_NEW_VISITOR_HXX
#define OPENGM_NEW_VISITOR_HXX

#include <iostream>
#include <opengm/opengm.hxx>
#include <opengm/utilities/timer.hxx>

template<class INFERENCE>
class EmptyVisitor{
public:
	EmptyVisitor(){
	}
	void begin(INFERENCE & inf){
	}
	bool operator()(INFERENCE & inf){
		return true;
	}
	void end(INFERENCE & inf){
	}
};

template<class INFERENCE>
class VerboseVisitor{
public:
	VerboseVisitor(){
	}
	void begin(INFERENCE & inf){
		std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
	}
	bool operator()(INFERENCE & inf){
		std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
		return true;
	}
	void end(INFERENCE & inf){
		std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
	}
};

template<class INFERENCE>
class TimingVisitor{
public:
	typedef typename  INFERENCE::ValueType ValueType;

	TimingVisitor()
	:
		iteration_(0)
		times_(),
		values_(),
		bounds_(),
		iterations_(),
		timer_()
	{
		timer_.tic();
	}

	void begin(INFERENCE & inf){
		// stop timer
		timer_.toc();
		// store values
		const ValueType val=inf.value();
		const ValueType bound=inf.bound();
        times_.push_back(timer_.elapsedTime());
        values_.push_back(values_);
        bounds_.push_back(bounds_);

        std::cout<<"value "<<val<<" bound "<<bound<<"\n";

        ++iteration_;
		// restart timer
		timer_.tic():
	}

	bool operator()(INFERENCE & inf){
		// stop timer
		timer_.toc();
		// store values
		const ValueType val=inf.value();
		const ValueType bound=inf.bound();
        times_.push_back(timer_.elapsedTime());
        values_.push_back(values_);
        bounds_.push_back(bounds_);

        std::cout<<"value "<<val<<" bound "<<bound<<"\n";

        ++iteration_;
		// restart timer
		timer_.tic():
		return true;
	}

	void end(INFERENCE & inf){
		// stop timer
		timer_.toc();
		// store values
		const ValueType val=inf.value();
		const ValueType bound=inf.bound();
        times_.push_back(timer_.elapsedTime());
        values_.push_back(values_);
        bounds_.push_back(bounds_);

        std::cout<<"value "<<val<<" bound "<<bound<<"\n";

	}
private:
	iteration_;
	std::vector<float  > times_;
	std::vector<float  > values_;
	std::vector<float  > bounds_;
	std::vector<size_t > iterations_;
	opengm::Timer timer_;
};

#endif //OPENGM_NEW_VISITOR_HXX<|endoftext|>


<commit_before>#include <boost/scope_exit.hpp>

#include "wonderland.subsystem.detail/key.hxx"
#include "wonderland.subsystem.detail/key_helper.hxx"
#include "wonderland.subsystem.detail/subsystem_base.hxx"

#ifdef WRP_WONDERLAND_SUBSYSTEM_GLFW3
  #include "wonderland.subsystem.detail/glfw3.hxx"
#elif defined(WRP_WONDERLAND_SUBSYSTEM_GLFW2)
  #include "wonderland.subsystem.detail/glfw2.hxx"
#elif defined(WRP_WONDERLAND_SUBSYSTEM_SDL2)
  #include "wonderland.subsystem.detail/sdl2.hxx"
#elif defined(WRP_WONDERLAND_SUBSYSTEM_SDL1)
  #include "wonderland.subsystem.detail/sdl1.hxx"
#endif
<commit_msg>add default subsystem define to GLFW2 for Emscripten, to GLFW3 the other<commit_after>#if not defined( WRP_WONDERLAND_SUBSYSTEM_GLFW3 ) \
    not defined( WRP_WONDERLAND_SUBSYSTEM_GLFW2 ) \
    not defined( WRP_WONDERLAND_SUBSYSTEM_SDL2 ) \
    not defined( WRP_WONDERLAND_SUBSYSTEM_SDL1 )
  #ifndef EMSCRIPTEN
    #define WRP_WONDERLAND_SUBSYSTEM_GLFW3
  #else
    #define WRP_WONDERLAND_SUBSYSTEM_GLFW2
  #endif
#endif

#include <boost/scope_exit.hpp>

#include "wonderland.subsystem.detail/key.hxx"
#include "wonderland.subsystem.detail/key_helper.hxx"
#include "wonderland.subsystem.detail/subsystem_base.hxx"

#ifdef WRP_WONDERLAND_SUBSYSTEM_GLFW3
  #include "wonderland.subsystem.detail/glfw3.hxx"
#elif defined(WRP_WONDERLAND_SUBSYSTEM_GLFW2)
  #include "wonderland.subsystem.detail/glfw2.hxx"
#elif defined(WRP_WONDERLAND_SUBSYSTEM_SDL2)
  #include "wonderland.subsystem.detail/sdl2.hxx"
#elif defined(WRP_WONDERLAND_SUBSYSTEM_SDL1)
  #include "wonderland.subsystem.detail/sdl1.hxx"
#endif
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

namespace {
  class JITtedFunctionCollector : public llvm::JITEventListener {
  private:
    llvm::SmallVector<llvm::Function*, 24> m_functions;
    llvm::ExecutionEngine *m_engine;

  public:
    JITtedFunctionCollector(): m_functions(), m_engine(0) { }
    virtual ~JITtedFunctionCollector() { }

    virtual void NotifyFunctionEmitted(const llvm::Function& F, void *, size_t,
                              const JITEventListener::EmittedFunctionDetails&) {
      m_functions.push_back(const_cast<llvm::Function *>(&F));
    }
    virtual void NotifyFreeingMachineCode(void* /*OldPtr*/) {}

    void UnregisterFunctionMapping(llvm::ExecutionEngine&);
  };
}

void JITtedFunctionCollector::UnregisterFunctionMapping(
                                                  llvm::ExecutionEngine &engine)
{
  for (llvm::SmallVectorImpl<llvm::Function *>::reverse_iterator
         it = m_functions.rbegin(), et = m_functions.rend();
       it != et; ++it) {
    llvm::Function *ff = *it;
    engine.freeMachineCodeForFunction(ff);
    engine.updateGlobalMapping(ff, 0);
  }
  m_functions.clear();
}

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

ExecutionContext::ExecutionContext():
  m_engine(0),
  m_RunningStaticInits(false),
  m_CxaAtExitRemapped(false)
{
}

void
ExecutionContext::InitializeBuilder(llvm::Module* m)
{
  //
  //  Create an execution engine to use.
  //
  // Note: Engine takes ownership of the module.
  assert(m && "Module cannot be null");

  llvm::EngineBuilder builder(m);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);
  m_engine = builder.create();
  assert(m_engine && "Cannot initialize builder without module!");

  //m_engine->addModule(m); // Note: The engine takes ownership of the module.

  // install lazy function
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

ExecutionContext::~ExecutionContext()
{
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol (should never happen)!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  m_unresolvedSymbols.insert(mangled_name);

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret) return ret;
  }
  return HandleMissingFunction(mangled_name);
}

void
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.data());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: could not find function named " << funcname << '\n';
    return;
  }
  JITtedFunctionCollector listener;
  // register the listener
  m_engine->RegisterJITEventListener(&listener);
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol \'" << *i << "\' unresolved!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      assert(ff && "cannot find function to free");
      m_engine->updateGlobalMapping(ff, 0);
      m_engine->freeMachineCodeForFunction(ff);
    }
    m_unresolvedSymbols.clear();
    // cleanup functions
    listener.UnregisterFunctionMapping(*m_engine);
    m_engine->UnregisterJITEventListener(&listener);
    return;
  }
  // cleanup list and unregister our listener
  m_engine->UnregisterJITEventListener(&listener);

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType);
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().value);
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  m_engine->freeMachineCodeForFunction(f);
}

void
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");

  if (!m_engine)
    InitializeBuilder(m);

  assert(m_engine && "Code generation did not create an engine!");

  if (!m_RunningStaticInits) {
    m_RunningStaticInits = true;

    llvm::GlobalVariable* gctors
      = m->getGlobalVariable("llvm.global_ctors", true);
    if (gctors) {
      m_engine->runStaticConstructorsDestructors(false);
      gctors->eraseFromParent();
    }

    m_RunningStaticInits = false;
  }
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::outs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
    // Return a symbol's address, and whether it was jitted.
    void* address
      = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
    if (address) {
      if (fromJIT) *fromJIT = false;
    } else {
      if (fromJIT) *fromJIT = true;
      llvm::GlobalVariable* gvar
        = m->getGlobalVariable(symbolName, true);
      address = m_engine->getPointerToGlobal(gvar);
    }
    return address;
  }
<commit_msg>Be more verbose about missing symbols.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

namespace {
  class JITtedFunctionCollector : public llvm::JITEventListener {
  private:
    llvm::SmallVector<llvm::Function*, 24> m_functions;
    llvm::ExecutionEngine *m_engine;

  public:
    JITtedFunctionCollector(): m_functions(), m_engine(0) { }
    virtual ~JITtedFunctionCollector() { }

    virtual void NotifyFunctionEmitted(const llvm::Function& F, void *, size_t,
                              const JITEventListener::EmittedFunctionDetails&) {
      m_functions.push_back(const_cast<llvm::Function *>(&F));
    }
    virtual void NotifyFreeingMachineCode(void* /*OldPtr*/) {}

    void UnregisterFunctionMapping(llvm::ExecutionEngine&);
  };
}

void JITtedFunctionCollector::UnregisterFunctionMapping(
                                                  llvm::ExecutionEngine &engine)
{
  for (llvm::SmallVectorImpl<llvm::Function *>::reverse_iterator
         it = m_functions.rbegin(), et = m_functions.rend();
       it != et; ++it) {
    llvm::Function *ff = *it;
    engine.freeMachineCodeForFunction(ff);
    engine.updateGlobalMapping(ff, 0);
  }
  m_functions.clear();
}

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

ExecutionContext::ExecutionContext():
  m_engine(0),
  m_RunningStaticInits(false),
  m_CxaAtExitRemapped(false)
{
}

void
ExecutionContext::InitializeBuilder(llvm::Module* m)
{
  //
  //  Create an execution engine to use.
  //
  // Note: Engine takes ownership of the module.
  assert(m && "Module cannot be null");

  llvm::EngineBuilder builder(m);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);
  m_engine = builder.create();
  assert(m_engine && "Cannot initialize builder without module!");

  //m_engine->addModule(m); // Note: The engine takes ownership of the module.

  // install lazy function
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

ExecutionContext::~ExecutionContext()
{
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol (should never happen)!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "ExecutionContext: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret) return ret;
  }
  return HandleMissingFunction(mangled_name);
}

void
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.data());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: could not find function named " << funcname << '\n';
    return;
  }
  JITtedFunctionCollector listener;
  // register the listener
  m_engine->RegisterJITEventListener(&listener);
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol \'" << *i << "\' unresolved!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      assert(ff && "cannot find function to free");
      m_engine->updateGlobalMapping(ff, 0);
      m_engine->freeMachineCodeForFunction(ff);
    }
    m_unresolvedSymbols.clear();
    // cleanup functions
    listener.UnregisterFunctionMapping(*m_engine);
    m_engine->UnregisterJITEventListener(&listener);
    return;
  }
  // cleanup list and unregister our listener
  m_engine->UnregisterJITEventListener(&listener);

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType);
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().value);
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  m_engine->freeMachineCodeForFunction(f);
}

void
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");

  if (!m_engine)
    InitializeBuilder(m);

  assert(m_engine && "Code generation did not create an engine!");

  if (!m_RunningStaticInits) {
    m_RunningStaticInits = true;

    llvm::GlobalVariable* gctors
      = m->getGlobalVariable("llvm.global_ctors", true);
    if (gctors) {
      m_engine->runStaticConstructorsDestructors(false);
      gctors->eraseFromParent();
    }

    m_RunningStaticInits = false;
  }
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::outs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
    // Return a symbol's address, and whether it was jitted.
    void* address
      = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
    if (address) {
      if (fromJIT) *fromJIT = false;
    } else {
      if (fromJIT) *fromJIT = true;
      llvm::GlobalVariable* gvar
        = m->getGlobalVariable(symbolName, true);
      address = m_engine->getPointerToGlobal(gvar);
    }
    return address;
  }
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "InputValidator.h"
#include "MetaLexer.h"
#include <algorithm>

namespace cling {
  bool InputValidator::inBlockComment() const {
    return std::find(m_ParenStack.begin(), m_ParenStack.end(), tok::slash)
             != m_ParenStack.end();
  }

  static int findNestedBlockComments(const char* startPos, const char* endPos) {
    // While probably not standard compliant, it should work fine for the indent
    // Let the real parser error if the balancing is incorrect

    // search forward for //, then backward for block comments
    // */ last, comment has ended, doesn't matter how many /* before
    // /* last, comment has begun, doesn't matter if priors ended or not
    char commentTok = 0;
    while (startPos < endPos) {
      if (*startPos == '/') {
        if (++commentTok == 2) {
          while (endPos > startPos) {
            switch (*endPos) {
              case '*':
                if (commentTok == '*')
                  return -1;
                else
                  commentTok = '/';
                break;
              case '/':
                if (commentTok == '/')
                  return 1;
                else
                  commentTok = '*';
                break;
              default:
                commentTok = 0;
                break;
            }
            --endPos;
          }
          return 0;
        }
      } else if (commentTok)
        commentTok = 0; // need a new start to double slash
      ++startPos;
    }
    return 0;
  }

  static void unwindTokens(std::deque<int>& queue, int tok) {
    assert(!queue.empty() && "Token stack is empty!");
    while (queue.back() != tok) {
      queue.pop_back();
      assert(!queue.empty() && "Token stack is empty!");
    }
    queue.pop_back();
  }

  InputValidator::ValidationResult
  InputValidator::validate(llvm::StringRef line) {
    ValidationResult Res = kComplete;

    Token Tok;
    const char* curPos = line.data();
    bool multilineComment = inBlockComment();
    int commentTok = multilineComment ? tok::asterik : tok::slash;

    if (!multilineComment && m_ParenStack.empty()) {
      // Only check for 'template' if we're not already indented
      MetaLexer Lex(curPos, true);
      Lex.Lex(Tok);
      curPos = Lex.getLocation();
      if (Tok.is(tok::ident)) {
        if (Tok.getIdent()=="template")
          m_ParenStack.push_back(tok::greater);
      } else
        curPos -= Tok.getLength(); // Rewind buffer for LexPunctuatorAndAdvance
    }

    do {
      const char* prevStart = curPos;
      if (!MetaLexer::LexPunctuatorAndAdvance(curPos, Tok)) {
        // there were tokens between the previous and this Tok.
        commentTok = tok::slash;
      }
      const int kind = (int)Tok.getKind();

      if (kind == commentTok) {
        if (kind == tok::slash) {
          if (multilineComment) {
            // exiting a comment, unwind the stack
            multilineComment = false;
            commentTok = tok::slash;
            unwindTokens(m_ParenStack, tok::slash);
          }
          // If we have a closing comment without a start it will be transformed
          // to */; and clang reports an error for both the */ and the ;
          // If we return kIncomplete, then just one error is printed, but too
          // late: after the user has another expression which will always fail.
          // So just deal with two errors for now
          // else if (prevKind == tok::asterik) {
          //  Res = kIncomplete;
          // break;
          // }
          else   // wait for an asterik
            commentTok = tok::asterik;
        }
        else {
          assert(commentTok == tok::asterik && "Comment token not / or *");
          if (!multilineComment) {
            // entering a new comment
            multilineComment = true;
            m_ParenStack.push_back(tok::slash);
          }
          else // wait for closing / (must be next token)
            commentTok = tok::slash;
        }
      }
      else {
        // If we're in a multiline, and waiting for the closing slash
        // we gonna have to wait for another asterik first
        if (multilineComment) {
          if (kind == tok::eof) {
            switch (findNestedBlockComments(prevStart, curPos)) {
              case -1: unwindTokens(m_ParenStack, tok::slash);
              case  1:
              case  0: break;
              default: assert(0 && "Nested block comment count"); break;
            }
            // eof, were done anyway
            break;
          }
          else if (commentTok == tok::slash) {
            // Cancel the wait for a slash, but only if current token isn't
            // also an asterik.
            if (kind != tok::asterik)
              commentTok = tok::asterik;
          }
        }

        if (kind >= (int)tok::l_square && kind <= (int)tok::r_brace) {
          // The closing paren kind is open paren kind + 1 (i.e odd number)
          if (kind % 2) {
            int prev = m_ParenStack.empty() ? -1: m_ParenStack.back();
            // closing the right one?
            if (prev != kind - 1) {
              if (multilineComment)
                continue;
              Res = kMismatch;
              break;
            }
            m_ParenStack.pop_back();

            // Right brace will pop a template if their is one
            if (kind == tok::r_brace && m_ParenStack.size() == 1 ) {
              if (m_ParenStack.back() == tok::greater)
                m_ParenStack.pop_back();
            }
          }
          else
            m_ParenStack.push_back(kind);
        }
        else if (kind == tok::hash) {
          MetaLexer Lex(curPos);
          Lex.SkipWhitespace();
          Lex.LexAnyString(Tok);
          const llvm::StringRef PPtk = Tok.getIdent();
          if (PPtk.startswith("endif")
              && (PPtk.size() > 5 ? PPtk[5]=='/' || isspace(PPtk[5]) : true)) {
            if (m_ParenStack.empty() || m_ParenStack.back() != tok::hash) {
              Res = kMismatch;
              break;
            }
            m_ParenStack.pop_back();
          }
          else if (PPtk.startswith("if")) {
            m_ParenStack.push_back(tok::hash);
          }
        }
        else if (kind == tok::semicolon) {
          // Template forward declatation
          if (m_ParenStack.size() == 1 && m_ParenStack.back()==tok::greater)
            m_ParenStack.pop_back();
        }
        else if (kind >= (int)tok::stringlit && kind <= (int)tok::charlit) {
          MetaLexer::LexQuotedStringAndAdvance(curPos, Tok);
        }
      }
    } while (Tok.isNot(tok::eof));

    if (!m_ParenStack.empty() && Res != kMismatch)
      Res = kIncomplete;

    if (!m_Input.empty()) {
      if (!m_ParenStack.empty() && (m_ParenStack.back() == tok::stringlit
                                    || m_ParenStack.back() == tok::charlit))
        m_Input.append("\\n");
      else
        m_Input.append("\n");
    }
    else
      m_Input = "";

    m_Input.append(line);

    return Res;
  }

  void InputValidator::reset(std::string* input) {
    if (input) {
      assert(input->empty() && "InputValidator::reset got non empty argument");
      input->swap(m_Input);
    } else
      std::string().swap(m_Input);

    std::deque<int>().swap(m_ParenStack);
  }
} // end namespace cling
<commit_msg>Remove useless assignment.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "InputValidator.h"
#include "MetaLexer.h"
#include <algorithm>

namespace cling {
  bool InputValidator::inBlockComment() const {
    return std::find(m_ParenStack.begin(), m_ParenStack.end(), tok::slash)
             != m_ParenStack.end();
  }

  static int findNestedBlockComments(const char* startPos, const char* endPos) {
    // While probably not standard compliant, it should work fine for the indent
    // Let the real parser error if the balancing is incorrect

    // search forward for //, then backward for block comments
    // */ last, comment has ended, doesn't matter how many /* before
    // /* last, comment has begun, doesn't matter if priors ended or not
    char commentTok = 0;
    while (startPos < endPos) {
      if (*startPos == '/') {
        if (++commentTok == 2) {
          while (endPos > startPos) {
            switch (*endPos) {
              case '*':
                if (commentTok == '*')
                  return -1;
                else
                  commentTok = '/';
                break;
              case '/':
                if (commentTok == '/')
                  return 1;
                else
                  commentTok = '*';
                break;
              default:
                commentTok = 0;
                break;
            }
            --endPos;
          }
          return 0;
        }
      } else if (commentTok)
        commentTok = 0; // need a new start to double slash
      ++startPos;
    }
    return 0;
  }

  static void unwindTokens(std::deque<int>& queue, int tok) {
    assert(!queue.empty() && "Token stack is empty!");
    while (queue.back() != tok) {
      queue.pop_back();
      assert(!queue.empty() && "Token stack is empty!");
    }
    queue.pop_back();
  }

  InputValidator::ValidationResult
  InputValidator::validate(llvm::StringRef line) {
    ValidationResult Res = kComplete;

    Token Tok;
    const char* curPos = line.data();
    bool multilineComment = inBlockComment();
    int commentTok = multilineComment ? tok::asterik : tok::slash;

    if (!multilineComment && m_ParenStack.empty()) {
      // Only check for 'template' if we're not already indented
      MetaLexer Lex(curPos, true);
      Lex.Lex(Tok);
      curPos = Lex.getLocation();
      if (Tok.is(tok::ident)) {
        if (Tok.getIdent()=="template")
          m_ParenStack.push_back(tok::greater);
      } else
        curPos -= Tok.getLength(); // Rewind buffer for LexPunctuatorAndAdvance
    }

    do {
      const char* prevStart = curPos;
      if (!MetaLexer::LexPunctuatorAndAdvance(curPos, Tok)) {
        // there were tokens between the previous and this Tok.
        commentTok = tok::slash;
      }
      const int kind = (int)Tok.getKind();

      if (kind == commentTok) {
        if (kind == tok::slash) {
          if (multilineComment) {
            // exiting a comment, unwind the stack
            multilineComment = false;
            commentTok = tok::slash;
            unwindTokens(m_ParenStack, tok::slash);
          }
          // If we have a closing comment without a start it will be transformed
          // to */; and clang reports an error for both the */ and the ;
          // If we return kIncomplete, then just one error is printed, but too
          // late: after the user has another expression which will always fail.
          // So just deal with two errors for now
          // else if (prevKind == tok::asterik) {
          //  Res = kIncomplete;
          // break;
          // }
          else   // wait for an asterik
            commentTok = tok::asterik;
        }
        else {
          assert(commentTok == tok::asterik && "Comment token not / or *");
          if (!multilineComment) {
            // entering a new comment
            multilineComment = true;
            m_ParenStack.push_back(tok::slash);
          }
          else // wait for closing / (must be next token)
            commentTok = tok::slash;
        }
      }
      else {
        // If we're in a multiline, and waiting for the closing slash
        // we gonna have to wait for another asterik first
        if (multilineComment) {
          if (kind == tok::eof) {
            switch (findNestedBlockComments(prevStart, curPos)) {
              case -1: unwindTokens(m_ParenStack, tok::slash);
              case  1:
              case  0: break;
              default: assert(0 && "Nested block comment count"); break;
            }
            // eof, were done anyway
            break;
          }
          else if (commentTok == tok::slash) {
            // Cancel the wait for a slash, but only if current token isn't
            // also an asterik.
            if (kind != tok::asterik)
              commentTok = tok::asterik;
          }
        }

        if (kind >= (int)tok::l_square && kind <= (int)tok::r_brace) {
          // The closing paren kind is open paren kind + 1 (i.e odd number)
          if (kind % 2) {
            int prev = m_ParenStack.empty() ? -1: m_ParenStack.back();
            // closing the right one?
            if (prev != kind - 1) {
              if (multilineComment)
                continue;
              Res = kMismatch;
              break;
            }
            m_ParenStack.pop_back();

            // Right brace will pop a template if their is one
            if (kind == tok::r_brace && m_ParenStack.size() == 1 ) {
              if (m_ParenStack.back() == tok::greater)
                m_ParenStack.pop_back();
            }
          }
          else
            m_ParenStack.push_back(kind);
        }
        else if (kind == tok::hash) {
          MetaLexer Lex(curPos);
          Lex.SkipWhitespace();
          Lex.LexAnyString(Tok);
          const llvm::StringRef PPtk = Tok.getIdent();
          if (PPtk.startswith("endif")
              && (PPtk.size() > 5 ? PPtk[5]=='/' || isspace(PPtk[5]) : true)) {
            if (m_ParenStack.empty() || m_ParenStack.back() != tok::hash) {
              Res = kMismatch;
              break;
            }
            m_ParenStack.pop_back();
          }
          else if (PPtk.startswith("if")) {
            m_ParenStack.push_back(tok::hash);
          }
        }
        else if (kind == tok::semicolon) {
          // Template forward declatation
          if (m_ParenStack.size() == 1 && m_ParenStack.back()==tok::greater)
            m_ParenStack.pop_back();
        }
        else if (kind >= (int)tok::stringlit && kind <= (int)tok::charlit) {
          MetaLexer::LexQuotedStringAndAdvance(curPos, Tok);
        }
      }
    } while (Tok.isNot(tok::eof));

    if (!m_ParenStack.empty() && Res != kMismatch)
      Res = kIncomplete;

    if (!m_Input.empty()) {
      if (!m_ParenStack.empty() && (m_ParenStack.back() == tok::stringlit
                                    || m_ParenStack.back() == tok::charlit))
        m_Input.append("\\n");
      else
        m_Input.append("\n");
    }

    m_Input.append(line);

    return Res;
  }

  void InputValidator::reset(std::string* input) {
    if (input) {
      assert(input->empty() && "InputValidator::reset got non empty argument");
      input->swap(m_Input);
    } else
      std::string().swap(m_Input);

    std::deque<int>().swap(m_ParenStack);
  }
} // end namespace cling
<|endoftext|>