<commit_before>
// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <stdlib.h>
#include <stdio.h>
#include <cmath>
#include <iterator>

#include <GL/glfw3.h>

#include "software/SfMViewer/document.h"
#include "openMVG/multiview/projection.hpp"
#include "openMVG/image/image.hpp"

#include "third_party/cmdLine/cmdLine.h"

static int running = 1;
static Document m_doc;
static int cur_cam = -1;

struct GLWImage {
    int width, height;
    GLuint texture;
    double opacity;
    int camera;
 };

static GLWImage m_cur_image;

/* close callback */
static int window_close_callback(GLFWwindow* window)
{
    running = 0;
    return GL_TRUE;
}

/* new window size */
void reshape( GLFWwindow* window, int width, int height )
{
  glViewport( 0, 0, (GLint) width, (GLint) height );
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  GLfloat zNear = 1e-2;
  GLfloat zFar = 1e5;
  GLfloat aspect = float(width)/float(height);
  GLfloat fH = std::tan( float(60 / 360.0f * 3.14159f) ) * zNear;
  GLfloat fW = fH * aspect;
  glFrustum( -fW, fW, -fH, fH, zNear, zFar );
  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity();
}

void glCheckError() {
#ifndef NDEBUG
	std::vector<unsigned> errors;
	unsigned error = GL_NO_ERROR;
	for (; (error = glGetError()) != GL_NO_ERROR;)
		errors.push_back(error);
	if (errors.empty())
		return;
	std::ostringstream oss;
	oss << "OpenGL errors :\n";
	for (const unsigned error : errors)
		oss << " - " << getErrorString(error) << '\n';
	throw std::runtime_error(oss.str());
#endif
}

void key( GLFWwindow* window, int k, int action)
{
  if( action != GLFW_PRESS ) return;

bool bTextureChange = false;

  switch (k) {
  case GLFW_KEY_ESCAPE:
    running = 0;
    break;
  case GLFW_KEY_LEFT:
    cur_cam--;
    if (cur_cam<0)  {
      cur_cam = m_doc._map_camera.size()-1;
    }
    bTextureChange = true;
    break;
  case GLFW_KEY_RIGHT:
    cur_cam++;
    if (cur_cam >= m_doc._map_camera.size())  {
      cur_cam = 0;
    }
    bTextureChange = true;
    break;
  default:
    return;
  }

  if (bTextureChange)
  {
    std::string sImageName =
      stlplus::create_filespec(
        stlplus::folder_append_separator(m_doc._sDirectory)+"images",
        m_doc._vec_imageNames[cur_cam]);
    std::vector<unsigned char> img;
    int w,h,depth;
    if (ReadImage(sImageName.c_str(),
              &img,
              &w,
              &h,
              &depth))
    {
      glEnable(GL_TEXTURE_2D);
      std::cout << "Read image : " << sImageName << std::endl;
      glDeleteTextures(1, &m_cur_image.texture);

      // Create texture
      glGenTextures( 1, &m_cur_image.texture);
      // select our current texture
      glBindTexture(GL_TEXTURE_2D, m_cur_image.texture);

      m_cur_image.width = w;
      m_cur_image.height = h;
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,  m_cur_image.width,
                m_cur_image.height, 0, GL_RGB, GL_UNSIGNED_BYTE,
                &img[0]);
      std::cout << std::endl;

      glCheckError();
      glBindTexture(GL_TEXTURE_2D, m_cur_image.texture);
    }
  }
}

// the conversion matrix from OpenGL default coordinate system
//  to the camera coordinate system:
// [ 1  0  0  0] * [ x ] = [ x ]
//   0 -1  0  0      y      -y
//   0  0 -1  0      z      -z
//   0  0  0  1      1       1
const GLfloat m_convert[4][4] = {
  {1.,  0.,  0., 0.},
  {0., -1.,  0., 0.},
  {0.,  0., -1., 0.},
  {0.,  0.,  0., 1.}};

//Local to World
static openMVG::Mat4 l2w_Camera(const Mat3 & R, const Vec3 & t)
{
  //World to Local
  /// given rotation matrix R and translation vector t,
  /// column-major matrix m is equal to:
  /// [ R11 R12 R13 t.x ]
  /// | R21 R22 R23 t.y |
  /// | R31 R32 R33 t.z |
  /// [ 0.0 0.0 0.0 1.0 ]

  //Local to World => Coordinates of the camera in the 3d space
  openMVG::Mat4 l2wmat = Mat4::Identity();
  l2wmat.block(0,0,3,4) = HStack(R,t);
  return l2wmat;
}

/* OpenGL draw function & timing */
static void draw(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  {
    const PinholeCamera & camera = m_doc._map_camera.find(cur_cam)->second;

    glPushMatrix();
    openMVG::Mat4 l2w = l2w_Camera(camera._R, camera._t);
    glMultMatrixf((GLfloat*)m_convert); // second, convert the camera coordinates to the opengl camera coordinates
    glMultMatrixd((GLdouble*)l2w.data());

    glPointSize(3);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_LIGHTING);
    //glCallList(m_pointcloud);

    //Draw Structure
    size_t nbPoint = m_doc._vec_points.size()/3;
    size_t cpt = 0;
    glBegin(GL_POINTS);
    for(size_t i = 0; i < nbPoint; i++,cpt+=3) {
      glColor3f(0.f,1.f,0.f);
      glVertex3f(m_doc._vec_points[cpt], m_doc._vec_points[cpt+1], m_doc._vec_points[cpt+2]);
    }
    glEnd();

/*
    //-- Draw other cameras:
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST);

    glDisable(GL_CULL_FACE);
    for (std::map<size_t, SimpleCamera >::const_iterator iterCam = m_doc->map_camera.begin();
      iterCam != m_doc->map_camera.end(); ++iterCam)
    {
      glPushMatrix();

      if (std::distance(m_doc->map_camera.begin(),iterCam) != cur_cam)
      {
        Mat4 l2w = iterCam->second.l2w();
        //glMultMatrixd(l2w.data());
        glMultMatrixf((GLfloat*)m_convert); // second, convert the camera coordinates to the opengl camera coordinates
        //glMultMatrixf((GLfloat*)prj);       // first, project the points in the world coordinates to the camera coorrdinates
        glMultMatrixd((GLdouble*)l2w.data());
        int w = m_doc->map_imageSize.find(std::distance(m_doc->map_camera.begin(),iterCam))->second.first;
        int h = m_doc->map_imageSize.find(std::distance(m_doc->map_camera.begin(),iterCam))->second.second;
        double focal = iterCam->second.K(0,0);
        double maxx = 0.5*w/focal;
        double maxy = 0.5*h/focal;

        glBegin(GL_QUADS);
        glColor4f(0.5f,0.5f,0.5f,0.6f);
        glTexCoord2d(0.0,0.0);        glVertex3d(-maxx,-maxy,-1.0);
        glTexCoord2d(1.0,0.0);        glVertex3d(+maxx,-maxy,-1.0);
        glTexCoord2d(1.0,1.0);        glVertex3d(+maxx,+maxy,-1.0);
        glTexCoord2d(0.0,1.0);        glVertex3d(-maxx,+maxy,-1.0);
        glEnd();

      }
      glPopMatrix();
    }

    glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST);
*/

    glPopMatrix();

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST);

    //Draw the image

    int w = m_doc._map_imageSize.find(cur_cam)->second.first;
    int h = m_doc._map_imageSize.find(cur_cam)->second.second;
    double focal = camera._K(0,0);

    double maxx = 0.5 * w / focal;
    double maxy = 0.5 * h / focal;
    glEnable(GL_TEXTURE_2D);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindTexture(GL_TEXTURE_2D, m_cur_image.texture);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glColor4f(0.5f,0.5f,0.5f,0.6f);
    glBegin(GL_QUADS);
    glTexCoord2d(0.0,1.0);    glVertex3d(-maxx,-maxy,-1.0);
    glTexCoord2d(1.0,1.0);    glVertex3d(+maxx,-maxy,-1.0);
    glTexCoord2d(1.0,0.0);    glVertex3d(+maxx,+maxy,-1.0);
    glTexCoord2d(0.0,0.0);    glVertex3d(-maxx,+maxy,-1.0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST);
  }
}

int main(int argc, char *argv[]) {

  CmdLine cmd;

  std::string sSfM_Dir;

  cmd.add( make_option('i', sSfM_Dir, "sfmdir") );

  try {
    if (argc == 1) throw std::string("Invalid command line parameter.");
    cmd.process(argc, argv);
  } catch(const std::string& s) {
    std::cerr << "Usage: " << argv[0] << ' '
    << "[-i|--sfmdir SfM_Output path] "
    << std::endl;

    std::cerr << s << std::endl;
    return EXIT_FAILURE;
  }

  if (m_doc.load(sSfM_Dir))
  {
    cur_cam = 0;
    std::cout << "Press left or right key to navigate ;-)" << std::endl;
    std::cout << "Esc to quit" << std::endl;
  }
  else{
    exit( EXIT_FAILURE);
  }

  //-- Create the GL window context
  GLFWwindow* window;
  int width, height;

  if( !glfwInit() )
  {
    fprintf( stderr, "Failed to initialize GLFW\n" );
    exit( EXIT_FAILURE );
  }

  glfwWindowHint(GLFW_DEPTH_BITS, 16);

  window = glfwCreateWindow( 600, 300, "SfmViewer", NULL, NULL );
  if (!window)
  {
    fprintf( stderr, "Failed to open GLFW window\n" );
    glfwTerminate();
    exit( EXIT_FAILURE );
  }

  // Set callback functions
  glfwSetWindowCloseCallback(window, window_close_callback);
  glfwSetWindowSizeCallback(window, reshape);
  glfwSetKeyCallback(window, key);

  glfwMakeContextCurrent(window);
  glfwSwapInterval( 1 );

  glfwGetWindowSize(window, &width, &height);
  reshape(window, width, height);

  m_cur_image.camera = -1;
  // Main loop
  while( running )
  {
    // Draw SfM Scene
    draw();

    // Swap buffers
    glfwSwapBuffers(window);
    glfwPollEvents();
  }

  // Terminate GLFW
  glfwTerminate();

  // Exit program
  exit( EXIT_SUCCESS );
}
<commit_msg>Fix compilation error for windows. #27<commit_after>
// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <stdlib.h>
#include <stdio.h>
#include <cmath>
#include <iterator>

#include <GL/glfw3.h>

#include "software/SfMViewer/document.h"
#include "openMVG/multiview/projection.hpp"
#include "openMVG/image/image.hpp"

#include "third_party/cmdLine/cmdLine.h"

static int running = 1;
static Document m_doc;
static int cur_cam = -1;

struct GLWImage {
    int width, height;
    GLuint texture;
    double opacity;
    int camera;
 };

static GLWImage m_cur_image;

/* close callback */
static int window_close_callback(GLFWwindow* window)
{
    running = 0;
    return GL_TRUE;
}

/* new window size */
void reshape( GLFWwindow* window, int width, int height )
{
  glViewport( 0, 0, (GLint) width, (GLint) height );
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  GLfloat zNear = 1e-2;
  GLfloat zFar = 1e5;
  GLfloat aspect = float(width)/float(height);
  GLfloat fH = std::tan( float(60 / 360.0f * 3.14159f) ) * zNear;
  GLfloat fW = fH * aspect;
  glFrustum( -fW, fW, -fH, fH, zNear, zFar );
  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity();
}

void key( GLFWwindow* window, int k, int action)
{
  if( action != GLFW_PRESS ) return;

  bool bTextureChange = false;

  switch (k) {
  case GLFW_KEY_ESCAPE:
    running = 0;
    break;
  case GLFW_KEY_LEFT:
    cur_cam--;
    if (cur_cam<0)  {
      cur_cam = m_doc._map_camera.size()-1;
    }
    bTextureChange = true;
    break;
  case GLFW_KEY_RIGHT:
    cur_cam++;
    if (cur_cam >= m_doc._map_camera.size())  {
      cur_cam = 0;
    }
    bTextureChange = true;
    break;
  default:
    return;
  }

  if (bTextureChange)
  {
    std::string sImageName =
      stlplus::create_filespec(
        stlplus::folder_append_separator(m_doc._sDirectory)+"images",
        m_doc._vec_imageNames[cur_cam]);
    std::vector<unsigned char> img;
    int w,h,depth;
    if (ReadImage(sImageName.c_str(),
              &img,
              &w,
              &h,
              &depth))
    {
      glEnable(GL_TEXTURE_2D);
      std::cout << "Read image : " << sImageName << "\n" << std::endl;
      glDeleteTextures(1, &m_cur_image.texture);

      // Create texture
      glGenTextures( 1, &m_cur_image.texture);
      // select our current texture
      glBindTexture(GL_TEXTURE_2D, m_cur_image.texture);

      m_cur_image.width = w;
      m_cur_image.height = h;
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,  m_cur_image.width,
                m_cur_image.height, 0, GL_RGB, GL_UNSIGNED_BYTE,
                &img[0]);

      glBindTexture(GL_TEXTURE_2D, m_cur_image.texture);
    }
  }
}

// the conversion matrix from OpenGL default coordinate system
//  to the camera coordinate system:
// [ 1  0  0  0] * [ x ] = [ x ]
//   0 -1  0  0      y      -y
//   0  0 -1  0      z      -z
//   0  0  0  1      1       1
const GLfloat m_convert[4][4] = {
  {1.,  0.,  0., 0.},
  {0., -1.,  0., 0.},
  {0.,  0., -1., 0.},
  {0.,  0.,  0., 1.}};

//Local to World
static openMVG::Mat4 l2w_Camera(const Mat3 & R, const Vec3 & t)
{
  //World to Local
  /// given rotation matrix R and translation vector t,
  /// column-major matrix m is equal to:
  /// [ R11 R12 R13 t.x ]
  /// | R21 R22 R23 t.y |
  /// | R31 R32 R33 t.z |
  /// [ 0.0 0.0 0.0 1.0 ]

  //Local to World => Coordinates of the camera in the 3d space
  openMVG::Mat4 l2wmat = Mat4::Identity();
  l2wmat.block(0,0,3,4) = HStack(R,t);
  return l2wmat;
}

/* OpenGL draw function & timing */
static void draw(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  {
    const PinholeCamera & camera = m_doc._map_camera.find(cur_cam)->second;

    glPushMatrix();
    openMVG::Mat4 l2w = l2w_Camera(camera._R, camera._t);
    glMultMatrixf((GLfloat*)m_convert); // second, convert the camera coordinates to the opengl camera coordinates
    glMultMatrixd((GLdouble*)l2w.data());

    glPointSize(3);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_LIGHTING);
    //glCallList(m_pointcloud);

    //Draw Structure
    size_t nbPoint = m_doc._vec_points.size()/3;
    size_t cpt = 0;
    glBegin(GL_POINTS);
    for(size_t i = 0; i < nbPoint; i++,cpt+=3) {
      glColor3f(0.f,1.f,0.f);
      glVertex3f(m_doc._vec_points[cpt], m_doc._vec_points[cpt+1], m_doc._vec_points[cpt+2]);
    }
    glEnd();

/*
    //-- Draw other cameras:
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST);

    glDisable(GL_CULL_FACE);
    for (std::map<size_t, SimpleCamera >::const_iterator iterCam = m_doc->map_camera.begin();
      iterCam != m_doc->map_camera.end(); ++iterCam)
    {
      glPushMatrix();

      if (std::distance(m_doc->map_camera.begin(),iterCam) != cur_cam)
      {
        Mat4 l2w = iterCam->second.l2w();
        //glMultMatrixd(l2w.data());
        glMultMatrixf((GLfloat*)m_convert); // second, convert the camera coordinates to the opengl camera coordinates
        //glMultMatrixf((GLfloat*)prj);       // first, project the points in the world coordinates to the camera coorrdinates
        glMultMatrixd((GLdouble*)l2w.data());
        int w = m_doc->map_imageSize.find(std::distance(m_doc->map_camera.begin(),iterCam))->second.first;
        int h = m_doc->map_imageSize.find(std::distance(m_doc->map_camera.begin(),iterCam))->second.second;
        double focal = iterCam->second.K(0,0);
        double maxx = 0.5*w/focal;
        double maxy = 0.5*h/focal;

        glBegin(GL_QUADS);
        glColor4f(0.5f,0.5f,0.5f,0.6f);
        glTexCoord2d(0.0,0.0);        glVertex3d(-maxx,-maxy,-1.0);
        glTexCoord2d(1.0,0.0);        glVertex3d(+maxx,-maxy,-1.0);
        glTexCoord2d(1.0,1.0);        glVertex3d(+maxx,+maxy,-1.0);
        glTexCoord2d(0.0,1.0);        glVertex3d(-maxx,+maxy,-1.0);
        glEnd();

      }
      glPopMatrix();
    }

    glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST);
*/

    glPopMatrix();

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST);

    //Draw the image

    int w = m_doc._map_imageSize.find(cur_cam)->second.first;
    int h = m_doc._map_imageSize.find(cur_cam)->second.second;
    double focal = camera._K(0,0);

    double maxx = 0.5 * w / focal;
    double maxy = 0.5 * h / focal;
    glEnable(GL_TEXTURE_2D);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindTexture(GL_TEXTURE_2D, m_cur_image.texture);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glColor4f(0.5f,0.5f,0.5f,0.6f);
    glBegin(GL_QUADS);
    glTexCoord2d(0.0,1.0);    glVertex3d(-maxx,-maxy,-1.0);
    glTexCoord2d(1.0,1.0);    glVertex3d(+maxx,-maxy,-1.0);
    glTexCoord2d(1.0,0.0);    glVertex3d(+maxx,+maxy,-1.0);
    glTexCoord2d(0.0,0.0);    glVertex3d(-maxx,+maxy,-1.0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST);
  }
}

int main(int argc, char *argv[]) {

  CmdLine cmd;
  std::string sSfM_Dir;
  cmd.add( make_option('i', sSfM_Dir, "sfmdir") );

  try {
    if (argc == 1) throw std::string("Invalid command line parameter.");
    cmd.process(argc, argv);
  } catch(const std::string& s) {
    std::cerr << "Usage: " << argv[0] << ' '
    << "[-i|--sfmdir SfM_Output path] "
    << std::endl;

    std::cerr << s << std::endl;
    return EXIT_FAILURE;
  }

  if (m_doc.load(sSfM_Dir))
  {
    cur_cam = 0;
    std::cout << "Press left or right key to navigate ;-)" << std::endl;
    std::cout << "Esc to quit" << std::endl;
  }
  else{
    exit( EXIT_FAILURE);
  }

  //-- Create the GL window context
  GLFWwindow* window;
  int width, height;

  if( !glfwInit() )
  {
    fprintf( stderr, "Failed to initialize GLFW\n" );
    exit( EXIT_FAILURE );
  }

  glfwWindowHint(GLFW_DEPTH_BITS, 16);

  window = glfwCreateWindow( 600, 300, "SfmViewer", NULL, NULL );
  if (!window)
  {
    fprintf( stderr, "Failed to open GLFW window\n" );
    glfwTerminate();
    exit( EXIT_FAILURE );
  }

  // Set callback functions
  glfwSetWindowCloseCallback(window, window_close_callback);
  glfwSetWindowSizeCallback(window, reshape);
  glfwSetKeyCallback(window, key);

  glfwMakeContextCurrent(window);
  glfwSwapInterval( 1 );

  glfwGetWindowSize(window, &width, &height);
  reshape(window, width, height);

  m_cur_image.camera = -1;
  // Main loop
  while( running )
  {
    // Draw SfM Scene
    draw();

    // Swap buffers
    glfwSwapBuffers(window);
    glfwPollEvents();
  }

  // Terminate GLFW
  glfwTerminate();

  // Exit program
  exit( EXIT_SUCCESS );
}
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

#include "libmesh/diff_system.h"
#include "libmesh/dof_map.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/petsc_diff_solver.h"
#include "libmesh/petsc_matrix.h"
#include "libmesh/petsc_vector.h"

#ifdef LIBMESH_HAVE_PETSC

namespace libMesh
{

//--------------------------------------------------------------------
// Functions with C linkage to pass to PETSc.  PETSc will call these
// methods as needed.
//
// Since they must have C linkage they have no knowledge of a namespace.
// Give them an obscure name to avoid namespace pollution.
extern "C"
{
  // Older versions of PETSc do not have the different int typedefs.
  // On 64-bit machines, PetscInt may actually be a long long int.
  // This change occurred in Petsc-2.2.1.
#if PETSC_VERSION_LESS_THAN(2,2,1)
  typedef int PetscErrorCode;
  typedef int PetscInt;
#endif

// Function to hand to PETSc's SNES,
// which monitors convergence at X
PetscErrorCode
__libmesh_petsc_diff_solver_monitor (SNES, PetscInt its,
                                     PetscReal fnorm, void *ctx)
{
  PetscDiffSolver& solver =
    *(static_cast<PetscDiffSolver*> (ctx));

  if (solver.verbose)
    libMesh::out << "  PetscDiffSolver step " << its
                 << ", |residual|_2 = " << fnorm << std::endl;

  return 0;
}

// Functions to hand to PETSc's SNES,
// which compute the residual or jacobian at X
PetscErrorCode
__libmesh_petsc_diff_solver_residual (SNES, Vec x, Vec r, void *ctx)
{
  libmesh_assert(x);
  libmesh_assert(r);
  libmesh_assert(ctx);

  PetscDiffSolver& solver =
    *(static_cast<PetscDiffSolver*> (ctx));
  ImplicitSystem &sys = solver.system();

  if (solver.verbose)
    libMesh::out << "Assembling the residual" << std::endl;

  PetscVector<Number>& X_system =
    *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get());
  PetscVector<Number>& R_system =
    *libmesh_cast_ptr<PetscVector<Number>*>(sys.rhs);
  PetscVector<Number> X_input(x, sys.comm()), R_input(r, sys.comm());

  // DiffSystem assembles from the solution and into the rhs, so swap
  // those with our input vectors before assembling.  They'll probably
  // already be references to the same vectors, but PETSc might do
  // something tricky.
  X_input.swap(X_system);
  R_input.swap(R_system);

  // We may need to correct a non-conforming solution
  sys.get_dof_map().enforce_constraints_exactly(sys);

  // We may need to localize a parallel solution
  sys.update();

  // Do DiffSystem assembly
  sys.assembly(true, false);
  R_system.close();

  // Swap back
  X_input.swap(X_system);
  R_input.swap(R_system);

  // No errors, we hope
  return 0;
}

PetscErrorCode
__libmesh_petsc_diff_solver_jacobian (SNES, Vec x, Mat *libmesh_dbg_var(j), Mat *pc,
                                      MatStructure *msflag, void *ctx)
{
  libmesh_assert(x);
  libmesh_assert(j);
//  libmesh_assert_equal_to (pc, j);  // We don't use separate preconditioners yet
  libmesh_assert(ctx);

  PetscDiffSolver& solver =
    *(static_cast<PetscDiffSolver*> (ctx));
  ImplicitSystem &sys = solver.system();

  if (solver.verbose)
    libMesh::out << "Assembling the Jacobian" << std::endl;

  PetscVector<Number>& X_system =
    *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get());
  PetscVector<Number> X_input(x, sys.comm());

  PetscMatrix<Number> J_input(*pc, sys.comm());
  PetscMatrix<Number>& J_system =
    *libmesh_cast_ptr<PetscMatrix<Number>*>(sys.matrix);

  // DiffSystem assembles from the solution and into the jacobian, so
  // swap those with our input vectors before assembling.  They'll
  // probably already be references to the same vectors, but PETSc
  // might do something tricky.
  X_input.swap(X_system);
  J_input.swap(J_system);

  // We may need to correct a non-conforming solution
  sys.get_dof_map().enforce_constraints_exactly(sys);

  // We may need to localize a parallel solution
  sys.update();

  // Do DiffSystem assembly
  sys.assembly(false, true);
  J_system.close();

  // Swap back
  X_input.swap(X_system);
  J_input.swap(J_system);

  *msflag = SAME_NONZERO_PATTERN;

  // No errors, we hope
  return 0;
}

} // extern "C"

PetscDiffSolver::PetscDiffSolver (sys_type& s)
  : Parent(s)
{
}

void PetscDiffSolver::init ()
{
  START_LOG("init()", "PetscDiffSolver");

  Parent::init();

  int ierr=0;

#if PETSC_VERSION_LESS_THAN(2,1,2)
  // At least until Petsc 2.1.1, the SNESCreate had a different
  // calling syntax.  The second argument was of type SNESProblemType,
  // and could have a value of either SNES_NONLINEAR_EQUATIONS or
  // SNES_UNCONSTRAINED_MINIMIZATION.
  ierr = SNESCreate(this->comm().get(), SNES_NONLINEAR_EQUATIONS, &_snes);
  LIBMESH_CHKERRABORT(ierr);
#else
  ierr = SNESCreate(this->comm().get(),&_snes);
  LIBMESH_CHKERRABORT(ierr);
#endif

#if PETSC_VERSION_LESS_THAN(2,3,3)
  ierr = SNESSetMonitor (_snes, __libmesh_petsc_diff_solver_monitor,
                         this, PETSC_NULL);
#else
  // API name change in PETSc 2.3.3
  ierr = SNESMonitorSet (_snes, __libmesh_petsc_diff_solver_monitor,
                         this, PETSC_NULL);
#endif
  LIBMESH_CHKERRABORT(ierr);

  ierr = SNESSetFromOptions(_snes);
  LIBMESH_CHKERRABORT(ierr);

  STOP_LOG("init()", "PetscDiffSolver");
}

PetscDiffSolver::~PetscDiffSolver ()
{
}

void PetscDiffSolver::clear()
{
  START_LOG("clear()", "PetscDiffSolver");

  int ierr=0;

  ierr = LibMeshSNESDestroy(&_snes);
  LIBMESH_CHKERRABORT(ierr);

  STOP_LOG("clear()", "PetscDiffSolver");
}

void PetscDiffSolver::reinit()
{
  Parent::reinit();
}

unsigned int PetscDiffSolver::solve()
{
  this->init();

  START_LOG("solve()", "PetscDiffSolver");

  PetscVector<Number> &x =
    *(libmesh_cast_ptr<PetscVector<Number>*>(_system.solution.get()));
  PetscMatrix<Number> &jac =
    *(libmesh_cast_ptr<PetscMatrix<Number>*>(_system.matrix));
  PetscVector<Number> &r =
    *(libmesh_cast_ptr<PetscVector<Number>*>(_system.rhs));

#ifdef LIBMESH_ENABLE_CONSTRAINTS
  _system.get_dof_map().enforce_constraints_exactly(_system);
#endif

  int ierr = 0;

  ierr = SNESSetFunction (_snes, r.vec(),
                          __libmesh_petsc_diff_solver_residual, this);
    LIBMESH_CHKERRABORT(ierr);

  ierr = SNESSetJacobian (_snes, jac.mat(), jac.mat(),
                          __libmesh_petsc_diff_solver_jacobian, this);
    LIBMESH_CHKERRABORT(ierr);

# if PETSC_VERSION_LESS_THAN(2,2,0)

  ierr = SNESSolve (_snes, x.vec(), &_outer_iterations);
         LIBMESH_CHKERRABORT(ierr);

// 2.2.x style
#elif PETSC_VERSION_LESS_THAN(2,3,0)

  ierr = SNESSolve (_snes, x.vec());
         LIBMESH_CHKERRABORT(ierr);

// 2.3.x & newer style
#else

  ierr = SNESSolve (_snes, PETSC_NULL, x.vec());
         LIBMESH_CHKERRABORT(ierr);

#endif

  STOP_LOG("solve()", "PetscDiffSolver");

  this->clear();

  // FIXME - We'll worry about getting the solve result right later...

  return DiffSolver::CONVERGED_RELATIVE_RESIDUAL;
}

} // namespace libMesh

#endif // LIBMESH_HAVE_PETSC
<commit_msg>Return correct solve result<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

#include "libmesh/diff_system.h"
#include "libmesh/dof_map.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/petsc_diff_solver.h"
#include "libmesh/petsc_matrix.h"
#include "libmesh/petsc_vector.h"

#ifdef LIBMESH_HAVE_PETSC

namespace libMesh
{

//--------------------------------------------------------------------
// Functions with C linkage to pass to PETSc.  PETSc will call these
// methods as needed.
//
// Since they must have C linkage they have no knowledge of a namespace.
// Give them an obscure name to avoid namespace pollution.
extern "C"
{
  // Older versions of PETSc do not have the different int typedefs.
  // On 64-bit machines, PetscInt may actually be a long long int.
  // This change occurred in Petsc-2.2.1.
#if PETSC_VERSION_LESS_THAN(2,2,1)
  typedef int PetscErrorCode;
  typedef int PetscInt;
#endif

// Function to hand to PETSc's SNES,
// which monitors convergence at X
PetscErrorCode
__libmesh_petsc_diff_solver_monitor (SNES, PetscInt its,
                                     PetscReal fnorm, void *ctx)
{
  PetscDiffSolver& solver =
    *(static_cast<PetscDiffSolver*> (ctx));

  if (solver.verbose)
    libMesh::out << "  PetscDiffSolver step " << its
                 << ", |residual|_2 = " << fnorm << std::endl;

  return 0;
}

// Functions to hand to PETSc's SNES,
// which compute the residual or jacobian at X
PetscErrorCode
__libmesh_petsc_diff_solver_residual (SNES, Vec x, Vec r, void *ctx)
{
  libmesh_assert(x);
  libmesh_assert(r);
  libmesh_assert(ctx);

  PetscDiffSolver& solver =
    *(static_cast<PetscDiffSolver*> (ctx));
  ImplicitSystem &sys = solver.system();

  if (solver.verbose)
    libMesh::out << "Assembling the residual" << std::endl;

  PetscVector<Number>& X_system =
    *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get());
  PetscVector<Number>& R_system =
    *libmesh_cast_ptr<PetscVector<Number>*>(sys.rhs);
  PetscVector<Number> X_input(x, sys.comm()), R_input(r, sys.comm());

  // DiffSystem assembles from the solution and into the rhs, so swap
  // those with our input vectors before assembling.  They'll probably
  // already be references to the same vectors, but PETSc might do
  // something tricky.
  X_input.swap(X_system);
  R_input.swap(R_system);

  // We may need to correct a non-conforming solution
  sys.get_dof_map().enforce_constraints_exactly(sys);

  // We may need to localize a parallel solution
  sys.update();

  // Do DiffSystem assembly
  sys.assembly(true, false);
  R_system.close();

  // Swap back
  X_input.swap(X_system);
  R_input.swap(R_system);

  // No errors, we hope
  return 0;
}

PetscErrorCode
__libmesh_petsc_diff_solver_jacobian (SNES, Vec x, Mat *libmesh_dbg_var(j), Mat *pc,
                                      MatStructure *msflag, void *ctx)
{
  libmesh_assert(x);
  libmesh_assert(j);
//  libmesh_assert_equal_to (pc, j);  // We don't use separate preconditioners yet
  libmesh_assert(ctx);

  PetscDiffSolver& solver =
    *(static_cast<PetscDiffSolver*> (ctx));
  ImplicitSystem &sys = solver.system();

  if (solver.verbose)
    libMesh::out << "Assembling the Jacobian" << std::endl;

  PetscVector<Number>& X_system =
    *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get());
  PetscVector<Number> X_input(x, sys.comm());

  PetscMatrix<Number> J_input(*pc, sys.comm());
  PetscMatrix<Number>& J_system =
    *libmesh_cast_ptr<PetscMatrix<Number>*>(sys.matrix);

  // DiffSystem assembles from the solution and into the jacobian, so
  // swap those with our input vectors before assembling.  They'll
  // probably already be references to the same vectors, but PETSc
  // might do something tricky.
  X_input.swap(X_system);
  J_input.swap(J_system);

  // We may need to correct a non-conforming solution
  sys.get_dof_map().enforce_constraints_exactly(sys);

  // We may need to localize a parallel solution
  sys.update();

  // Do DiffSystem assembly
  sys.assembly(false, true);
  J_system.close();

  // Swap back
  X_input.swap(X_system);
  J_input.swap(J_system);

  *msflag = SAME_NONZERO_PATTERN;

  // No errors, we hope
  return 0;
}

} // extern "C"

PetscDiffSolver::PetscDiffSolver (sys_type& s)
  : Parent(s)
{
}

void PetscDiffSolver::init ()
{
  START_LOG("init()", "PetscDiffSolver");

  Parent::init();

  int ierr=0;

#if PETSC_VERSION_LESS_THAN(2,1,2)
  // At least until Petsc 2.1.1, the SNESCreate had a different
  // calling syntax.  The second argument was of type SNESProblemType,
  // and could have a value of either SNES_NONLINEAR_EQUATIONS or
  // SNES_UNCONSTRAINED_MINIMIZATION.
  ierr = SNESCreate(this->comm().get(), SNES_NONLINEAR_EQUATIONS, &_snes);
  LIBMESH_CHKERRABORT(ierr);
#else
  ierr = SNESCreate(this->comm().get(),&_snes);
  LIBMESH_CHKERRABORT(ierr);
#endif

#if PETSC_VERSION_LESS_THAN(2,3,3)
  ierr = SNESSetMonitor (_snes, __libmesh_petsc_diff_solver_monitor,
                         this, PETSC_NULL);
#else
  // API name change in PETSc 2.3.3
  ierr = SNESMonitorSet (_snes, __libmesh_petsc_diff_solver_monitor,
                         this, PETSC_NULL);
#endif
  LIBMESH_CHKERRABORT(ierr);

  ierr = SNESSetFromOptions(_snes);
  LIBMESH_CHKERRABORT(ierr);

  STOP_LOG("init()", "PetscDiffSolver");
}

PetscDiffSolver::~PetscDiffSolver ()
{
}

void PetscDiffSolver::clear()
{
  START_LOG("clear()", "PetscDiffSolver");

  int ierr=0;

  ierr = LibMeshSNESDestroy(&_snes);
  LIBMESH_CHKERRABORT(ierr);

  STOP_LOG("clear()", "PetscDiffSolver");
}

void PetscDiffSolver::reinit()
{
  Parent::reinit();
}

DiffSolver::SolveResult convert_solve_result(SNESConvergedReason r) {
	switch (r) {
		case SNES_CONVERGED_FNORM_ABS:
			return DiffSolver::CONVERGED_ABSOLUTE_RESIDUAL;
		case SNES_CONVERGED_FNORM_RELATIVE:
			return DiffSolver::CONVERGED_RELATIVE_RESIDUAL;
		case SNES_CONVERGED_SNORM_RELATIVE:
			return DiffSolver::CONVERGED_RELATIVE_STEP;
		case SNES_CONVERGED_ITS:
		case SNES_CONVERGED_TR_DELTA:
			return DiffSolver::CONVERGED_NO_REASON;
		case SNES_DIVERGED_FUNCTION_DOMAIN:
		case SNES_DIVERGED_FUNCTION_COUNT:
		case SNES_DIVERGED_FNORM_NAN:
		case SNES_DIVERGED_INNER:
		case SNES_DIVERGED_LINEAR_SOLVE:
		case SNES_DIVERGED_LOCAL_MIN:
			return DiffSolver::DIVERGED_NO_REASON;
		case SNES_DIVERGED_MAX_IT:
			return DiffSolver::DIVERGED_MAX_NONLINEAR_ITERATIONS;
		case SNES_DIVERGED_LINE_SEARCH:
			return DiffSolver::DIVERGED_BACKTRACKING_FAILURE;
	}
	return DiffSolver::INVALID_SOLVE_RESULT;
}

unsigned int PetscDiffSolver::solve()
{
  this->init();

  START_LOG("solve()", "PetscDiffSolver");

  PetscVector<Number> &x =
    *(libmesh_cast_ptr<PetscVector<Number>*>(_system.solution.get()));
  PetscMatrix<Number> &jac =
    *(libmesh_cast_ptr<PetscMatrix<Number>*>(_system.matrix));
  PetscVector<Number> &r =
    *(libmesh_cast_ptr<PetscVector<Number>*>(_system.rhs));

#ifdef LIBMESH_ENABLE_CONSTRAINTS
  _system.get_dof_map().enforce_constraints_exactly(_system);
#endif

  int ierr = 0;

  ierr = SNESSetFunction (_snes, r.vec(),
                          __libmesh_petsc_diff_solver_residual, this);
    LIBMESH_CHKERRABORT(ierr);

  ierr = SNESSetJacobian (_snes, jac.mat(), jac.mat(),
                          __libmesh_petsc_diff_solver_jacobian, this);
    LIBMESH_CHKERRABORT(ierr);

# if PETSC_VERSION_LESS_THAN(2,2,0)

  ierr = SNESSolve (_snes, x.vec(), &_outer_iterations);
         LIBMESH_CHKERRABORT(ierr);

// 2.2.x style
#elif PETSC_VERSION_LESS_THAN(2,3,0)

  ierr = SNESSolve (_snes, x.vec());
         LIBMESH_CHKERRABORT(ierr);

// 2.3.x & newer style
#else

  ierr = SNESSolve (_snes, PETSC_NULL, x.vec());
         LIBMESH_CHKERRABORT(ierr);

#endif

  STOP_LOG("solve()", "PetscDiffSolver");

  SNESConvergedReason reason;
  SNESGetConvergedReason(_snes, &reason);

  this->clear();

  return convert_solve_result(reason);
}

} // namespace libMesh

#endif // LIBMESH_HAVE_PETSC
<|endoftext|>


<commit_before>#include "util/Role.h"
#include "core/RoleFactory.h"
#include "core/global.h"
#include <map>
#include <hash_map>
#include "dcparser/dcClass.h"
#include "dcparser/dcField.h"

#pragma region definitions
#define STATESERVER_OBJECT_GENERATE_WITH_REQUIRED 2001
#define STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER 2003
#define STATESERVER_OBJECT_UPDATE_FIELD  2004
#define STATESERVER_OBJECT_UPDATE_FIELD_MULTIPLE  2005
#define STATESERVER_OBJECT_DELETE_RAM  2007
#define STATESERVER_OBJECT_SET_ZONE  2008
#define STATESERVER_OBJECT_CHANGE_ZONE  2009
#define STATESERVER_OBJECT_NOTFOUND  2015
#define STATESERVER_QUERY_OBJECT_ALL  2020
#define STATESERVER_QUERY_ZONE_OBJECT_ALL  2021
#define STATESERVER_OBJECT_LOCATE  2022
#define STATESERVER_OBJECT_LOCATE_RESP  2023
#define STATESERVER_OBJECT_QUERY_FIELD  2024
#define STATESERVER_QUERY_OBJECT_ALL_RESP  2030
#define STATESERVER_OBJECT_LEAVING_AI_INTEREST  2033
#define STATESERVER_ADD_AI_RECV  2045
#define STATESERVER_QUERY_ZONE_OBJECT_ALL_DONE  2046
#define STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT  2050
#define STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT  2051
#define STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT_RESP  2052
#define STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT_RESP  2053
#define STATESERVER_OBJECT_DELETE_DISK  2060
#define STATESERVER_SHARD_REST  2061
#define STATESERVER_OBJECT_QUERY_FIELD_RESP  2062
#define STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED  2065
#define STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED_OTHER  2066
#define STATESERVER_OBJECT_ENTER_AI_RECV  2067
#define STATESERVER_OBJECT_ENTER_OWNER_RECV  2068
#define STATESERVER_OBJECT_CHANGE_OWNER_RECV  2069
#define STATESERVER_OBJECT_SET_OWNER_RECV  2070
#define STATESERVER_OBJECT_QUERY_FIELDS  2080
#define STATESERVER_OBJECT_QUERY_FIELDS_RESP  2081
#define STATESERVER_OBJECT_QUERY_FIELDS_STRING  2082
#define STATESERVER_OBJECT_QUERY_MANAGING_AI  2083
#define STATESERVER_BOUNCE_MESSAGE  2086
#define STATESERVER_QUERY_OBJECT_CHILDREN_LOCAL  2087
#define STATESERVER_QUERY_OBJECT_CHILDREN_LOCAL_DONE  2089
#define STATESERVER_QUERY_OBJECT_CHILDREN_RESP  2087

#define LOCATION2CHANNEL(p, z) unsigned long long(p)<<32|unsigned long long(z)
#pragma endregion

void UnpackFieldFromDG(DCPackerInterface *field, DatagramIterator &dgi, std::string &str)
{
	if(field->has_fixed_byte_size())
	{
		str += dgi.read_data(field->get_fixed_byte_size());
	}
	else if(field->get_num_length_bytes() > 0)
	{
		unsigned int length = field->get_num_length_bytes();
		switch(length)
		{
		case 2:
		{
			unsigned short l = dgi.read_uint16();
			str += std::string((char*)&l, 2);
			length = l;
		}
		break;
		case 4:
		{
			unsigned int l = dgi.read_uint32();
			str += std::string((char*)&l, 4);
			length = l;
		}
		break;
		break;
		}
		str += dgi.read_data(length);
	}
	else
	{
		unsigned int nNested = field->get_num_nested_fields();
		for(unsigned int i = 0; i < nNested; ++i)
		{
			UnpackFieldFromDG(field->get_nested_field(i), dgi, str);
		}
	}
}

struct DistributedObject
{
	unsigned long long owner;
	unsigned int parentId;
	unsigned int zoneId;
	unsigned int doId;
	DCClass *dcc;
	std::map<DCField*, std::string> fields;
};

std::map<unsigned int, DistributedObject*> distObjs;

ConfigVariable<unsigned long long> cfg_channel("control", 0);

class StateServer : public Role
{
	public:
		StateServer(RoleConfig roleconfig) : Role(roleconfig)
		{
			MessageDirector::singleton.subscribe_channel(this, cfg_channel.get_rval(m_roleconfig));
		}

		virtual bool handle_datagram(Datagram *dg, DatagramIterator &dgi)
		{
			unsigned long long sender = dgi.read_uint64();
			unsigned short MsgType = dgi.read_uint16();
			switch(MsgType)
			{
				case STATESERVER_OBJECT_GENERATE_WITH_REQUIRED:
				{
					unsigned int parentId = dgi.read_uint32();
					unsigned int zoneId = dgi.read_uint32();
					unsigned short dcId = dgi.read_uint16();
					unsigned int doId = dgi.read_uint32();

					DistributedObject *obj = new DistributedObject;
					obj->doId = doId;
					obj->parentId = parentId;
					obj->zoneId = zoneId;
					obj->owner = sender;
					obj->dcc = gDCF->get_class(dcId);
					for(int i = 0; i < obj->dcc->get_num_inherited_fields(); ++i)
					{
						DCField *field = obj->dcc->get_inherited_field(i);
						if(field->is_required() && !field->as_molecular_field())
						{
							UnpackFieldFromDG(field, dgi, obj->fields[field]);
						}
					}
					distObjs[doId] = obj;
					MessageDirector::singleton.subscribe_channel(this, doId);

					Datagram resp;
					resp.add_uint8(1);
					resp.add_uint64(LOCATION2CHANNEL(parentId, zoneId));
					resp.add_uint64(doId);
					resp.add_uint16(STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED);
					resp.add_uint32(parentId);
					resp.add_uint32(zoneId);
					resp.add_uint16(dcId);
					resp.add_uint32(doId);
					for(auto it = obj->fields.begin(); it != obj->fields.end(); ++it)
					{
						resp.add_data(it->second);
					}

					MessageDirector::singleton.handle_datagram(&resp, this);
				}
				break;
				case STATESERVER_OBJECT_DELETE_RAM:
				{
					unsigned int doId = dgi.read_uint32();
					DistributedObject *obj = distObjs[doId];
					if(obj)
					{
						unsigned long long loc = LOCATION2CHANNEL(obj->parentId, obj->zoneId);
						Datagram resp;
						resp.add_uint8(1);
						resp.add_uint64(loc);
						resp.add_uint64(doId);
						resp.add_uint16(STATESERVER_OBJECT_DELETE_RAM);
						resp.add_uint32(doId);
						MessageDirector::singleton.handle_datagram(&resp, this);
						distObjs[doId] = NULL;
						delete obj;
					}
				}
				break;
				default:
					gLogger->error() << "StateServer recv'd unknown msgtype: " << MsgType << std::endl;
			}
			return true;
		}
};

RoleFactoryItem<StateServer> ss_fact("stateserver");<commit_msg>StateServer: Implement STATESERVER_OBJECT_UPDATE_FIELD; 2/2 tests pass<commit_after>#include "util/Role.h"
#include "core/RoleFactory.h"
#include "core/global.h"
#include <map>
#include <hash_map>
#include "dcparser/dcClass.h"
#include "dcparser/dcField.h"

#pragma region definitions
#define STATESERVER_OBJECT_GENERATE_WITH_REQUIRED 2001
#define STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER 2003
#define STATESERVER_OBJECT_UPDATE_FIELD  2004
#define STATESERVER_OBJECT_UPDATE_FIELD_MULTIPLE  2005
#define STATESERVER_OBJECT_DELETE_RAM  2007
#define STATESERVER_OBJECT_SET_ZONE  2008
#define STATESERVER_OBJECT_CHANGE_ZONE  2009
#define STATESERVER_OBJECT_NOTFOUND  2015
#define STATESERVER_QUERY_OBJECT_ALL  2020
#define STATESERVER_QUERY_ZONE_OBJECT_ALL  2021
#define STATESERVER_OBJECT_LOCATE  2022
#define STATESERVER_OBJECT_LOCATE_RESP  2023
#define STATESERVER_OBJECT_QUERY_FIELD  2024
#define STATESERVER_QUERY_OBJECT_ALL_RESP  2030
#define STATESERVER_OBJECT_LEAVING_AI_INTEREST  2033
#define STATESERVER_ADD_AI_RECV  2045
#define STATESERVER_QUERY_ZONE_OBJECT_ALL_DONE  2046
#define STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT  2050
#define STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT  2051
#define STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT_RESP  2052
#define STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT_RESP  2053
#define STATESERVER_OBJECT_DELETE_DISK  2060
#define STATESERVER_SHARD_REST  2061
#define STATESERVER_OBJECT_QUERY_FIELD_RESP  2062
#define STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED  2065
#define STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED_OTHER  2066
#define STATESERVER_OBJECT_ENTER_AI_RECV  2067
#define STATESERVER_OBJECT_ENTER_OWNER_RECV  2068
#define STATESERVER_OBJECT_CHANGE_OWNER_RECV  2069
#define STATESERVER_OBJECT_SET_OWNER_RECV  2070
#define STATESERVER_OBJECT_QUERY_FIELDS  2080
#define STATESERVER_OBJECT_QUERY_FIELDS_RESP  2081
#define STATESERVER_OBJECT_QUERY_FIELDS_STRING  2082
#define STATESERVER_OBJECT_QUERY_MANAGING_AI  2083
#define STATESERVER_BOUNCE_MESSAGE  2086
#define STATESERVER_QUERY_OBJECT_CHILDREN_LOCAL  2087
#define STATESERVER_QUERY_OBJECT_CHILDREN_LOCAL_DONE  2089
#define STATESERVER_QUERY_OBJECT_CHILDREN_RESP  2087

#define LOCATION2CHANNEL(p, z) unsigned long long(p)<<32|unsigned long long(z)
#pragma endregion

void UnpackFieldFromDG(DCPackerInterface *field, DatagramIterator &dgi, std::string &str)
{
	if(field->has_fixed_byte_size())
	{
		str += dgi.read_data(field->get_fixed_byte_size());
	}
	else if(field->get_num_length_bytes() > 0)
	{
		unsigned int length = field->get_num_length_bytes();
		switch(length)
		{
		case 2:
		{
			unsigned short l = dgi.read_uint16();
			str += std::string((char*)&l, 2);
			length = l;
		}
		break;
		case 4:
		{
			unsigned int l = dgi.read_uint32();
			str += std::string((char*)&l, 4);
			length = l;
		}
		break;
		break;
		}
		str += dgi.read_data(length);
	}
	else
	{
		unsigned int nNested = field->get_num_nested_fields();
		for(unsigned int i = 0; i < nNested; ++i)
		{
			UnpackFieldFromDG(field->get_nested_field(i), dgi, str);
		}
	}
}

struct DistributedObject
{
	unsigned long long owner;
	unsigned int parentId;
	unsigned int zoneId;
	unsigned int doId;
	DCClass *dcc;
	std::map<DCField*, std::string> fields;
};

std::map<unsigned int, DistributedObject*> distObjs;

ConfigVariable<unsigned long long> cfg_channel("control", 0);

class StateServer : public Role
{
	public:
		StateServer(RoleConfig roleconfig) : Role(roleconfig)
		{
			MessageDirector::singleton.subscribe_channel(this, cfg_channel.get_rval(m_roleconfig));
		}

		virtual bool handle_datagram(Datagram *dg, DatagramIterator &dgi)
		{
			unsigned long long sender = dgi.read_uint64();
			unsigned short MsgType = dgi.read_uint16();
			switch(MsgType)
			{
				case STATESERVER_OBJECT_GENERATE_WITH_REQUIRED:
				{
					unsigned int parentId = dgi.read_uint32();
					unsigned int zoneId = dgi.read_uint32();
					unsigned short dcId = dgi.read_uint16();
					unsigned int doId = dgi.read_uint32();

					DistributedObject *obj = new DistributedObject;
					obj->doId = doId;
					obj->parentId = parentId;
					obj->zoneId = zoneId;
					obj->owner = sender;
					obj->dcc = gDCF->get_class(dcId);
					for(int i = 0; i < obj->dcc->get_num_inherited_fields(); ++i)
					{
						DCField *field = obj->dcc->get_inherited_field(i);
						if(field->is_required() && !field->as_molecular_field())
						{
							UnpackFieldFromDG(field, dgi, obj->fields[field]);
						}
					}
					distObjs[doId] = obj;
					MessageDirector::singleton.subscribe_channel(this, doId);

					Datagram resp;
					resp.add_uint8(1);
					resp.add_uint64(LOCATION2CHANNEL(parentId, zoneId));
					resp.add_uint64(doId);
					resp.add_uint16(STATESERVER_OBJECT_ENTERZONE_WITH_REQUIRED);
					resp.add_uint32(parentId);
					resp.add_uint32(zoneId);
					resp.add_uint16(dcId);
					resp.add_uint32(doId);
					for(auto it = obj->fields.begin(); it != obj->fields.end(); ++it)
					{
						resp.add_data(it->second);
					}

					MessageDirector::singleton.handle_datagram(&resp, this);
				}
				break;
				case STATESERVER_OBJECT_DELETE_RAM:
				{
					unsigned int doId = dgi.read_uint32();
					DistributedObject *obj = distObjs[doId];
					if(obj)
					{
						unsigned long long loc = LOCATION2CHANNEL(obj->parentId, obj->zoneId);
						Datagram resp;
						resp.add_uint8(1);
						resp.add_uint64(loc);
						resp.add_uint64(doId);
						resp.add_uint16(STATESERVER_OBJECT_DELETE_RAM);
						resp.add_uint32(doId);
						MessageDirector::singleton.handle_datagram(&resp, this);
						distObjs[doId] = NULL;
						delete obj;
					}
				}
				break;
				case STATESERVER_OBJECT_UPDATE_FIELD:
				{
					unsigned int doId = dgi.read_uint32();
					unsigned int fieldId = dgi.read_uint16();
					if(distObjs[doId])
					{
						std::string data;
						DCField *field = distObjs[doId]->dcc->get_field_by_index(fieldId);
						UnpackFieldFromDG(field, dgi, data);
						if(field->is_required())
						{
							distObjs[doId]->fields[field] = data;
						}
						if(field->is_broadcast())
						{
							Datagram resp;
							resp.add_uint8(1);
							resp.add_uint64(LOCATION2CHANNEL(distObjs[doId]->parentId, distObjs[doId]->zoneId));
							resp.add_uint64(sender);
							resp.add_uint16(STATESERVER_OBJECT_UPDATE_FIELD);
							resp.add_uint32(doId);
							resp.add_uint16(fieldId);
							resp.add_data(data);
							MessageDirector::singleton.handle_datagram(&resp, this);
						}
					}
				}
				break;
				default:
					gLogger->error() << "StateServer recv'd unknown msgtype: " << MsgType << std::endl;
			}
			return true;
		}
};

RoleFactoryItem<StateServer> ss_fact("stateserver");<|endoftext|>


<commit_before>/*
* (C) 2019 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "tests.h"

#if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_HAS_THREAD_UTILS)

#include <botan/internal/thread_pool.h>
#include <chrono>

namespace Botan_Tests {

// TODO test Barrier
// TODO test Semaphore

namespace {

Test::Result thread_pool()
   {
   Test::Result result("Thread_Pool");

   // Using lots of threads since here the works spend most of the time sleeping
   Botan::Thread_Pool pool(16);

   auto sleep_and_return = [](size_t x) -> size_t {
      std::this_thread::sleep_for(std::chrono::milliseconds((x*97)%127));
      return x;
      };

   std::vector<std::future<size_t>> futures;
   for(size_t i = 0; i != 100; ++i)
      {
      auto fut = pool.run(sleep_and_return, i);
      futures.push_back(std::move(fut));
      }

   for(size_t i = 0; i != futures.size(); ++i)
      {
      result.test_eq("Expected return value", futures[i].get(), i);
      }

   pool.shutdown();

   return result;
   }

BOTAN_REGISTER_TEST_FN("thread_pool", thread_pool);

}

}

#endif
<commit_msg>Add a test that Theaad_Pool is tolerant of exceptions during tasks<commit_after>/*
* (C) 2019 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "tests.h"

#if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_HAS_THREAD_UTILS)

#include <botan/internal/thread_pool.h>
#include <chrono>

namespace Botan_Tests {

// TODO test Barrier
// TODO test Semaphore

namespace {

Test::Result thread_pool()
   {
   Test::Result result("Thread_Pool");

   // Using lots of threads since here the works spend most of the time sleeping
   Botan::Thread_Pool pool(16);

   auto sleep_or_throw = [](size_t x) -> size_t {
      std::this_thread::sleep_for(std::chrono::milliseconds((x*97)%127));

      if(x % 2 == 0)
         throw x;
      return x;
      };

   std::vector<std::future<size_t>> futures;
   for(size_t i = 0; i != 100; ++i)
      {
      auto fut = pool.run(sleep_or_throw, i);
      futures.push_back(std::move(fut));
      }

   for(size_t i = 0; i != futures.size(); ++i)
      {
      if(i % 2 == 0)
         {
         try
            {
            futures[i].get();
            result.test_failure("Expected future to throw");
            }
         catch(size_t x)
            {
            result.test_eq("Expected thrown value", x, i);
            }
         }
      else
         {
         result.test_eq("Expected return value", futures[i].get(), i);
         }
      }

   pool.shutdown();

   return result;
   }

BOTAN_REGISTER_TEST_FN("thread_pool", thread_pool);

}

}

#endif
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Project headers.
#include "commandlinehandler.h"

// appleseed.shared headers.
#include "application/application.h"
#include "application/superlogger.h"

// appleseed.foundation headers.
#include "foundation/core/exceptions/exception.h"
#include "foundation/core/exceptions/stringexception.h"
#include "foundation/image/canvasproperties.h"
#include "foundation/image/genericprogressiveimagefilereader.h"
#include "foundation/image/imageattributes.h"
#include "foundation/image/progressiveexrimagefilewriter.h"
#include "foundation/image/tile.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/log.h"

// OpenEXR headers.
#include "OpenEXR/ImfChannelList.h"
#include "OpenEXR/ImfFrameBuffer.h"
#include "OpenEXR/ImfHeader.h"
#include "OpenEXR/ImfPixelType.h"
#include "OpenEXR/ImfTileDescription.h"

// Standard headers.
#include <cstddef>

using namespace appleseed::maketiledexr;
using namespace appleseed::shared;
using namespace foundation;
using namespace std;

//
// Entry point of maketiledexr.
//

int main(int argc, const char* argv[])
{
    SuperLogger logger;

    Application::check_installation(logger);

    CommandLineHandler cl;
    cl.parse(argc, argv, logger);

    // Retrieve the tile size.
    size_t tile_width = 32;
    size_t tile_height = 32;
    if (cl.m_tile_size.is_set())
    {
        const int tw = cl.m_tile_size.values()[0];
        const int th = cl.m_tile_size.values()[1];
        if (tw > 0 && th > 0)
        {
            tile_width = static_cast<size_t>(tw);
            tile_height = static_cast<size_t>(th);
        }
        else
        {
            LOG_ERROR(
                logger,
                "invalid tile size, using default size %dx%d pixels.",
                tile_width,
                tile_height);
        }
    }

    try
    {
        // Open the input file.
        GenericProgressiveImageFileReader reader(&logger, tile_width, tile_height);
        reader.open(cl.m_filenames.values()[0].c_str());

        // Read canvas properties from the input file.
        CanvasProperties props;
        reader.read_canvas_properties(props);

        // Read image attributes from the input file.
        ImageAttributes attrs;
        reader.read_image_attributes(attrs);

        // Open the output file.
        ProgressiveEXRImageFileWriter writer(&logger);
        writer.open(cl.m_filenames.values()[1].c_str(), props, attrs);

        // Copy the tiles.
        for (size_t y = 0; y < props.m_tile_count_y; ++y)
        {
            // Print a progress message.
            if (cl.m_progress_messages.is_set())
            {
                LOG_INFO(
                    logger,
                    "processing tile row " FMT_SIZE_T "/" FMT_SIZE_T "...",
                    y + 1,
                    props.m_tile_count_y);
            }

            for (size_t x = 0; x < props.m_tile_count_x; ++x)
            {
                // Read the tile.
                auto_release_ptr<Tile> tile(reader.read_tile(x, y));

                // Write the tile.
                writer.write_tile(*tile.get(), x, y);
            }
        }

        // Close the files.
        writer.close();
        reader.close();
    }
    catch (const StringException& e)
    {
        LOG_FATAL(logger, "%s: %s", e.what(), e.string());
        return 1;
    }
    catch (const Exception& e)
    {
        LOG_FATAL(logger, "%s", e.what());
        return 1;
    }

    return 0;
}
<commit_msg>maketiledexr will now generate a floating-point (32-bit) OpenEXR file if the pixel format of the input image is not supported by OpenEXR.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Project headers.
#include "commandlinehandler.h"

// appleseed.shared headers.
#include "application/application.h"
#include "application/superlogger.h"

// appleseed.foundation headers.
#include "foundation/core/exceptions/exception.h"
#include "foundation/core/exceptions/stringexception.h"
#include "foundation/image/canvasproperties.h"
#include "foundation/image/exceptionunsupportedimageformat.h"
#include "foundation/image/genericprogressiveimagefilereader.h"
#include "foundation/image/imageattributes.h"
#include "foundation/image/pixel.h"
#include "foundation/image/progressiveexrimagefilewriter.h"
#include "foundation/image/tile.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/log.h"

// OpenEXR headers.
#include "OpenEXR/ImfChannelList.h"
#include "OpenEXR/ImfFrameBuffer.h"
#include "OpenEXR/ImfHeader.h"
#include "OpenEXR/ImfPixelType.h"
#include "OpenEXR/ImfTileDescription.h"

// Standard headers.
#include <cstddef>
#include <memory>

using namespace appleseed::maketiledexr;
using namespace appleseed::shared;
using namespace foundation;
using namespace std;

//
// Entry point of maketiledexr.
//

int main(int argc, const char* argv[])
{
    SuperLogger logger;
    Application::check_installation(logger);

    CommandLineHandler cl;
    cl.parse(argc, argv, logger);

    // Retrieve the tile size.
    size_t tile_width = 32;
    size_t tile_height = 32;
    if (cl.m_tile_size.is_set())
    {
        const int tw = cl.m_tile_size.values()[0];
        const int th = cl.m_tile_size.values()[1];
        if (tw > 0 && th > 0)
        {
            tile_width = static_cast<size_t>(tw);
            tile_height = static_cast<size_t>(th);
        }
        else
        {
            LOG_ERROR(
                logger,
                "invalid tile size, using default size %dx%d pixels.",
                tile_width,
                tile_height);
        }
    }

    try
    {
        // Open the input file.
        GenericProgressiveImageFileReader reader(&logger, tile_width, tile_height);
        reader.open(cl.m_filenames.values()[0].c_str());

        // Read canvas properties from the input file.
        CanvasProperties props;
        reader.read_canvas_properties(props);

        // Read image attributes from the input file.
        ImageAttributes attrs;
        reader.read_image_attributes(attrs);

        // Open the output file.
        ProgressiveEXRImageFileWriter writer(&logger);
        bool require_format_conversion = false;
        try
        {
            writer.open(cl.m_filenames.values()[1].c_str(), props, attrs);
        }
        catch (const ExceptionUnsupportedImageFormat&)
        {
            props =
                CanvasProperties(
                    props.m_canvas_width,
                    props.m_canvas_height,
                    props.m_tile_width,
                    props.m_tile_height,
                    props.m_channel_count,
                    PixelFormatFloat);
            writer.open(cl.m_filenames.values()[1].c_str(), props, attrs);
            require_format_conversion = true;
        }

        // Copy the tiles.
        for (size_t y = 0; y < props.m_tile_count_y; ++y)
        {
            // Print a progress message for every row.
            if (cl.m_progress_messages.is_set())
            {
                LOG_INFO(
                    logger,
                    "processing tile row " FMT_SIZE_T "/" FMT_SIZE_T "...",
                    y + 1,
                    props.m_tile_count_y);
            }

            // Copy the tiles from this row.
            for (size_t x = 0; x < props.m_tile_count_x; ++x)
            {
                // Read the tile. Use auto_release_ptr<> because the image
                // was allocated in appleseed's shared library.
                auto_release_ptr<Tile> tile(reader.read_tile(x, y));

                if (require_format_conversion)
                {
                    // Convert and write the tile.
                    auto_ptr<Tile> converted_tile(new Tile(tile.ref(), PixelFormatFloat));
                    writer.write_tile(*converted_tile.get(), x, y);
                }
                else
                {
                    // Write the tile.
                    writer.write_tile(tile.ref(), x, y);
                }
            }
        }

        // Close the files.
        writer.close();
        reader.close();
    }
    catch (const StringException& e)
    {
        LOG_FATAL(logger, "%s: %s", e.what(), e.string());
        return 1;
    }
    catch (const Exception& e)
    {
        LOG_FATAL(logger, "%s", e.what());
        return 1;
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Private_DataStructures_STLContainerWrapper_inl_
#define _Stroika_Foundation_Containers_Private_DataStructures_STLContainerWrapper_inl_   1

#include    <algorithm>

#include    "../../../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace Private {
                namespace   DataStructures {

                    /*
                     ********************************************************************************
                     ******************* STLContainerWrapper<STL_CONTAINER_OF_T> ********************
                     ********************************************************************************
                     */
                    template    <typename STL_CONTAINER_OF_T>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::Contains (value_type item) const
                    {
                        return this->find (item) != this->end ();
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename FUNCTION>
                    inline  void    STLContainerWrapper<STL_CONTAINER_OF_T>::Apply (FUNCTION doToElement) const
                    {
                        for (auto i = this->begin (); i != this->end (); ++i) {
                            (doToElement) (*i);
                        }
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename FUNCTION>
                    inline  typename STL_CONTAINER_OF_T::const_iterator    STLContainerWrapper<STL_CONTAINER_OF_T>::ApplyUntilTrue (FUNCTION doToElement) const
                    {
                        for (auto i = this->begin (); i != this->end (); ++i) {
                            if ((doToElement) (*i)) {
                                return i;
                            }
                        }
                        return end ();
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template <typename PREDICATE>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::FindIf (PREDICATE pred) const
                    {
                        return std::find_if (this->begin (), this->end (), pred) != this->end ();
                    }

                    /*
                     ********************************************************************************
                     *********** STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator ***********
                     ********************************************************************************
                     */
                    template    <typename STL_CONTAINER_OF_T>
                    inline  STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::ForwardIterator (STLContainerWrapper<STL_CONTAINER_OF_T>* data)
                        : fData (data)
                        , fStdIterator (data->begin ())
                    {
                        RequireNotNull (data);
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    inline  STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::ForwardIterator (const ForwardIterator& from)
                        : fData (from.fData)
                        , fStdIterator (from.fStdIterator)
                    {
                        RequireNotNull (fData);
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::Done () const
                    {
                        AssertNotNull (fData);
                        return fStdIterator == fData->end ();
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename VALUE_TYPE>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::More (VALUE_TYPE* current, bool advance)
                    {
                        bool    done    =   Done ();
                        if (advance) {
                            if (not done) {
                                fStdIterator++;
                                done = Done ();
                            }
                        }
                        if ((current != nullptr) and (not done)) {
                            *current = *fStdIterator;
                        }
                        return not done;
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename VALUE_TYPE>
                    inline  void    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::More (Memory::Optional<VALUE_TYPE>* result, bool advance)
                    {
                        RequireNotNull (result);
                        if (advance) {
                            if (not Done ()) {
                                fStdIterator++;
                            }
                        }
                        if (Done ()) {
                            result->clear ();
                        }
                        else {
                            *result =  *fStdIterator;
                        }
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    inline  size_t    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::CurrentIndex () const
                    {
                        AssertNotNull (fData);
                        return fStdIterator - fData->begin ();
                    }

                }
            }
        }
    }
}
#endif /* _Stroika_Foundation_Containers_Private_DataStructures_STLContainerWrapper_inl_ */
<commit_msg>fixed small template bug (gcc picky)<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Private_DataStructures_STLContainerWrapper_inl_
#define _Stroika_Foundation_Containers_Private_DataStructures_STLContainerWrapper_inl_   1

#include    <algorithm>

#include    "../../../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace Private {
                namespace   DataStructures {

                    /*
                     ********************************************************************************
                     ******************* STLContainerWrapper<STL_CONTAINER_OF_T> ********************
                     ********************************************************************************
                     */
                    template    <typename STL_CONTAINER_OF_T>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::Contains (value_type item) const
                    {
                        return this->find (item) != this->end ();
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename FUNCTION>
                    inline  void    STLContainerWrapper<STL_CONTAINER_OF_T>::Apply (FUNCTION doToElement) const
                    {
                        for (auto i = this->begin (); i != this->end (); ++i) {
                            (doToElement) (*i);
                        }
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename FUNCTION>
                    inline  typename STL_CONTAINER_OF_T::const_iterator    STLContainerWrapper<STL_CONTAINER_OF_T>::ApplyUntilTrue (FUNCTION doToElement) const
                    {
                        for (auto i = this->begin (); i != this->end (); ++i) {
                            if ((doToElement) (*i)) {
                                return i;
                            }
                        }
                        return this->end ();
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template <typename PREDICATE>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::FindIf (PREDICATE pred) const
                    {
                        return std::find_if (this->begin (), this->end (), pred) != this->end ();
                    }

                    /*
                     ********************************************************************************
                     *********** STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator ***********
                     ********************************************************************************
                     */
                    template    <typename STL_CONTAINER_OF_T>
                    inline  STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::ForwardIterator (STLContainerWrapper<STL_CONTAINER_OF_T>* data)
                        : fData (data)
                        , fStdIterator (data->begin ())
                    {
                        RequireNotNull (data);
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    inline  STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::ForwardIterator (const ForwardIterator& from)
                        : fData (from.fData)
                        , fStdIterator (from.fStdIterator)
                    {
                        RequireNotNull (fData);
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::Done () const
                    {
                        AssertNotNull (fData);
                        return fStdIterator == fData->end ();
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename VALUE_TYPE>
                    inline  bool    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::More (VALUE_TYPE* current, bool advance)
                    {
                        bool    done    =   Done ();
                        if (advance) {
                            if (not done) {
                                fStdIterator++;
                                done = Done ();
                            }
                        }
                        if ((current != nullptr) and (not done)) {
                            *current = *fStdIterator;
                        }
                        return not done;
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    template    <typename VALUE_TYPE>
                    inline  void    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::More (Memory::Optional<VALUE_TYPE>* result, bool advance)
                    {
                        RequireNotNull (result);
                        if (advance) {
                            if (not Done ()) {
                                fStdIterator++;
                            }
                        }
                        if (Done ()) {
                            result->clear ();
                        }
                        else {
                            *result =  *fStdIterator;
                        }
                    }
                    template    <typename STL_CONTAINER_OF_T>
                    inline  size_t    STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::CurrentIndex () const
                    {
                        AssertNotNull (fData);
                        return fStdIterator - fData->begin ();
                    }

                }
            }
        }
    }
}
#endif /* _Stroika_Foundation_Containers_Private_DataStructures_STLContainerWrapper_inl_ */
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "gtest/gtest.h"
#include "corgi/vector_pool.h"

#define TEST_ALL_SIZES_F(MY_TEST) \
  TEST_F(VectorPoolTests, MY_TEST##_int8) { \
    MY_TEST##_Test<int8_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_uint8) { \
    MY_TEST##_Test<uint8_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_int16) { \
    MY_TEST##_Test<int16_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_uint16) { \
    MY_TEST##_Test<uint16_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_int32) { \
    MY_TEST##_Test<int32_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_uint32) { \
    MY_TEST##_Test<uint32_t>(); \
  }

class VectorPoolTests : public ::testing::Test {
protected:
  virtual void SetUp() {}
  virtual void TearDown() {}
};

template <typename T>
struct TestStruct {
  TestStruct() { value = 123; }
  TestStruct(T val) : value(val) {}
  T value;
};

#define VECTORPOOL_REF typename \
    corgi::VectorPool<TestStruct<DataType>>::VectorPoolReference

// Test that allocated variables are initialized according to their constructor.
template<class DataType>
void AllocAndFree_Constructor_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  for (int i = 0; i < 100; i++) {
    VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToFront);
    EXPECT_EQ(ref->value, 123);
  }
}
TEST_ALL_SIZES_F(AllocAndFree_Constructor)

// Test allocating and freeing one element.
template<class DataType>
void AllocAndFree_OneElement_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;
  EXPECT_EQ(pool.active_count(), 0);
  ref = pool.GetNewElement(corgi::kAddToFront);
  EXPECT_TRUE(ref.IsValid());
  EXPECT_EQ(pool.active_count(), 1);
  pool.FreeElement(ref);
  EXPECT_EQ(pool.active_count(), 0);
  EXPECT_FALSE(ref.IsValid());
}
TEST_ALL_SIZES_F(AllocAndFree_OneElement)

// Test allocating and freeing two elements.
template<class DataType>
void AllocAndFree_TwoElementsElement_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref1;
  VECTORPOOL_REF ref2;
  EXPECT_EQ(pool.active_count(), 0);
  ref1 = pool.GetNewElement(corgi::kAddToFront);
  ref2 = pool.GetNewElement(corgi::kAddToFront);
  EXPECT_TRUE(ref1.IsValid());
  EXPECT_TRUE(ref2.IsValid());
  EXPECT_EQ(pool.active_count(), 2);

  pool.FreeElement(ref1);
  EXPECT_FALSE(ref1.IsValid());
  EXPECT_EQ(pool.active_count(), 1);

  pool.FreeElement(ref2);
  EXPECT_FALSE(ref2.IsValid());
  EXPECT_EQ(pool.active_count(), 0);
}
TEST_ALL_SIZES_F(AllocAndFree_TwoElementsElement)

// Test allocating and freeing many elements.
// Starts out allocating 100 elements, numbered 1 to 100.
// Then removes the odd numbered elements.  Then adds 50 more elements
// to the front and back of the list.  So the final list should look like:
// 0-49: [elements numbered 49-0]
// 50-99: [odd numbered elements numbered 1-99]
// 100-149: [elements numbered 50-99]
template<class DataType>
void AllocAndFree_ManyElementsElement_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;
  for (int i = 0; i < 100; i++) {
    ref = pool.GetNewElement(corgi::kAddToBack);
    EXPECT_TRUE(ref.IsValid());
    ref->value = i;
  }
  // Remove all the even numbers.
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    ref = iter.ToReference();
    ++iter;
    pool.FreeElement(ref);
    EXPECT_FALSE(ref.IsValid());
  }
  // The list now contains the even numbers between 0 and 98.
  // Add in more numbers before and after the list:
  for (int i = 0; i < 50; i++) {
    ref = pool.GetNewElement(corgi::kAddToFront);
    ref->value = i;
    ref = pool.GetNewElement(corgi::kAddToBack);
    ref->value = i + 50;
  }

  // Check our list contents:
  auto iter = pool.begin();

  // First 50 (numbered 0-49)
  for (int i = 49; i >= 0; i--) {
    EXPECT_EQ(iter->value, i);
    ++iter;
  }
  // Second 50, numbered 0-49
  for (int i = 1; i < 100; i += 2) {
    EXPECT_EQ(iter->value, i);
    ++iter;
  }
  // Final 50, numbered 50-99
  for (int i = 50; i < 100; i++) {
    EXPECT_EQ(iter->value, i);
    ++iter;
  }
  EXPECT_EQ(iter, pool.end());
}
TEST_ALL_SIZES_F(AllocAndFree_ManyElementsElement)

// Test adding a bunch of elements to the back, and making sure the
// order is what we expect.
template<class DataType>
void InsertionOrder_AddToBack_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;

  for (int i = 0; i < 100; i++) {
    ref = pool.GetNewElement(corgi::kAddToBack);
    EXPECT_TRUE(ref.IsValid());
    ref->value = i;
  }

  int i = 0;
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    EXPECT_EQ(i, iter->value);
    i++;
  }
}
TEST_ALL_SIZES_F(InsertionOrder_AddToBack)

// Test adding a bunch of elements to the front, and making sure the
// order is what we expect.
template<class DataType>
void InsertionOrder_AddToFront_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;

  for (int i = 0; i < 100; i++) {
    ref = pool.GetNewElement(corgi::kAddToFront);
    EXPECT_TRUE(ref.IsValid());
    ref->value = i;
  }

  int i = 99;
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    EXPECT_EQ(i, iter->value);
    i--;
  }
}
TEST_ALL_SIZES_F(InsertionOrder_AddToFront)

// Tests that begin and end point to each other in an empty pool,
// Don't point to each other in a non-empty-pool, and then do
// point to each other again if the non-empty pool has been emptied.
template<class DataType>
void Iterator_BeginEnd_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  EXPECT_EQ(pool.begin(), pool.end());
  VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToFront);
  EXPECT_NE(pool.begin(), pool.end());
  pool.FreeElement(ref);
  EXPECT_EQ(pool.begin(), pool.end());
}
TEST_ALL_SIZES_F(Iterator_BeginEnd)

// Test that we can step through the pool via an iterator,
// and that it takes us the correct number of steps.
template<class DataType>
void Iterator_StepThrough_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  for (int i = 0; i < 100; i ++) {
    VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToBack);
    ref->value = i;
  }

  int counter = 0;
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    EXPECT_EQ(iter->value, counter);
    counter++;
  }
  EXPECT_EQ(counter, 100);
}
TEST_ALL_SIZES_F(Iterator_StepThrough)

// Test that we can step backwards through the pool via an iterator,
// and that it takes us the correct number of steps.
template<class DataType>
void Iterator_StepBackwards_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  for (int i = 0; i < 100; i ++) {
    VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToBack);
    ref->value = i;
  }

  int counter = 0;

  for (auto iter = --pool.end(); iter != pool.begin(); --iter) {
    counter++;
    EXPECT_EQ(iter->value, 100 - counter);
  }
  // Not 100 here, because we had to advance it once during initialization,
  // to get our iterator off of end().
  EXPECT_EQ(counter, 99);
}
TEST_ALL_SIZES_F(Iterator_StepBackwards)

#if !defined(__ANDROID__)
int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
#endif // !defined(__ANDROID__)
<commit_msg>Fix signed/unsigned comparison warnings.<commit_after>// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "gtest/gtest.h"
#include "corgi/vector_pool.h"

#define TEST_ALL_SIZES_F(MY_TEST) \
  TEST_F(VectorPoolTests, MY_TEST##_int8) { \
    MY_TEST##_Test<int8_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_uint8) { \
    MY_TEST##_Test<uint8_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_int16) { \
    MY_TEST##_Test<int16_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_uint16) { \
    MY_TEST##_Test<uint16_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_int32) { \
    MY_TEST##_Test<int32_t>(); \
  } \
  TEST_F(VectorPoolTests, MY_TEST##_uint32) { \
    MY_TEST##_Test<uint32_t>(); \
  }

class VectorPoolTests : public ::testing::Test {
protected:
  virtual void SetUp() {}
  virtual void TearDown() {}
};

template <typename T>
struct TestStruct {
  TestStruct() { value = 123; }
  TestStruct(T val) : value(val) {}
  T value;
};

#define VECTORPOOL_REF typename \
    corgi::VectorPool<TestStruct<DataType>>::VectorPoolReference

// Test that allocated variables are initialized according to their constructor.
template<class DataType>
void AllocAndFree_Constructor_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  for (int i = 0; i < 100; i++) {
    VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToFront);
    EXPECT_EQ(ref->value, static_cast<DataType>(123));
  }
}
TEST_ALL_SIZES_F(AllocAndFree_Constructor)

// Test allocating and freeing one element.
template<class DataType>
void AllocAndFree_OneElement_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;
  EXPECT_EQ(pool.active_count(), 0u);
  ref = pool.GetNewElement(corgi::kAddToFront);
  EXPECT_TRUE(ref.IsValid());
  EXPECT_EQ(pool.active_count(), 1u);
  pool.FreeElement(ref);
  EXPECT_EQ(pool.active_count(), 0u);
  EXPECT_FALSE(ref.IsValid());
}
TEST_ALL_SIZES_F(AllocAndFree_OneElement)

// Test allocating and freeing two elements.
template<class DataType>
void AllocAndFree_TwoElementsElement_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref1;
  VECTORPOOL_REF ref2;
  EXPECT_EQ(pool.active_count(), 0u);
  ref1 = pool.GetNewElement(corgi::kAddToFront);
  ref2 = pool.GetNewElement(corgi::kAddToFront);
  EXPECT_TRUE(ref1.IsValid());
  EXPECT_TRUE(ref2.IsValid());
  EXPECT_EQ(pool.active_count(), 2u);

  pool.FreeElement(ref1);
  EXPECT_FALSE(ref1.IsValid());
  EXPECT_EQ(pool.active_count(), 1u);

  pool.FreeElement(ref2);
  EXPECT_FALSE(ref2.IsValid());
  EXPECT_EQ(pool.active_count(), 0u);
}
TEST_ALL_SIZES_F(AllocAndFree_TwoElementsElement)

// Test allocating and freeing many elements.
// Starts out allocating 100 elements, numbered 1 to 100.
// Then removes the odd numbered elements.  Then adds 50 more elements
// to the front and back of the list.  So the final list should look like:
// 0-49: [elements numbered 49-0]
// 50-99: [odd numbered elements numbered 1-99]
// 100-149: [elements numbered 50-99]
template<class DataType>
void AllocAndFree_ManyElementsElement_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;
  for (int i = 0; i < 100; i++) {
    ref = pool.GetNewElement(corgi::kAddToBack);
    EXPECT_TRUE(ref.IsValid());
    ref->value = i;
  }
  // Remove all the even numbers.
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    ref = iter.ToReference();
    ++iter;
    pool.FreeElement(ref);
    EXPECT_FALSE(ref.IsValid());
  }
  // The list now contains the even numbers between 0 and 98.
  // Add in more numbers before and after the list:
  for (int i = 0; i < 50; i++) {
    ref = pool.GetNewElement(corgi::kAddToFront);
    ref->value = i;
    ref = pool.GetNewElement(corgi::kAddToBack);
    ref->value = i + 50;
  }

  // Check our list contents:
  auto iter = pool.begin();

  // First 50 (numbered 0-49)
  for (int i = 49; i >= 0; i--) {
    EXPECT_EQ(iter->value, static_cast<DataType>(i));
    ++iter;
  }
  // Second 50, numbered 0-49
  for (int i = 1; i < 100; i += 2) {
    EXPECT_EQ(iter->value, static_cast<DataType>(i));
    ++iter;
  }
  // Final 50, numbered 50-99
  for (int i = 50; i < 100; i++) {
    EXPECT_EQ(iter->value, static_cast<DataType>(i));
    ++iter;
  }
  EXPECT_EQ(iter, pool.end());
}
TEST_ALL_SIZES_F(AllocAndFree_ManyElementsElement)

// Test adding a bunch of elements to the back, and making sure the
// order is what we expect.
template<class DataType>
void InsertionOrder_AddToBack_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;

  for (int i = 0; i < 100; i++) {
    ref = pool.GetNewElement(corgi::kAddToBack);
    EXPECT_TRUE(ref.IsValid());
    ref->value = i;
  }

  int i = 0;
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    EXPECT_EQ(i, static_cast<int>(iter->value));
    i++;
  }
}
TEST_ALL_SIZES_F(InsertionOrder_AddToBack)

// Test adding a bunch of elements to the front, and making sure the
// order is what we expect.
template<class DataType>
void InsertionOrder_AddToFront_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  VECTORPOOL_REF ref;

  for (int i = 0; i < 100; i++) {
    ref = pool.GetNewElement(corgi::kAddToFront);
    EXPECT_TRUE(ref.IsValid());
    ref->value = i;
  }

  int i = 99;
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    EXPECT_EQ(i, static_cast<int>(iter->value));
    i--;
  }
}
TEST_ALL_SIZES_F(InsertionOrder_AddToFront)

// Tests that begin and end point to each other in an empty pool,
// Don't point to each other in a non-empty-pool, and then do
// point to each other again if the non-empty pool has been emptied.
template<class DataType>
void Iterator_BeginEnd_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  EXPECT_EQ(pool.begin(), pool.end());
  VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToFront);
  EXPECT_NE(pool.begin(), pool.end());
  pool.FreeElement(ref);
  EXPECT_EQ(pool.begin(), pool.end());
}
TEST_ALL_SIZES_F(Iterator_BeginEnd)

// Test that we can step through the pool via an iterator,
// and that it takes us the correct number of steps.
template<class DataType>
void Iterator_StepThrough_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  for (int i = 0; i < 100; i ++) {
    VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToBack);
    ref->value = i;
  }

  int counter = 0;
  for (auto iter = pool.begin(); iter != pool.end(); ++iter) {
    EXPECT_EQ(static_cast<int>(iter->value), counter);
    counter++;
  }
  EXPECT_EQ(counter, 100);
}
TEST_ALL_SIZES_F(Iterator_StepThrough)

// Test that we can step backwards through the pool via an iterator,
// and that it takes us the correct number of steps.
template<class DataType>
void Iterator_StepBackwards_Test() {
  corgi::VectorPool<TestStruct<DataType>> pool;
  for (int i = 0; i < 100; i ++) {
    VECTORPOOL_REF ref = pool.GetNewElement(corgi::kAddToBack);
    ref->value = i;
  }

  int counter = 0;

  for (auto iter = --pool.end(); iter != pool.begin(); --iter) {
    counter++;
    EXPECT_EQ(static_cast<int>(iter->value), 100 - counter);
  }
  // Not 100 here, because we had to advance it once during initialization,
  // to get our iterator off of end().
  EXPECT_EQ(counter, 99);
}
TEST_ALL_SIZES_F(Iterator_StepBackwards)

#if !defined(__ANDROID__)
int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
#endif // !defined(__ANDROID__)
<|endoftext|>


<commit_before>//===-- ArchSpecTest.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"

#include "lldb/Core/ArchSpec.h"

#include "llvm/BinaryFormat/MachO.h"

using namespace lldb;
using namespace lldb_private;

TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleSimple) {

  // Success conditions.  Valid cpu/subtype combinations using both - and .
  ArchSpec AS;
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12.15", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());

  // Failure conditions.

  // Valid string, unknown cpu/subtype.
  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("13.11", AS));
  EXPECT_EQ(0u, AS.GetMachOCPUType());
  EXPECT_EQ(0u, AS.GetMachOCPUSubType());

  // Missing / invalid cpu or subtype
  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13", AS));

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13.A", AS));

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("A.13", AS));

  // Empty string.
  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("", AS));
}

TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleExtra) {
  ArchSpec AS;
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor-os", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());
  EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
  EXPECT_EQ("os", AS.GetTriple().getOSName());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor-os-name", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());
  EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
  EXPECT_EQ("os", AS.GetTriple().getOSName());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor.os-name", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());
  EXPECT_EQ("vendor.os", AS.GetTriple().getVendorName());
  EXPECT_EQ("name", AS.GetTriple().getOSName());

  // These there should parse correctly, but the vendor / OS should be defaulted
  // since they are unrecognized.
  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());
  EXPECT_EQ("apple", AS.GetTriple().getVendorName());
  EXPECT_EQ("", AS.GetTriple().getOSName());

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12.10.10", AS));

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12-10.10", AS));
}

TEST(ArchSpecTest, TestSetTriple) {
  ArchSpec AS;

  // Various flavors of valid triples.
  EXPECT_TRUE(AS.SetTriple("12-10-apple-darwin"));
  EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_ARM), AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());
  EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
                  .consume_front("armv7f-apple-darwin"));
  EXPECT_EQ(ArchSpec::eCore_arm_armv7f, AS.GetCore());

  AS = ArchSpec();
  EXPECT_TRUE(AS.SetTriple("18.100-apple-darwin"));
  EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_POWERPC), AS.GetMachOCPUType());
  EXPECT_EQ(100u, AS.GetMachOCPUSubType());
  EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
                  .consume_front("powerpc-apple-darwin"));
  EXPECT_EQ(ArchSpec::eCore_ppc_ppc970, AS.GetCore());

  AS = ArchSpec();
  EXPECT_TRUE(AS.SetTriple("i686-pc-windows"));
  EXPECT_EQ(llvm::Triple::x86, AS.GetTriple().getArch());
  EXPECT_EQ(llvm::Triple::PC, AS.GetTriple().getVendor());
  EXPECT_EQ(llvm::Triple::Win32, AS.GetTriple().getOS());
  EXPECT_TRUE(
      llvm::StringRef(AS.GetTriple().str()).consume_front("i686-pc-windows"));
  EXPECT_STREQ("i686", AS.GetArchitectureName());
  EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore());

  // Various flavors of invalid triples.
  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));

  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple("unknown"));

  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple(""));
}

TEST(ArchSpecTest, MergeFrom) {
  ArchSpec A;
  ArchSpec B("x86_64-pc-linux");

  EXPECT_FALSE(A.IsValid());
  ASSERT_TRUE(B.IsValid());
  EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
  EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
  EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
  EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());

  A.MergeFrom(B);
  ASSERT_TRUE(A.IsValid());
  EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
  EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
  EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
  EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
}
<commit_msg>[ArchSpec] Add a unittest to complement the change in r321856.<commit_after>//===-- ArchSpecTest.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"

#include "lldb/Core/ArchSpec.h"

#include "llvm/BinaryFormat/MachO.h"

using namespace lldb;
using namespace lldb_private;

TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleSimple) {

  // Success conditions.  Valid cpu/subtype combinations using both - and .
  ArchSpec AS;
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12.15", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());

  // Failure conditions.

  // Valid string, unknown cpu/subtype.
  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("13.11", AS));
  EXPECT_EQ(0u, AS.GetMachOCPUType());
  EXPECT_EQ(0u, AS.GetMachOCPUSubType());

  // Missing / invalid cpu or subtype
  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13", AS));

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13.A", AS));

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("A.13", AS));

  // Empty string.
  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("", AS));
}

TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleExtra) {
  ArchSpec AS;
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor-os", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());
  EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
  EXPECT_EQ("os", AS.GetTriple().getOSName());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor-os-name", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());
  EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
  EXPECT_EQ("os", AS.GetTriple().getOSName());

  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor.os-name", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(15u, AS.GetMachOCPUSubType());
  EXPECT_EQ("vendor.os", AS.GetTriple().getVendorName());
  EXPECT_EQ("name", AS.GetTriple().getOSName());

  // These there should parse correctly, but the vendor / OS should be defaulted
  // since they are unrecognized.
  AS = ArchSpec();
  EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor", AS));
  EXPECT_EQ(12u, AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());
  EXPECT_EQ("apple", AS.GetTriple().getVendorName());
  EXPECT_EQ("", AS.GetTriple().getOSName());

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12.10.10", AS));

  AS = ArchSpec();
  EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12-10.10", AS));
}

TEST(ArchSpecTest, TestSetTriple) {
  ArchSpec AS;

  // Various flavors of valid triples.
  EXPECT_TRUE(AS.SetTriple("12-10-apple-darwin"));
  EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_ARM), AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());
  EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
                  .consume_front("armv7f-apple-darwin"));
  EXPECT_EQ(ArchSpec::eCore_arm_armv7f, AS.GetCore());

  AS = ArchSpec();
  EXPECT_TRUE(AS.SetTriple("18.100-apple-darwin"));
  EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_POWERPC), AS.GetMachOCPUType());
  EXPECT_EQ(100u, AS.GetMachOCPUSubType());
  EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
                  .consume_front("powerpc-apple-darwin"));
  EXPECT_EQ(ArchSpec::eCore_ppc_ppc970, AS.GetCore());

  AS = ArchSpec();
  EXPECT_TRUE(AS.SetTriple("i686-pc-windows"));
  EXPECT_EQ(llvm::Triple::x86, AS.GetTriple().getArch());
  EXPECT_EQ(llvm::Triple::PC, AS.GetTriple().getVendor());
  EXPECT_EQ(llvm::Triple::Win32, AS.GetTriple().getOS());
  EXPECT_TRUE(
      llvm::StringRef(AS.GetTriple().str()).consume_front("i686-pc-windows"));
  EXPECT_STREQ("i686", AS.GetArchitectureName());
  EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore());

  // Various flavors of invalid triples.
  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));

  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple("unknown"));

  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple(""));
}

TEST(ArchSpecTest, MergeFrom) {
  ArchSpec A;
  ArchSpec B("x86_64-pc-linux");

  EXPECT_FALSE(A.IsValid());
  ASSERT_TRUE(B.IsValid());
  EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
  EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
  EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
  EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());

  A.MergeFrom(B);
  ASSERT_TRUE(A.IsValid());
  EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
  EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
  EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
  EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
}

TEST(ArchSpecTest, MergeFromMachOUnknown) {
  class MyArchSpec : public ArchSpec {
  public:
    MyArchSpec() {
      this->SetTriple("unknown-mach-64");
      this->m_core = ArchSpec::eCore_uknownMach64;
      this->m_byte_order = eByteOrderLittle;
      this->m_flags = 0;
    }
  };

  MyArchSpec A;
  ASSERT_TRUE(A.IsValid());
  MyArchSpec B;
  ASSERT_TRUE(B.IsValid());
  A.MergeFrom(B);
  ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64);
}
<|endoftext|>