<commit_before>/*
 * INTEL CONFIDENTIAL
 * Copyright © 2011 Intel
 * Corporation All Rights Reserved.
 *
 * The source code contained or described herein and all documents related to
 * the source code ("Material") are owned by Intel Corporation or its suppliers
 * or licensors. Title to the Material remains with Intel Corporation or its
 * suppliers and licensors. The Material contains trade secrets and proprietary
 * and confidential information of Intel or its suppliers and licensors. The
 * Material is protected by worldwide copyright and trade secret laws and
 * treaty provisions. No part of the Material may be used, copied, reproduced,
 * modified, published, uploaded, posted, transmitted, distributed, or
 * disclosed in any way without Intel’s prior express written permission.
 *
 * No license under any patent, copyright, trade secret or other intellectual
 * property right is granted to or conferred upon you by disclosure or delivery
 * of the Materials, either expressly, by implication, inducement, estoppel or
 * otherwise. Any license under such intellectual property rights must be
 * express and approved by Intel in writing.
 *
 * CREATED: 2012-03-29
 * UPDATED: 2012-03-29
 */
#include "SubsystemLibrary.h"
#include "NamedElementBuilderTemplate.h"
#include "FSSubsystem.h"

extern "C"
{
void getFSSubsystemBuilder(CSubsystemLibrary* pSubsystemLibrary)
{
    pSubsystemLibrary->addElementBuilder(new TNamedElementBuilderTemplate<CFSSubsystem>("FS"));
}
}
<commit_msg>Change the element builder semantic<commit_after>/*
 * INTEL CONFIDENTIAL
 * Copyright © 2011 Intel
 * Corporation All Rights Reserved.
 *
 * The source code contained or described herein and all documents related to
 * the source code ("Material") are owned by Intel Corporation or its suppliers
 * or licensors. Title to the Material remains with Intel Corporation or its
 * suppliers and licensors. The Material contains trade secrets and proprietary
 * and confidential information of Intel or its suppliers and licensors. The
 * Material is protected by worldwide copyright and trade secret laws and
 * treaty provisions. No part of the Material may be used, copied, reproduced,
 * modified, published, uploaded, posted, transmitted, distributed, or
 * disclosed in any way without Intel’s prior express written permission.
 *
 * No license under any patent, copyright, trade secret or other intellectual
 * property right is granted to or conferred upon you by disclosure or delivery
 * of the Materials, either expressly, by implication, inducement, estoppel or
 * otherwise. Any license under such intellectual property rights must be
 * express and approved by Intel in writing.
 *
 * CREATED: 2012-03-29
 * UPDATED: 2012-03-29
 */
#include "SubsystemLibrary.h"
#include "NamedElementBuilderTemplate.h"
#include "FSSubsystem.h"

extern "C"
{
void getFSSubsystemBuilder(CSubsystemLibrary* pSubsystemLibrary)
{
    pSubsystemLibrary->addElementBuilder("FS", new TNamedElementBuilderTemplate<CFSSubsystem>());
}
}
<|endoftext|>


<commit_before>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

/// One implementation of GUPS. This does no load-balancing, and may
/// suffer from some load imbalance.

#include <Grappa.hpp>
#include "ForkJoin.hpp"
#include "GlobalAllocator.hpp"

#include <boost/test/unit_test.hpp>

DEFINE_int64( iterations, 1 << 30, "Iterations" );
DEFINE_int64( sizeA, 1000, "Size of array that gups increments" );

double wall_clock_time() {
  const double nano = 1.0e-9;
  timespec t;
  clock_gettime( CLOCK_MONOTONIC, &t );
  return nano * t.tv_nsec + t.tv_sec;
}

BOOST_AUTO_TEST_SUITE( Gups_tests );

LOOP_FUNCTION( func_start_profiling, index ) {
  Grappa_start_profiling();
}

LOOP_FUNCTION( func_stop_profiling, index ) {
  Grappa_stop_profiling();
}

/// Functor to execute one GUP.
LOOP_FUNCTOR( func_gups, index, ((GlobalAddress<int64_t>, Array)) ) {
  const uint64_t LARGE_PRIME = 18446744073709551557UL;
  uint64_t b = (index*LARGE_PRIME) % FLAGS_sizeA;
  Grappa_delegate_fetch_and_add_word( Array + b, 1 );
}

void user_main( int * args ) {

  func_start_profiling start_profiling;
  func_stop_profiling stop_profiling;

  GlobalAddress<int64_t> A = Grappa_typed_malloc<int64_t>(FLAGS_sizeA);

  func_gups gups( A );

  fork_join_custom( &start_profiling );

  double start = wall_clock_time();
  fork_join( &gups, 1, FLAGS_iterations );
  double end = wall_clock_time();

  fork_join_custom( &stop_profiling );

<<<<<<< HEAD
  Grappa_merge_and_dump_stats();

=======
>>>>>>> change stats to dump a single JSON blob
  double runtime = end - start;
  double throughput = FLAGS_iterations / runtime;

  int nnodes = atoi(getenv("SLURM_NNODES"));
  double throughput_per_node = throughput/nnodes;

  SoftXMT_add_profiling_value( &runtime, "runtime", "s", false, 0.0 );
  SoftXMT_add_profiling_integer( &FLAGS_iterations, "iterations", "it", false, 0 );
  SoftXMT_add_profiling_integer( &FLAGS_sizeA, "sizeA", "entries", false, 0 );
  SoftXMT_add_profiling_value( &throughput, "updates_per_s", "up/s", false, 0.0 );
  SoftXMT_add_profiling_value( &throughput_per_node, "updates_per_s_per_node", "up/s", false, 0.0 );

  SoftXMT_merge_and_dump_stats();

  LOG(INFO) << "GUPS: "
            << FLAGS_iterations << " updates at "
            << throughput << "updates/s ("
            << throughput/nnodes << " updates/s/node).";
}

BOOST_AUTO_TEST_CASE( test1 ) {
    Grappa_init( &(boost::unit_test::framework::master_test_suite().argc),
		  &(boost::unit_test::framework::master_test_suite().argv) );
    Grappa_activate();

    Grappa_run_user_main( &user_main, (int*)NULL );

    Grappa_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>Move gups user stats insertion before work<commit_after>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

/// One implementation of GUPS. This does no load-balancing, and may
/// suffer from some load imbalance.

#include <Grappa.hpp>
#include "ForkJoin.hpp"
#include "GlobalAllocator.hpp"

#include <boost/test/unit_test.hpp>

DEFINE_int64( iterations, 1 << 30, "Iterations" );
DEFINE_int64( sizeA, 1000, "Size of array that gups increments" );

double wall_clock_time() {
  const double nano = 1.0e-9;
  timespec t;
  clock_gettime( CLOCK_MONOTONIC, &t );
  return nano * t.tv_nsec + t.tv_sec;
}

BOOST_AUTO_TEST_SUITE( Gups_tests );

LOOP_FUNCTION( func_start_profiling, index ) {
  Grappa_start_profiling();
}

LOOP_FUNCTION( func_stop_profiling, index ) {
  Grappa_stop_profiling();
}

/// Functor to execute one GUP.
LOOP_FUNCTOR( func_gups, index, ((GlobalAddress<int64_t>, Array)) ) {
  const uint64_t LARGE_PRIME = 18446744073709551557UL;
  uint64_t b = (index*LARGE_PRIME) % FLAGS_sizeA;
  Grappa_delegate_fetch_and_add_word( Array + b, 1 );
}

void user_main( int * args ) {

  func_start_profiling start_profiling;
  func_stop_profiling stop_profiling;

  GlobalAddress<int64_t> A = Grappa_typed_malloc<int64_t>(FLAGS_sizeA);

  func_gups gups( A );

  double runtime = 0.0;
  double throughput = 0.0;
  int nnodes = atoi(getenv("SLURM_NNODES"));
  double throughput_per_node = 0.0;

  SoftXMT_add_profiling_value( &runtime, "runtime", "s", false, 0.0 );
  SoftXMT_add_profiling_integer( &FLAGS_iterations, "iterations", "it", false, 0 );
  SoftXMT_add_profiling_integer( &FLAGS_sizeA, "sizeA", "entries", false, 0 );
  SoftXMT_add_profiling_value( &throughput, "updates_per_s", "up/s", false, 0.0 );
  SoftXMT_add_profiling_value( &throughput_per_node, "updates_per_s_per_node", "up/s", false, 0.0 );

  fork_join_custom( &start_profiling );

  double start = wall_clock_time();
  fork_join( &gups, 1, FLAGS_iterations );
  double end = wall_clock_time();

  fork_join_custom( &stop_profiling );

  runtime = end - start;
  throughput = FLAGS_iterations / runtime;

  throughput_per_node = throughput/nnodes;

  SoftXMT_merge_and_dump_stats();

  LOG(INFO) << "GUPS: "
            << FLAGS_iterations << " updates at "
            << throughput << "updates/s ("
            << throughput/nnodes << " updates/s/node).";
}

BOOST_AUTO_TEST_CASE( test1 ) {
    Grappa_init( &(boost::unit_test::framework::master_test_suite().argc),
		  &(boost::unit_test::framework::master_test_suite().argv) );
    Grappa_activate();

    Grappa_run_user_main( &user_main, (int*)NULL );

    Grappa_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>/*

Copyright (c) 2014, Project OSRM, Felix Guendling
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef MULTI_TARGET_PLUGIN_H
#define MULTI_TARGET_PLUGIN_H

#include "./plugin_base.hpp"

#include "../algorithms/object_encoder.hpp"
#include "../data_structures/search_engine.hpp"
#include "../Util/json_renderer.hpp"
#include "../Util/timing_util.hpp"

template <class DataFacadeT, bool forward> class MultiTargetPlugin final : public BasePlugin
{
  public:
    explicit MultiTargetPlugin(DataFacadeT *facade)
        : facade(facade), search_engine_ptr(std::make_shared<SearchEngine<DataFacadeT>>(facade))
    {
    }

    virtual ~MultiTargetPlugin() {}

    std::shared_ptr<std::vector<std::pair<EdgeWeight, double>>>
    HandleRequest(const RouteParameters &route_parameters,
                  unsigned &calctime_in_us)
    {
        // check number of parameters
        if (2 > route_parameters.coordinates.size())
        {
            return nullptr;
        }

        if (std::any_of(begin(route_parameters.coordinates), end(route_parameters.coordinates),
                        [&](FixedPointCoordinate coordinate)
                        {
                return !coordinate.is_valid();
            }))
        {
            return nullptr;
        }

        const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
        PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
        for (unsigned i = 0; i < route_parameters.coordinates.size(); ++i)
        {
            if (checksum_OK && i < route_parameters.hints.size() &&
                !route_parameters.hints[i].empty())
            {
                PhantomNode current_phantom_node;
                ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
                if (current_phantom_node.is_valid(facade->GetNumberOfNodes()))
                {
                    phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
                    continue;
                }
            }
            facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
                                                            phantom_node_vector[i],
                                                            1);

            BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
        }

        std::shared_ptr<std::vector<std::pair<EdgeWeight, double>>> ret;

        TIMER_START(multi_target);
        if (forward)
        {
            ret = search_engine_ptr->multi_target(phantom_node_vector);
        }
        else
        {
            ret = search_engine_ptr->multi_source(phantom_node_vector);
        }
        TIMER_STOP(multi_target);
        calctime_in_us = TIMER_USEC(multi_target);

        return ret;
    }

    int HandleRequest(const RouteParameters &route_parameters,
                      osrm::json::Object &json_result)
    {
        unsigned calctime_in_ms = 0;
        auto result_table = HandleRequest(route_parameters, calctime_in_ms);

        if (!result_table)
        {
            return 400;
        }

        osrm::json::Array json_array;
        for (unsigned column = 0; column < route_parameters.coordinates.size() - 1; ++column)
        {
            auto routing_result = result_table->operator[](column);

            osrm::json::Object result;
            result.values["time_cost"] = routing_result.first;
            result.values["distance"] = routing_result.second;
            json_array.values.emplace_back(result);
        }
        json_result.values["distances"] = json_array;
        return 200;
    }

    const std::string GetDescriptor() const { return forward ? "multitarget" : "multisource"; }

  private:
    DataFacadeT *facade;
    std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
};

#endif // MULTI_TARGET_PLUGIN_H
<commit_msg>fix case for util include in plugins/multi_target.hpp<commit_after>/*

Copyright (c) 2014, Project OSRM, Felix Guendling
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef MULTI_TARGET_PLUGIN_H
#define MULTI_TARGET_PLUGIN_H

#include "./plugin_base.hpp"

#include "../algorithms/object_encoder.hpp"
#include "../data_structures/search_engine.hpp"
#include "../util/json_renderer.hpp"
#include "../util/timing_util.hpp"

template <class DataFacadeT, bool forward> class MultiTargetPlugin final : public BasePlugin
{
  public:
    explicit MultiTargetPlugin(DataFacadeT *facade)
        : facade(facade), search_engine_ptr(std::make_shared<SearchEngine<DataFacadeT>>(facade))
    {
    }

    virtual ~MultiTargetPlugin() {}

    std::shared_ptr<std::vector<std::pair<EdgeWeight, double>>>
    HandleRequest(const RouteParameters &route_parameters,
                  unsigned &calctime_in_us)
    {
        // check number of parameters
        if (2 > route_parameters.coordinates.size())
        {
            return nullptr;
        }

        if (std::any_of(begin(route_parameters.coordinates), end(route_parameters.coordinates),
                        [&](FixedPointCoordinate coordinate)
                        {
                return !coordinate.is_valid();
            }))
        {
            return nullptr;
        }

        const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
        PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
        for (unsigned i = 0; i < route_parameters.coordinates.size(); ++i)
        {
            if (checksum_OK && i < route_parameters.hints.size() &&
                !route_parameters.hints[i].empty())
            {
                PhantomNode current_phantom_node;
                ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
                if (current_phantom_node.is_valid(facade->GetNumberOfNodes()))
                {
                    phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
                    continue;
                }
            }
            facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
                                                            phantom_node_vector[i],
                                                            1);

            BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
        }

        std::shared_ptr<std::vector<std::pair<EdgeWeight, double>>> ret;

        TIMER_START(multi_target);
        if (forward)
        {
            ret = search_engine_ptr->multi_target(phantom_node_vector);
        }
        else
        {
            ret = search_engine_ptr->multi_source(phantom_node_vector);
        }
        TIMER_STOP(multi_target);
        calctime_in_us = TIMER_USEC(multi_target);

        return ret;
    }

    int HandleRequest(const RouteParameters &route_parameters,
                      osrm::json::Object &json_result)
    {
        unsigned calctime_in_ms = 0;
        auto result_table = HandleRequest(route_parameters, calctime_in_ms);

        if (!result_table)
        {
            return 400;
        }

        osrm::json::Array json_array;
        for (unsigned column = 0; column < route_parameters.coordinates.size() - 1; ++column)
        {
            auto routing_result = result_table->operator[](column);

            osrm::json::Object result;
            result.values["time_cost"] = routing_result.first;
            result.values["distance"] = routing_result.second;
            json_array.values.emplace_back(result);
        }
        json_result.values["distances"] = json_array;
        return 200;
    }

    const std::string GetDescriptor() const { return forward ? "multitarget" : "multisource"; }

  private:
    DataFacadeT *facade;
    std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
};

#endif // MULTI_TARGET_PLUGIN_H
<|endoftext|>


<commit_before>#include <clams/slam_calibrator.h>

using namespace std;
using namespace Eigen;

namespace clams
{

  SlamCalibrator::SlamCalibrator(const FrameProjector& proj, double max_range, double vgsize) :
    proj_(proj),
    max_range_(max_range),
    vgsize_(vgsize),
    increment_(1)
  {
  }

  void filterFringe(Frame* frame)
  {
    DepthMat& depth = *frame->depth_;

    cv::Mat1b mask(depth.rows(), depth.cols());  // points to be removed.
    mask = 0;
    ushort threshold = 5000;  // millimeters
    for(int y = 1; y < depth.rows(); ++y) {
      for(int x = 1; x < depth.cols(); ++x) {
        if(depth(y, x) == 0 || depth(y-1, x) == 0 || depth(y, x-1) == 0 ||
           fabs(depth(y, x) - depth(y-1, x)) > threshold ||
           fabs(depth(y, x) - depth(y, x-1)) > threshold)
        {
          mask(y, x) = 255;
        }
      }
    }

    // cv::imshow("mask", mask);
    // cv::imshow("depth", frame->depthImage());
    // cv::waitKey();

    cv::dilate(mask, mask, cv::Mat(), cv::Point(-1, -1), 8);
    // cv::imshow("mask", mask);
    // cv::waitKey();

    for(int y = 1; y < depth.rows(); ++y)
      for(int x = 1; x < depth.cols(); ++x)
        if(mask(y, x))
          depth(y, x) = 0;

    // cv::imshow("depth", frame->depthImage());
    // cv::waitKey();
  }

  Cloud::Ptr SlamCalibrator::buildMap(StreamSequenceBase::ConstPtr sseq, const Trajectory& traj, double max_range, double vgsize)
  {
    ROS_DEBUG_STREAM("Building slam calibration map using max range of " << max_range);

    Cloud::Ptr map(new Cloud);
    int num_used_frames = 0;
    for(size_t i = 0; i < traj.size(); ++i) {
      if(!traj.exists(i))
        continue;

      cout << "Using frame " << i << " / " << traj.size() << endl;
      Frame frame;

      sseq->readFrame(i, &frame);
      filterFringe(&frame);

      Cloud::Ptr tmp(new Cloud);
      sseq->proj_.frameToCloud(frame, tmp.get(), max_range);
      Cloud::Ptr nonans(new Cloud);
      nonans->reserve(tmp->size());
      for(size_t j = 0; j < tmp->size(); ++j)
        if(isFinite(tmp->at(j)))
          nonans->push_back(tmp->at(j));

      pcl::transformPointCloud(*nonans, *nonans, traj.get(i).cast<float>());

      *map += *nonans;
      ++num_used_frames;
      // Added intermediate filtering to handle memory overload on huge maps
      if(num_used_frames % 50 == 0)
      {
        cout << "Filtering..." << endl;
        HighResTimer hrt("filtering");
        hrt.start();
        pcl::VoxelGrid<Point> vg;
        vg.setLeafSize(vgsize, vgsize, vgsize);
        Cloud::Ptr tmp(new Cloud);
        vg.setInputCloud(map);
        vg.filter(*tmp);
        *map = *tmp;
        hrt.stop();
      }
    }

    cout << "Filtering..." << endl;
    HighResTimer hrt("filtering");
    hrt.start();
    pcl::VoxelGrid<Point> vg;
    vg.setLeafSize(vgsize, vgsize, vgsize);
    Cloud::Ptr tmp(new Cloud);
    vg.setInputCloud(map);
    vg.filter(*tmp);
    *map = *tmp;
    hrt.stop();
    cout << hrt.reportMilliseconds() << endl;
    cout << "Filtered map has " << map->size() << " points." << endl;

    return map;
  }

  Cloud::Ptr SlamCalibrator::buildMap(size_t idx) const
  {
    ROS_ASSERT(idx < trajectories_.size());
    ROS_ASSERT(trajectories_.size() == sseqs_.size());
    return buildMap(sseqs_[idx], trajectories_[idx], max_range_, vgsize_);
  }

  size_t SlamCalibrator::size() const
  {
    ROS_ASSERT(trajectories_.size() == sseqs_.size());
    return trajectories_.size();
  }

  DiscreteDepthDistortionModel SlamCalibrator::calibrate() const
  {
    ROS_ASSERT(!sseqs_.empty());
    DiscreteDepthDistortionModel model(sseqs_[0]->proj_.width_, sseqs_[0]->proj_.height_);

    size_t total_num_training = 0;
    for(size_t i = 0; i < size(); ++i) {
      // -- Construct the map from the data and the trajectory.
      StreamSequenceBase::ConstPtr sseq = sseqs_[i];
      const Trajectory& traj = trajectories_[i];
      Cloud::Ptr map = buildMap(i);
      total_num_training += processMap(*sseq, traj, *map, &model);
    }

    cout << "Training new DiscreteDepthDistortionModel using "
         << total_num_training << " training examples." << endl;

    return model;
  }

  size_t SlamCalibrator::processMap(const StreamSequenceBase& sseq,
                                    const Trajectory& traj, const Cloud& map,
                                    DiscreteDepthDistortionModel* model) const
  {
    // -- Select which frame indices from the sequence to use.
    //    Consider only those with a pose in the Trajectory,
    //    and apply downsampling based on increment_.
    vector<size_t> indices;
    indices.reserve(traj.numValid());
    int num = 0;
    for(size_t i = 0; i < traj.size(); ++i) {
      if(traj.exists(i) && num % increment_ == 0) {
        indices.push_back(i);
        ++num;
      }
    }

    // -- For all selected frames, accumulate training examples
    //    in the distortion model.
    VectorXi counts = VectorXi::Zero(indices.size());
#pragma omp parallel for
    for(size_t i = 0; i < indices.size(); ++i) {
      size_t idx = indices[i];
      ROS_ASSERT(traj.exists(idx));
      cout << "." << flush;

      Frame measurement;
      sseq.readFrame(idx, &measurement);

      Frame mapframe;
      mapframe.depth_ = DepthMatPtr(new DepthMat);
      sseq.proj_.estimateMapDepth(map, traj.get(idx).inverse().cast<float>(),
                                  measurement, mapframe.depth_.get());
      counts[i] = model->accumulate(*mapframe.depth_, *measurement.depth_);
    }

    return counts.sum();
  }

}  // namespace clams
<commit_msg>Adding a quick and dirty way to inspect the distortion on a per-beam basis.<commit_after>#include <clams/slam_calibrator.h>

using namespace std;
using namespace Eigen;

namespace clams
{

  SlamCalibrator::SlamCalibrator(const FrameProjector& proj, double max_range, double vgsize) :
    proj_(proj),
    max_range_(max_range),
    vgsize_(vgsize),
    increment_(1)
  {
  }

  void filterFringe(Frame* frame)
  {
    DepthMat& depth = *frame->depth_;

    cv::Mat1b mask(depth.rows(), depth.cols());  // points to be removed.
    mask = 0;
    ushort threshold = 5000;  // millimeters
    for(int y = 1; y < depth.rows(); ++y) {
      for(int x = 1; x < depth.cols(); ++x) {
        if(depth(y, x) == 0 || depth(y-1, x) == 0 || depth(y, x-1) == 0 ||
           fabs(depth(y, x) - depth(y-1, x)) > threshold ||
           fabs(depth(y, x) - depth(y, x-1)) > threshold)
        {
          mask(y, x) = 255;
        }
      }
    }

    // cv::imshow("mask", mask);
    // cv::imshow("depth", frame->depthImage());
    // cv::waitKey();

    cv::dilate(mask, mask, cv::Mat(), cv::Point(-1, -1), 8);
    // cv::imshow("mask", mask);
    // cv::waitKey();

    for(int y = 1; y < depth.rows(); ++y)
      for(int x = 1; x < depth.cols(); ++x)
        if(mask(y, x))
          depth(y, x) = 0;

    // cv::imshow("depth", frame->depthImage());
    // cv::waitKey();
  }

  Cloud::Ptr SlamCalibrator::buildMap(StreamSequenceBase::ConstPtr sseq, const Trajectory& traj, double max_range, double vgsize)
  {
    ROS_DEBUG_STREAM("Building slam calibration map using max range of " << max_range);

    Cloud::Ptr map(new Cloud);
    int num_used_frames = 0;
    for(size_t i = 0; i < traj.size(); ++i) {
      if(!traj.exists(i))
        continue;

      cout << "Using frame " << i << " / " << traj.size() << endl;
      Frame frame;

      sseq->readFrame(i, &frame);
      filterFringe(&frame);

      Cloud::Ptr tmp(new Cloud);
      sseq->proj_.frameToCloud(frame, tmp.get(), max_range);
      Cloud::Ptr nonans(new Cloud);
      nonans->reserve(tmp->size());
      for(size_t j = 0; j < tmp->size(); ++j)
        if(isFinite(tmp->at(j)))
          nonans->push_back(tmp->at(j));

      pcl::transformPointCloud(*nonans, *nonans, traj.get(i).cast<float>());

      *map += *nonans;
      ++num_used_frames;
      // Added intermediate filtering to handle memory overload on huge maps
      if(num_used_frames % 50 == 0)
      {
        cout << "Filtering..." << endl;
        HighResTimer hrt("filtering");
        hrt.start();
        pcl::VoxelGrid<Point> vg;
        vg.setLeafSize(vgsize, vgsize, vgsize);
        Cloud::Ptr tmp(new Cloud);
        vg.setInputCloud(map);
        vg.filter(*tmp);
        *map = *tmp;
        hrt.stop();
      }
    }

    cout << "Filtering..." << endl;
    HighResTimer hrt("filtering");
    hrt.start();
    pcl::VoxelGrid<Point> vg;
    vg.setLeafSize(vgsize, vgsize, vgsize);
    Cloud::Ptr tmp(new Cloud);
    vg.setInputCloud(map);
    vg.filter(*tmp);
    *map = *tmp;
    hrt.stop();
    cout << hrt.reportMilliseconds() << endl;
    cout << "Filtered map has " << map->size() << " points." << endl;

    return map;
  }

  Cloud::Ptr SlamCalibrator::buildMap(size_t idx) const
  {
    ROS_ASSERT(idx < trajectories_.size());
    ROS_ASSERT(trajectories_.size() == sseqs_.size());
    return buildMap(sseqs_[idx], trajectories_[idx], max_range_, vgsize_);
  }

  size_t SlamCalibrator::size() const
  {
    ROS_ASSERT(trajectories_.size() == sseqs_.size());
    return trajectories_.size();
  }

  DiscreteDepthDistortionModel SlamCalibrator::calibrate() const
  {
    ROS_ASSERT(!sseqs_.empty());
    DiscreteDepthDistortionModel model(sseqs_[0]->proj_.width_, sseqs_[0]->proj_.height_);

    size_t total_num_training = 0;
    for(size_t i = 0; i < size(); ++i) {
      // -- Construct the map from the data and the trajectory.
      StreamSequenceBase::ConstPtr sseq = sseqs_[i];
      const Trajectory& traj = trajectories_[i];
      Cloud::Ptr map = buildMap(i);
      total_num_training += processMap(*sseq, traj, *map, &model);
    }

    cout << "Training new DiscreteDepthDistortionModel using "
         << total_num_training << " training examples." << endl;

    return model;
  }

  size_t SlamCalibrator::processMap(const StreamSequenceBase& sseq,
                                    const Trajectory& traj, const Cloud& map,
                                    DiscreteDepthDistortionModel* model) const
  {
    // -- Select which frame indices from the sequence to use.
    //    Consider only those with a pose in the Trajectory,
    //    and apply downsampling based on increment_.
    vector<size_t> indices;
    indices.reserve(traj.numValid());
    int num = 0;
    for(size_t i = 0; i < traj.size(); ++i) {
      if(traj.exists(i) && num % increment_ == 0) {
        indices.push_back(i);
        ++num;
      }
    }

    // -- For all selected frames, accumulate training examples
    //    in the distortion model.
    VectorXi counts = VectorXi::Zero(indices.size());
#pragma omp parallel for
    for(size_t i = 0; i < indices.size(); ++i) {
      size_t idx = indices[i];
      ROS_ASSERT(traj.exists(idx));
      cout << "." << flush;

      Frame measurement;
      sseq.readFrame(idx, &measurement);

      Frame mapframe;
      mapframe.depth_ = DepthMatPtr(new DepthMat);
      sseq.proj_.estimateMapDepth(map, traj.get(idx).inverse().cast<float>(),
                                  measurement, mapframe.depth_.get());
      counts[i] = model->accumulate(*mapframe.depth_, *measurement.depth_);

      // -- Quick and dirty option for data inspection.
      if(getenv("U") && getenv("V")) {
        int u_center = atoi(getenv("U"));
        int v_center = atoi(getenv("V"));
        int radius = 1;
        for(int u = max(0, u_center - radius); u < min(640, u_center + radius + 1); ++u) {
          for(int v = max(0, v_center - radius); v < min(480, v_center + radius + 1); ++v) {
            if(mapframe.depth_->coeffRef(v, u) == 0)
              continue;
            if(measurement.depth_->coeffRef(v, u) == 0)
              continue;
            cerr << mapframe.depth_->coeffRef(v, u) * 0.001
                 << " "
                 << measurement.depth_->coeffRef(v, u) * 0.001
                 << endl;
          }
        }
      }
    }

    return counts.sum();
  }

}  // namespace clams
<|endoftext|>


<commit_before>#include "testing/testing.hpp"

#include "routing/route.hpp"
#include "routing/router.hpp"
#include "routing/routing_session.hpp"

#include "geometry/point2d.hpp"

#include "base/logging.hpp"

#include "std/chrono.hpp"
#include "std/mutex.hpp"
#include "std/string.hpp"
#include "std/vector.hpp"

namespace routing
{
// Simple router. It returns route given to him on creation.
class DummyRouter : public IRouter
{
private:
  Route & m_route;
  ResultCode m_code;
  size_t & m_buildCount;

public:
  DummyRouter(Route & route, ResultCode code, size_t & buildCounter)
    : m_route(route), m_code(code), m_buildCount(buildCounter)
  {
  }
  string GetName() const override { return "dummy"; }
  void ClearState() override {}
  ResultCode CalculateRoute(m2::PointD const & /* startPoint */,
                            m2::PointD const & /* startDirection */,
                            m2::PointD const & /* finalPoint */,
                            RouterDelegate const & /* delegate */, Route & route) override
  {
    ++m_buildCount;
    route = m_route;
    return m_code;
  }
};

static vector<m2::PointD> kTestRoute = {{0., 1.}, {0., 2.}, {0., 3.}, {0., 4.}};
static auto kRouteBuildingMaxDuration = seconds(30);

UNIT_TEST(TestRouteBuilding)
{
  RoutingSession session;
  session.Init(nullptr, nullptr);
  vector<m2::PointD> routePoints = kTestRoute;
  Route masterRoute("dummy", routePoints.begin(), routePoints.end());
  size_t counter = 0;
  timed_mutex routeBuilded;
  routeBuilded.lock();
  unique_ptr<DummyRouter> router = make_unique<DummyRouter>(masterRoute, DummyRouter::NoError, counter);
  session.SetRouter(move(router), nullptr);
  session.BuildRoute(kTestRoute.front(), kTestRoute.back(),
                     [&routeBuilded](Route const &, IRouter::ResultCode)
                     {
                       routeBuilded.unlock();
                     },
                     nullptr, 0);
  TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ());
  TEST_EQUAL(counter, 1, ());
}

UNIT_TEST(TestRouteRebuilding)
{
  Index index;
  RoutingSession session;
  session.Init(nullptr, nullptr);
  vector<m2::PointD> routePoints = kTestRoute;
  Route masterRoute("dummy", routePoints.begin(), routePoints.end());
  size_t counter = 0;
  timed_mutex routeBuilded;
  auto fn = [&routeBuilded](Route const &, IRouter::ResultCode)
            {
              routeBuilded.unlock();
            };
  routeBuilded.lock();
  unique_ptr<DummyRouter> router = make_unique<DummyRouter>(masterRoute, DummyRouter::NoError, counter);
  session.SetRouter(move(router), nullptr);

  // Go along the route.
  session.BuildRoute(kTestRoute.front(), kTestRoute.back(), fn, nullptr, 0);
  TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ());

  location::GpsInfo info;
  info.m_horizontalAccuracy = 0.01;
  info.m_verticalAccuracy = 0.01;
  info.m_longitude = 0.;
  info.m_latitude = 1.;
  RoutingSession::State code;
  while (info.m_latitude < kTestRoute.back().y)
  {
    code = session.OnLocationPositionChanged(
        MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index);
    TEST_EQUAL(code, RoutingSession::State::OnRoute, ());
    info.m_latitude += 0.01;
  }
  TEST_EQUAL(counter, 1, ());

  // Rebuild route and go in opposite direction. So initiate a route rebuilding flag.
  counter = 0;
  session.BuildRoute(kTestRoute.front(), kTestRoute.back(), fn, nullptr, 0);
  TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ());

  info.m_longitude = 0.;
  info.m_latitude = 1.;
  for (size_t i = 0; i < 10; ++i)
  {
    code = session.OnLocationPositionChanged(
        MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index);
    info.m_latitude -= 0.1;
  }
  TEST_EQUAL(code, RoutingSession::State::RouteNeedRebuild, ());
}
}  // namespace routing
<commit_msg>Routing session tests UB fix.<commit_after>#include "testing/testing.hpp"

#include "routing/route.hpp"
#include "routing/router.hpp"
#include "routing/routing_session.hpp"

#include "geometry/point2d.hpp"

#include "base/logging.hpp"

#include "std/atomic.hpp"
#include "std/chrono.hpp"
#include "std/string.hpp"
#include "std/vector.hpp"

namespace routing
{
// Simple router. It returns route given to him on creation.
class DummyRouter : public IRouter
{
private:
  Route & m_route;
  ResultCode m_code;
  size_t & m_buildCount;

public:
  DummyRouter(Route & route, ResultCode code, size_t & buildCounter)
    : m_route(route), m_code(code), m_buildCount(buildCounter)
  {
  }
  string GetName() const override { return "dummy"; }
  void ClearState() override {}
  ResultCode CalculateRoute(m2::PointD const & /* startPoint */,
                            m2::PointD const & /* startDirection */,
                            m2::PointD const & /* finalPoint */,
                            RouterDelegate const & /* delegate */, Route & route) override
  {
    ++m_buildCount;
    route = m_route;
    return m_code;
  }
};

static vector<m2::PointD> kTestRoute = {{0., 1.}, {0., 2.}, {0., 3.}, {0., 4.}};
static auto kTestMaxDuration = seconds(30);

UNIT_TEST(TestRouteBuilding)
{
  RoutingSession session;
  session.Init(nullptr, nullptr);
  vector<m2::PointD> routePoints = kTestRoute;
  Route masterRoute("dummy", routePoints.begin(), routePoints.end());
  size_t counter = 0;
  atomic<bool> routeBuilded(false);
  unique_ptr<DummyRouter> router = make_unique<DummyRouter>(masterRoute, DummyRouter::NoError, counter);
  session.SetRouter(move(router), nullptr);
  session.BuildRoute(kTestRoute.front(), kTestRoute.back(),
                     [&routeBuilded](Route const &, IRouter::ResultCode)
                     {
                       routeBuilded = true;
                     },
                     nullptr, 0);
  // Manual check of the routeBuilded mutex to avoid spurious results.
  auto time = steady_clock::now() + kTestMaxDuration;
  while (steady_clock::now() < time  && !routeBuilded)
  {
  }
  TEST(routeBuilded, ("Route was not built."));
  TEST_EQUAL(counter, 1, ());
}

UNIT_TEST(TestRouteRebuilding)
{
  Index index;
  RoutingSession session;
  session.Init(nullptr, nullptr);
  vector<m2::PointD> routePoints = kTestRoute;
  Route masterRoute("dummy", routePoints.begin(), routePoints.end());
  size_t counter = 0;
  atomic<bool> routeBuilded(false);
  auto fn = [&routeBuilded](Route const &, IRouter::ResultCode)
            {
              routeBuilded = true;
            };
  unique_ptr<DummyRouter> router = make_unique<DummyRouter>(masterRoute, DummyRouter::NoError, counter);
  session.SetRouter(move(router), nullptr);

  // Go along the route.
  session.BuildRoute(kTestRoute.front(), kTestRoute.back(), fn, nullptr, 0);
  // Manual check of the routeBuilded mutex to avoid spurious results.
  auto time = steady_clock::now() + kTestMaxDuration;
  while (steady_clock::now() < time  && !routeBuilded)
  {
  }
  TEST(routeBuilded, ("Route was not built."));

  location::GpsInfo info;
  info.m_horizontalAccuracy = 0.01;
  info.m_verticalAccuracy = 0.01;
  info.m_longitude = 0.;
  info.m_latitude = 1.;
  RoutingSession::State code;
  while (info.m_latitude < kTestRoute.back().y)
  {
    code = session.OnLocationPositionChanged(
        MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index);
    TEST_EQUAL(code, RoutingSession::State::OnRoute, ());
    info.m_latitude += 0.01;
  }
  TEST_EQUAL(counter, 1, ());

  // Rebuild route and go in opposite direction. So initiate a route rebuilding flag.
  counter = 0;
  routeBuilded = false;
  session.BuildRoute(kTestRoute.front(), kTestRoute.back(), fn, nullptr, 0);
  while (steady_clock::now() < time  && !routeBuilded)
  {
  }
  TEST(routeBuilded, ("Route was not built."));

  info.m_longitude = 0.;
  info.m_latitude = 1.;
  for (size_t i = 0; i < 10; ++i)
  {
    code = session.OnLocationPositionChanged(
        MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index);
    info.m_latitude -= 0.1;
  }
  TEST_EQUAL(code, RoutingSession::State::RouteNeedRebuild, ());
}
}  // namespace routing
<|endoftext|>


<commit_before>//
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
// such as the client area of a window, including any back buffers.
// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.

#include <tchar.h>

#include <algorithm>

#include "libEGL/Surface.h"

#include "common/debug.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/renderer/SwapChain.h"
#include "libGLESv2/main.h"

#include "libEGL/main.h"
#include "libEGL/Display.h"

namespace egl
{

Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported)
    : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
{
    mRenderer = mDisplay->getRenderer();
    mSwapChain = NULL;
    mShareHandle = NULL;
    mTexture = NULL;
    mTextureFormat = EGL_NO_TEXTURE;
    mTextureTarget = EGL_NO_TEXTURE;

    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
    mRenderBuffer = EGL_BACK_BUFFER;
    mSwapBehavior = EGL_BUFFER_PRESERVED;
    mSwapInterval = -1;
    mWidth = -1;
    mHeight = -1;
    setSwapInterval(1);

    subclassWindow();
}

Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
    : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{
    mRenderer = mDisplay->getRenderer();
    mSwapChain = NULL;
    mWindowSubclassed = false;
    mTexture = NULL;
    mTextureFormat = textureFormat;
    mTextureTarget = textureType;

    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
    mRenderBuffer = EGL_BACK_BUFFER;
    mSwapBehavior = EGL_BUFFER_PRESERVED;
    mSwapInterval = -1;
    setSwapInterval(1);
}

Surface::~Surface()
{
    unsubclassWindow();
    release();
}

bool Surface::initialize()
{
    if (!resetSwapChain())
      return false;

    return true;
}

void Surface::release()
{
    delete mSwapChain;
    mSwapChain = NULL;

    if (mTexture)
    {
        mTexture->releaseTexImage();
        mTexture = NULL;
    }
}

bool Surface::resetSwapChain()
{
    ASSERT(!mSwapChain);

    int width;
    int height;

    if (mWindow)
    {
        RECT windowRect;
        if (!GetClientRect(getWindowHandle(), &windowRect))
        {
            ASSERT(false);

            ERR("Could not retrieve the window dimensions");
            return error(EGL_BAD_SURFACE, false);
        }

        width = windowRect.right - windowRect.left;
        height = windowRect.bottom - windowRect.top;
    }
    else
    {
        // non-window surface - size is determined at creation
        width = mWidth;
        height = mHeight;
    }

    mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle,
                                            mConfig->mRenderTargetFormat,
                                            mConfig->mDepthStencilFormat);
    if (!mSwapChain)
    {
        return error(EGL_BAD_ALLOC, false);
    }

    if (!resetSwapChain(width, height))
    {
        delete mSwapChain;
        mSwapChain = NULL;
        return false;
    }

    return true;
}

bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
{
    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
    ASSERT(mSwapChain);

    EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);

    if (status == EGL_CONTEXT_LOST)
    {
        mDisplay->notifyDeviceLost();
        return false;
    }
    else if (status != EGL_SUCCESS)
    {
        return error(status, false);
    }

    mWidth = backbufferWidth;
    mHeight = backbufferHeight;

    return true;
}

bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
    ASSERT(mSwapChain);

    EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval);

    if (status == EGL_CONTEXT_LOST)
    {
        mRenderer->notifyDeviceLost();
        return false;
    }
    else if (status != EGL_SUCCESS)
    {
        return error(status, false);
    }

    mWidth = backbufferWidth;
    mHeight = backbufferHeight;
    mSwapIntervalDirty = false;

    return true;
}

bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
    if (!mSwapChain)
    {
        return true;
    }

    if (x + width > mWidth)
    {
        width = mWidth - x;
    }

    if (y + height > mHeight)
    {
        height = mHeight - y;
    }

    if (width == 0 || height == 0)
    {
        return true;
    }

    EGLint status = mSwapChain->swapRect(x, y, width, height);

    if (status == EGL_CONTEXT_LOST)
    {
        mRenderer->notifyDeviceLost();
        return false;
    }
    else if (status != EGL_SUCCESS)
    {
        return error(status, false);
    }

    checkForOutOfDateSwapChain();

    return true;
}

HWND Surface::getWindowHandle()
{
    return mWindow;
}

#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")

static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
  if (message == WM_SIZE)
  {
      Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
      if(surf)
      {
          surf->checkForOutOfDateSwapChain();
      }
  }
  WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
  return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
}

void Surface::subclassWindow()
{
    if (!mWindow)
    {
        return;
    }

    DWORD processId;
    DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
    if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
    {
        return;
    }

    SetLastError(0);
    LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
    if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
    {
        mWindowSubclassed = false;
        return;
    }

    SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
    SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
    mWindowSubclassed = true;
}

void Surface::unsubclassWindow()
{
    if(!mWindowSubclassed)
    {
        return;
    }

    // un-subclass
    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));

    // Check the windowproc is still SurfaceWindowProc.
    // If this assert fails, then it is likely the application has subclassed the
    // hwnd as well and did not unsubclass before destroying its EGL context. The
    // application should be modified to either subclass before initializing the
    // EGL context, or to unsubclass before destroying the EGL context.
    if(parentWndFunc)
    {
        LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
        ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
    }

    RemoveProp(mWindow, kSurfaceProperty);
    RemoveProp(mWindow, kParentWndProc);
    mWindowSubclassed = false;
}

bool Surface::checkForOutOfDateSwapChain()
{
    RECT client;
    if (!GetClientRect(getWindowHandle(), &client))
    {
        ASSERT(false);
        return false;
    }

    // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
    int clientWidth = client.right - client.left;
    int clientHeight = client.bottom - client.top;
    bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();

    if (mSwapIntervalDirty)
    {
        resetSwapChain(clientWidth, clientHeight);
    }
    else if (sizeDirty)
    {
        resizeSwapChain(clientWidth, clientHeight);
    }

    if (mSwapIntervalDirty || sizeDirty)
    {
        if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
        {
            glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
        }

        return true;
    }

    return false;
}

bool Surface::swap()
{
    return swapRect(0, 0, mWidth, mHeight);
}

bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
    if (!mPostSubBufferSupported)
    {
        // Spec is not clear about how this should be handled.
        return true;
    }

    return swapRect(x, y, width, height);
}

EGLint Surface::getWidth() const
{
    return mWidth;
}

EGLint Surface::getHeight() const
{
    return mHeight;
}

EGLint Surface::isPostSubBufferSupported() const
{
    return mPostSubBufferSupported;
}

rx::SwapChain *Surface::getSwapChain() const
{
    return mSwapChain;
}

void Surface::setSwapInterval(EGLint interval)
{
    if (mSwapInterval == interval)
    {
        return;
    }

    mSwapInterval = interval;
    mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval());
    mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval());

    mSwapIntervalDirty = true;
}

EGLenum Surface::getTextureFormat() const
{
    return mTextureFormat;
}

EGLenum Surface::getTextureTarget() const
{
    return mTextureTarget;
}

void Surface::setBoundTexture(gl::Texture2D *texture)
{
    mTexture = texture;
}

gl::Texture2D *Surface::getBoundTexture() const
{
    return mTexture;
}

EGLenum Surface::getFormat() const
{
    return mConfig->mRenderTargetFormat;
}
}
<commit_msg>Disable automatically resizing swapchain if window is iconified<commit_after>//
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
// such as the client area of a window, including any back buffers.
// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.

#include <tchar.h>

#include <algorithm>

#include "libEGL/Surface.h"

#include "common/debug.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/renderer/SwapChain.h"
#include "libGLESv2/main.h"

#include "libEGL/main.h"
#include "libEGL/Display.h"

namespace egl
{

Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported)
    : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
{
    mRenderer = mDisplay->getRenderer();
    mSwapChain = NULL;
    mShareHandle = NULL;
    mTexture = NULL;
    mTextureFormat = EGL_NO_TEXTURE;
    mTextureTarget = EGL_NO_TEXTURE;

    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
    mRenderBuffer = EGL_BACK_BUFFER;
    mSwapBehavior = EGL_BUFFER_PRESERVED;
    mSwapInterval = -1;
    mWidth = -1;
    mHeight = -1;
    setSwapInterval(1);

    subclassWindow();
}

Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
    : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{
    mRenderer = mDisplay->getRenderer();
    mSwapChain = NULL;
    mWindowSubclassed = false;
    mTexture = NULL;
    mTextureFormat = textureFormat;
    mTextureTarget = textureType;

    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
    mRenderBuffer = EGL_BACK_BUFFER;
    mSwapBehavior = EGL_BUFFER_PRESERVED;
    mSwapInterval = -1;
    setSwapInterval(1);
}

Surface::~Surface()
{
    unsubclassWindow();
    release();
}

bool Surface::initialize()
{
    if (!resetSwapChain())
      return false;

    return true;
}

void Surface::release()
{
    delete mSwapChain;
    mSwapChain = NULL;

    if (mTexture)
    {
        mTexture->releaseTexImage();
        mTexture = NULL;
    }
}

bool Surface::resetSwapChain()
{
    ASSERT(!mSwapChain);

    int width;
    int height;

    if (mWindow)
    {
        RECT windowRect;
        if (!GetClientRect(getWindowHandle(), &windowRect))
        {
            ASSERT(false);

            ERR("Could not retrieve the window dimensions");
            return error(EGL_BAD_SURFACE, false);
        }

        width = windowRect.right - windowRect.left;
        height = windowRect.bottom - windowRect.top;
    }
    else
    {
        // non-window surface - size is determined at creation
        width = mWidth;
        height = mHeight;
    }

    mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle,
                                            mConfig->mRenderTargetFormat,
                                            mConfig->mDepthStencilFormat);
    if (!mSwapChain)
    {
        return error(EGL_BAD_ALLOC, false);
    }

    if (!resetSwapChain(width, height))
    {
        delete mSwapChain;
        mSwapChain = NULL;
        return false;
    }

    return true;
}

bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
{
    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
    ASSERT(mSwapChain);

    EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);

    if (status == EGL_CONTEXT_LOST)
    {
        mDisplay->notifyDeviceLost();
        return false;
    }
    else if (status != EGL_SUCCESS)
    {
        return error(status, false);
    }

    mWidth = backbufferWidth;
    mHeight = backbufferHeight;

    return true;
}

bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
    ASSERT(mSwapChain);

    EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval);

    if (status == EGL_CONTEXT_LOST)
    {
        mRenderer->notifyDeviceLost();
        return false;
    }
    else if (status != EGL_SUCCESS)
    {
        return error(status, false);
    }

    mWidth = backbufferWidth;
    mHeight = backbufferHeight;
    mSwapIntervalDirty = false;

    return true;
}

bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
    if (!mSwapChain)
    {
        return true;
    }

    if (x + width > mWidth)
    {
        width = mWidth - x;
    }

    if (y + height > mHeight)
    {
        height = mHeight - y;
    }

    if (width == 0 || height == 0)
    {
        return true;
    }

    EGLint status = mSwapChain->swapRect(x, y, width, height);

    if (status == EGL_CONTEXT_LOST)
    {
        mRenderer->notifyDeviceLost();
        return false;
    }
    else if (status != EGL_SUCCESS)
    {
        return error(status, false);
    }

    checkForOutOfDateSwapChain();

    return true;
}

HWND Surface::getWindowHandle()
{
    return mWindow;
}

#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")

static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
  if (message == WM_SIZE)
  {
      Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
      if(surf)
      {
          surf->checkForOutOfDateSwapChain();
      }
  }
  WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
  return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
}

void Surface::subclassWindow()
{
    if (!mWindow)
    {
        return;
    }

    DWORD processId;
    DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
    if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
    {
        return;
    }

    SetLastError(0);
    LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
    if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
    {
        mWindowSubclassed = false;
        return;
    }

    SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
    SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
    mWindowSubclassed = true;
}

void Surface::unsubclassWindow()
{
    if(!mWindowSubclassed)
    {
        return;
    }

    // un-subclass
    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));

    // Check the windowproc is still SurfaceWindowProc.
    // If this assert fails, then it is likely the application has subclassed the
    // hwnd as well and did not unsubclass before destroying its EGL context. The
    // application should be modified to either subclass before initializing the
    // EGL context, or to unsubclass before destroying the EGL context.
    if(parentWndFunc)
    {
        LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
        ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
    }

    RemoveProp(mWindow, kSurfaceProperty);
    RemoveProp(mWindow, kParentWndProc);
    mWindowSubclassed = false;
}

bool Surface::checkForOutOfDateSwapChain()
{
    RECT client;
    if (!GetClientRect(getWindowHandle(), &client))
    {
        ASSERT(false);
        return false;
    }

    // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
    int clientWidth = client.right - client.left;
    int clientHeight = client.bottom - client.top;
    bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();

    if (IsIconic(getWindowHandle()))
    {
        // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
        // because that's not a useful size to render to.
        sizeDirty = false;
    }

    if (mSwapIntervalDirty)
    {
        resetSwapChain(clientWidth, clientHeight);
    }
    else if (sizeDirty)
    {
        resizeSwapChain(clientWidth, clientHeight);
    }

    if (mSwapIntervalDirty || sizeDirty)
    {
        if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
        {
            glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
        }

        return true;
    }

    return false;
}

bool Surface::swap()
{
    return swapRect(0, 0, mWidth, mHeight);
}

bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
    if (!mPostSubBufferSupported)
    {
        // Spec is not clear about how this should be handled.
        return true;
    }

    return swapRect(x, y, width, height);
}

EGLint Surface::getWidth() const
{
    return mWidth;
}

EGLint Surface::getHeight() const
{
    return mHeight;
}

EGLint Surface::isPostSubBufferSupported() const
{
    return mPostSubBufferSupported;
}

rx::SwapChain *Surface::getSwapChain() const
{
    return mSwapChain;
}

void Surface::setSwapInterval(EGLint interval)
{
    if (mSwapInterval == interval)
    {
        return;
    }

    mSwapInterval = interval;
    mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval());
    mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval());

    mSwapIntervalDirty = true;
}

EGLenum Surface::getTextureFormat() const
{
    return mTextureFormat;
}

EGLenum Surface::getTextureTarget() const
{
    return mTextureTarget;
}

void Surface::setBoundTexture(gl::Texture2D *texture)
{
    mTexture = texture;
}

gl::Texture2D *Surface::getBoundTexture() const
{
    return mTexture;
}

EGLenum Surface::getFormat() const
{
    return mConfig->mRenderTargetFormat;
}
}
<|endoftext|>


<commit_before>#ifndef ITER_CHUNKED_HPP_
#define ITER_CHUNKED_HPP_

#include "internal/iterbase.hpp"
#include "internal/iteratoriterator.hpp"

#include <vector>
#include <algorithm>
#include <type_traits>
#include <functional>
#include <utility>
#include <iterator>

namespace iter {
  namespace impl {
    template <typename Container>
    class Chunker;

    using ChunkedFn = IterToolFnBindSizeTSecond<Chunker>;
  }
  constexpr impl::ChunkedFn chunked{};
}

template <typename Container>
class iter::impl::Chunker {
 private:
  Container container;
  std::size_t chunk_size;

  Chunker(Container&& c, std::size_t sz)
      : container(std::forward<Container>(c)), chunk_size{sz} {}

  friend ChunkedFn;

  using IndexVector = std::vector<iterator_type<Container>>;
  using DerefVec = IterIterWrapper<IndexVector>;

 public:
  Chunker(Chunker&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag, DerefVec> {
   private:
    iterator_type<Container> sub_iter;
    iterator_type<Container> sub_end;
    DerefVec chunk;
    std::size_t chunk_size = 0;

    bool done() const {
      return this->chunk.empty();
    }

    void refill_chunk() {
      this->chunk.get().clear();
      std::size_t i{0};
      while (i < chunk_size && this->sub_iter != this->sub_end) {
        chunk.get().push_back(this->sub_iter);
        ++this->sub_iter;
        ++i;
      }
    }

   public:
    Iterator(iterator_type<Container>&& in_iter,
        iterator_type<Container>&& in_end, std::size_t s)
        : sub_iter{std::move(in_iter)},
          sub_end{std::move(in_end)},
          chunk_size{s} {
      this->chunk.get().reserve(this->chunk_size);
      this->refill_chunk();
    }

    Iterator& operator++() {
      this->refill_chunk();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return !(*this == other);
    }

    bool operator==(const Iterator& other) const {
      return this->done() == other.done()
             && (this->done() || !(this->sub_iter != other.sub_iter));
    }

    DerefVec& operator*() {
      return this->chunk;
    }

    DerefVec* operator->() {
      return &this->chunk;
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::end(this->container), chunk_size};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->container), chunk_size};
  }
};

#endif
<commit_msg>Supports different begin and end in chunked<commit_after>#ifndef ITER_CHUNKED_HPP_
#define ITER_CHUNKED_HPP_

#include "internal/iterbase.hpp"
#include "internal/iteratoriterator.hpp"
#include "internal/iterator_wrapper.hpp"

#include <vector>
#include <algorithm>
#include <type_traits>
#include <functional>
#include <utility>
#include <iterator>

namespace iter {
  namespace impl {
    template <typename Container>
    class Chunker;

    using ChunkedFn = IterToolFnBindSizeTSecond<Chunker>;
  }
  constexpr impl::ChunkedFn chunked{};
}

template <typename Container>
class iter::impl::Chunker {
 private:
  Container container;
  std::size_t chunk_size;

  Chunker(Container&& c, std::size_t sz)
      : container(std::forward<Container>(c)), chunk_size{sz} {}

  friend ChunkedFn;

  using IndexVector = std::vector<IteratorWrapper<Container>>;
  using DerefVec = IterIterWrapper<IndexVector>;

 public:
  Chunker(Chunker&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag, DerefVec> {
   private:
    IteratorWrapper<Container> sub_iter;
    IteratorWrapper<Container> sub_end;
    DerefVec chunk;
    std::size_t chunk_size = 0;

    bool done() const {
      return this->chunk.empty();
    }

    void refill_chunk() {
      this->chunk.get().clear();
      std::size_t i{0};
      while (i < chunk_size && this->sub_iter != this->sub_end) {
        chunk.get().push_back(this->sub_iter);
        ++this->sub_iter;
        ++i;
      }
    }

   public:
    Iterator(IteratorWrapper<Container>&& in_iter,
        IteratorWrapper<Container>&& in_end, std::size_t s)
        : sub_iter{std::move(in_iter)},
          sub_end{std::move(in_end)},
          chunk_size{s} {
      this->chunk.get().reserve(this->chunk_size);
      this->refill_chunk();
    }

    Iterator& operator++() {
      this->refill_chunk();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return !(*this == other);
    }

    bool operator==(const Iterator& other) const {
      return this->done() == other.done()
             && (this->done() || !(this->sub_iter != other.sub_iter));
    }

    DerefVec& operator*() {
      return this->chunk;
    }

    DerefVec* operator->() {
      return &this->chunk;
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::end(this->container), chunk_size};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->container), chunk_size};
  }
};

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <RandomNumberGenerator.h>
#include "Sampler.h"
#include "MyModel.h"

using namespace std;
using namespace DNest3;

int main()
{
	RandomNumberGenerator::initialise_instance();

	Sampler<MyModel> s(100, 1000);
	s.initialise();

	for(int i=0; i<10000; i++)
		s.update();

	return 0;
}

<commit_msg>Seed with time<commit_after>#include <iostream>
#include <ctime>
#include <RandomNumberGenerator.h>
#include "Sampler.h"
#include "MyModel.h"

using namespace std;
using namespace DNest3;

int main()
{
	// Initialise RNG and seed with time
	RandomNumberGenerator::initialise_instance();
	RandomNumberGenerator::get_instance().set_seed(time(0));

	Sampler<MyModel> s(100, 1000);
	s.initialise();

	for(int i=0; i<1000; i++)
		s.update();

	return 0;
}

<|endoftext|>


<commit_before>#include "config.h"

#include <cerrno>
#include <algorithm>
#include <vector>

#define _XOPEN_SOURCE 600
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>

#include "archive.hh"
#include "util.hh"

namespace nix {

static string archiveVersion1 = "nix-archive-1";

PathFilter defaultPathFilter;

static void dump(const string & path, Sink & sink, PathFilter & filter);

static void dumpEntries(const Path & path, Sink & sink, PathFilter & filter)
{
    Strings names = readDirectory(path);
    vector<string> names2(names.begin(), names.end());
    sort(names2.begin(), names2.end());

    for (vector<string>::iterator i = names2.begin();
         i != names2.end(); ++i)
    {
        Path entry = path + "/" + *i;
        if (filter(entry)) {
            writeString("entry", sink);
            writeString("(", sink);
            writeString("name", sink);
            writeString(*i, sink);
            writeString("node", sink);
            dump(entry, sink, filter);
            writeString(")", sink);
        }
    }
}

static void dumpContents(const Path & path, size_t size,
    Sink & sink)
{
    writeString("contents", sink);
    writeLongLong(size, sink);

    AutoCloseFD fd = open(path.c_str(), O_RDONLY);
    if (fd == -1) throw SysError(format("opening file `%1%'") % path);

    unsigned char buf[65536];
    size_t left = size;

    while (left > 0) {
        size_t n = left > sizeof(buf) ? sizeof(buf) : left;
        readFull(fd, buf, n);
        left -= n;
        sink(buf, n);
    }

    writePadding(size, sink);
}

static void dump(const Path & path, Sink & sink, PathFilter & filter)
{
    struct stat st;
    if (lstat(path.c_str(), &st))
        throw SysError(format("getting attributes of path `%1%'") % path);

    writeString("(", sink);

    if (S_ISREG(st.st_mode)) {
        writeString("type", sink);
        writeString("regular", sink);
        if (st.st_mode & S_IXUSR) {
            writeString("executable", sink);
            writeString("", sink);
        }
        dumpContents(path, (size_t) st.st_size, sink);
    }

    else if (S_ISDIR(st.st_mode)) {
        writeString("type", sink);
        writeString("directory", sink);
        dumpEntries(path, sink, filter);
    }

    else if (S_ISLNK(st.st_mode)) {
        writeString("type", sink);
        writeString("symlink", sink);
        writeString("target", sink);
        writeString(readLink(path), sink);
    }

    else throw Error(format("file `%1%' has an unknown type") % path);

    writeString(")", sink);
}

void dumpPath(const Path & path, Sink & sink, PathFilter & filter)
{
    writeString(archiveVersion1, sink);
    dump(path, sink, filter);
}

static SerialisationError badArchive(string s)
{
    return SerialisationError("bad archive: " + s);
}

static void skipGeneric(Source & source)
{
    if (readString(source) == "(") {
        while (readString(source) != ")")
            skipGeneric(source);
    }
}

static void parse(ParseSink & sink, Source & source, const Path & path);

static void parseEntry(ParseSink & sink, Source & source, const Path & path)
{
    string s, name;

    s = readString(source);
    if (s != "(") throw badArchive("expected open tag");

    while (1) {
        checkInterrupt();

        s = readString(source);

        if (s == ")") {
            break;
        } else if (s == "name") {
            name = readString(source);
        } else if (s == "node") {
            if (s == "") throw badArchive("entry name missing");
            parse(sink, source, path + "/" + name);
        } else {
            throw badArchive("unknown field " + s);
            skipGeneric(source);
        }
    }
}

static void parseContents(ParseSink & sink, Source & source, const Path & path)
{
    unsigned long long size = readLongLong(source);

    sink.preallocateContents(size);

    unsigned long long left = size;
    unsigned char buf[65536];

    while (left) {
        checkInterrupt();
        unsigned int n = sizeof(buf);
        if ((unsigned long long) n > left) n = left;
        source(buf, n);
        sink.receiveContents(buf, n);
        left -= n;
    }

    readPadding(size, source);
}

static void parse(ParseSink & sink, Source & source, const Path & path)
{
    string s;

    s = readString(source);
    if (s != "(") throw badArchive("expected open tag");

    enum { tpUnknown, tpRegular, tpDirectory, tpSymlink } type = tpUnknown;

    while (1) {
        checkInterrupt();

        s = readString(source);

        if (s == ")") {
            break;
        }

        else if (s == "type") {
            if (type != tpUnknown)
                throw badArchive("multiple type fields");
            string t = readString(source);

            if (t == "regular") {
                type = tpRegular;
                sink.createRegularFile(path);
            }

            else if (t == "directory") {
                sink.createDirectory(path);
                type = tpDirectory;
            }

            else if (t == "symlink") {
                type = tpSymlink;
            }

            else throw badArchive("unknown file type " + t);

        }

        else if (s == "contents" && type == tpRegular) {
            parseContents(sink, source, path);
        }

        else if (s == "executable" && type == tpRegular) {
            readString(source);
            sink.isExecutable();
        }

        else if (s == "entry" && type == tpDirectory) {
            parseEntry(sink, source, path);
        }

        else if (s == "target" && type == tpSymlink) {
            string target = readString(source);
            sink.createSymlink(path, target);
        }

        else {
            throw badArchive("unknown field " + s);
            skipGeneric(source);
        }
    }
}

void parseDump(ParseSink & sink, Source & source)
{
    string version;
    try {
        version = readString(source);
    } catch (SerialisationError & e) {
        /* This generally means the integer at the start couldn't be
           decoded.  Ignore and throw the exception below. */
    }
    if (version != archiveVersion1)
        throw badArchive("input doesn't look like a Nix archive");
    parse(sink, source, "");
}

struct RestoreSink : ParseSink
{
    Path dstPath;
    AutoCloseFD fd;

    void createDirectory(const Path & path)
    {
        Path p = dstPath + path;
        if (mkdir(p.c_str(), 0777) == -1)
            throw SysError(format("creating directory `%1%'") % p);
    };

    void createRegularFile(const Path & path)
    {
        Path p = dstPath + path;
        fd = open(p.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666);
        if (fd == -1) throw SysError(format("creating file `%1%'") % p);
    }

    void isExecutable()
    {
        struct stat st;
        if (fstat(fd, &st) == -1)
            throw SysError("fstat");
        if (fchmod(fd, st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1)
            throw SysError("fchmod");
    }

    void preallocateContents(unsigned long long len)
    {
#if HAVE_POSIX_FALLOCATE
        if (len) {
            errno = posix_fallocate(fd, 0, len);
            /* Note that EINVAL may indicate that the underlying
               filesystem doesn't support preallocation (e.g. on
               OpenSolaris).  Since preallocation is just an
               optimisation, ignore it. */
            if (errno && errno != EINVAL)
                throw SysError(format("preallocating file of %1% bytes") % len);
        }
#endif
    }

    void receiveContents(unsigned char * data, unsigned int len)
    {
        writeFull(fd, data, len);
    }

    void createSymlink(const Path & path, const string & target)
    {
        Path p = dstPath + path;
        if (symlink(target.c_str(), p.c_str()) == -1)
            throw SysError(format("creating symlink `%1%'") % p);
    }
};

void restorePath(const Path & path, Source & source)
{
    RestoreSink sink;
    sink.dstPath = path;
    parseDump(sink, source);
}

}
<commit_msg>RestoreSink: Slightly reduce the number of concurrent FDs<commit_after>#include "config.h"

#include <cerrno>
#include <algorithm>
#include <vector>

#define _XOPEN_SOURCE 600
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>

#include "archive.hh"
#include "util.hh"

namespace nix {

static string archiveVersion1 = "nix-archive-1";

PathFilter defaultPathFilter;

static void dump(const string & path, Sink & sink, PathFilter & filter);

static void dumpEntries(const Path & path, Sink & sink, PathFilter & filter)
{
    Strings names = readDirectory(path);
    vector<string> names2(names.begin(), names.end());
    sort(names2.begin(), names2.end());

    for (vector<string>::iterator i = names2.begin();
         i != names2.end(); ++i)
    {
        Path entry = path + "/" + *i;
        if (filter(entry)) {
            writeString("entry", sink);
            writeString("(", sink);
            writeString("name", sink);
            writeString(*i, sink);
            writeString("node", sink);
            dump(entry, sink, filter);
            writeString(")", sink);
        }
    }
}

static void dumpContents(const Path & path, size_t size,
    Sink & sink)
{
    writeString("contents", sink);
    writeLongLong(size, sink);

    AutoCloseFD fd = open(path.c_str(), O_RDONLY);
    if (fd == -1) throw SysError(format("opening file `%1%'") % path);

    unsigned char buf[65536];
    size_t left = size;

    while (left > 0) {
        size_t n = left > sizeof(buf) ? sizeof(buf) : left;
        readFull(fd, buf, n);
        left -= n;
        sink(buf, n);
    }

    writePadding(size, sink);
}

static void dump(const Path & path, Sink & sink, PathFilter & filter)
{
    struct stat st;
    if (lstat(path.c_str(), &st))
        throw SysError(format("getting attributes of path `%1%'") % path);

    writeString("(", sink);

    if (S_ISREG(st.st_mode)) {
        writeString("type", sink);
        writeString("regular", sink);
        if (st.st_mode & S_IXUSR) {
            writeString("executable", sink);
            writeString("", sink);
        }
        dumpContents(path, (size_t) st.st_size, sink);
    }

    else if (S_ISDIR(st.st_mode)) {
        writeString("type", sink);
        writeString("directory", sink);
        dumpEntries(path, sink, filter);
    }

    else if (S_ISLNK(st.st_mode)) {
        writeString("type", sink);
        writeString("symlink", sink);
        writeString("target", sink);
        writeString(readLink(path), sink);
    }

    else throw Error(format("file `%1%' has an unknown type") % path);

    writeString(")", sink);
}

void dumpPath(const Path & path, Sink & sink, PathFilter & filter)
{
    writeString(archiveVersion1, sink);
    dump(path, sink, filter);
}

static SerialisationError badArchive(string s)
{
    return SerialisationError("bad archive: " + s);
}

static void skipGeneric(Source & source)
{
    if (readString(source) == "(") {
        while (readString(source) != ")")
            skipGeneric(source);
    }
}

static void parse(ParseSink & sink, Source & source, const Path & path);

static void parseEntry(ParseSink & sink, Source & source, const Path & path)
{
    string s, name;

    s = readString(source);
    if (s != "(") throw badArchive("expected open tag");

    while (1) {
        checkInterrupt();

        s = readString(source);

        if (s == ")") {
            break;
        } else if (s == "name") {
            name = readString(source);
        } else if (s == "node") {
            if (s == "") throw badArchive("entry name missing");
            parse(sink, source, path + "/" + name);
        } else {
            throw badArchive("unknown field " + s);
            skipGeneric(source);
        }
    }
}

static void parseContents(ParseSink & sink, Source & source, const Path & path)
{
    unsigned long long size = readLongLong(source);

    sink.preallocateContents(size);

    unsigned long long left = size;
    unsigned char buf[65536];

    while (left) {
        checkInterrupt();
        unsigned int n = sizeof(buf);
        if ((unsigned long long) n > left) n = left;
        source(buf, n);
        sink.receiveContents(buf, n);
        left -= n;
    }

    readPadding(size, source);
}

static void parse(ParseSink & sink, Source & source, const Path & path)
{
    string s;

    s = readString(source);
    if (s != "(") throw badArchive("expected open tag");

    enum { tpUnknown, tpRegular, tpDirectory, tpSymlink } type = tpUnknown;

    while (1) {
        checkInterrupt();

        s = readString(source);

        if (s == ")") {
            break;
        }

        else if (s == "type") {
            if (type != tpUnknown)
                throw badArchive("multiple type fields");
            string t = readString(source);

            if (t == "regular") {
                type = tpRegular;
                sink.createRegularFile(path);
            }

            else if (t == "directory") {
                sink.createDirectory(path);
                type = tpDirectory;
            }

            else if (t == "symlink") {
                type = tpSymlink;
            }

            else throw badArchive("unknown file type " + t);

        }

        else if (s == "contents" && type == tpRegular) {
            parseContents(sink, source, path);
        }

        else if (s == "executable" && type == tpRegular) {
            readString(source);
            sink.isExecutable();
        }

        else if (s == "entry" && type == tpDirectory) {
            parseEntry(sink, source, path);
        }

        else if (s == "target" && type == tpSymlink) {
            string target = readString(source);
            sink.createSymlink(path, target);
        }

        else {
            throw badArchive("unknown field " + s);
            skipGeneric(source);
        }
    }
}

void parseDump(ParseSink & sink, Source & source)
{
    string version;
    try {
        version = readString(source);
    } catch (SerialisationError & e) {
        /* This generally means the integer at the start couldn't be
           decoded.  Ignore and throw the exception below. */
    }
    if (version != archiveVersion1)
        throw badArchive("input doesn't look like a Nix archive");
    parse(sink, source, "");
}

struct RestoreSink : ParseSink
{
    Path dstPath;
    AutoCloseFD fd;

    void createDirectory(const Path & path)
    {
        Path p = dstPath + path;
        if (mkdir(p.c_str(), 0777) == -1)
            throw SysError(format("creating directory `%1%'") % p);
    };

    void createRegularFile(const Path & path)
    {
        Path p = dstPath + path;
        fd.close();
        fd = open(p.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666);
        if (fd == -1) throw SysError(format("creating file `%1%'") % p);
    }

    void isExecutable()
    {
        struct stat st;
        if (fstat(fd, &st) == -1)
            throw SysError("fstat");
        if (fchmod(fd, st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1)
            throw SysError("fchmod");
    }

    void preallocateContents(unsigned long long len)
    {
#if HAVE_POSIX_FALLOCATE
        if (len) {
            errno = posix_fallocate(fd, 0, len);
            /* Note that EINVAL may indicate that the underlying
               filesystem doesn't support preallocation (e.g. on
               OpenSolaris).  Since preallocation is just an
               optimisation, ignore it. */
            if (errno && errno != EINVAL)
                throw SysError(format("preallocating file of %1% bytes") % len);
        }
#endif
    }

    void receiveContents(unsigned char * data, unsigned int len)
    {
        writeFull(fd, data, len);
    }

    void createSymlink(const Path & path, const string & target)
    {
        Path p = dstPath + path;
        if (symlink(target.c_str(), p.c_str()) == -1)
            throw SysError(format("creating symlink `%1%'") % p);
    }
};

void restorePath(const Path & path, Source & source)
{
    RestoreSink sink;
    sink.dstPath = path;
    parseDump(sink, source);
}

}
<|endoftext|>


<commit_before>#ifndef line_and_column_hh_INCLUDED
#define line_and_column_hh_INCLUDED

namespace Kakoune
{

template<typename EffectiveType>
struct LineAndColumn
{
    int line;
    int column;

    LineAndColumn(int line = 0, int column = 0)
        : line(line), column(column) {}

    EffectiveType operator+(const EffectiveType& other) const
    {
        return EffectiveType(line + other.line, column + other.column);
    }

    EffectiveType& operator+=(const EffectiveType& other)
    {
        line   += other.line;
        column += other.column;
        return *static_cast<EffectiveType*>(this);
    }

    EffectiveType operator-(const EffectiveType& other) const
    {
        return EffectiveType(line + other.line, column + other.column);
    }

    EffectiveType& operator-=(const EffectiveType& other)
    {
        line   += other.line;
        column += other.column;
        return *static_cast<EffectiveType*>(this);
    }
};

}

#endif // line_and_column_hh_INCLUDED
<commit_msg>LineAndColumn: add comparison operators<commit_after>#ifndef line_and_column_hh_INCLUDED
#define line_and_column_hh_INCLUDED

namespace Kakoune
{

template<typename EffectiveType>
struct LineAndColumn
{
    int line;
    int column;

    LineAndColumn(int line = 0, int column = 0)
        : line(line), column(column) {}

    EffectiveType operator+(const EffectiveType& other) const
    {
        return EffectiveType(line + other.line, column + other.column);
    }

    EffectiveType& operator+=(const EffectiveType& other)
    {
        line   += other.line;
        column += other.column;
        return *static_cast<EffectiveType*>(this);
    }

    EffectiveType operator-(const EffectiveType& other) const
    {
        return EffectiveType(line - other.line, column - other.column);
    }

    EffectiveType& operator-=(const EffectiveType& other)
    {
        line   -= other.line;
        column -= other.column;
        return *static_cast<EffectiveType*>(this);
    }

    bool operator< (const EffectiveType& other) const
    {
        if (line != other.line)
            return line < other.line;
        return column < other.column;
    }

    bool operator<= (const EffectiveType& other) const
    {
        if (line != other.line)
            return line < other.line;
        return column <= other.column;
    }

    bool operator== (const EffectiveType& other) const
    {
        return line == other.line and column == other.column;
    }
};

}

#endif // line_and_column_hh_INCLUDED
<|endoftext|>