<commit_before>// Copyright (C) 2014 The Regents of the University of California (Regents).
// 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.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// 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 HOLDERS 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.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include "theia/sfm/filter_view_pairs_from_relative_translation.h"

#include <ceres/rotation.h>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <memory>
#include <mutex>  // NOLINT
#include <unordered_map>

#include "theia/math/util.h"
#include "theia/util/hash.h"
#include "theia/util/map_util.h"
#include "theia/util/random.h"
#include "theia/util/threadpool.h"
#include "theia/sfm/twoview_info.h"
#include "theia/sfm/types.h"

namespace theia {

using Eigen::Vector3d;

// Helper struct to maintain the graph for the translation projection problem.
struct MFASNode {
  std::unordered_map<ViewId, double> incoming_nodes;
  std::unordered_map<ViewId, double> outgoing_nodes;
  double incoming_weight = 0;
  double outgoing_weight = 0;
};

// Rotate the translation direction based on the known orientation such that the
// translation is in the global reference frame.
std::unordered_map<ViewIdPair, Vector3d>
      RotateRelativeTranslationsToGlobalFrame(
          const std::unordered_map<ViewId, Vector3d>& orientations,
          const std::unordered_map<ViewIdPair, TwoViewInfo>& view_pairs) {
  std::unordered_map<ViewIdPair, Vector3d> rotated_translations;
  rotated_translations.reserve(orientations.size());

  for (const auto& view_pair : view_pairs) {
    const Vector3d view_to_world_rotation =
        -1.0 * FindOrDie(orientations, view_pair.first.first);
    Vector3d rotated_translation;
    ceres::AngleAxisRotatePoint(view_to_world_rotation.data(),
                                view_pair.second.position_2.data(),
                                rotated_translation.data());
    rotated_translations.emplace(view_pair.first, rotated_translation);
  }
  return rotated_translations;
}

// Find the next view to add to the order. We attempt to choose a source (i.e.,
// a node with no incoming edges) or choose a node based on a heuristic such
// that it has the most source-like properties.
ViewId FindNextViewInOrder(
    const std::unordered_map<ViewId, MFASNode>& degrees_for_view) {
  ViewId best_choice = kInvalidViewId;
  double best_score = 0;
  for (const auto& view : degrees_for_view) {
    // If the view is a source view, return it.
    if (view.second.incoming_nodes.size() == 0) {
      return view.first;
    }

    // Otherwise, keep track of the max score seen so far.
    const double score = (view.second.outgoing_weight + 1.0) /
                         (view.second.incoming_weight + 1.0);
    if (score > best_score) {
      best_choice = view.first;
      best_score = score;
    }
  }

  return best_choice;
}

// Based on the 1D translation projections, compute an ordering of the
// translations.
std::unordered_map<ViewId, int> OrderTranslationsFromProjections(
    const std::unordered_map<ViewIdPair, double>&
        translation_direction_projections) {
  // Compute the degrees of all vertices as the sum of weights coming in or out.
  std::unordered_map<ViewId, MFASNode> degrees_for_view;
  for (const auto& translation_projection : translation_direction_projections) {
    const ViewIdPair view_id_pair =
        (translation_projection.second > 0)
            ? translation_projection.first
            : ViewIdPair(translation_projection.first.second,
                         translation_projection.first.first);

    // Update the MFAS entry.
    const double weight = std::abs(translation_projection.second);
    degrees_for_view[view_id_pair.second].incoming_weight += weight;
    degrees_for_view[view_id_pair.first].outgoing_weight += weight;
    degrees_for_view[view_id_pair.second].incoming_nodes.emplace(
        view_id_pair.first, weight);
    degrees_for_view[view_id_pair.first].outgoing_nodes.emplace(
        view_id_pair.second, weight);
  }

  // Compute the ordering.
  const int num_views = degrees_for_view.size();
  std::unordered_map<ViewId, int> translation_ordering;
  for (int i = 0; i < num_views; i++) {
    // Find the next view to add.
    const ViewId next_view_in_order = FindNextViewInOrder(degrees_for_view);
    translation_ordering[next_view_in_order] = i;

    // Update the MFAS graph and remove the next view from the degrees_for_view.
    const auto& next_view_info =
        FindOrDie(degrees_for_view, next_view_in_order);
    for (auto& neighbor_info : next_view_info.incoming_nodes) {
      degrees_for_view[neighbor_info.first].outgoing_weight -=
          neighbor_info.second;
      degrees_for_view[neighbor_info.first].outgoing_nodes.erase(
          next_view_in_order);
    }
    for (auto& neighbor_info : next_view_info.outgoing_nodes) {
      degrees_for_view[neighbor_info.first].incoming_weight -=
          neighbor_info.second;
      degrees_for_view[neighbor_info.first].incoming_nodes.erase(
          next_view_in_order);
    }
    degrees_for_view.erase(next_view_in_order);
  }

  return translation_ordering;
}

// Projects all the of the translation onto the given axis.
std::unordered_map<ViewIdPair, double> ProjectTranslationsOntoAxis(
    const Vector3d& axis,
    const std::unordered_map<ViewIdPair, Vector3d>& relative_translations) {
  std::unordered_map<ViewIdPair, double> projection_weights;
  projection_weights.reserve(relative_translations.size());

  for (const auto& relative_translation : relative_translations) {
    const double projection_weight = relative_translation.second.dot(axis);
    projection_weights.emplace(relative_translation.first, projection_weight);
  }
  return projection_weights;
}

// This chooses a random axis based on the given relative translations.
Vector3d ChooseRandomAxis(
    const std::unordered_map<ViewIdPair, Vector3d>& relative_translations) {
  // Choose a random element in the relative translations.
  const int random_index = RandInt(0, relative_translations.size() - 1);
  auto it = relative_translations.begin();
  std::advance(it, random_index);
  Eigen::AngleAxisd noise_rotation(DegToRad(RandGaussian(0, 5.0)),
                                   Vector3d::Random().normalized());
  return noise_rotation * (it->second);
}

// Performs a single iterations of the translation filtering. This method is
// thread-safe.
void TranslationFilteringIteration(
    const std::unordered_map<ViewIdPair, Vector3d>& relative_translations,
    std::mutex* mutex,
    std::unordered_map<ViewIdPair, double>* bad_edge_weight) {
  // Get a random vector to project all relative translations on to.
  const Vector3d& random_axis = ChooseRandomAxis(relative_translations);

  // Project all vectors.
  const std::unordered_map<ViewIdPair, double>&
      translation_direction_projections =
          ProjectTranslationsOntoAxis(random_axis, relative_translations);

  // Compute ordering.
  const std::unordered_map<ViewId, int>& translation_ordering =
      OrderTranslationsFromProjections(translation_direction_projections);

  // Compute bad edge weights.
  for (auto& edge : *bad_edge_weight) {
    const int ordering_diff =
        FindOrDie(translation_ordering, edge.first.second) -
        FindOrDie(translation_ordering, edge.first.first);
    const double& projection_weight_of_edge =
        FindOrDieNoPrint(translation_direction_projections, edge.first);

    VLOG(3) << "Edge (" << edge.first.first << ", " << edge.first.second
            << ") has ordering diff of " << ordering_diff
            << " and a projection of " << projection_weight_of_edge << " from "
            << FindOrDieNoPrint(relative_translations, edge.first).transpose();
    // If the ordering is inconsistent, add the absolute value of the bad weight
    // to the aggregate bad weight.
    if ((ordering_diff < 0 && projection_weight_of_edge > 0) ||
        (ordering_diff > 0 && projection_weight_of_edge < 0)) {
      mutex->lock();
      edge.second += std::abs(projection_weight_of_edge);
      mutex->unlock();
    }
  }
}

void FilterViewPairsFromRelativeTranslation(
    const FilterViewPairsFromRelativeTranslationOptions& options,
    const std::unordered_map<ViewId, Vector3d>& orientations,
    std::unordered_map<ViewIdPair, TwoViewInfo>* view_pairs) {
  // Weights of edges that have been accumulated throughout the iterations. A
  // higher weight means the edge is more likely to be bad.
  std::unordered_map<ViewIdPair, double> bad_edge_weight;
  for (const auto& view_pair : *view_pairs) {
    bad_edge_weight[view_pair.first] = 0.0;
  }

  // Compute the adjusted translations so that they are oriented in the global
  // frame.
  const std::unordered_map<ViewIdPair, Vector3d>& rotated_translations =
      RotateRelativeTranslationsToGlobalFrame(orientations, *view_pairs);

  std::unique_ptr<ThreadPool> pool(new ThreadPool(options.num_threads));
  std::mutex mutex;
  for (int i = 0; i < options.num_iterations; i++) {
    pool->Add(TranslationFilteringIteration,
              rotated_translations,
              &mutex,
              &bad_edge_weight);
  }
  pool.reset(nullptr);

  // Remove all the bad edges.
  const double max_aggregated_projection_tolerance =
      options.translation_projection_tolerance * options.num_iterations;
  int num_view_pairs_removed = 0;
  for (const auto& view_pair : bad_edge_weight) {
    if (view_pair.second > max_aggregated_projection_tolerance) {
      view_pairs->erase(view_pair.first);
      ++num_view_pairs_removed;
    }
  }

  VLOG(1) << "Removed " << num_view_pairs_removed
          << " view pairs by relative translation filtering.";
}

}  // namespace theia
<commit_msg>Using a gaussian density estimator for random axis projections. This increases performance and unit test is passing now.<commit_after>// Copyright (C) 2014 The Regents of the University of California (Regents).
// 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.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// 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 HOLDERS 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.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include "theia/sfm/filter_view_pairs_from_relative_translation.h"

#include <ceres/rotation.h>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <memory>
#include <mutex>  // NOLINT
#include <unordered_map>

#include "theia/math/util.h"
#include "theia/util/hash.h"
#include "theia/util/map_util.h"
#include "theia/util/random.h"
#include "theia/util/threadpool.h"
#include "theia/sfm/twoview_info.h"
#include "theia/sfm/types.h"

namespace theia {

using Eigen::Vector3d;

// Helper struct to maintain the graph for the translation projection problem.
struct MFASNode {
  std::unordered_map<ViewId, double> incoming_nodes;
  std::unordered_map<ViewId, double> outgoing_nodes;
  double incoming_weight = 0;
  double outgoing_weight = 0;
};

// Rotate the translation direction based on the known orientation such that the
// translation is in the global reference frame.
std::unordered_map<ViewIdPair, Vector3d>
      RotateRelativeTranslationsToGlobalFrame(
          const std::unordered_map<ViewId, Vector3d>& orientations,
          const std::unordered_map<ViewIdPair, TwoViewInfo>& view_pairs) {
  std::unordered_map<ViewIdPair, Vector3d> rotated_translations;
  rotated_translations.reserve(orientations.size());

  for (const auto& view_pair : view_pairs) {
    const Vector3d view_to_world_rotation =
        -1.0 * FindOrDie(orientations, view_pair.first.first);
    Vector3d rotated_translation;
    ceres::AngleAxisRotatePoint(view_to_world_rotation.data(),
                                view_pair.second.position_2.data(),
                                rotated_translation.data());
    rotated_translations.emplace(view_pair.first, rotated_translation);
  }
  return rotated_translations;
}

// Find the next view to add to the order. We attempt to choose a source (i.e.,
// a node with no incoming edges) or choose a node based on a heuristic such
// that it has the most source-like properties.
ViewId FindNextViewInOrder(
    const std::unordered_map<ViewId, MFASNode>& degrees_for_view) {
  ViewId best_choice = kInvalidViewId;
  double best_score = 0;
  for (const auto& view : degrees_for_view) {
    // If the view is a source view, return it.
    if (view.second.incoming_nodes.size() == 0) {
      return view.first;
    }

    // Otherwise, keep track of the max score seen so far.
    const double score = (view.second.outgoing_weight + 1.0) /
                         (view.second.incoming_weight + 1.0);
    if (score > best_score) {
      best_choice = view.first;
      best_score = score;
    }
  }

  return best_choice;
}

// Based on the 1D translation projections, compute an ordering of the
// translations.
std::unordered_map<ViewId, int> OrderTranslationsFromProjections(
    const std::unordered_map<ViewIdPair, double>&
        translation_direction_projections) {
  // Compute the degrees of all vertices as the sum of weights coming in or out.
  std::unordered_map<ViewId, MFASNode> degrees_for_view;
  for (const auto& translation_projection : translation_direction_projections) {
    const ViewIdPair view_id_pair =
        (translation_projection.second > 0)
            ? translation_projection.first
            : ViewIdPair(translation_projection.first.second,
                         translation_projection.first.first);

    // Update the MFAS entry.
    const double weight = std::abs(translation_projection.second);
    degrees_for_view[view_id_pair.second].incoming_weight += weight;
    degrees_for_view[view_id_pair.first].outgoing_weight += weight;
    degrees_for_view[view_id_pair.second].incoming_nodes.emplace(
        view_id_pair.first, weight);
    degrees_for_view[view_id_pair.first].outgoing_nodes.emplace(
        view_id_pair.second, weight);
  }

  // Compute the ordering.
  const int num_views = degrees_for_view.size();
  std::unordered_map<ViewId, int> translation_ordering;
  for (int i = 0; i < num_views; i++) {
    // Find the next view to add.
    const ViewId next_view_in_order = FindNextViewInOrder(degrees_for_view);
    translation_ordering[next_view_in_order] = i;

    // Update the MFAS graph and remove the next view from the degrees_for_view.
    const auto& next_view_info =
        FindOrDie(degrees_for_view, next_view_in_order);
    for (auto& neighbor_info : next_view_info.incoming_nodes) {
      degrees_for_view[neighbor_info.first].outgoing_weight -=
          neighbor_info.second;
      degrees_for_view[neighbor_info.first].outgoing_nodes.erase(
          next_view_in_order);
    }
    for (auto& neighbor_info : next_view_info.outgoing_nodes) {
      degrees_for_view[neighbor_info.first].incoming_weight -=
          neighbor_info.second;
      degrees_for_view[neighbor_info.first].incoming_nodes.erase(
          next_view_in_order);
    }
    degrees_for_view.erase(next_view_in_order);
  }

  return translation_ordering;
}

// Projects all the of the translation onto the given axis.
std::unordered_map<ViewIdPair, double> ProjectTranslationsOntoAxis(
    const Vector3d& axis,
    const std::unordered_map<ViewIdPair, Vector3d>& relative_translations) {
  std::unordered_map<ViewIdPair, double> projection_weights;
  projection_weights.reserve(relative_translations.size());

  for (const auto& relative_translation : relative_translations) {
    const double projection_weight = relative_translation.second.dot(axis);
    projection_weights.emplace(relative_translation.first, projection_weight);
  }
  return projection_weights;
}

// This chooses a random axis based on the given relative translations.
void ComputeMeanVariance(
    const std::unordered_map<ViewIdPair, Vector3d>& relative_translations,
    Vector3d* mean,
    Vector3d* variance) {
  mean->setZero();
  variance->setZero();
  for (const auto& translation : relative_translations) {
    *mean += translation.second;
  }
  *mean /= static_cast<double>(relative_translations.size());

  for (const auto& translation : relative_translations) {
    *variance += (translation.second - *mean).cwiseAbs2();
  }
  *variance /= static_cast<double>(relative_translations.size() - 1);
}

// Performs a single iterations of the translation filtering. This method is
// thread-safe.
void TranslationFilteringIteration(
    const std::unordered_map<ViewIdPair, Vector3d>& relative_translations,
    const Vector3d& direction_mean,
    const Vector3d& direction_variance,
    std::mutex* mutex,
    std::unordered_map<ViewIdPair, double>* bad_edge_weight) {
  // Get a random vector to project all relative translations on to.
  const Vector3d random_axis(
      RandGaussian(direction_mean[0], direction_variance[0]),
      RandGaussian(direction_mean[1], direction_variance[1]),
      RandGaussian(direction_mean[2], direction_variance[2]));

  // Project all vectors.
  const std::unordered_map<ViewIdPair, double>&
      translation_direction_projections =
          ProjectTranslationsOntoAxis(random_axis, relative_translations);

  // Compute ordering.
  const std::unordered_map<ViewId, int>& translation_ordering =
      OrderTranslationsFromProjections(translation_direction_projections);

  // Compute bad edge weights.
  for (auto& edge : *bad_edge_weight) {
    const int ordering_diff =
        FindOrDie(translation_ordering, edge.first.second) -
        FindOrDie(translation_ordering, edge.first.first);
    const double& projection_weight_of_edge =
        FindOrDieNoPrint(translation_direction_projections, edge.first);

    VLOG(3) << "Edge (" << edge.first.first << ", " << edge.first.second
            << ") has ordering diff of " << ordering_diff
            << " and a projection of " << projection_weight_of_edge << " from "
            << FindOrDieNoPrint(relative_translations, edge.first).transpose();
    // If the ordering is inconsistent, add the absolute value of the bad weight
    // to the aggregate bad weight.
    if ((ordering_diff < 0 && projection_weight_of_edge > 0) ||
        (ordering_diff > 0 && projection_weight_of_edge < 0)) {
      mutex->lock();
      edge.second += std::abs(projection_weight_of_edge);
      mutex->unlock();
    }
  }
}

void FilterViewPairsFromRelativeTranslation(
    const FilterViewPairsFromRelativeTranslationOptions& options,
    const std::unordered_map<ViewId, Vector3d>& orientations,
    std::unordered_map<ViewIdPair, TwoViewInfo>* view_pairs) {
  // Weights of edges that have been accumulated throughout the iterations. A
  // higher weight means the edge is more likely to be bad.
  std::unordered_map<ViewIdPair, double> bad_edge_weight;
  for (const auto& view_pair : *view_pairs) {
    bad_edge_weight[view_pair.first] = 0.0;
  }

  // Compute the adjusted translations so that they are oriented in the global
  // frame.
  const std::unordered_map<ViewIdPair, Vector3d>& rotated_translations =
      RotateRelativeTranslationsToGlobalFrame(orientations, *view_pairs);

  Vector3d translation_mean, translation_variance;
  ComputeMeanVariance(rotated_translations,
                      &translation_mean,
                      &translation_variance);

  std::unique_ptr<ThreadPool> pool(new ThreadPool(options.num_threads));
  std::mutex mutex;
  for (int i = 0; i < options.num_iterations; i++) {
    pool->Add(TranslationFilteringIteration,
              rotated_translations,
              translation_mean,
              translation_variance,
              &mutex,
              &bad_edge_weight);
  }
  pool.reset(nullptr);

  // Remove all the bad edges.
  const double max_aggregated_projection_tolerance =
      options.translation_projection_tolerance * options.num_iterations;
  int num_view_pairs_removed = 0;
  for (const auto& view_pair : bad_edge_weight) {
    VLOG(3) << "View pair (" << view_pair.first.first << ", "
            << view_pair.first.second << ") projection = " << view_pair.second;
    if (view_pair.second > max_aggregated_projection_tolerance) {
      view_pairs->erase(view_pair.first);
      ++num_view_pairs_removed;
    }
  }

  VLOG(1) << "Removed " << num_view_pairs_removed
          << " view pairs by relative translation filtering.";
}

}  // namespace theia
<|endoftext|>


<commit_before>
#include "PropertyGeneration.h"

#include "base_types.h"
#include "utils.h"
#include "logging.h"

#include "standard_properties.h"

#include <linux/videodev2.h>
#include <cstring>
#include <algorithm>

using namespace tcam;

std::vector<std::shared_ptr<Property>> tcam::generate_simulated_properties (std::vector<std::shared_ptr<Property>> props,
                                                                                std::shared_ptr<PropertyImpl> impl)
{
    std::vector<std::shared_ptr<Property>> new_properties;

    // requirements for auto center
    if (find_property(props, "Offset Auto Center") == nullptr &&
        find_property(props, "Offset X") != nullptr &&
        find_property(props, "Offset Y") != nullptr)
    {
        camera_property cp = {};
        strcpy(cp.name, "Offset Auto Center");
        cp.type = PROPERTY_TYPE_BOOLEAN;
        cp.value.b.default_value = false;
        cp.value.b.value = cp.value.b.default_value;
        cp.flags = set_bit(cp.flags, PROPERTY_FLAG_EXTERNAL);

        auto property_auto_offset = std::make_shared<PropertyBoolean>(impl, cp, Property::BOOLEAN);

        // property_description pd = { EMULATED_PROPERTY, property_auto_offset};

        tcam_log(TCAM_LOG_DEBUG, "Adding 'Offset Auto Center' to property list");

        new_properties.push_back(property_auto_offset);
    }

    return new_properties;
}

bool tcam::handle_auto_center (const Property& new_property,
                                      std::vector<std::shared_ptr<Property>>& props,
                                      const IMG_SIZE& sensor,
                                      const IMG_SIZE& current_format)
{
    if (new_property.getType() != PROPERTY_TYPE_BOOLEAN)
    {
        return false;
    }

    auto p = static_cast<const PropertyBoolean&>(new_property);

    if (p.getValue())
    {
        IMG_SIZE values = calculate_auto_center(sensor, current_format);

        auto prop_off_x = find_property(props, "Offset X");
        auto prop_off_y = find_property(props, "Offset Y");

        std::static_pointer_cast<PropertyInteger>(prop_off_x)->setValue(values.width);
        std::static_pointer_cast<PropertyInteger>(prop_off_y)->setValue(values.height);

        // TODO: set properties read only
    }
    else
    {
        // TODO: remove read only

        auto prop_off_x = find_property(props, "Offset X");
        auto prop_off_y = find_property(props, "Offset Y");

        std::static_pointer_cast<PropertyInteger>(prop_off_x)->setValue(0);
        std::static_pointer_cast<PropertyInteger>(prop_off_y)->setValue(0);
    }
}
<commit_msg>Switched property offset auto simulation to PROPERTY_ID usage<commit_after>
#include "PropertyGeneration.h"

#include "base_types.h"
#include "utils.h"
#include "logging.h"

#include "standard_properties.h"

#include <linux/videodev2.h>
#include <cstring>
#include <algorithm>

using namespace tcam;

std::vector<std::shared_ptr<Property>> tcam::generate_simulated_properties (std::vector<std::shared_ptr<Property>> props,
                                                                                std::shared_ptr<PropertyImpl> impl)
{
    std::vector<std::shared_ptr<Property>> new_properties;

    // requirements for auto center
    if (find_property(props, PROPERTY_OFFSET_AUTO) == nullptr &&
        find_property(props, PROPERTY_OFFSET_X) != nullptr &&
        find_property(props, PROPERTY_OFFSET_Y) != nullptr)
    {
        camera_property cp = {};
        cp.id = PROPERTY_OFFSET_AUTO;
        strcpy(cp.name, "Offset Auto Center");
        cp.type = PROPERTY_TYPE_BOOLEAN;
        cp.value.b.default_value = false;
        cp.value.b.value = cp.value.b.default_value;
        cp.flags = set_bit(cp.flags, PROPERTY_FLAG_EXTERNAL);

        auto property_auto_offset = std::make_shared<PropertyBoolean>(impl, cp, Property::BOOLEAN);

        // property_description pd = { EMULATED_PROPERTY, property_auto_offset};

        tcam_log(TCAM_LOG_DEBUG, "Adding 'Offset Auto Center' to property list");

        new_properties.push_back(property_auto_offset);
    }

    return new_properties;
}

bool tcam::handle_auto_center (const Property& new_property,
                                      std::vector<std::shared_ptr<Property>>& props,
                                      const IMG_SIZE& sensor,
                                      const IMG_SIZE& current_format)
{
    if (new_property.getType() != PROPERTY_TYPE_BOOLEAN)
    {
        return false;
    }

    auto p = static_cast<const PropertyBoolean&>(new_property);

    if (p.getValue())
    {
        IMG_SIZE values = calculate_auto_center(sensor, current_format);

        auto prop_off_x = find_property(props, "Offset X");
        auto prop_off_y = find_property(props, "Offset Y");

        std::static_pointer_cast<PropertyInteger>(prop_off_x)->setValue(values.width);
        std::static_pointer_cast<PropertyInteger>(prop_off_y)->setValue(values.height);

        // TODO: set properties read only
    }
    else
    {
        // TODO: remove read only

        auto prop_off_x = find_property(props, "Offset X");
        auto prop_off_y = find_property(props, "Offset Y");

        std::static_pointer_cast<PropertyInteger>(prop_off_x)->setValue(0);
        std::static_pointer_cast<PropertyInteger>(prop_off_y)->setValue(0);
    }
}
<|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.
==============================================================================*/

#if GOOGLE_CUDA

#include "tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.h"

#include <algorithm>
#include <vector>

#include "tensorflow/core/common_runtime/gpu/gpu_init.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/lib/random/simple_philox.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/stream_executor.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/test_benchmark.h"
#include "tensorflow/core/platform/types.h"

namespace gpu = ::perftools::gputools;

namespace tensorflow {
namespace {

static void CheckStats(Allocator* a, int64 num_allocs, int64 bytes_in_use,
                       int64 max_bytes_in_use, int64 max_alloc_size) {
  AllocatorStats stats;
  a->GetStats(&stats);
  LOG(INFO) << "Alloc stats: " << std::endl << stats.DebugString();
  EXPECT_EQ(stats.bytes_in_use, bytes_in_use);
  EXPECT_EQ(stats.max_bytes_in_use, max_bytes_in_use);
  EXPECT_EQ(stats.num_allocs, num_allocs);
  EXPECT_EQ(stats.max_alloc_size, max_alloc_size);
}

TEST(GPUBFCAllocatorTest, NoDups) {
  GPUBFCAllocator a(0, 1 << 30);
  CheckStats(&a, 0, 0, 0, 0);

  // Allocate a lot of raw pointers
  std::vector<void*> ptrs;
  for (int s = 1; s < 1024; s++) {
    void* raw = a.AllocateRaw(1, s);
    ptrs.push_back(raw);
  }
  CheckStats(&a, 1023, 654336, 654336, 1024);

  std::sort(ptrs.begin(), ptrs.end());

  // Make sure none of them are equal, and that none of them overlap.
  for (size_t i = 1; i < ptrs.size(); i++) {
    ASSERT_NE(ptrs[i], ptrs[i - 1]);  // No dups
    size_t req_size = a.RequestedSize(ptrs[i - 1]);
    ASSERT_GT(req_size, 0);
    ASSERT_GE(static_cast<char*>(ptrs[i]) - static_cast<char*>(ptrs[i - 1]),
              req_size);
  }

  for (size_t i = 0; i < ptrs.size(); i++) {
    a.DeallocateRaw(ptrs[i]);
  }
  CheckStats(&a, 1023, 0, 654336, 1024);
}

TEST(GPUBFCAllocatorTest, AllocationsAndDeallocations) {
  GPUBFCAllocator a(0, 1 << 30);
  // Allocate 256 raw pointers of sizes between 100 bytes and about
  // a meg
  random::PhiloxRandom philox(123, 17);
  random::SimplePhilox rand(&philox);

  std::vector<void*> initial_ptrs;
  for (int s = 1; s < 256; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % 1048576, 100), 1048576);
    void* raw = a.AllocateRaw(1, size);

    initial_ptrs.push_back(raw);
  }

  // Deallocate half of the memory, and keep track of the others.
  std::vector<void*> existing_ptrs;
  for (size_t i = 0; i < initial_ptrs.size(); i++) {
    if (i % 2 == 1) {
      a.DeallocateRaw(initial_ptrs[i]);
    } else {
      existing_ptrs.push_back(initial_ptrs[i]);
    }
  }

  // Allocate a lot of raw pointers
  for (int s = 1; s < 256; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % 1048576, 100), 1048576);
    void* raw = a.AllocateRaw(1, size);
    existing_ptrs.push_back(raw);
  }

  std::sort(existing_ptrs.begin(), existing_ptrs.end());
  // Make sure none of them are equal
  for (size_t i = 1; i < existing_ptrs.size(); i++) {
    CHECK_NE(existing_ptrs[i], existing_ptrs[i - 1]);  // No dups

    size_t req_size = a.RequestedSize(existing_ptrs[i - 1]);
    ASSERT_GT(req_size, 0);

    // Check that they don't overlap.
    ASSERT_GE(static_cast<char*>(existing_ptrs[i]) -
                  static_cast<char*>(existing_ptrs[i - 1]),
              req_size);
  }

  for (size_t i = 0; i < existing_ptrs.size(); i++) {
    a.DeallocateRaw(existing_ptrs[i]);
  }
}

TEST(GPUBFCAllocatorTest, ExerciseCoalescing) {
  GPUBFCAllocator a(0, 1 << 30);
  CheckStats(&a, 0, 0, 0, 0);

  float* first_ptr = a.Allocate<float>(1024);
  a.DeallocateRaw(first_ptr);
  CheckStats(&a, 1, 0, 4096, 4096);
  for (int i = 0; i < 1024; ++i) {
    // Allocate several buffers of different sizes, and then clean them
    // all up.  We should be able to repeat this endlessly without
    // causing fragmentation and growth.
    float* t1 = a.Allocate<float>(1024);

    int64* t2 = a.Allocate<int64>(1048576);
    double* t3 = a.Allocate<double>(2048);
    float* t4 = a.Allocate<float>(10485760);

    a.DeallocateRaw(t1);
    a.DeallocateRaw(t2);
    a.DeallocateRaw(t3);
    a.DeallocateRaw(t4);
  }
  CheckStats(&a, 4097, 0, 1024 * sizeof(float) + 1048576 * sizeof(int64) +
                              2048 * sizeof(double) + 10485760 * sizeof(float),
             10485760 * sizeof(float));

  // At the end, we should have coalesced all memory into one region
  // starting at the beginning, so validate that allocating a pointer
  // starts from this region.
  float* first_ptr_after = a.Allocate<float>(1024);
  EXPECT_EQ(first_ptr, first_ptr_after);
  a.DeallocateRaw(first_ptr_after);
}

TEST(GPUBFCAllocatorTest, AllocateZeroBufSize) {
  GPUBFCAllocator a(0, 1 << 30);
  float* ptr = a.Allocate<float>(0);
  EXPECT_EQ(nullptr, ptr);
}

TEST(GPUBFCAllocatorTest, TracksSizes) {
  GPUBFCAllocator a(0, 1 << 30);
  EXPECT_EQ(true, a.TracksAllocationSizes());
}

TEST(GPUBFCAllocatorTest, AllocatedVsRequested) {
  GPUBFCAllocator a(0, 1 << 30);
  float* t1 = a.Allocate<float>(1);
  EXPECT_EQ(4, a.RequestedSize(t1));
  EXPECT_EQ(256, a.AllocatedSize(t1));
  a.DeallocateRaw(t1);
}

TEST(GPUBFCAllocatorTest, TestCustomMemoryLimit) {
  // Configure a 1MiB byte limit
  GPUBFCAllocator a(0, 1 << 20);

  float* first_ptr = a.Allocate<float>(1 << 6);
  float* second_ptr = a.Allocate<float>(1 << 20);

  EXPECT_NE(nullptr, first_ptr);
  EXPECT_EQ(nullptr, second_ptr);
  a.DeallocateRaw(first_ptr);
}

TEST(GPUBFCAllocatorTest, AllocationsAndDeallocationsWithGrowth) {
  GPUOptions options;
  options.set_allow_growth(true);

  // Max of 2GiB, but starts out small.
  GPUBFCAllocator a(0, 1LL << 31, options);

  // Allocate 10 raw pointers of sizes between 100 bytes and about
  // 64 megs.
  random::PhiloxRandom philox(123, 17);
  random::SimplePhilox rand(&philox);

  const int32 max_mem = 1 << 27;

  std::vector<void*> initial_ptrs;
  for (int s = 1; s < 10; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % max_mem, 100), max_mem);
    void* raw = a.AllocateRaw(1, size);

    initial_ptrs.push_back(raw);
  }

  // Deallocate half of the memory, and keep track of the others.
  std::vector<void*> existing_ptrs;
  for (size_t i = 0; i < initial_ptrs.size(); i++) {
    if (i % 2 == 1) {
      a.DeallocateRaw(initial_ptrs[i]);
    } else {
      existing_ptrs.push_back(initial_ptrs[i]);
    }
  }

  const int32 max_mem_2 = 1 << 26;
  // Allocate a lot of raw pointers between 100 bytes and 64 megs.
  for (int s = 1; s < 10; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % max_mem_2, 100), max_mem_2);
    void* raw = a.AllocateRaw(1, size);
    existing_ptrs.push_back(raw);
  }

  std::sort(existing_ptrs.begin(), existing_ptrs.end());
  // Make sure none of them are equal
  for (size_t i = 1; i < existing_ptrs.size(); i++) {
    CHECK_NE(existing_ptrs[i], existing_ptrs[i - 1]);  // No dups

    size_t req_size = a.RequestedSize(existing_ptrs[i - 1]);
    ASSERT_GT(req_size, 0);

    // Check that they don't overlap.
    ASSERT_GE(static_cast<char*>(existing_ptrs[i]) -
                  static_cast<char*>(existing_ptrs[i - 1]),
              req_size);
  }

  for (size_t i = 0; i < existing_ptrs.size(); i++) {
    a.DeallocateRaw(existing_ptrs[i]);
  }

  AllocatorStats stats;
  a.GetStats(&stats);
  LOG(INFO) << "Alloc stats: \n" << stats.DebugString();
}

static void BM_Allocation(int iters) {
  GPUBFCAllocator a(0, 1uLL << 33);
  // Exercise a few different allocation sizes
  std::vector<size_t> sizes = {256,        4096,      16384,    524288,
                               512,        1048576,   10485760, 104857600,
                               1048576000, 2048576000};
  int size_index = 0;

  while (--iters > 0) {
    size_t bytes = sizes[size_index++ % sizes.size()];
    void* p = a.AllocateRaw(1, bytes);
    a.DeallocateRaw(p);
  }
}
BENCHMARK(BM_Allocation);

static void BM_AllocationThreaded(int iters, int num_threads) {
  GPUBFCAllocator a(0, 1uLL << 33);
  thread::ThreadPool pool(Env::Default(), "test", num_threads);
  std::atomic_int_fast32_t count(iters);
  mutex done_lock;
  condition_variable done;
  bool done_flag = false;

  for (int t = 0; t < num_threads; t++) {
    pool.Schedule([&a, &count, &done_lock, &done, &done_flag, iters]() {
      // Exercise a few different allocation sizes
      std::vector<int> sizes = {256, 4096,    16384,    524288,
                                512, 1048576, 10485760, 104857600};
      int size_index = 0;
      for (int i = 0; i < iters; i++) {
        int bytes = sizes[size_index++ % sizes.size()];
        void* p = a.AllocateRaw(1, bytes);
        a.DeallocateRaw(p);
        if (count.fetch_sub(1) == 1) {
          mutex_lock l(done_lock);
          done_flag = true;
          done.notify_all();
          break;
        }
      }
    });
  }
  mutex_lock l(done_lock);
  if (!done_flag) {
    done.wait(l);
  }
}
BENCHMARK(BM_AllocationThreaded)->Arg(1)->Arg(4)->Arg(16);

// A more complex benchmark that defers deallocation of an object for
// "delay" allocations.
static void BM_AllocationDelayed(int iters, int delay) {
  GPUBFCAllocator a(0, 1 << 30);
  // Exercise a few different allocation sizes
  std::vector<int> sizes = {256, 4096, 16384, 4096, 512, 1024, 1024};
  int size_index = 0;

  std::vector<void*> ptrs;
  for (int i = 0; i < delay; i++) {
    ptrs.push_back(nullptr);
  }
  int pindex = 0;
  while (--iters > 0) {
    if (ptrs[pindex] != nullptr) {
      a.DeallocateRaw(ptrs[pindex]);
      ptrs[pindex] = nullptr;
    }
    int bytes = sizes[size_index++ % sizes.size()];
    void* p = a.AllocateRaw(1, bytes);
    ptrs[pindex] = p;
    pindex = (pindex + 1) % ptrs.size();
  }
  for (int i = 0; i < ptrs.size(); i++) {
    if (ptrs[i] != nullptr) {
      a.DeallocateRaw(ptrs[i]);
    }
  }
}
BENCHMARK(BM_AllocationDelayed)->Arg(1)->Arg(10)->Arg(100)->Arg(1000);

}  // namespace
}  // namespace tensorflow

#endif  // GOOGLE_CUDA
<commit_msg>Fix GPU BUILD Change: 119431584<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.
==============================================================================*/

#if GOOGLE_CUDA

#include "tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.h"

#include <algorithm>
#include <vector>

#include "tensorflow/core/common_runtime/gpu/gpu_init.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/lib/random/simple_philox.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/stream_executor.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/test_benchmark.h"
#include "tensorflow/core/platform/types.h"

namespace gpu = ::perftools::gputools;

namespace tensorflow {
namespace {

static void CheckStats(Allocator* a, int64 num_allocs, int64 bytes_in_use,
                       int64 max_bytes_in_use, int64 max_alloc_size) {
  AllocatorStats stats;
  a->GetStats(&stats);
  LOG(INFO) << "Alloc stats: " << std::endl << stats.DebugString();
  EXPECT_EQ(stats.bytes_in_use, bytes_in_use);
  EXPECT_EQ(stats.max_bytes_in_use, max_bytes_in_use);
  EXPECT_EQ(stats.num_allocs, num_allocs);
  EXPECT_EQ(stats.max_alloc_size, max_alloc_size);
}

TEST(GPUBFCAllocatorTest, NoDups) {
  GPUBFCAllocator a(0, 1 << 30);
  CheckStats(&a, 0, 0, 0, 0);

  // Allocate a lot of raw pointers
  std::vector<void*> ptrs;
  for (int s = 1; s < 1024; s++) {
    void* raw = a.AllocateRaw(1, s);
    ptrs.push_back(raw);
  }
  CheckStats(&a, 1023, 654336, 654336, 1024);

  std::sort(ptrs.begin(), ptrs.end());

  // Make sure none of them are equal, and that none of them overlap.
  for (size_t i = 1; i < ptrs.size(); i++) {
    ASSERT_NE(ptrs[i], ptrs[i - 1]);  // No dups
    size_t req_size = a.RequestedSize(ptrs[i - 1]);
    ASSERT_GT(req_size, 0);
    ASSERT_GE(static_cast<char*>(ptrs[i]) - static_cast<char*>(ptrs[i - 1]),
              req_size);
  }

  for (size_t i = 0; i < ptrs.size(); i++) {
    a.DeallocateRaw(ptrs[i]);
  }
  CheckStats(&a, 1023, 0, 654336, 1024);
}

TEST(GPUBFCAllocatorTest, AllocationsAndDeallocations) {
  GPUBFCAllocator a(0, 1 << 30);
  // Allocate 256 raw pointers of sizes between 100 bytes and about
  // a meg
  random::PhiloxRandom philox(123, 17);
  random::SimplePhilox rand(&philox);

  std::vector<void*> initial_ptrs;
  for (int s = 1; s < 256; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % 1048576, 100), 1048576);
    void* raw = a.AllocateRaw(1, size);

    initial_ptrs.push_back(raw);
  }

  // Deallocate half of the memory, and keep track of the others.
  std::vector<void*> existing_ptrs;
  for (size_t i = 0; i < initial_ptrs.size(); i++) {
    if (i % 2 == 1) {
      a.DeallocateRaw(initial_ptrs[i]);
    } else {
      existing_ptrs.push_back(initial_ptrs[i]);
    }
  }

  // Allocate a lot of raw pointers
  for (int s = 1; s < 256; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % 1048576, 100), 1048576);
    void* raw = a.AllocateRaw(1, size);
    existing_ptrs.push_back(raw);
  }

  std::sort(existing_ptrs.begin(), existing_ptrs.end());
  // Make sure none of them are equal
  for (size_t i = 1; i < existing_ptrs.size(); i++) {
    CHECK_NE(existing_ptrs[i], existing_ptrs[i - 1]);  // No dups

    size_t req_size = a.RequestedSize(existing_ptrs[i - 1]);
    ASSERT_GT(req_size, 0);

    // Check that they don't overlap.
    ASSERT_GE(static_cast<char*>(existing_ptrs[i]) -
                  static_cast<char*>(existing_ptrs[i - 1]),
              req_size);
  }

  for (size_t i = 0; i < existing_ptrs.size(); i++) {
    a.DeallocateRaw(existing_ptrs[i]);
  }
}

TEST(GPUBFCAllocatorTest, ExerciseCoalescing) {
  GPUBFCAllocator a(0, 1 << 30);
  CheckStats(&a, 0, 0, 0, 0);

  float* first_ptr = a.Allocate<float>(1024);
  a.DeallocateRaw(first_ptr);
  CheckStats(&a, 1, 0, 4096, 4096);
  for (int i = 0; i < 1024; ++i) {
    // Allocate several buffers of different sizes, and then clean them
    // all up.  We should be able to repeat this endlessly without
    // causing fragmentation and growth.
    float* t1 = a.Allocate<float>(1024);

    int64* t2 = a.Allocate<int64>(1048576);
    double* t3 = a.Allocate<double>(2048);
    float* t4 = a.Allocate<float>(10485760);

    a.DeallocateRaw(t1);
    a.DeallocateRaw(t2);
    a.DeallocateRaw(t3);
    a.DeallocateRaw(t4);
  }
  CheckStats(&a, 4097, 0, 1024 * sizeof(float) + 1048576 * sizeof(int64) +
                              2048 * sizeof(double) + 10485760 * sizeof(float),
             10485760 * sizeof(float));

  // At the end, we should have coalesced all memory into one region
  // starting at the beginning, so validate that allocating a pointer
  // starts from this region.
  float* first_ptr_after = a.Allocate<float>(1024);
  EXPECT_EQ(first_ptr, first_ptr_after);
  a.DeallocateRaw(first_ptr_after);
}

TEST(GPUBFCAllocatorTest, AllocateZeroBufSize) {
  GPUBFCAllocator a(0, 1 << 30);
  float* ptr = a.Allocate<float>(0);
  EXPECT_EQ(nullptr, ptr);
}

TEST(GPUBFCAllocatorTest, TracksSizes) {
  GPUBFCAllocator a(0, 1 << 30);
  EXPECT_EQ(true, a.TracksAllocationSizes());
}

TEST(GPUBFCAllocatorTest, AllocatedVsRequested) {
  GPUBFCAllocator a(0, 1 << 30);
  float* t1 = a.Allocate<float>(1);
  EXPECT_EQ(4, a.RequestedSize(t1));
  EXPECT_EQ(256, a.AllocatedSize(t1));
  a.DeallocateRaw(t1);
}

TEST(GPUBFCAllocatorTest, TestCustomMemoryLimit) {
  // Configure a 1MiB byte limit
  GPUBFCAllocator a(0, 1 << 20);

  float* first_ptr = a.Allocate<float>(1 << 6);
  float* second_ptr = a.Allocate<float>(1 << 20);

  EXPECT_NE(nullptr, first_ptr);
  EXPECT_EQ(nullptr, second_ptr);
  a.DeallocateRaw(first_ptr);
}

TEST(GPUBFCAllocatorTest, AllocationsAndDeallocationsWithGrowth) {
  GPUOptions options;
  options.set_allow_growth(true);

  // Max of 2GiB, but starts out small.
  GPUBFCAllocator a(0, 1LL << 31, options);

  // Allocate 10 raw pointers of sizes between 100 bytes and about
  // 64 megs.
  random::PhiloxRandom philox(123, 17);
  random::SimplePhilox rand(&philox);

  const int32 max_mem = 1 << 27;

  std::vector<void*> initial_ptrs;
  for (int s = 1; s < 10; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % max_mem, 100), max_mem);
    void* raw = a.AllocateRaw(1, size);

    initial_ptrs.push_back(raw);
  }

  // Deallocate half of the memory, and keep track of the others.
  std::vector<void*> existing_ptrs;
  for (size_t i = 0; i < initial_ptrs.size(); i++) {
    if (i % 2 == 1) {
      a.DeallocateRaw(initial_ptrs[i]);
    } else {
      existing_ptrs.push_back(initial_ptrs[i]);
    }
  }

  const int32 max_mem_2 = 1 << 26;
  // Allocate a lot of raw pointers between 100 bytes and 64 megs.
  for (int s = 1; s < 10; s++) {
    size_t size = std::min<size_t>(
        std::max<size_t>(rand.Rand32() % max_mem_2, 100), max_mem_2);
    void* raw = a.AllocateRaw(1, size);
    existing_ptrs.push_back(raw);
  }

  std::sort(existing_ptrs.begin(), existing_ptrs.end());
  // Make sure none of them are equal
  for (size_t i = 1; i < existing_ptrs.size(); i++) {
    CHECK_NE(existing_ptrs[i], existing_ptrs[i - 1]);  // No dups

    size_t req_size = a.RequestedSize(existing_ptrs[i - 1]);
    ASSERT_GT(req_size, 0);

    // Check that they don't overlap.
    ASSERT_GE(static_cast<char*>(existing_ptrs[i]) -
                  static_cast<char*>(existing_ptrs[i - 1]),
              req_size);
  }

  for (size_t i = 0; i < existing_ptrs.size(); i++) {
    a.DeallocateRaw(existing_ptrs[i]);
  }

  AllocatorStats stats;
  a.GetStats(&stats);
  LOG(INFO) << "Alloc stats: \n" << stats.DebugString();
}

static void BM_Allocation(int iters) {
  GPUBFCAllocator a(0, 1uLL << 33);
  // Exercise a few different allocation sizes
  std::vector<size_t> sizes = {256,        4096,      16384,    524288,
                               512,        1048576,   10485760, 104857600,
                               1048576000, 2048576000};
  int size_index = 0;

  while (--iters > 0) {
    size_t bytes = sizes[size_index++ % sizes.size()];
    void* p = a.AllocateRaw(1, bytes);
    a.DeallocateRaw(p);
  }
}
BENCHMARK(BM_Allocation);

static void BM_AllocationThreaded(int iters, int num_threads) {
  GPUBFCAllocator a(0, 1uLL << 33);
  thread::ThreadPool pool(Env::Default(), "test", num_threads);
  std::atomic_int_fast32_t count(iters);
  mutex done_lock;
  condition_variable done;
  bool done_flag = false;

  for (int t = 0; t < num_threads; t++) {
    pool.Schedule([&a, &count, &done_lock, &done, &done_flag, iters]() {
      // Exercise a few different allocation sizes
      std::vector<int> sizes = {256, 4096,    16384,    524288,
                                512, 1048576, 10485760, 104857600};
      int size_index = 0;
      for (int i = 0; i < iters; i++) {
        int bytes = sizes[size_index++ % sizes.size()];
        void* p = a.AllocateRaw(1, bytes);
        a.DeallocateRaw(p);
        if (count.fetch_sub(1) == 1) {
          mutex_lock l(done_lock);
          done_flag = true;
          done.notify_all();
          break;
        }
      }
    });
  }
  mutex_lock l(done_lock);
  if (!done_flag) {
    done.wait(l);
  }
}
BENCHMARK(BM_AllocationThreaded)->Arg(1)->Arg(4)->Arg(16);

// A more complex benchmark that defers deallocation of an object for
// "delay" allocations.
static void BM_AllocationDelayed(int iters, int delay) {
  GPUBFCAllocator a(0, 1 << 30);
  // Exercise a few different allocation sizes
  std::vector<int> sizes = {256, 4096, 16384, 4096, 512, 1024, 1024};
  int size_index = 0;

  std::vector<void*> ptrs;
  for (int i = 0; i < delay; i++) {
    ptrs.push_back(nullptr);
  }
  int pindex = 0;
  while (--iters > 0) {
    if (ptrs[pindex] != nullptr) {
      a.DeallocateRaw(ptrs[pindex]);
      ptrs[pindex] = nullptr;
    }
    int bytes = sizes[size_index++ % sizes.size()];
    void* p = a.AllocateRaw(1, bytes);
    ptrs[pindex] = p;
    pindex = (pindex + 1) % ptrs.size();
  }
  for (int i = 0; i < ptrs.size(); i++) {
    if (ptrs[i] != nullptr) {
      a.DeallocateRaw(ptrs[i]);
    }
  }
}
BENCHMARK(BM_AllocationDelayed)->Arg(1)->Arg(10)->Arg(100)->Arg(1000);

}  // namespace
}  // namespace tensorflow

#endif  // GOOGLE_CUDA
<|endoftext|>


<commit_before>#include "ScaledImageFactory.h"

#include <memory>

#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include <stb/stb_image_resize.h>

using namespace std;

// blends a foreground RGB triplet (fg) onto a background RGB triplet (bg)
// using the given alpha value; returns the blended result
// http://stackoverflow.com/questions/12011081/alpha-blending-2-rgba-colors-in-c/12016968#12016968
inline void BlendRgb
    (
    unsigned char* dst,
    const unsigned char* fg,
    const unsigned char* bg,
    const unsigned char alpha
    )
{
    const unsigned int intAlpha = alpha + 1;
    const unsigned int invAlpha = 256 - alpha;
    for( size_t i = 0; i < 3; ++i )
    {
        dst[i] = ( ( intAlpha * fg[i] + invAlpha * bg[i] ) >> 8 );
    }
}

// blends fg onto a repeating pattern of bg into dst
// bg dimensions must be powers-of-two
void BlendPattern
    (
    wxImage& dst,
    const wxImage& fg,
    const wxImage& bg
    )
{
    const size_t fgW = static_cast< size_t >( fg.GetWidth() );
    const size_t dstW = static_cast< size_t >( dst.GetWidth() );
    const size_t dstH = static_cast< size_t >( dst.GetHeight() );

    const size_t bgW = static_cast< size_t >( bg.GetWidth() );
    const size_t bgH = static_cast< size_t >( bg.GetHeight() );

    const unsigned char* fgData = fg.GetData();
    const unsigned char* fgAlpha = fg.GetAlpha();
    unsigned char* bgData = bg.GetData();
    unsigned char* dstData = dst.GetData();

    for( size_t y = 0; y < dstH; ++y )
    {
        unsigned char* dstPx = &dstData[ y * dstW * 3 ];

        const unsigned char* fgPx = &fgData[ y * fgW * 3 ];
        const unsigned char* fgAlphaPx = &fgAlpha[ y * fgW ];

        const size_t bgY = ( y & ( bgH-1 ) ) * bgW * 3;
        const unsigned char* bgRow = &bgData[ bgY ];

        for( size_t x = 0; x < dstW; ++x )
        {
            const size_t bgX = ( x & ( bgW-1 ) ) * 3;
            const unsigned char* bgPx = &bgRow[ bgX ];

            BlendRgb( dstPx, fgPx, bgPx, *fgAlphaPx );

            dstPx += 3;
            fgPx += 3;
            fgAlphaPx += 1;
        }
    }
}

void GetScaledSubrect( wxImage& dst, const wxImage& src, const double scale, const wxPoint& pos, const int filter )
{
    if( filter == -1 )
    {
        const size_t srcW = static_cast< size_t >( src.GetWidth() );
        const size_t dstW = static_cast< size_t >( dst.GetWidth() );
        const size_t dstH = static_cast< size_t >( dst.GetHeight() );

        const float scaleInv = 1.0f / scale;

        // color
        {
            const unsigned char* srcData = src.GetData();
            unsigned char* dstData = dst.GetData();

            for( size_t dstY = 0; dstY < dstH; ++dstY )
            {
                unsigned char* dstRow = &dstData[ dstY * dstW * 3 ];

                const size_t srcY( ( dstY + pos.y ) * scaleInv );
                const unsigned char* srcRow = &srcData[ srcY * srcW * 3 ];

                for( size_t dstX = 0; dstX < dstW; ++dstX )
                {
                    const size_t srcX( ( dstX + pos.x ) * scaleInv );
                    const unsigned char* srcPx = &srcRow[ srcX * 3 ];
                    dstRow[ dstX * 3 + 0 ] = srcPx[ 0 ];
                    dstRow[ dstX * 3 + 1 ] = srcPx[ 1 ];
                    dstRow[ dstX * 3 + 2 ] = srcPx[ 2 ];
                }
            }
        }

        if( !src.HasAlpha() )
            return;

        // alpha
        {
            const unsigned char* srcData = src.GetAlpha();
            unsigned char* dstData = dst.GetAlpha();

            for( size_t dstY = 0; dstY < dstH; ++dstY )
            {
                unsigned char* dstRow = &dstData[ dstY * dstW ];

                const size_t srcY( ( dstY + pos.y ) * scaleInv );
                const unsigned char* srcRow = &srcData[ srcY * srcW ];

                for( size_t dstX = 0; dstX < dstW; ++dstX )
                {
                    const size_t srcX( ( dstX + pos.x ) * scaleInv );
                    const unsigned char* srcPx = &srcRow[ srcX ];
                    dstRow[ dstX + 0 ] = srcPx[ 0 ];
                }
            }
        }
    }
    else
    {
        const stbir_filter filter = STBIR_FILTER_TRIANGLE;
        const stbir_edge edge = STBIR_EDGE_CLAMP;
        const stbir_colorspace colorspace = STBIR_COLORSPACE_SRGB;

        stbir_resize_subpixel
            (
            src.GetData(), src.GetWidth(), src.GetHeight(), 0,
            dst.GetData(), dst.GetWidth(), dst.GetHeight(), 0,
            STBIR_TYPE_UINT8,
            3,
            0,
            STBIR_ALPHA_CHANNEL_NONE,
            edge, edge,
            filter, filter,
            colorspace,
            NULL,
            scale, scale,
            static_cast< float >( pos.x ), static_cast< float >( pos.y )
            );

        if( !src.HasAlpha() )
            return;

        stbir_resize_subpixel
            (
            src.GetAlpha(), src.GetWidth(), src.GetHeight(), 0,
            dst.GetAlpha(), dst.GetWidth(), dst.GetHeight(), 0,
            STBIR_TYPE_UINT8,
            1,
            0,
            STBIR_FLAG_ALPHA_PREMULTIPLIED,
            edge, edge,
            filter, filter,
            colorspace,
            NULL,
            scale, scale,
            static_cast< float >( pos.x ), static_cast< float >( pos.y )
            );
    }
}

// threadland
wxThread::ExitCode ScaledImageFactory::Entry()
{
    JobItem job;
    while( wxMSGQUEUE_NO_ERROR == mJobPool.Receive( job ) )
    {
        if( NULL == job.second.mImage || wxThread::This()->TestDestroy() )
            break;

        const ExtRect& rect = job.first;
        Context& ctx = job.second;

        ResultItem result;
        result.mGeneration = ctx.mGeneration;
        result.mRect = rect;

        // skip this rect if it isn't currently visible
        {
            wxCriticalSectionLocker locker( mVisibleCs );
            if( !mVisible.Intersects( get<2>( rect ) ) )
            {
                mResultQueue.Post( result );
                continue;
            }
        }

        wxImagePtr temp( new wxImage( get<2>( rect ).GetSize(), false ) );
        if( ctx.mImage->HasAlpha() )
        {
            temp->SetAlpha( NULL );
        }

        GetScaledSubrect
            (
            *temp,
            *ctx.mImage,
            ctx.mScale,
            get<2>( rect ).GetPosition(),
            get<1>( rect )
            );

        if( ctx.mImage->HasAlpha() )
        {
            result.mImage = new wxImage( get<2>( rect ).GetSize(), false );
            BlendPattern( *result.mImage, *temp, mStipple );
        }
        else
        {
            result.mImage = temp;
        }

        mResultQueue.Post( result );

        wxQueueEvent( mEventSink, new wxThreadEvent( wxEVT_THREAD, mEventId ) );
    }

    return static_cast< wxThread::ExitCode >( 0 );
}

ScaledImageFactory::ScaledImageFactory( wxEvtHandler* eventSink, int id )
    : mEventSink( eventSink ), mEventId( id )
{
    size_t numThreads = wxThread::GetCPUCount();
    if( numThreads <= 0 )   numThreads = 1;
    if( numThreads > 1 )    numThreads--;

    for( size_t i = 0; i < numThreads; ++i )
    {
        CreateThread();
    }

    for( wxThread*& thread : GetThreads() )
    {
        if( NULL == thread )
            continue;

        if( thread->Run() != wxTHREAD_NO_ERROR )
        {
            delete thread;
            thread = NULL;
        }
    }

    mCurrentCtx.mGeneration = 0;
    mCurrentCtx.mScale = 1.0;

    mStipple.LoadFile( "background.png" );
}

ScaledImageFactory::~ScaledImageFactory()
{
    // clear job queue and send down "kill" jobs
    mJobPool.Clear();
    for( size_t i = 0; i < GetThreads().size(); ++i )
    {
        mJobPool.Post( JobItem( ExtRect(), Context() ) );
    }

    for( wxThread* thread : GetThreads() )
    {
        if( NULL == thread )
            continue;

        thread->Wait();
    }
}

void ScaledImageFactory::SetImage( wxImagePtr& newImage )
{
    if( NULL == newImage )
        throw std::runtime_error( "Image not set!" );

    mCurrentCtx.mImage = newImage;
    mJobPool.Clear();
}

void ScaledImageFactory::SetScale( double newScale )
{
    if( NULL == mCurrentCtx.mImage )
        throw std::runtime_error( "Image not set!" );

    mCurrentCtx.mGeneration++;
    mCurrentCtx.mScale = newScale;
    mJobPool.Clear();
}

bool ScaledImageFactory::AddRect( const ExtRect& rect )
{
    if( NULL == mCurrentCtx.mImage )
        throw std::runtime_error( "Image not set!" );

    return( wxMSGQUEUE_NO_ERROR == mJobPool.Post( JobItem( rect, mCurrentCtx ) ) );
}

bool ScaledImageFactory::GetImage( ExtRect& rect, wxImagePtr& image )
{
    ResultItem item;
    wxMessageQueueError err;
    while( true )
    {
        err = mResultQueue.ReceiveTimeout( 0, item );
        if( wxMSGQUEUE_TIMEOUT == err )
            return false;
        if( wxMSGQUEUE_MISC_ERROR == err )
            throw std::runtime_error( "ResultQueue misc error!" );
        if( item.mGeneration != mCurrentCtx.mGeneration )
            continue;
        break;
    }

    rect = item.mRect;
    image = item.mImage;
    return true;
}

void ScaledImageFactory::SetVisibleArea( const wxRect& visible )
{
    wxCriticalSectionLocker locker( mVisibleCs );
    mVisible = visible;
}
<commit_msg>Fix error enums for jobpool<commit_after>#include "ScaledImageFactory.h"

#include <memory>

#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include <stb/stb_image_resize.h>

using namespace std;

// blends a foreground RGB triplet (fg) onto a background RGB triplet (bg)
// using the given alpha value; returns the blended result
// http://stackoverflow.com/questions/12011081/alpha-blending-2-rgba-colors-in-c/12016968#12016968
inline void BlendRgb
    (
    unsigned char* dst,
    const unsigned char* fg,
    const unsigned char* bg,
    const unsigned char alpha
    )
{
    const unsigned int intAlpha = alpha + 1;
    const unsigned int invAlpha = 256 - alpha;
    for( size_t i = 0; i < 3; ++i )
    {
        dst[i] = ( ( intAlpha * fg[i] + invAlpha * bg[i] ) >> 8 );
    }
}

// blends fg onto a repeating pattern of bg into dst
// bg dimensions must be powers-of-two
void BlendPattern
    (
    wxImage& dst,
    const wxImage& fg,
    const wxImage& bg
    )
{
    const size_t fgW = static_cast< size_t >( fg.GetWidth() );
    const size_t dstW = static_cast< size_t >( dst.GetWidth() );
    const size_t dstH = static_cast< size_t >( dst.GetHeight() );

    const size_t bgW = static_cast< size_t >( bg.GetWidth() );
    const size_t bgH = static_cast< size_t >( bg.GetHeight() );

    const unsigned char* fgData = fg.GetData();
    const unsigned char* fgAlpha = fg.GetAlpha();
    unsigned char* bgData = bg.GetData();
    unsigned char* dstData = dst.GetData();

    for( size_t y = 0; y < dstH; ++y )
    {
        unsigned char* dstPx = &dstData[ y * dstW * 3 ];

        const unsigned char* fgPx = &fgData[ y * fgW * 3 ];
        const unsigned char* fgAlphaPx = &fgAlpha[ y * fgW ];

        const size_t bgY = ( y & ( bgH-1 ) ) * bgW * 3;
        const unsigned char* bgRow = &bgData[ bgY ];

        for( size_t x = 0; x < dstW; ++x )
        {
            const size_t bgX = ( x & ( bgW-1 ) ) * 3;
            const unsigned char* bgPx = &bgRow[ bgX ];

            BlendRgb( dstPx, fgPx, bgPx, *fgAlphaPx );

            dstPx += 3;
            fgPx += 3;
            fgAlphaPx += 1;
        }
    }
}

void GetScaledSubrect( wxImage& dst, const wxImage& src, const double scale, const wxPoint& pos, const int filter )
{
    if( filter == -1 )
    {
        const size_t srcW = static_cast< size_t >( src.GetWidth() );
        const size_t dstW = static_cast< size_t >( dst.GetWidth() );
        const size_t dstH = static_cast< size_t >( dst.GetHeight() );

        const float scaleInv = 1.0f / scale;

        // color
        {
            const unsigned char* srcData = src.GetData();
            unsigned char* dstData = dst.GetData();

            for( size_t dstY = 0; dstY < dstH; ++dstY )
            {
                unsigned char* dstRow = &dstData[ dstY * dstW * 3 ];

                const size_t srcY( ( dstY + pos.y ) * scaleInv );
                const unsigned char* srcRow = &srcData[ srcY * srcW * 3 ];

                for( size_t dstX = 0; dstX < dstW; ++dstX )
                {
                    const size_t srcX( ( dstX + pos.x ) * scaleInv );
                    const unsigned char* srcPx = &srcRow[ srcX * 3 ];
                    dstRow[ dstX * 3 + 0 ] = srcPx[ 0 ];
                    dstRow[ dstX * 3 + 1 ] = srcPx[ 1 ];
                    dstRow[ dstX * 3 + 2 ] = srcPx[ 2 ];
                }
            }
        }

        if( !src.HasAlpha() )
            return;

        // alpha
        {
            const unsigned char* srcData = src.GetAlpha();
            unsigned char* dstData = dst.GetAlpha();

            for( size_t dstY = 0; dstY < dstH; ++dstY )
            {
                unsigned char* dstRow = &dstData[ dstY * dstW ];

                const size_t srcY( ( dstY + pos.y ) * scaleInv );
                const unsigned char* srcRow = &srcData[ srcY * srcW ];

                for( size_t dstX = 0; dstX < dstW; ++dstX )
                {
                    const size_t srcX( ( dstX + pos.x ) * scaleInv );
                    const unsigned char* srcPx = &srcRow[ srcX ];
                    dstRow[ dstX + 0 ] = srcPx[ 0 ];
                }
            }
        }
    }
    else
    {
        const stbir_filter filter = STBIR_FILTER_TRIANGLE;
        const stbir_edge edge = STBIR_EDGE_CLAMP;
        const stbir_colorspace colorspace = STBIR_COLORSPACE_SRGB;

        stbir_resize_subpixel
            (
            src.GetData(), src.GetWidth(), src.GetHeight(), 0,
            dst.GetData(), dst.GetWidth(), dst.GetHeight(), 0,
            STBIR_TYPE_UINT8,
            3,
            0,
            STBIR_ALPHA_CHANNEL_NONE,
            edge, edge,
            filter, filter,
            colorspace,
            NULL,
            scale, scale,
            static_cast< float >( pos.x ), static_cast< float >( pos.y )
            );

        if( !src.HasAlpha() )
            return;

        stbir_resize_subpixel
            (
            src.GetAlpha(), src.GetWidth(), src.GetHeight(), 0,
            dst.GetAlpha(), dst.GetWidth(), dst.GetHeight(), 0,
            STBIR_TYPE_UINT8,
            1,
            0,
            STBIR_FLAG_ALPHA_PREMULTIPLIED,
            edge, edge,
            filter, filter,
            colorspace,
            NULL,
            scale, scale,
            static_cast< float >( pos.x ), static_cast< float >( pos.y )
            );
    }
}

// threadland
wxThread::ExitCode ScaledImageFactory::Entry()
{
    JobItem job;
    while( wxSORTABLEMSGQUEUE_NO_ERROR == mJobPool.Receive( job ) )
    {
        if( NULL == job.second.mImage || wxThread::This()->TestDestroy() )
            break;

        const ExtRect& rect = job.first;
        Context& ctx = job.second;

        ResultItem result;
        result.mGeneration = ctx.mGeneration;
        result.mRect = rect;

        // skip this rect if it isn't currently visible
        {
            wxCriticalSectionLocker locker( mVisibleCs );
            if( !mVisible.Intersects( get<2>( rect ) ) )
            {
                mResultQueue.Post( result );
                continue;
            }
        }

        wxImagePtr temp( new wxImage( get<2>( rect ).GetSize(), false ) );
        if( ctx.mImage->HasAlpha() )
        {
            temp->SetAlpha( NULL );
        }

        GetScaledSubrect
            (
            *temp,
            *ctx.mImage,
            ctx.mScale,
            get<2>( rect ).GetPosition(),
            get<1>( rect )
            );

        if( ctx.mImage->HasAlpha() )
        {
            result.mImage = new wxImage( get<2>( rect ).GetSize(), false );
            BlendPattern( *result.mImage, *temp, mStipple );
        }
        else
        {
            result.mImage = temp;
        }

        mResultQueue.Post( result );

        wxQueueEvent( mEventSink, new wxThreadEvent( wxEVT_THREAD, mEventId ) );
    }

    return static_cast< wxThread::ExitCode >( 0 );
}

ScaledImageFactory::ScaledImageFactory( wxEvtHandler* eventSink, int id )
    : mEventSink( eventSink ), mEventId( id )
{
    size_t numThreads = wxThread::GetCPUCount();
    if( numThreads <= 0 )   numThreads = 1;
    if( numThreads > 1 )    numThreads--;

    for( size_t i = 0; i < numThreads; ++i )
    {
        CreateThread();
    }

    for( wxThread*& thread : GetThreads() )
    {
        if( NULL == thread )
            continue;

        if( thread->Run() != wxTHREAD_NO_ERROR )
        {
            delete thread;
            thread = NULL;
        }
    }

    mCurrentCtx.mGeneration = 0;
    mCurrentCtx.mScale = 1.0;

    mStipple.LoadFile( "background.png" );
}

ScaledImageFactory::~ScaledImageFactory()
{
    // clear job queue and send down "kill" jobs
    mJobPool.Clear();
    for( size_t i = 0; i < GetThreads().size(); ++i )
    {
        mJobPool.Post( JobItem( ExtRect(), Context() ) );
    }

    for( wxThread* thread : GetThreads() )
    {
        if( NULL == thread )
            continue;

        thread->Wait();
    }
}

void ScaledImageFactory::SetImage( wxImagePtr& newImage )
{
    if( NULL == newImage )
        throw std::runtime_error( "Image not set!" );

    mCurrentCtx.mImage = newImage;
    mJobPool.Clear();
}

void ScaledImageFactory::SetScale( double newScale )
{
    if( NULL == mCurrentCtx.mImage )
        throw std::runtime_error( "Image not set!" );

    mCurrentCtx.mGeneration++;
    mCurrentCtx.mScale = newScale;
    mJobPool.Clear();
}

bool ScaledImageFactory::AddRect( const ExtRect& rect )
{
    if( NULL == mCurrentCtx.mImage )
        throw std::runtime_error( "Image not set!" );

    return( wxSORTABLEMSGQUEUE_NO_ERROR == mJobPool.Post( JobItem( rect, mCurrentCtx ) ) );
}

bool ScaledImageFactory::GetImage( ExtRect& rect, wxImagePtr& image )
{
    ResultItem item;
    wxMessageQueueError err;
    while( true )
    {
        err = mResultQueue.ReceiveTimeout( 0, item );
        if( wxMSGQUEUE_TIMEOUT == err )
            return false;
        if( wxMSGQUEUE_MISC_ERROR == err )
            throw std::runtime_error( "ResultQueue misc error!" );
        if( item.mGeneration != mCurrentCtx.mGeneration )
            continue;
        break;
    }

    rect = item.mRect;
    image = item.mImage;
    return true;
}

void ScaledImageFactory::SetVisibleArea( const wxRect& visible )
{
    wxCriticalSectionLocker locker( mVisibleCs );
    mVisible = visible;
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s

class A {
public:
	template <class U>
    A(U p) {
	}
	template <>
    A(int p) { // expected-warning{{explicit specialization of 'A' within class scope in a Microsoft extension}}
	}

	template <class U>
    void f(U p) {
	}

	template <>
    void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope in a Microsoft extension}}
	}

	void f(int p) {
    }
};

void test1()
{
   A a(3);
   char* b ;
   a.f(b);
   a.f<int>(99);
   a.f(100);
}

template <class T>
class B {
public:
	template <class U>
    B(U p) {
	}
	template <>
    B(int p) { // expected-warning{{explicit specialization of 'B<T>' within class scope in a Microsoft extension}}
	}

	template <class U>
    void f(U p) {
	  T y = 9;
	}

    template <>
    void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope in a Microsoft extension}}
	  T a = 3;
	}

	void f(int p) {
 	  T a = 3;
    }
};

void test2()
{
   B<char> b(3);
   char* ptr;
   b.f(ptr);
   b.f<int>(99);
   b.f(100);
}

<commit_msg>fix typo in test.<commit_after>// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s

class A {
public:
	template <class U>
    A(U p) {
	}
	template <>
    A(int p) { // expected-warning{{explicit specialization of 'A' within class scope is a Microsoft extension}}
	}

	template <class U>
    void f(U p) {
	}

	template <>
    void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope is a Microsoft extension}}
	}

	void f(int p) {
    }
};

void test1()
{
   A a(3);
   char* b ;
   a.f(b);
   a.f<int>(99);
   a.f(100);
}

template <class T>
class B {
public:
	template <class U>
    B(U p) {
	}
	template <>
    B(int p) { // expected-warning{{explicit specialization of 'B<T>' within class scope is a Microsoft extension}}
	}

	template <class U>
    void f(U p) {
	  T y = 9;
	}

    template <>
    void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope is a Microsoft extension}}
	  T a = 3;
	}

	void f(int p) {
 	  T a = 3;
    }
};

void test2()
{
   B<char> b(3);
   char* ptr;
   b.f(ptr);
   b.f<int>(99);
   b.f(100);
}

<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// test quick_exit and at_quick_exit

#include <cstdlib>
#include <type_traits>

void f();

int main()
{
    std::at_quick_exit(f);
    quick_exit(0);
}
<commit_msg>Don't refer to a function that doesn't exist in the quick_exit test.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// test quick_exit and at_quick_exit

#include <cstdlib>
#include <type_traits>

void f() {}

int main()
{
    std::at_quick_exit(f);
    quick_exit(0);
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016-2018 mvs developers
 *
 * This file is part of metaverse-explorer.
 *
 * metaverse-explorer is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <metaverse/explorer/json_helper.hpp>
#include <metaverse/explorer/dispatch.hpp>
#include <metaverse/explorer/extensions/commands/issue.hpp>
#include <metaverse/explorer/extensions/command_extension_func.hpp>
#include <metaverse/explorer/extensions/command_assistant.hpp>
#include <metaverse/explorer/extensions/exception.hpp>
#include <metaverse/explorer/extensions/base_helper.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp>

using std::placeholders::_1;

namespace libbitcoin {
namespace explorer {
namespace commands {

console_result issue::invoke (Json::Value& jv_output,
                              libbitcoin::server::server_node& node)
{
    auto& blockchain = node.chain_impl();

    blockchain.is_account_passwd_valid(auth_.name, auth_.auth);
    blockchain.uppercase_symbol(argument_.symbol);

    // check asset symbol
    check_asset_symbol(argument_.symbol);

    // check fee
    auto fee_of_issue = get_fee_of_issue_asset(blockchain, auth_.name);
    if (argument_.fee == -1) {
        argument_.fee = fee_of_issue;
    }
    else if (argument_.fee < fee_of_issue) {
        throw asset_issue_poundage_exception{
            "issue asset fee less than "
            + std::to_string(fee_of_issue) + " that's "
            + std::to_string(fee_of_issue / 100000000) + " ETPs"};
    }

    // fail if asset is already in blockchain
    if (blockchain.is_asset_exist(argument_.symbol, false)) {
        throw asset_symbol_existed_exception{
            "asset " + argument_.symbol
            + " already exists in blockchain"};
    }

    // local database asset check
    auto sh_asset = blockchain.get_account_unissued_asset(auth_.name, argument_.symbol);
    if (!sh_asset) {
        throw asset_symbol_notfound_exception{"asset " + argument_.symbol + " not found"};
    }

    auto to_did = sh_asset->get_issuer();
    auto to_address = get_address_from_did(to_did, blockchain);
    if (!blockchain.is_valid_address(to_address)) {
        throw address_invalid_exception{"invalid asset issuer " + to_did};
    }

    std::string cert_symbol;
    asset_cert_type cert_type = asset_cert_ns::none;
    bool is_domain_cert_exist = false;

    // domain cert check
    auto&& domain = asset_cert::get_domain(argument_.symbol);
    if (asset_cert::is_valid_domain(domain)) {
        bool exist = blockchain.is_asset_cert_exist(domain, asset_cert_ns::domain);
        if (!exist) {
            // domain cert does not exist, issue new domain cert to this address
            is_domain_cert_exist = false;
            cert_type = asset_cert_ns::domain;
            cert_symbol = domain;
        }
        else {
            // if domain cert exists then check whether it belongs to the account.
            is_domain_cert_exist = true;
            auto cert = blockchain.get_account_asset_cert(auth_.name, domain, asset_cert_ns::domain);
            if (cert) {
                cert_symbol = domain;
                cert_type = cert->get_type();
            }
            else {
                // if domain cert does not belong to the account then check naming cert
                exist = blockchain.is_asset_cert_exist(argument_.symbol, asset_cert_ns::naming);
                if (!exist) {
                    throw asset_cert_notfound_exception{
                        "Domain cert " + argument_.symbol + " exists on the blockchain and is not owned by " + auth_.name};
                }
                else {
                    cert = blockchain.get_account_asset_cert(auth_.name, argument_.symbol, asset_cert_ns::naming);
                    if (!cert) {
                        throw asset_cert_notowned_exception{
                            "No domain cert or naming cert owned by " + auth_.name};
                    }

                    cert_symbol = argument_.symbol;
                    cert_type = cert->get_type();
                }
            }
        }
    }

    // receiver
    std::vector<receiver_record> receiver{
        {to_address, argument_.symbol, 0, 0, utxo_attach_type::asset_issue, attachment("", to_did)}
    };

    // asset_cert utxo
    auto certs = sh_asset->get_asset_cert_mask();
    if (!certs.empty()) {
        for (auto each_cert_type : certs) {
            receiver.push_back(
            {   to_address, argument_.symbol, 0, 0,
                each_cert_type, utxo_attach_type::asset_cert_autoissue, attachment("", to_did)
            });
        }
    }

    // domain cert or naming cert
    if (asset_cert::is_valid_domain(domain)) {
        receiver.push_back(
        {   to_address, cert_symbol, 0, 0, cert_type,
            (is_domain_cert_exist ? utxo_attach_type::asset_cert : utxo_attach_type::asset_cert_autoissue),
            attachment("", to_did)
        });
    }

    auto issue_helper = issuing_asset(
                            *this, blockchain,
                            std::move(auth_.name), std::move(auth_.auth),
                            "", std::move(argument_.symbol),
                            std::move(option_.attenuation_model_param),
                            std::move(receiver), argument_.fee);

    issue_helper.exec();

    // json output
    auto tx = issue_helper.get_transaction();
    jv_output =  config::json_helper(get_api_version()).prop_tree(tx, true);

    return console_result::okay;
}

} // namespace commands
} // namespace explorer
} // namespace libbitcoin

<commit_msg>fix compile error on Mac.<commit_after>/**
 * Copyright (c) 2016-2018 mvs developers
 *
 * This file is part of metaverse-explorer.
 *
 * metaverse-explorer is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <metaverse/explorer/json_helper.hpp>
#include <metaverse/explorer/dispatch.hpp>
#include <metaverse/explorer/extensions/commands/issue.hpp>
#include <metaverse/explorer/extensions/command_extension_func.hpp>
#include <metaverse/explorer/extensions/command_assistant.hpp>
#include <metaverse/explorer/extensions/exception.hpp>
#include <metaverse/explorer/extensions/base_helper.hpp>
#include <metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp>

using std::placeholders::_1;

namespace libbitcoin {
namespace explorer {
namespace commands {

console_result issue::invoke (Json::Value& jv_output,
                              libbitcoin::server::server_node& node)
{
    auto& blockchain = node.chain_impl();

    blockchain.is_account_passwd_valid(auth_.name, auth_.auth);
    blockchain.uppercase_symbol(argument_.symbol);

    // check asset symbol
    check_asset_symbol(argument_.symbol);

    // check fee
    auto fee_of_issue = get_fee_of_issue_asset(blockchain, auth_.name);
    if (argument_.fee == (uint64_t)-1) {
        argument_.fee = fee_of_issue;
    }
    else if (argument_.fee < fee_of_issue) {
        throw asset_issue_poundage_exception{
            "issue asset fee less than "
            + std::to_string(fee_of_issue) + " that's "
            + std::to_string(fee_of_issue / 100000000) + " ETPs"};
    }

    // fail if asset is already in blockchain
    if (blockchain.is_asset_exist(argument_.symbol, false)) {
        throw asset_symbol_existed_exception{
            "asset " + argument_.symbol
            + " already exists in blockchain"};
    }

    // local database asset check
    auto sh_asset = blockchain.get_account_unissued_asset(auth_.name, argument_.symbol);
    if (!sh_asset) {
        throw asset_symbol_notfound_exception{"asset " + argument_.symbol + " not found"};
    }

    auto to_did = sh_asset->get_issuer();
    auto to_address = get_address_from_did(to_did, blockchain);
    if (!blockchain.is_valid_address(to_address)) {
        throw address_invalid_exception{"invalid asset issuer " + to_did};
    }

    std::string cert_symbol;
    asset_cert_type cert_type = asset_cert_ns::none;
    bool is_domain_cert_exist = false;

    // domain cert check
    auto&& domain = asset_cert::get_domain(argument_.symbol);
    if (asset_cert::is_valid_domain(domain)) {
        bool exist = blockchain.is_asset_cert_exist(domain, asset_cert_ns::domain);
        if (!exist) {
            // domain cert does not exist, issue new domain cert to this address
            is_domain_cert_exist = false;
            cert_type = asset_cert_ns::domain;
            cert_symbol = domain;
        }
        else {
            // if domain cert exists then check whether it belongs to the account.
            is_domain_cert_exist = true;
            auto cert = blockchain.get_account_asset_cert(auth_.name, domain, asset_cert_ns::domain);
            if (cert) {
                cert_symbol = domain;
                cert_type = cert->get_type();
            }
            else {
                // if domain cert does not belong to the account then check naming cert
                exist = blockchain.is_asset_cert_exist(argument_.symbol, asset_cert_ns::naming);
                if (!exist) {
                    throw asset_cert_notfound_exception{
                        "Domain cert " + argument_.symbol + " exists on the blockchain and is not owned by " + auth_.name};
                }
                else {
                    cert = blockchain.get_account_asset_cert(auth_.name, argument_.symbol, asset_cert_ns::naming);
                    if (!cert) {
                        throw asset_cert_notowned_exception{
                            "No domain cert or naming cert owned by " + auth_.name};
                    }

                    cert_symbol = argument_.symbol;
                    cert_type = cert->get_type();
                }
            }
        }
    }

    // receiver
    std::vector<receiver_record> receiver{
        {to_address, argument_.symbol, 0, 0, utxo_attach_type::asset_issue, attachment("", to_did)}
    };

    // asset_cert utxo
    auto certs = sh_asset->get_asset_cert_mask();
    if (!certs.empty()) {
        for (auto each_cert_type : certs) {
            receiver.push_back(
            {   to_address, argument_.symbol, 0, 0,
                each_cert_type, utxo_attach_type::asset_cert_autoissue, attachment("", to_did)
            });
        }
    }

    // domain cert or naming cert
    if (asset_cert::is_valid_domain(domain)) {
        receiver.push_back(
        {   to_address, cert_symbol, 0, 0, cert_type,
            (is_domain_cert_exist ? utxo_attach_type::asset_cert : utxo_attach_type::asset_cert_autoissue),
            attachment("", to_did)
        });
    }

    auto issue_helper = issuing_asset(
                            *this, blockchain,
                            std::move(auth_.name), std::move(auth_.auth),
                            "", std::move(argument_.symbol),
                            std::move(option_.attenuation_model_param),
                            std::move(receiver), argument_.fee);

    issue_helper.exec();

    // json output
    auto tx = issue_helper.get_transaction();
    jv_output =  config::json_helper(get_api_version()).prop_tree(tx, true);

    return console_result::okay;
}

} // namespace commands
} // namespace explorer
} // namespace libbitcoin

<|endoftext|>


<commit_before>#include "SymbianDTMFPrivate.h"
#include "SymbianCallInitiator.h"

SymbianDTMFPrivate::SymbianDTMFPrivate(SymbianCallInitiator *p)
: CActive(EPriorityNormal)
, iTelephony (NULL)
, parent (p)
{
    iTelephony = CTelephony::NewL();
}//SymbianDTMFPrivate::SymbianDTMFPrivate

SymbianDTMFPrivate::~SymbianDTMFPrivate ()
{
    Cancel();
    if (NULL != iTelephony) {
        delete iTelephony;
    }
    iTelephony = NULL;
    parent = NULL;
}//SymbianDTMFPrivate::~SymbianDTMFPrivate

void
SymbianDTMFPrivate::RunL ()
{
    qDebug("RunL");
    bool bSuccess = (iStatus == KErrNone);
    if (NULL != parent) {
        qDebug("RunL about to call onDtmfSent");
        parent->onDtmfSent (this, bSuccess);
    }
    qDebug("RunL called onDtmfSent");
}//SymbianDTMFPrivate::RunL

void
SymbianDTMFPrivate::DoCancel ()
{
    iTelephony->CancelAsync(CTelephony::ESendDTMFTonesCancel);
}//SymbianDTMFPrivate::DoCancel

void
SymbianDTMFPrivate::sendDTMF (const QString &strTones)
{
    if (NULL == iTelephony) {
        qCritical ("CTelephony object not initialized");
        return;
    }

#define SIZE_LIMIT 40
    if (strTones.length () > SIZE_LIMIT) {
        qDebug ("Too many DTMF characters");
        return;
    }
    TBuf<SIZE_LIMIT>aNumber;
#undef SIZE_LIMIT

    TPtrC8 ptr(reinterpret_cast<const TUint8*>(strTones.toLatin1().constData()));
    aNumber.Copy(ptr);

    qDebug("Before sending DTMF");
    iTelephony->SendDTMFTones(iStatus, aNumber);
    qDebug("After sending DTMF");
    SetActive ();
    qDebug("After SetActive");
    CleanupStack::PopAndDestroy();
    qDebug("After PopAndDestroy");
}//SymbianDTMFPrivate::sendDTMF
<commit_msg>Test<commit_after>#include "SymbianDTMFPrivate.h"
#include "SymbianCallInitiator.h"

SymbianDTMFPrivate::SymbianDTMFPrivate(SymbianCallInitiator *p)
: CActive(EPriorityNormal)
, iTelephony (NULL)
, parent (p)
{
    iTelephony = CTelephony::NewL();
}//SymbianDTMFPrivate::SymbianDTMFPrivate

SymbianDTMFPrivate::~SymbianDTMFPrivate ()
{
    Cancel();
    if (NULL != iTelephony) {
        delete iTelephony;
    }
    iTelephony = NULL;
    parent = NULL;
}//SymbianDTMFPrivate::~SymbianDTMFPrivate

void
SymbianDTMFPrivate::RunL ()
{
    qDebug("RunL");
    bool bSuccess = (iStatus == KErrNone);
    if (NULL != parent) {
        qDebug("RunL about to call onDtmfSent");
        parent->onDtmfSent (this, bSuccess);
    }
    qDebug("RunL called onDtmfSent");
}//SymbianDTMFPrivate::RunL

void
SymbianDTMFPrivate::DoCancel ()
{
    iTelephony->CancelAsync(CTelephony::ESendDTMFTonesCancel);
}//SymbianDTMFPrivate::DoCancel

void
SymbianDTMFPrivate::sendDTMF (const QString &strTones)
{
    if (NULL == iTelephony) {
        qCritical ("CTelephony object not initialized");
        return;
    }

#define SIZE_LIMIT 40
    if (strTones.length () > SIZE_LIMIT) {
        qDebug ("Too many DTMF characters");
        return;
    }
    TBuf<SIZE_LIMIT>aNumber;
#undef SIZE_LIMIT

    TPtrC8 ptr(reinterpret_cast<const TUint8*>(strTones.toLatin1().constData()));
    aNumber.Copy(ptr);

    qDebug("Before sending DTMF");
    iTelephony->SendDTMFTones(iStatus, aNumber);
    qDebug("After sending DTMF");
    SetActive ();
    qDebug("After SetActive");
}//SymbianDTMFPrivate::sendDTMF
<|endoftext|>