<commit_before>#include <stdio.h>
#include <vector>
#include <iostream>
#include <cybozu/stacktrace.hpp>

void putStackTrace()
{
	std::cout << "no memory!!\n" << cybozu::StackTrace() << std::endl;
	exit(1);
}

void func()
{
	puts("func");
	size_t size = 1024 * 1024;
	std::vector<double> v;
	for (int i = 0; i < 10240; i++) {
		std::cout << "i=" << i << ", size=" << size << std::endl;
		v.resize(size);
		size *= 16;
	}
}

void g()
{
	func();
}

void h()
{
	g();
}

int main()
	try
{
	std::set_new_handler(putStackTrace);
	h();
} catch (std::exception& e) {
	printf("e=%s\n", e.what());
}

<commit_msg>avoid lage malloc<commit_after>/*
	sample how to use stacktrace
	g++ -I ../include/ stacktrace_smpl.cpp -g -rdynamic && ./a.out
*/
#include <stdio.h>
#include <iostream>
#define CYBOZU_USE_STACKTRACE
#include <cybozu/stacktrace.hpp>

void putStackTrace()
{
	std::cout << "no memory!!\n" << cybozu::StackTrace() << std::endl;
	exit(1);
}

struct A {
	void f() {
		putStackTrace();
	}
};

struct B {
	A a;
	void g() {
		a.f();
	}
};

void func()
{
	puts("func");
	B b;
	b.g();
}

void g()
{
	func();
}

void h()
{
	g();
}

int main()
	try
{
	h();
} catch (std::exception& e) {
	printf("e=%s\n", e.what());
}

<|endoftext|>


<commit_before>/*!
** \file URL.cpp
** \date Wed May 7 2008
** \author Steve Sloan <steve@finagle.org>
** Copyright (C) 2008 by Steve Sloan
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the GNU Lesser General Public License as published
** by the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This library is distributed in the hope that it will be useful, but
** WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, you may access it via the web
** at http://www.gnu.org/copyleft/lesser.html .
*/

#include <cctype>
#include "URL.h"

using namespace std;
using namespace Finagle;

/*!
** \namespace Finagle::URL
** \brief Uniform Resource Locator
*/

String URL::escape( String const &str )
{
  String out;
  for ( String::ConstIterator ch = str.begin(); ch != str.end(); ++ch ) {
    if ( isalnum( *ch ) || (*ch == '_') || (*ch == '.') || (*ch == '-') )
      out.append( 1, *ch );
    else
    if ( *ch == ' ' )
      out.append( 1, '+' );
    else
      out.append( String::format( "%%%02X", (char) *ch ) );
  }

  return out;
}

URL URL::HTTP( String const &userInfo, IPAddress const &host, unsigned port, String const &path, Map<String, String> const &query, String const &fragment )
{
  URL url( "http", "//" );

  if ( userInfo ) {
    url.append( userInfo );
    url.append( 1, '@' );
  }

  url.append( host.name() );

  if ( port ) {
    url.append( 1, ':' );
    url.append( String(port) );
  }

  if ( path[0] != '/' )
    url.append( 1, '/' );

  url.append( path );

  if ( !query.empty() ) {
    Map<String, String>::ConstIterator q = query.begin();
    url.append( 1, '?' );
    url.append( URL::escape(q.key()) + "=" + URL::escape(q.val()) );
    ++q;

    for ( ; q != query.end(); ++q ) {
      url.append( 1, ';' );
      url.append( URL::escape(q.key()) + "=" + URL::escape(q.val()) );
    }
  }
  if ( fragment ) {
    url.append( 1, '#' );
    url.append( URL::escape(fragment) );
  }

  return url;
}
<commit_msg>URL: changed param delim from ';' to '&' (hack for Axis camera support).<commit_after>/*!
** \file URL.cpp
** \date Wed May 7 2008
** \author Steve Sloan <steve@finagle.org>
** Copyright (C) 2008 by Steve Sloan
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the GNU Lesser General Public License as published
** by the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This library is distributed in the hope that it will be useful, but
** WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, you may access it via the web
** at http://www.gnu.org/copyleft/lesser.html .
*/

#include <cctype>
#include "URL.h"

using namespace std;
using namespace Finagle;

/*!
** \namespace Finagle::URL
** \brief Uniform Resource Locator
*/

String URL::escape( String const &str )
{
  String out;
  for ( String::ConstIterator ch = str.begin(); ch != str.end(); ++ch ) {
    if ( isalnum( *ch ) || (*ch == '_') || (*ch == '.') || (*ch == '-') )
      out.append( 1, *ch );
    else
    if ( *ch == ' ' )
      out.append( 1, '+' );
    else
      out.append( String::format( "%%%02X", (char) *ch ) );
  }

  return out;
}

URL URL::HTTP( String const &userInfo, IPAddress const &host, unsigned port, String const &path, Map<String, String> const &query, String const &fragment )
{
  URL url( "http", "//" );

  if ( userInfo ) {
    url.append( userInfo );
    url.append( 1, '@' );
  }

  url.append( host.name() );

  if ( port ) {
    url.append( 1, ':' );
    url.append( String(port) );
  }

  if ( path[0] != '/' )
    url.append( 1, '/' );

  url.append( path );

  if ( !query.empty() ) {
    Map<String, String>::ConstIterator q = query.begin();
    url.append( 1, '?' );
    url.append( URL::escape(q.key()) + "=" + URL::escape(q.val()) );
    ++q;

    for ( ; q != query.end(); ++q ) {
      url.append( 1, '&' );
      url.append( URL::escape(q.key()) + "=" + URL::escape(q.val()) );
    }
  }
  if ( fragment ) {
    url.append( 1, '#' );
    url.append( URL::escape(fragment) );
  }

  return url;
}
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/gl/kernels/mean.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "tensorflow/lite/delegates/gpu/common/status.h"
#include "tensorflow/lite/delegates/gpu/common/types.h"
#include "tensorflow/lite/delegates/gpu/common/util.h"

namespace tflite {
namespace gpu {
namespace gl {
namespace {

bool UseSubgroupBasedImpl(const GpuInfo& gpu_info) {
  return gpu_info.IsApiVulkan() &&
         (gpu_info.vulkan_info.api_version_major > 1 ||
          gpu_info.vulkan_info.api_version_minor >= 1) &&
         gpu_info.vulkan_info.subgroup_size >= 32 &&
         gpu_info.vulkan_info.supports_subgroup_arithmetic;
}

// An implementation of Mean for desktop GPUs and some phones with recent
// Vulkan drivers. It is more parallel than the trivial Mean operation, but
// still limited to using a single work group.
void GenerateSubgroupBasedMean(const NodeShader::GenerationContext& ctx,
                               GeneratedCode* generated_code) {
  int height = ctx.input_shapes[0][1];
  int width = ctx.input_shapes[0][2];
  int depth = ctx.input_shapes[0][3];
  std::vector<Variable> parameters = {
      {"input_data_0_h", height},
      {"input_data_0_w", width},
      {"output_data_0_h", 1},
      {"output_data_0_w", 1},
  };

  std::string source = R"(
  // Round columns and rows per invocation up, to ensure that we read the
  // entire input.
  const uint columns_per_invocation =
      ($input_data_0_w$ + (gl_WorkGroupSize.x - 1))/gl_WorkGroupSize.x;
  const uint rows_per_invocation =
      ($input_data_0_h$ + (gl_WorkGroupSize.y - 1))/gl_WorkGroupSize.y;
  const uint first_row = gl_GlobalInvocationID.y*rows_per_invocation;
  const uint first_col = gl_GlobalInvocationID.x*columns_per_invocation;
  const uint last_row_exclusive =
      min(first_row+rows_per_invocation, $input_data_0_h$);
  const uint last_column_exclusive =
      min(first_col+columns_per_invocation, $input_data_0_w$);
  vec4 value = vec4(0);
  for (uint h = first_row; h < last_row_exclusive; ++h) {
    for (uint w = first_col; w < last_column_exclusive; ++w) {
      value += $input_data_0[w, h, gid.z]$;
    }
  }
  highp vec4 subgroup_sum = subgroupAdd(value);
  if(subgroupElect()) {
    subgroup_sums[gl_SubgroupID] = subgroup_sum;
  }

  memoryBarrierShared();
  barrier();
  // Do the final reduction in the first subgroup.
  if(gl_SubgroupID == 0) {
    highp vec4 subtotal = vec4(0);
    if (gl_SubgroupInvocationID < gl_NumSubgroups) {
      subtotal = subgroup_sums[gl_SubgroupInvocationID];
    }
    highp vec4 grand_total = subgroupAdd(subtotal);
    if(subgroupElect()) {
      highp vec4 result = grand_total / $input_data_0_w$ / $input_data_0_h$;
      $output_data_0[0, 0, gid.z] = result$;
    }
  }
  )";

  const uint32_t subgroup_size = ctx.gpu_info->vulkan_info.subgroup_size;
  const uint32_t max_wg_size_x = ctx.gpu_info->GetMaxWorkGroupSizeForX();
  const uint32_t max_wg_size_y = ctx.gpu_info->GetMaxWorkGroupSizeForY();
  // Due to the design of the shader, at most subgroup_size subgroups can be
  // launched. This may limit the maximal workgroup size.
  const uint32_t max_wg_size =
      std::min(static_cast<uint32_t>(ctx.gpu_info->GetMaxWorkGroupTotalSize()),
               subgroup_size * subgroup_size);
  const uint32_t max_number_of_subgroups = max_wg_size / subgroup_size;
  uint32_t wg_size_x = 0;
  uint32_t wg_size_y = 0;
  if (width * height <= max_wg_size && width <= max_wg_size_x &&
      height <= max_wg_size_y) {
    wg_size_x = width;
    wg_size_y = height;
  } else {
    // Approximately square workgroup. Also make sure to limit by driver limit
    // and input size.
    wg_size_x = std::min({static_cast<uint32_t>(std::sqrt(max_wg_size)),
                          max_wg_size_x, static_cast<uint32_t>(width)});
    wg_size_y = std::min({max_wg_size / wg_size_x, max_wg_size_y,
                          static_cast<uint32_t>(height)});
  }

  std::vector<Variable> shared_variables = {
      {"subgroup_sums", std::vector<float4>(max_number_of_subgroups)},
  };

  *generated_code = {
      /*parameters=*/std::move(parameters),
      /*objects=*/{},
      /*shared_variables=*/{std::move(shared_variables)},
      // Make sure we get one dispatch of size wg_size_x*wg_size_y*1 per layer.
      /*workload=*/
      uint3(wg_size_x, wg_size_y, uint32_t(DivideRoundUp(depth, 4))),
      /*workgroup=*/uint3(wg_size_x, wg_size_y, 1u),
      /*source_code=*/std::move(source),
      /*input=*/IOStructure::ONLY_DEFINITIONS,
      /*output=*/IOStructure::ONLY_DEFINITIONS,
  };
}

void GenerateTrivialMean(const NodeShader::GenerationContext& ctx,
                         GeneratedCode* generated_code) {
  std::vector<Variable> parameters = {
      {"input_data_0_h", static_cast<int>(ctx.input_shapes[0][1])},
      {"input_data_0_w", static_cast<int>(ctx.input_shapes[0][2])}};

  // Shaders may be compiled with a precision hint mediump, which means that
  // GLSL compiler may drop the size of float data type from 32 to 16 bits.
  // If "sum" and "size" variables are 16bit floats, their values range
  // become not enough for providing a good results accuracy. That is why
  // their precision is forced to be 32bit by using highp qualifier.
  std::string source = R"(
    highp vec4 sum = vec4(0.0);
    highp float size = float($input_data_0_w$ * $input_data_0_h$);
    for (int w = 0; w < $input_data_0_w$; w++) {
      for (int h = 0; h < $input_data_0_h$; h++) {
        sum += $input_data_0[w, h, gid.z]$;
      }
    }
    value_0 = sum / size;
  )";
  *generated_code = {
      /*parameters=*/std::move(parameters),
      /*objects=*/{},
      /*shared_variables=*/{},
      /*workload=*/uint3(),
      /*workgroup=*/uint3(1, 1, 4),
      /*source_code=*/std::move(source),
      /*input=*/IOStructure::ONLY_DEFINITIONS,
      /*output=*/IOStructure::AUTO,
  };
}

// Tiled implementation.

constexpr uint3 kTileSize = {8, 8, 1};

inline bool UseTiledImpl(const NodeShader::GenerationContext& ctx) {
  const int h = ctx.input_shapes[0][1];
  const int w = ctx.input_shapes[0][2];
  const int c = ctx.input_shapes[0][3];
  return h % kTileSize.y == 0 && w % kTileSize.x == 0 && c % 4 == 0 &&
         (h / kTileSize.y) * (w / kTileSize.x) * c * sizeof(float) <=
             32768;  // required min value for GL_MAX_COMPUTE_SHARED_MEMORY_SIZE
}

void GenerateTiledMean(const NodeShader::GenerationContext& ctx,
                       GeneratedCode* generated_code) {
  const int h = ctx.input_shapes[0][1];
  const int w = ctx.input_shapes[0][2];
  const int s = DivideRoundUp(ctx.input_shapes[0][3], 4);

  std::vector<Variable> parameters = {
      {"input_data_0_h", h},
      {"input_data_0_w", w},
      {"tile_size_h", kTileSize.y},
      {"tile_size_w", kTileSize.x},
  };

  std::vector<Variable> shared_variables = {
      {"tile_sum",
       std::vector<float4>((w / kTileSize.x) * (h / kTileSize.y) * s)}};

  std::string source = R"(
  ivec2 tile_size = ivec2($tile_size_w$, $tile_size_h$);
  ivec2 num_tiles = ivec2($input_data_0_w$, $input_data_0_h$) / tile_size;

  highp vec4 partial_sum = vec4(0.0);
  for (int x = gid.x * tile_size.x; x < (gid.x + 1) * tile_size.x; ++x) {
    for (int y = gid.y * tile_size.y; y < (gid.y + 1) * tile_size.y; ++y) {
      partial_sum += $input_data_0[x, y, gid.z]$;
    }
  }
  $tile_sum$[num_tiles.x * num_tiles.y * gid.z + num_tiles.x * gid.y + gid.x] = partial_sum;

  memoryBarrierShared(); barrier();

  if (gid.x == 0 && gid.y == 0) {
    highp vec4 sum = vec4(0.0);
    for (int i = 0; i < num_tiles.x * num_tiles.y; ++i) {
      sum += $tile_sum$[num_tiles.x * num_tiles.y * gid.z + i];
    }
    highp vec4 mean = sum / float($input_data_0_w$ * $input_data_0_h$);
    $output_data_0[0, 0, gid.z] = mean$;
  }
)";
  *generated_code = {
      /*parameters=*/std::move(parameters),
      /*objects=*/{},
      /*shared_variables=*/std::move(shared_variables),
      /*workload=*/uint3(w, h, s),
      /*workgroup=*/kTileSize,
      /*source_code=*/std::move(source),
      /*input=*/IOStructure::ONLY_DEFINITIONS,
      /*output=*/IOStructure::ONLY_DEFINITIONS,
  };
}

class Mean : public NodeShader {
 public:
  absl::Status GenerateCode(const GenerationContext& ctx,
                            GeneratedCode* generated_code) const final {
    const auto& attr = absl::any_cast<const MeanAttributes&>(ctx.op_attr);
    if (attr.dims != std::set<Axis>({Axis::HEIGHT, Axis::WIDTH})) {
      return absl::InvalidArgumentError(
          "Mean calculation is supported only for height and width.");
    }

    if (!(ctx.input_shapes.size() == 1 && ctx.output_shapes.size() == 1 &&
          ctx.output_shapes[0][1] == 1 && ctx.output_shapes[0][2] == 1 &&
          ctx.output_shapes[0][3] == ctx.input_shapes[0][3])) {
      return absl::InvalidArgumentError(
          "Mean calculation is supported for one input and one 1x1 output with "
          "the same channel count.");
    }

    if (UseSubgroupBasedImpl(*ctx.gpu_info)) {
      GenerateSubgroupBasedMean(ctx, generated_code);
    } else if (UseTiledImpl(ctx)) {
      GenerateTiledMean(ctx, generated_code);
    } else {
      GenerateTrivialMean(ctx, generated_code);
    }
    return absl::OkStatus();
  }
};

}  // namespace

std::unique_ptr<NodeShader> NewMeanNodeShader() {
  return absl::make_unique<Mean>();
}

}  // namespace gl
}  // namespace gpu
}  // namespace tflite
<commit_msg>Adjust workload size of the optimized implementation of the tiled Mean operation.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/gl/kernels/mean.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "tensorflow/lite/delegates/gpu/common/status.h"
#include "tensorflow/lite/delegates/gpu/common/types.h"
#include "tensorflow/lite/delegates/gpu/common/util.h"

namespace tflite {
namespace gpu {
namespace gl {
namespace {

bool UseSubgroupBasedImpl(const GpuInfo& gpu_info) {
  return gpu_info.IsApiVulkan() &&
         (gpu_info.vulkan_info.api_version_major > 1 ||
          gpu_info.vulkan_info.api_version_minor >= 1) &&
         gpu_info.vulkan_info.subgroup_size >= 32 &&
         gpu_info.vulkan_info.supports_subgroup_arithmetic;
}

// An implementation of Mean for desktop GPUs and some phones with recent
// Vulkan drivers. It is more parallel than the trivial Mean operation, but
// still limited to using a single work group.
void GenerateSubgroupBasedMean(const NodeShader::GenerationContext& ctx,
                               GeneratedCode* generated_code) {
  int height = ctx.input_shapes[0][1];
  int width = ctx.input_shapes[0][2];
  int depth = ctx.input_shapes[0][3];
  std::vector<Variable> parameters = {
      {"input_data_0_h", height},
      {"input_data_0_w", width},
      {"output_data_0_h", 1},
      {"output_data_0_w", 1},
  };

  std::string source = R"(
  // Round columns and rows per invocation up, to ensure that we read the
  // entire input.
  const uint columns_per_invocation =
      ($input_data_0_w$ + (gl_WorkGroupSize.x - 1))/gl_WorkGroupSize.x;
  const uint rows_per_invocation =
      ($input_data_0_h$ + (gl_WorkGroupSize.y - 1))/gl_WorkGroupSize.y;
  const uint first_row = gl_GlobalInvocationID.y*rows_per_invocation;
  const uint first_col = gl_GlobalInvocationID.x*columns_per_invocation;
  const uint last_row_exclusive =
      min(first_row+rows_per_invocation, $input_data_0_h$);
  const uint last_column_exclusive =
      min(first_col+columns_per_invocation, $input_data_0_w$);
  vec4 value = vec4(0);
  for (uint h = first_row; h < last_row_exclusive; ++h) {
    for (uint w = first_col; w < last_column_exclusive; ++w) {
      value += $input_data_0[w, h, gid.z]$;
    }
  }
  highp vec4 subgroup_sum = subgroupAdd(value);
  if(subgroupElect()) {
    subgroup_sums[gl_SubgroupID] = subgroup_sum;
  }

  memoryBarrierShared();
  barrier();
  // Do the final reduction in the first subgroup.
  if(gl_SubgroupID == 0) {
    highp vec4 subtotal = vec4(0);
    if (gl_SubgroupInvocationID < gl_NumSubgroups) {
      subtotal = subgroup_sums[gl_SubgroupInvocationID];
    }
    highp vec4 grand_total = subgroupAdd(subtotal);
    if(subgroupElect()) {
      highp vec4 result = grand_total / $input_data_0_w$ / $input_data_0_h$;
      $output_data_0[0, 0, gid.z] = result$;
    }
  }
  )";

  const uint32_t subgroup_size = ctx.gpu_info->vulkan_info.subgroup_size;
  const uint32_t max_wg_size_x = ctx.gpu_info->GetMaxWorkGroupSizeForX();
  const uint32_t max_wg_size_y = ctx.gpu_info->GetMaxWorkGroupSizeForY();
  // Due to the design of the shader, at most subgroup_size subgroups can be
  // launched. This may limit the maximal workgroup size.
  const uint32_t max_wg_size =
      std::min(static_cast<uint32_t>(ctx.gpu_info->GetMaxWorkGroupTotalSize()),
               subgroup_size * subgroup_size);
  const uint32_t max_number_of_subgroups = max_wg_size / subgroup_size;
  uint32_t wg_size_x = 0;
  uint32_t wg_size_y = 0;
  if (width * height <= max_wg_size && width <= max_wg_size_x &&
      height <= max_wg_size_y) {
    wg_size_x = width;
    wg_size_y = height;
  } else {
    // Approximately square workgroup. Also make sure to limit by driver limit
    // and input size.
    wg_size_x = std::min({static_cast<uint32_t>(std::sqrt(max_wg_size)),
                          max_wg_size_x, static_cast<uint32_t>(width)});
    wg_size_y = std::min({max_wg_size / wg_size_x, max_wg_size_y,
                          static_cast<uint32_t>(height)});
  }

  std::vector<Variable> shared_variables = {
      {"subgroup_sums", std::vector<float4>(max_number_of_subgroups)},
  };

  *generated_code = {
      /*parameters=*/std::move(parameters),
      /*objects=*/{},
      /*shared_variables=*/{std::move(shared_variables)},
      // Make sure we get one dispatch of size wg_size_x*wg_size_y*1 per layer.
      /*workload=*/
      uint3(wg_size_x, wg_size_y, uint32_t(DivideRoundUp(depth, 4))),
      /*workgroup=*/uint3(wg_size_x, wg_size_y, 1u),
      /*source_code=*/std::move(source),
      /*input=*/IOStructure::ONLY_DEFINITIONS,
      /*output=*/IOStructure::ONLY_DEFINITIONS,
  };
}

void GenerateTrivialMean(const NodeShader::GenerationContext& ctx,
                         GeneratedCode* generated_code) {
  std::vector<Variable> parameters = {
      {"input_data_0_h", static_cast<int>(ctx.input_shapes[0][1])},
      {"input_data_0_w", static_cast<int>(ctx.input_shapes[0][2])}};

  // Shaders may be compiled with a precision hint mediump, which means that
  // GLSL compiler may drop the size of float data type from 32 to 16 bits.
  // If "sum" and "size" variables are 16bit floats, their values range
  // become not enough for providing a good results accuracy. That is why
  // their precision is forced to be 32bit by using highp qualifier.
  std::string source = R"(
    highp vec4 sum = vec4(0.0);
    highp float size = float($input_data_0_w$ * $input_data_0_h$);
    for (int w = 0; w < $input_data_0_w$; w++) {
      for (int h = 0; h < $input_data_0_h$; h++) {
        sum += $input_data_0[w, h, gid.z]$;
      }
    }
    value_0 = sum / size;
  )";
  *generated_code = {
      /*parameters=*/std::move(parameters),
      /*objects=*/{},
      /*shared_variables=*/{},
      /*workload=*/uint3(),
      /*workgroup=*/uint3(1, 1, 4),
      /*source_code=*/std::move(source),
      /*input=*/IOStructure::ONLY_DEFINITIONS,
      /*output=*/IOStructure::AUTO,
  };
}

// Tiled implementation.

constexpr uint3 kTileSize = {8, 8, 1};

inline bool UseTiledImpl(const NodeShader::GenerationContext& ctx) {
  const int h = ctx.input_shapes[0][1];
  const int w = ctx.input_shapes[0][2];
  const int c = ctx.input_shapes[0][3];
  return h % kTileSize.y == 0 && w % kTileSize.x == 0 && c % 4 == 0 &&
         (h / kTileSize.y) * (w / kTileSize.x) * c * sizeof(float) <=
             32768;  // required min value for GL_MAX_COMPUTE_SHARED_MEMORY_SIZE
}

void GenerateTiledMean(const NodeShader::GenerationContext& ctx,
                       GeneratedCode* generated_code) {
  const int h = ctx.input_shapes[0][1];
  const int w = ctx.input_shapes[0][2];
  const int s = DivideRoundUp(ctx.input_shapes[0][3], 4);

  std::vector<Variable> parameters = {
      {"input_data_0_h", h},
      {"input_data_0_w", w},
      {"tile_size_h", kTileSize.y},
      {"tile_size_w", kTileSize.x},
  };

  std::vector<Variable> shared_variables = {
      {"tile_sum",
       std::vector<float4>((w / kTileSize.x) * (h / kTileSize.y) * s)}};

  std::string source = R"(
  ivec2 tile_size = ivec2($tile_size_w$, $tile_size_h$);
  ivec2 num_tiles = ivec2($input_data_0_w$, $input_data_0_h$) / tile_size;

  highp vec4 partial_sum = vec4(0.0);
  for (int x = gid.x * tile_size.x; x < (gid.x + 1) * tile_size.x; ++x) {
    for (int y = gid.y * tile_size.y; y < (gid.y + 1) * tile_size.y; ++y) {
      partial_sum += $input_data_0[x, y, gid.z]$;
    }
  }
  $tile_sum$[num_tiles.x * num_tiles.y * gid.z + num_tiles.x * gid.y + gid.x] = partial_sum;

  memoryBarrierShared(); barrier();

  if (gid.x == 0 && gid.y == 0) {
    highp vec4 sum = vec4(0.0);
    for (int i = 0; i < num_tiles.x * num_tiles.y; ++i) {
      sum += $tile_sum$[num_tiles.x * num_tiles.y * gid.z + i];
    }
    highp vec4 mean = sum / float($input_data_0_w$ * $input_data_0_h$);
    $output_data_0[0, 0, gid.z] = mean$;
  }
)";
  *generated_code = {
      /*parameters=*/std::move(parameters),
      /*objects=*/{},
      /*shared_variables=*/std::move(shared_variables),
      /*workload=*/uint3(kTileSize.x, kTileSize.y, static_cast<uint32_t>(s)),
      /*workgroup=*/kTileSize,
      /*source_code=*/std::move(source),
      /*input=*/IOStructure::ONLY_DEFINITIONS,
      /*output=*/IOStructure::ONLY_DEFINITIONS,
  };
}

class Mean : public NodeShader {
 public:
  absl::Status GenerateCode(const GenerationContext& ctx,
                            GeneratedCode* generated_code) const final {
    const auto& attr = absl::any_cast<const MeanAttributes&>(ctx.op_attr);
    if (attr.dims != std::set<Axis>({Axis::HEIGHT, Axis::WIDTH})) {
      return absl::InvalidArgumentError(
          "Mean calculation is supported only for height and width.");
    }

    if (!(ctx.input_shapes.size() == 1 && ctx.output_shapes.size() == 1 &&
          ctx.output_shapes[0][1] == 1 && ctx.output_shapes[0][2] == 1 &&
          ctx.output_shapes[0][3] == ctx.input_shapes[0][3])) {
      return absl::InvalidArgumentError(
          "Mean calculation is supported for one input and one 1x1 output with "
          "the same channel count.");
    }

    if (UseSubgroupBasedImpl(*ctx.gpu_info)) {
      GenerateSubgroupBasedMean(ctx, generated_code);
    } else if (UseTiledImpl(ctx)) {
      GenerateTiledMean(ctx, generated_code);
    } else {
      GenerateTrivialMean(ctx, generated_code);
    }
    return absl::OkStatus();
  }
};

}  // namespace

std::unique_ptr<NodeShader> NewMeanNodeShader() {
  return absl::make_unique<Mean>();
}

}  // namespace gl
}  // namespace gpu
}  // namespace tflite
<|endoftext|>


<commit_before>#include "heuristic.hpp"

#include <random>

#include "position.hpp"

using namespace std;

// Returns the best known heuristic. These values were found via the training.
heuristic best_heuristic() {
  heuristic e{15};
  e.add_evaluator(eval_trapped_kings, 5);
  e.add_evaluator(eval_pyramid, 12);
  e.add_evaluator(eval_centralized_kings, 2);
  e.add_evaluator(eval_dyke, 10);
  e.add_evaluator(eval_a_diagonal, 12);
  e.add_evaluator(eval_b_diagonal, 15);
  e.add_evaluator(eval_c_diagonal, 15);
  e.add_evaluator(eval_d_diagonal, 8);
  e.add_evaluator(eval_e_diagonal, 11);
  e.add_evaluator(eval_f_diagonal, 13);
  e.add_evaluator(eval_g_diagonal, 15);

  return e;
}

// Evaluates a position, and returns the integer corresponding to its
int heuristic::operator()(const position &p) const {
  // These are a sufficient, but not necessary condition to ensure a loss.
  if (!__builtin_popcount(p[0] | p[2]))
    return -1000000;
  if (!__builtin_popcount(p[1] | p[3]))
    return 1000000;

  // Total number of kings on the board.
  const char king_count = __builtin_popcount(p[2] | p[3]);

  int retval = (__builtin_popcount(p[0]) - __builtin_popcount(p[1])) * 10;
  retval += (__builtin_popcount(p[2]) - __builtin_popcount(p[3])) * kingweight;

  // If there are relatively few kings on the board, prioritize trading the off
  if (king_count < 6)
    retval += (__builtin_popcount(p[2]) - __builtin_popcount(p[3])) *
              (6 - king_count);

  for (const auto &eval : evaluators)
    retval += eval_funcs[eval.first](p, eval.second);

  return retval;
}

// Randomly increase, decrease, or leave unaffected each evaluator's weight.
void heuristic::mutate() {
  mt19937 r{random_device()()};
  uniform_int_distribution<> dist{0, 2};

  switch (dist(r)) {
  case 0:
    kingweight++;
    break;
  case 1:
    kingweight--;
    break;
  }

  for (std::pair<eval_names, int> &eval : evaluators)
    switch (dist(r)) {
    case 0:
      eval.second++;
      break;
    case 1:
      eval.second--;
      break;
    }
}

std::ostream &operator<<(std::ostream &o, const heuristic &h) {
  o << "{(score:" << h.score << "),(kingweight:" << h.kingweight << ')';
  for (pair<eval_names, int> e : h.evaluators)
    o << ",(" << eval_names_text[e.first] << ',' << e.second << ')';
  o << '}';
  return o;
}
<commit_msg>Updated heuristic with latest training data.<commit_after>#include "heuristic.hpp"

#include <random>

#include "position.hpp"

using namespace std;

// Returns the best known heuristic. These values were found via the training.
heuristic best_heuristic() {
  heuristic e{14};
  e.add_evaluator(eval_trapped_kings, 4);
  e.add_evaluator(eval_pyramid, 10);
  e.add_evaluator(eval_centralized_kings, 1);
  e.add_evaluator(eval_dyke, 9);
  e.add_evaluator(eval_a_diagonal, 10);
  e.add_evaluator(eval_b_diagonal, 14);
  e.add_evaluator(eval_c_diagonal, 13);
  e.add_evaluator(eval_d_diagonal, 9);
  e.add_evaluator(eval_e_diagonal, 11);
  e.add_evaluator(eval_f_diagonal, 15);
  e.add_evaluator(eval_g_diagonal, 17);

  return e;
}

// Evaluates a position, and returns the integer corresponding to its
int heuristic::operator()(const position &p) const {
  // These are a sufficient, but not necessary condition to ensure a loss.
  if (!__builtin_popcount(p[0] | p[2]))
    return -1000000;
  if (!__builtin_popcount(p[1] | p[3]))
    return 1000000;

  // Total number of kings on the board.
  const char king_count = __builtin_popcount(p[2] | p[3]);

  int retval = (__builtin_popcount(p[0]) - __builtin_popcount(p[1])) * 10;
  retval += (__builtin_popcount(p[2]) - __builtin_popcount(p[3])) * kingweight;

  // If there are relatively few kings on the board, prioritize trading the off
  if (king_count < 6)
    retval += (__builtin_popcount(p[2]) - __builtin_popcount(p[3])) *
              (6 - king_count);

  for (const auto &eval : evaluators)
    retval += eval_funcs[eval.first](p, eval.second);

  return retval;
}

// Randomly increase, decrease, or leave unaffected each evaluator's weight.
void heuristic::mutate() {
  mt19937 r{random_device()()};
  uniform_int_distribution<> dist{0, 2};

  switch (dist(r)) {
  case 0:
    kingweight++;
    break;
  case 1:
    kingweight--;
    break;
  }

  for (std::pair<eval_names, int> &eval : evaluators)
    switch (dist(r)) {
    case 0:
      eval.second++;
      break;
    case 1:
      eval.second--;
      break;
    }
}

std::ostream &operator<<(std::ostream &o, const heuristic &h) {
  o << "{(score:" << h.score << "),(kingweight:" << h.kingweight << ')';
  for (pair<eval_names, int> e : h.evaluators)
    o << ",(" << eval_names_text[e.first] << ',' << e.second << ')';
  o << '}';
  return o;
}
<|endoftext|>


<commit_before>#include "IPTVTopologyOracle.hpp"
#include "Scheduler.hpp"
#include "boost/random/discrete_distribution.hpp"
#include "boost/random/uniform_int.hpp"
#include "boost/random/normal_distribution.hpp"
#include "zipf_distribution.hpp"
#include <boost/lexical_cast.hpp>
#include <initializer_list>
#include <boost/random/mersenne_twister.hpp>

// random generator
extern boost::mt19937 gen;

IPTVTopologyOracle::IPTVTopologyOracle(Topology* topo, po::variables_map vm,
        uint roundDuration) : TopologyOracle(topo, vm, roundDuration) {
  this->contentNum = vm["contents"].as<uint>() * vm["channels"].as<uint>();
  double zmExp = vm["zm-exponent"].as<double>();
  this->shiftDist = new boost::random::uniform_int_distribution<>(0,50);
  this->expDist = new boost::random::uniform_real_distribution<>(0.4, zmExp);
  this->rankDist = new boost::random::zipf_distribution<>(contentNum,
          (*shiftDist)(gen), (*expDist)(gen));
  this->relDayDist = new boost::random::zipf_distribution<>(7, 0, (*expDist)(gen));
  // allocate memory for the dailyCatalog and initialize contentRateVec
  std::vector<double> dailyRank(contentNum, 0.0);
  contentRateVec.resize(7, dailyRank);
  for (uint i = 0; i < 7; i++) {
    std::vector<ContentElement*> vec(contentNum, nullptr);
    dailyCatalog.push_back(vec);
  }
}

IPTVTopologyOracle::~IPTVTopologyOracle() {
  BOOST_FOREACH(std::vector<ContentElement*> list, dailyCatalog) {
    BOOST_FOREACH(ContentElement* content, list) {
      delete content;
    }
    list.clear();
  }
  dailyCatalog.clear();
  userWatchMap.clear();
  delete this->relDayDist;
  delete this->rankDist;
  delete this->expDist;
  delete this->shiftDist;
}

void IPTVTopologyOracle::generateUserViewMap(Scheduler* scheduler) {
  uint roundDuration = scheduler->getRoundDuration();
  double totalHours = 0, randomHours;
  boost::random::normal_distribution<> userSessionDist(avgHoursPerUser);
  boost::random::discrete_distribution<> hourDist(usrPctgByHour);
  boost::random::uniform_int_distribution<> minSecDist(0, 3599);
  // Generate a session start time and session length for each user
  SimTime sessionStart, sessionLength;

  BOOST_FOREACH(Vertex v, topo->getPonNodes()) {
    for (uint i = 0; i < topo->getPonCustomers(v); i++) {
      randomHours = userSessionDist(gen);
      // daily sessions can't be longer than a day, duh
      if (randomHours > 24)
        randomHours = 24;
      if (randomHours > 0)
        totalHours += randomHours;
      sessionLength = std::floor((randomHours * 3600) + 0.5);
      if (sessionLength <= 0) {
        BOOST_LOG_TRIVIAL(info) << "TopologyOracle::generateUserViewMap() - "
                  "non-positive sessionLength for user " << v << "," << i
                  << " - skipping it";
        continue;
      }
      /* the time we generate is assumed to be the middle point of the viewing
       * session, so we shift it of half sessionLength, but we need to ensure it
       * still fits inside the round
       */
      sessionStart = (hourDist(gen) * 3600 + minSecDist(gen)) -
              std::floor((sessionLength / 2) + 0.5);
      if (sessionStart < 0)
        sessionStart = 0;
      else if (sessionStart + sessionLength >= roundDuration)
        sessionStart = roundDuration - sessionLength;
      SimTimeInterval interval(sessionStart, sessionStart + sessionLength);
      PonUser user = std::make_pair(v,i);
      if (scheduler->getCurrentRound() == 0) {
        //first round, populate userWatchMap
        std::pair<PonUser, UserWatchingInfo> userWatchMapEntry = std::make_pair(user, UserWatchingInfo(interval));
        userWatchMap.insert(userWatchMapEntry);
      } else {
        // subsequent rounds, just store the new interval
        userWatchMap.at(user).dailySessionInterval = interval;
      }
      // generate first request and schedule it
      this->generateNewRequest(user, interval.getStart(), scheduler);
    }
  }
  BOOST_LOG_TRIVIAL(info) << "Total hours of scheduled viewing for the current day: "
          << totalHours << "; avg. hours per user: "
          << totalHours/(topo->getNumCustomers())
          << " (requested: " << avgHoursPerUser << ")";
}

void IPTVTopologyOracle::populateCatalog() {
  // normal distribution to generate content length in minutes
  boost::random::normal_distribution<> normDist(this->avgContentLength,
          this->devContentLength);
  Capacity size = 0;
  // generate content for the first day and the previous 6
  for (int day = -6; day < 1; day++) {
    for (uint i = 0; i < contentNum; i++) {
      size = std::ceil(normDist(gen) * 60 * this->bitrate);
      ContentElement* content = new ContentElement(
        boost::lexical_cast<string > ((day + 6) * contentNum + i), day, size,
              chunkSize);
      dailyCatalog[std::abs(day)].at(i) = content;
      auto chunks = content->getChunks();
      for (auto j = chunks.begin(); j != chunks.end(); j++)
        dailyRanking.at(std::abs(day)).insert(*j);
      this->addContent(content, 0);
    }
  }
}

void IPTVTopologyOracle::updateCatalog(uint currentRound) {
  // Update catalogue
  dailyRanking.at(6).clear();
  BOOST_FOREACH(ContentElement* content, dailyCatalog[6]) {
    this->removeContent(content, currentRound+1);
    delete content;
  }
  for (uint day = 6; day > 0; day--) {
    dailyCatalog[day] = dailyCatalog[day - 1];
    dailyRanking.at(day).resetRoundHits();
    dailyRanking.at(day) = dailyRanking.at(day-1);
  }
  dailyRanking.at(0).clear();
  // normal distribution to generate content length in minutes
  boost::random::normal_distribution<> normDist(this->avgContentLength,
          this->devContentLength);
  Capacity size = 0;
  for (uint i = 0; i < contentNum; i++) {
    size = std::ceil(normDist(gen) * 60 * this->bitrate);
    ContentElement* content = new ContentElement(
            boost::lexical_cast<string > ((currentRound + 7) * contentNum + i),
            currentRound + 1, size, chunkSize);
    dailyCatalog[0].at(i) = content;
    auto chunks = content->getChunks();
    for (auto j = chunks.begin(); j != chunks.end(); j++)
      dailyRanking.at(0).insert(*j);
    this->addContent(content, currentRound+1);
  }
}

/* selects a movie to be requested according to the popularity distributions,
 * determines how long the user is going to be watching it (because of zapping)
 * and stores the required information in the userWatchMap, then creates a new
 * Flow and schedules it.
 */
void IPTVTopologyOracle::generateNewRequest(PonUser user, SimTime time,
        Scheduler* scheduler) {
  SimTime sessionEnd = userWatchMap.at(user).dailySessionInterval.getEnd();
  if (time < sessionEnd) {
    boost::random::uniform_int_distribution<> indexDist(0, 17);
    uint i = (*relDayDist)(gen);
    ContentElement* content = dailyCatalog[i].at((*rankDist)(gen));
    Capacity reqLength = sessionLength[indexDist(gen)] * content->getSize();
    /* calculate the time at which the user will be done with this content */
    SimTime endTime = time + std::ceil(reqLength / this->bitrate);
    // check that the new request would not go past the desired session
    // length; this will make all requests past midnight end at midnight :(
    if (endTime > sessionEnd) {
      // new reqLength can't be less than 1 second worth of traffic
      endTime = std::max(time + 1, sessionEnd);
    }
    UserWatchingMap::iterator wIt = userWatchMap.find(user);
    assert (wIt != userWatchMap.end());
    wIt->second.content = content;
    wIt->second.watchingEndTime = endTime;
    // we are waiting for the first chunk to be downloaded
    wIt->second.waiting = true;
    /* Request enough chunks to fill the buffer.
     * FIXME: Note that I'm waiting one
     * second between each chunks to make it more likely that chunks arrive in
     * order and to avoid congestion for the first chunk, which is critical -
     * this has to be evaluated and possibly revised.
     */
    for (uint i = 0; i < bufferSize; i++) {
      // stop if we fetched all the chunks of this content
      if (i >= content->getTotalChunks())
        continue;
      Flow* request = new Flow(content, user, time+i, i);
      scheduler->schedule(request);
    }
  }
}

void IPTVTopologyOracle::notifyEndRound(uint endingRound) {
  delete this->rankDist;
  this->rankDist = new boost::random::zipf_distribution<>(contentNum,
          (*shiftDist)(gen), (*expDist)(gen));
  delete this->relDayDist;
  this->relDayDist = new boost::random::zipf_distribution<>(7, 0, (*expDist)(gen));
}

void IPTVTopologyOracle::preCache() {
  bool isFull = false;
  uint i(0), day(0), index(0);
  ContentElement* content = nullptr;
  while (!isFull) {
    day = std::floor(i / dailyCatalog.at(0).size()); // all the same size
    if (day >= dailyCatalog.size())
      break;
    index = i % dailyCatalog.at(day).size();
    content = dailyCatalog.at(day).at(index);
    for (uint as = 0; as < topo->getNumASes(); as++) {
      if (localCacheMap->at(as).fitsInCache(content->getSize())) {
        auto chunks = content->getChunks();
        std::pair<bool, std::set<ChunkPtr> > result;
        for (auto j = chunks.begin(); j != chunks.end(); j++) {
          result = localCacheMap->at(as).addToCache(*j, (*j)->getSize(), 0);
          assert(result.first == true);
          assert(result.second.empty() == true);
          assert(localCacheMap->at(as).isCached(*j));
        }
      }
      else {
        isFull = true;
        break;
      }
    }
    i++;
  }
  BOOST_LOG_TRIVIAL(trace) << "cached " << i << " contents in AS caches";
}<commit_msg>when generating a new request I was not correctly updating the hightestChunkFetched field in the userWatchingInfo map entry, which was resulting in wrong chunks being fetched later on.<commit_after>#include "IPTVTopologyOracle.hpp"
#include "Scheduler.hpp"
#include "boost/random/discrete_distribution.hpp"
#include "boost/random/uniform_int.hpp"
#include "boost/random/normal_distribution.hpp"
#include "zipf_distribution.hpp"
#include <boost/lexical_cast.hpp>
#include <initializer_list>
#include <boost/random/mersenne_twister.hpp>

// random generator
extern boost::mt19937 gen;

IPTVTopologyOracle::IPTVTopologyOracle(Topology* topo, po::variables_map vm,
        uint roundDuration) : TopologyOracle(topo, vm, roundDuration) {
  this->contentNum = vm["contents"].as<uint>() * vm["channels"].as<uint>();
  double zmExp = vm["zm-exponent"].as<double>();
  this->shiftDist = new boost::random::uniform_int_distribution<>(0,50);
  this->expDist = new boost::random::uniform_real_distribution<>(0.4, zmExp);
  this->rankDist = new boost::random::zipf_distribution<>(contentNum,
          (*shiftDist)(gen), (*expDist)(gen));
  this->relDayDist = new boost::random::zipf_distribution<>(7, 0, (*expDist)(gen));
  // allocate memory for the dailyCatalog and initialize contentRateVec
  std::vector<double> dailyRank(contentNum, 0.0);
  contentRateVec.resize(7, dailyRank);
  for (uint i = 0; i < 7; i++) {
    std::vector<ContentElement*> vec(contentNum, nullptr);
    dailyCatalog.push_back(vec);
  }
}

IPTVTopologyOracle::~IPTVTopologyOracle() {
  BOOST_FOREACH(std::vector<ContentElement*> list, dailyCatalog) {
    BOOST_FOREACH(ContentElement* content, list) {
      delete content;
    }
    list.clear();
  }
  dailyCatalog.clear();
  userWatchMap.clear();
  delete this->relDayDist;
  delete this->rankDist;
  delete this->expDist;
  delete this->shiftDist;
}

void IPTVTopologyOracle::generateUserViewMap(Scheduler* scheduler) {
  BOOST_LOG_TRIVIAL(debug) << "entering generateUserViewMap";
  uint roundDuration = scheduler->getRoundDuration();
  double totalHours = 0, randomHours;
  boost::random::normal_distribution<> userSessionDist(avgHoursPerUser);
  boost::random::discrete_distribution<> hourDist(usrPctgByHour);
  boost::random::uniform_int_distribution<> minSecDist(0, 3599);
  // Generate a session start time and session length for each user
  SimTime sessionStart, sessionLength;

  BOOST_FOREACH(Vertex v, topo->getPonNodes()) {
    for (uint i = 0; i < topo->getPonCustomers(v); i++) {
      randomHours = userSessionDist(gen);
      // daily sessions can't be longer than a day, duh
      if (randomHours > 24)
        randomHours = 24;
      if (randomHours > 0)
        totalHours += randomHours;
      sessionLength = std::floor((randomHours * 3600) + 0.5);
      if (sessionLength <= 0) {
        BOOST_LOG_TRIVIAL(info) << "TopologyOracle::generateUserViewMap() - "
                  "non-positive sessionLength for user " << v << "," << i
                  << " - skipping it";
        continue;
      }
      /* the time we generate is assumed to be the middle point of the viewing
       * session, so we shift it of half sessionLength, but we need to ensure it
       * still fits inside the round
       */
      sessionStart = (hourDist(gen) * 3600 + minSecDist(gen)) -
              std::floor((sessionLength / 2) + 0.5);
      if (sessionStart < 0)
        sessionStart = 0;
      else if (sessionStart + sessionLength >= roundDuration)
        sessionStart = roundDuration - sessionLength;
      SimTimeInterval interval(sessionStart, sessionStart + sessionLength);
      PonUser user = std::make_pair(v,i);
      if (scheduler->getCurrentRound() == 0) {
        //first round, populate userWatchMap
        std::pair<PonUser, UserWatchingInfo> userWatchMapEntry = std::make_pair(user, UserWatchingInfo(interval));
        userWatchMap.insert(userWatchMapEntry);
      } else {
        // subsequent rounds, just store the new interval
        userWatchMap.at(user).dailySessionInterval = interval;
      }
      // generate first request and schedule it
      this->generateNewRequest(user, interval.getStart(), scheduler);
    }
  }
  BOOST_LOG_TRIVIAL(info) << "Total hours of scheduled viewing for the current day: "
          << totalHours << "; avg. hours per user: "
          << totalHours/(topo->getNumCustomers())
          << " (requested: " << avgHoursPerUser << ")";
}

void IPTVTopologyOracle::populateCatalog() {
  // normal distribution to generate content length in minutes
  boost::random::normal_distribution<> normDist(this->avgContentLength,
          this->devContentLength);
  Capacity size = 0;
  // generate content for the first day and the previous 6
  for (int day = -6; day < 1; day++) {
    for (uint i = 0; i < contentNum; i++) {
      size = std::ceil(normDist(gen) * 60 * this->bitrate);
      ContentElement* content = new ContentElement(
        boost::lexical_cast<string > ((day + 6) * contentNum + i), day, size,
              chunkSize);
      dailyCatalog[std::abs(day)].at(i) = content;
      auto chunks = content->getChunks();
      for (auto j = chunks.begin(); j != chunks.end(); j++)
        dailyRanking.at(std::abs(day)).insert(*j);
      this->addContent(content, 0);
      BOOST_LOG_TRIVIAL(debug) << "generated content " << content->getName();
    }
  }
}

void IPTVTopologyOracle::updateCatalog(uint currentRound) {
  // Update catalogue
  dailyRanking.at(6).clear();
  BOOST_FOREACH(ContentElement* content, dailyCatalog[6]) {
    this->removeContent(content, currentRound+1);
    delete content;
  }
  for (uint day = 6; day > 0; day--) {
    dailyCatalog[day] = dailyCatalog[day - 1];
    dailyRanking.at(day).resetRoundHits();
    dailyRanking.at(day) = dailyRanking.at(day-1);
  }
  dailyRanking.at(0).clear();
  // normal distribution to generate content length in minutes
  boost::random::normal_distribution<> normDist(this->avgContentLength,
          this->devContentLength);
  Capacity size = 0;
  for (uint i = 0; i < contentNum; i++) {
    size = std::ceil(normDist(gen) * 60 * this->bitrate);
    ContentElement* content = new ContentElement(
            boost::lexical_cast<string > ((currentRound + 7) * contentNum + i),
            currentRound + 1, size, chunkSize);
    dailyCatalog[0].at(i) = content;
    auto chunks = content->getChunks();
    for (auto j = chunks.begin(); j != chunks.end(); j++)
      dailyRanking.at(0).insert(*j);
    this->addContent(content, currentRound+1);
  }
}

/* selects a movie to be requested according to the popularity distributions,
 * determines how long the user is going to be watching it (because of zapping)
 * and stores the required information in the userWatchMap, then creates a new
 * Flow and schedules it.
 */
void IPTVTopologyOracle::generateNewRequest(PonUser user, SimTime time,
        Scheduler* scheduler) {
  SimTime sessionEnd = userWatchMap.at(user).dailySessionInterval.getEnd();
  if (time < sessionEnd) {
    boost::random::uniform_int_distribution<> indexDist(0, 17);
    uint i = (*relDayDist)(gen);
    ContentElement* content = dailyCatalog[i].at((*rankDist)(gen));
    Capacity reqLength = sessionLength[indexDist(gen)] * content->getSize();
    /* calculate the time at which the user will be done with this content */
    SimTime endTime = time + std::ceil(reqLength / this->bitrate);
    // check that the new request would not go past the desired session
    // length; this will make all requests past midnight end at midnight :(
    if (endTime > sessionEnd) {
      // new reqLength can't be less than 1 second worth of traffic
      endTime = std::max(time + 1, sessionEnd);
    }
    UserWatchingMap::iterator wIt = userWatchMap.find(user);
    assert (wIt != userWatchMap.end());
    wIt->second.content = content;
    wIt->second.watchingEndTime = endTime;
    // we are waiting for the first chunk to be downloaded
    wIt->second.waiting = true;
    /* Request enough chunks to fill the buffer.
     */
    for (uint i = 0; i < bufferSize; i++) {
      // stop if we fetched all the chunks of this content
      if (i >= content->getTotalChunks())
        continue;
      Flow* request = new Flow(content, user, time, i);
      scheduler->schedule(request);
      wIt->second.highestChunkFetched = i;
    }
    BOOST_LOG_TRIVIAL(debug) << "generated request from user " << user.first
            << "," << user.second << " for content " << content->getName();
  }
}

void IPTVTopologyOracle::notifyEndRound(uint endingRound) {
  delete this->rankDist;
  this->rankDist = new boost::random::zipf_distribution<>(contentNum,
          (*shiftDist)(gen), (*expDist)(gen));
  delete this->relDayDist;
  this->relDayDist = new boost::random::zipf_distribution<>(7, 0, (*expDist)(gen));
}

void IPTVTopologyOracle::preCache() {
  bool isFull = false;
  uint i(0), day(0), index(0);
  ContentElement* content = nullptr;
  while (!isFull) {
    day = std::floor(i / dailyCatalog.at(0).size()); // all the same size
    if (day >= dailyCatalog.size())
      break;
    index = i % dailyCatalog.at(day).size();
    content = dailyCatalog.at(day).at(index);
    for (uint as = 0; as < topo->getNumASes(); as++) {
      if (localCacheMap->at(as).fitsInCache(content->getSize())) {
        auto chunks = content->getChunks();
        std::pair<bool, std::set<ChunkPtr> > result;
        for (auto j = chunks.begin(); j != chunks.end(); j++) {
          result = localCacheMap->at(as).addToCache(*j, (*j)->getSize(), 0);
          assert(result.first == true);
          assert(result.second.empty() == true);
          assert(localCacheMap->at(as).isCached(*j));
        }
      }
      else {
        isFull = true;
        break;
      }
    }
    i++;
  }
  BOOST_LOG_TRIVIAL(trace) << "cached " << i << " contents in AS caches";
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 University of Szeged
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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.
 */

#include "config.h"

#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)

#include "MacroAssemblerARM.h"

#if OS(LINUX)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
#include <asm/hwcap.h>
#endif

namespace JSC {

static bool isVFPPresent()
{
#if OS(LINUX)
    int fd = open("/proc/self/auxv", O_RDONLY);
    if (fd > 0) {
        Elf32_auxv_t aux;
        while (read(fd, &aux, sizeof(Elf32_auxv_t))) {
            if (aux.a_type == AT_HWCAP) {
                close(fd);
                return aux.a_un.a_val & HWCAP_VFP;
            }
        }
        close(fd);
    }
#endif

#if (COMPILER(RVCT) && defined(__TARGET_FPU_VFP)) || (COMPILER(GCC) && defined(__VFP_FP__))
    return true;
#else
    return false;
#endif
}

const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent();

#if CPU(ARMV5_OR_LOWER)
/* On ARMv5 and below, natural alignment is required. */
void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
{
    ARMWord op2;

    ASSERT(address.scale >= 0 && address.scale <= 3);
    op2 = m_assembler.lsl(address.index, static_cast<int>(address.scale));

    if (address.offset >= 0 && address.offset + 0x2 <= 0xff) {
        m_assembler.add(ARMRegisters::S0, address.base, op2);
        m_assembler.halfDtrUp(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset));
        m_assembler.halfDtrUp(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset + 0x2));
    } else if (address.offset < 0 && address.offset >= -0xff) {
        m_assembler.add(ARMRegisters::S0, address.base, op2);
        m_assembler.halfDtrDown(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset));
        m_assembler.halfDtrDown(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset - 0x2));
    } else {
        m_assembler.moveImm(address.offset, ARMRegisters::S0);
        m_assembler.add(ARMRegisters::S0, ARMRegisters::S0, op2);
        m_assembler.halfDtrUpRegister(ARMAssembler::LoadUint16, dest, address.base, ARMRegisters::S0);
        m_assembler.add(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::Op2Immediate | 0x2);
        m_assembler.halfDtrUpRegister(ARMAssembler::LoadUint16, ARMRegisters::S0, address.base, ARMRegisters::S0);
    }
    m_assembler.orr(dest, dest, m_assembler.lsl(ARMRegisters::S0, 16));
}
#endif

}

#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
<commit_msg>Fix build on Android (part 2)<commit_after>/*
 * Copyright (C) 2009 University of Szeged
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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.
 */

#include "config.h"

#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)

#include "MacroAssemblerARM.h"

#if OS(LINUX)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
#define HWCAP_VFP·      (1 << 6)
#endif

namespace JSC {

static bool isVFPPresent()
{
#if OS(LINUX)
    int fd = open("/proc/self/auxv", O_RDONLY);
    if (fd > 0) {
        Elf32_auxv_t aux;
        while (read(fd, &aux, sizeof(Elf32_auxv_t))) {
            if (aux.a_type == AT_HWCAP) {
                close(fd);
                return aux.a_un.a_val & HWCAP_VFP;
            }
        }
        close(fd);
    }
#endif

#if (COMPILER(RVCT) && defined(__TARGET_FPU_VFP)) || (COMPILER(GCC) && defined(__VFP_FP__))
    return true;
#else
    return false;
#endif
}

const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent();

#if CPU(ARMV5_OR_LOWER)
/* On ARMv5 and below, natural alignment is required. */
void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
{
    ARMWord op2;

    ASSERT(address.scale >= 0 && address.scale <= 3);
    op2 = m_assembler.lsl(address.index, static_cast<int>(address.scale));

    if (address.offset >= 0 && address.offset + 0x2 <= 0xff) {
        m_assembler.add(ARMRegisters::S0, address.base, op2);
        m_assembler.halfDtrUp(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset));
        m_assembler.halfDtrUp(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(address.offset + 0x2));
    } else if (address.offset < 0 && address.offset >= -0xff) {
        m_assembler.add(ARMRegisters::S0, address.base, op2);
        m_assembler.halfDtrDown(ARMAssembler::LoadUint16, dest, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset));
        m_assembler.halfDtrDown(ARMAssembler::LoadUint16, ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Half(-address.offset - 0x2));
    } else {
        m_assembler.moveImm(address.offset, ARMRegisters::S0);
        m_assembler.add(ARMRegisters::S0, ARMRegisters::S0, op2);
        m_assembler.halfDtrUpRegister(ARMAssembler::LoadUint16, dest, address.base, ARMRegisters::S0);
        m_assembler.add(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::Op2Immediate | 0x2);
        m_assembler.halfDtrUpRegister(ARMAssembler::LoadUint16, ARMRegisters::S0, address.base, ARMRegisters::S0);
    }
    m_assembler.orr(dest, dest, m_assembler.lsl(ARMRegisters::S0, 16));
}
#endif

}

#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
<|endoftext|>


<commit_before>#include "pixelboost/debug/assert.h"
#include "pixelboost/logic/entity.h"
#include "pixelboost/logic/message/update.h"
#include "pixelboost/logic/scene.h"
#include "pixelboost/logic/system.h"
#include "pixelboost/scripting/lua.h"

using namespace pb;

Scene::Scene()
{
    _NextFreeUid = (1<<24) + 1;
}

Scene::~Scene()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        Entity* entity = it->second;
        it->second = 0;
        delete entity;
    }

    for (EntityMap::iterator it = _NewEntities.begin(); it != _NewEntities.end(); ++it)
    {
        Entity* entity = it->second;
        it->second = 0;
        delete entity;
    }

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        delete it->second;
    }
}

void Scene::RegisterLuaClass(lua_State* state)
{
    luabridge::getGlobalNamespace(state)
    .beginNamespace("pb")
        .beginClass<Scene>("Scene")
        .endClass()
    .endNamespace();
}

void Scene::Update(float timeDelta, float gameDelta)
{
    for (EntitySet::iterator it = _PurgeSet.begin(); it != _PurgeSet.end(); ++it)
    {
        (*it)->Purge();
    }
    _PurgeSet.clear();

    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end();)
    {
        if (it->second->GetState() == Entity::kEntityDestroyed)
        {
            delete it->second;
            _PurgeSet.erase(it->second);
            _Entities.erase(it++);
        } else {
            ++it;
        }
    }

    for (EntityMap::iterator it = _NewEntities.begin(); it != _NewEntities.end(); ++it)
    {
        PbAssert(_Entities.find(it->first) == _Entities.end());

        _Entities[it->first] = it->second;
    }
    _NewEntities.clear();

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Update(this, timeDelta, gameDelta);
    }

    BroadcastMessage(UpdateMessage(timeDelta, gameDelta));
    BroadcastMessage(PostUpdateMessage());
}

void Scene::Render(Viewport* viewport, RenderPass renderPass)
{
    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Render(this, viewport, renderPass);
    }
}

bool Scene::AddSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
        return false;

    _Systems[system->GetType()] = system;

    return true;
}

void Scene::RemoveSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
    {
        _Systems.erase(it);
    }
}

pb::Uid Scene::GenerateEntityId()
{
    return _NextFreeUid++;
}

void Scene::AddEntity(Entity* entity)
{
    PbAssert(_NewEntities.find(entity->GetUid()) == _NewEntities.end());

    _NewEntities[entity->GetUid()] = entity;
}

void Scene::AddEntityPurge(Entity* entity)
{
    _PurgeSet.insert(entity);
}

void Scene::DestroyEntity(Entity* entity)
{
    entity->Destroy();
}

void Scene::DestroyAllEntities()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        it->second->Destroy();
    }
}

Entity* Scene::GetEntityById(Uid uid)
{
    EntityMap::iterator it = _Entities.find(uid);

    if (it != _Entities.end())
        return it->second;

    it = _NewEntities.find(uid);

    if (it != _NewEntities.end())
        return it->second;

    return 0;
}

const Scene::EntityMap& Scene::GetEntities() const
{
    return _Entities;
}

void Scene::BroadcastMessage(const Message& message)
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        if (it->second->GetState() != Entity::kEntityDestroyed)
            it->second->SendMessage(message);
    }

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->HandleMessage(this, message);
    }
}

void Scene::SendMessage(Uid uid, const Message& message)
{
    Entity* entity = GetEntityById(uid);

    if (entity && entity->GetState() != Entity::kEntityDestroyed)
        entity->SendMessage(message);
}
<commit_msg>Allow passing null into DestroyEntity<commit_after>#include "pixelboost/debug/assert.h"
#include "pixelboost/logic/entity.h"
#include "pixelboost/logic/message/update.h"
#include "pixelboost/logic/scene.h"
#include "pixelboost/logic/system.h"
#include "pixelboost/scripting/lua.h"

using namespace pb;

Scene::Scene()
{
    _NextFreeUid = (1<<24) + 1;
}

Scene::~Scene()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        Entity* entity = it->second;
        it->second = 0;
        delete entity;
    }

    for (EntityMap::iterator it = _NewEntities.begin(); it != _NewEntities.end(); ++it)
    {
        Entity* entity = it->second;
        it->second = 0;
        delete entity;
    }

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        delete it->second;
    }
}

void Scene::RegisterLuaClass(lua_State* state)
{
    luabridge::getGlobalNamespace(state)
    .beginNamespace("pb")
        .beginClass<Scene>("Scene")
        .endClass()
    .endNamespace();
}

void Scene::Update(float timeDelta, float gameDelta)
{
    for (EntitySet::iterator it = _PurgeSet.begin(); it != _PurgeSet.end(); ++it)
    {
        (*it)->Purge();
    }
    _PurgeSet.clear();

    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end();)
    {
        if (it->second->GetState() == Entity::kEntityDestroyed)
        {
            delete it->second;
            _PurgeSet.erase(it->second);
            _Entities.erase(it++);
        } else {
            ++it;
        }
    }

    for (EntityMap::iterator it = _NewEntities.begin(); it != _NewEntities.end(); ++it)
    {
        PbAssert(_Entities.find(it->first) == _Entities.end());

        _Entities[it->first] = it->second;
    }
    _NewEntities.clear();

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Update(this, timeDelta, gameDelta);
    }

    BroadcastMessage(UpdateMessage(timeDelta, gameDelta));
    BroadcastMessage(PostUpdateMessage());
}

void Scene::Render(Viewport* viewport, RenderPass renderPass)
{
    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->Render(this, viewport, renderPass);
    }
}

bool Scene::AddSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
        return false;

    _Systems[system->GetType()] = system;

    return true;
}

void Scene::RemoveSystem(SceneSystem* system)
{
    SystemMap::iterator it = _Systems.find(system->GetType());

    if (it != _Systems.end())
    {
        _Systems.erase(it);
    }
}

pb::Uid Scene::GenerateEntityId()
{
    return _NextFreeUid++;
}

void Scene::AddEntity(Entity* entity)
{
    PbAssert(_NewEntities.find(entity->GetUid()) == _NewEntities.end());

    _NewEntities[entity->GetUid()] = entity;
}

void Scene::AddEntityPurge(Entity* entity)
{
    _PurgeSet.insert(entity);
}

void Scene::DestroyEntity(Entity* entity)
{
    if (entity)
    {
        entity->Destroy();
    }
}

void Scene::DestroyAllEntities()
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        it->second->Destroy();
    }
}

Entity* Scene::GetEntityById(Uid uid)
{
    EntityMap::iterator it = _Entities.find(uid);

    if (it != _Entities.end())
        return it->second;

    it = _NewEntities.find(uid);

    if (it != _NewEntities.end())
        return it->second;

    return 0;
}

const Scene::EntityMap& Scene::GetEntities() const
{
    return _Entities;
}

void Scene::BroadcastMessage(const Message& message)
{
    for (EntityMap::iterator it = _Entities.begin(); it != _Entities.end(); ++it)
    {
        if (it->second->GetState() != Entity::kEntityDestroyed)
            it->second->SendMessage(message);
    }

    for (SystemMap::iterator it = _Systems.begin(); it != _Systems.end(); ++it)
    {
        it->second->HandleMessage(this, message);
    }
}

void Scene::SendMessage(Uid uid, const Message& message)
{
    Entity* entity = GetEntityById(uid);

    if (entity && entity->GetState() != Entity::kEntityDestroyed)
        entity->SendMessage(message);
}
<|endoftext|>


<commit_before>#include <fstream>
#include "halley/resources/resource_data.h"
#include "halley/resources/metadata.h"
#include "halley/support/exception.h"
#include <halley/concurrency/concurrent.h>
#include "halley/file/compression.h"

using namespace Halley;

ResourceData::ResourceData(String p)
	: path(p)
{
}

ResourceDataStatic::ResourceDataStatic(String path)
	: ResourceData(path)
	, loaded(false)
{
}

ResourceDataStatic::ResourceDataStatic(const void* _data, size_t _size, String path, bool owning)
	: ResourceData(path)
	, loaded(false)
{
	set(_data, _size, owning);
}

static void deleter(const char* data)
{
	delete[] data;
}

static void noOpDeleter(const char*)
{
}

void ResourceDataStatic::set(const void* _data, size_t _size, bool owning)
{
	data = std::shared_ptr<const char>(static_cast<const char*>(_data), owning ? deleter : noOpDeleter);
	size = _size;
	loaded = true;
}

const void* ResourceDataStatic::getData() const
{
	if (!loaded) throw Exception("Resource data not yet loaded");
	return data.get();
}

gsl::span<const gsl::byte> ResourceDataStatic::getSpan() const
{
	return gsl::span<const gsl::byte>(reinterpret_cast<const gsl::byte*>(getData()), getSize());
}

size_t ResourceDataStatic::getSize() const
{
	if (!loaded) throw Exception("Resource data not yet loaded");
	return size;
}

bool ResourceDataStatic::isLoaded() const
{
	return loaded;
}

String ResourceDataStatic::getString() const
{
	return String(static_cast<const char*>(getData()), getSize());
}

void ResourceDataStatic::inflate()
{
	std::cout << "Inflating...\n";
	data = Compression::inflateRaw(getSpan(), size);
}

std::unique_ptr<ResourceDataStatic> ResourceDataStatic::loadFromFileSystem(Path path)
{
	std::ifstream fp(path.string(), std::ios::binary | std::ios::in);
	fp.seekg(0, std::ios::end);
	size_t size = fp.tellg();
	fp.seekg(0, std::ios::beg);
	char* buffer = new char[size]; // ResourceDataStatic will own this
	try {
		fp.read(buffer, size);
		fp.close();
		return std::make_unique<ResourceDataStatic>(buffer, size, path.string());
	} catch (...) {
		delete[] buffer; // ...unless it fails, so delete it before re-throwing error
		throw;
	}
}

void ResourceDataStatic::writeToFileSystem(String filePath) const
{
	std::ofstream fp(filePath, std::ios::binary | std::ios::out);
	fp.write(data.get(), size);
	fp.close();
}

ResourceDataStream::ResourceDataStream(String path, ResourceDataMakeReader makeReader)
	: ResourceData(path)
	, make(makeReader)
{
}

ResourceLoader::ResourceLoader(ResourceLoader&& loader) noexcept
	: locator(loader.locator)
	, name(std::move(loader.name))
	, priority(loader.priority)
	, api(loader.api)
{
}

ResourceLoader::~ResourceLoader()
{
}

ResourceLoader::ResourceLoader(IResourceLocator& locator, const String& name, AssetType type, ResourceLoadPriority priority, HalleyAPI* api)
	: locator(locator)
	, name(name)
	, type(type)
	, priority(priority)
	, api(api)
{
	metadata = &locator.getMetaData(name, type);
}

std::unique_ptr<ResourceDataStatic> ResourceLoader::getStatic()
{
	auto result = locator.getStatic(name, type);
	if (result) {
		if (metadata->getString("asset_compression", "") == "deflate") {
			result->inflate();
		}
		loaded = true;
	}
	return result;
}

std::unique_ptr<ResourceDataStream> ResourceLoader::getStream()
{
	auto result = locator.getStream(name, type);
	if (result) {
		loaded = true;
	}
	return result;
}

Future<std::unique_ptr<ResourceDataStatic>> ResourceLoader::getAsync() const
{
	std::reference_wrapper<IResourceLocator> loc = locator;
	auto n = name;
	auto t = type;
	auto meta = getMeta();
	return Concurrent::execute(Executors::getDiskIO(), [meta, loc, n, t] () -> std::unique_ptr<ResourceDataStatic>
	{
		auto result = loc.get().getStatic(n, t);
		if (meta.getString("asset_compression", "") == "deflate") {
			result->inflate();
		}
		return result;
	});
}
<commit_msg>Remove debug message.<commit_after>#include <fstream>
#include "halley/resources/resource_data.h"
#include "halley/resources/metadata.h"
#include "halley/support/exception.h"
#include <halley/concurrency/concurrent.h>
#include "halley/file/compression.h"

using namespace Halley;

ResourceData::ResourceData(String p)
	: path(p)
{
}

ResourceDataStatic::ResourceDataStatic(String path)
	: ResourceData(path)
	, loaded(false)
{
}

ResourceDataStatic::ResourceDataStatic(const void* _data, size_t _size, String path, bool owning)
	: ResourceData(path)
	, loaded(false)
{
	set(_data, _size, owning);
}

static void deleter(const char* data)
{
	delete[] data;
}

static void noOpDeleter(const char*)
{
}

void ResourceDataStatic::set(const void* _data, size_t _size, bool owning)
{
	data = std::shared_ptr<const char>(static_cast<const char*>(_data), owning ? deleter : noOpDeleter);
	size = _size;
	loaded = true;
}

const void* ResourceDataStatic::getData() const
{
	if (!loaded) throw Exception("Resource data not yet loaded");
	return data.get();
}

gsl::span<const gsl::byte> ResourceDataStatic::getSpan() const
{
	return gsl::span<const gsl::byte>(reinterpret_cast<const gsl::byte*>(getData()), getSize());
}

size_t ResourceDataStatic::getSize() const
{
	if (!loaded) throw Exception("Resource data not yet loaded");
	return size;
}

bool ResourceDataStatic::isLoaded() const
{
	return loaded;
}

String ResourceDataStatic::getString() const
{
	return String(static_cast<const char*>(getData()), getSize());
}

void ResourceDataStatic::inflate()
{
	data = Compression::inflateRaw(getSpan(), size);
}

std::unique_ptr<ResourceDataStatic> ResourceDataStatic::loadFromFileSystem(Path path)
{
	std::ifstream fp(path.string(), std::ios::binary | std::ios::in);
	fp.seekg(0, std::ios::end);
	size_t size = fp.tellg();
	fp.seekg(0, std::ios::beg);
	char* buffer = new char[size]; // ResourceDataStatic will own this
	try {
		fp.read(buffer, size);
		fp.close();
		return std::make_unique<ResourceDataStatic>(buffer, size, path.string());
	} catch (...) {
		delete[] buffer; // ...unless it fails, so delete it before re-throwing error
		throw;
	}
}

void ResourceDataStatic::writeToFileSystem(String filePath) const
{
	std::ofstream fp(filePath, std::ios::binary | std::ios::out);
	fp.write(data.get(), size);
	fp.close();
}

ResourceDataStream::ResourceDataStream(String path, ResourceDataMakeReader makeReader)
	: ResourceData(path)
	, make(makeReader)
{
}

ResourceLoader::ResourceLoader(ResourceLoader&& loader) noexcept
	: locator(loader.locator)
	, name(std::move(loader.name))
	, priority(loader.priority)
	, api(loader.api)
{
}

ResourceLoader::~ResourceLoader()
{
}

ResourceLoader::ResourceLoader(IResourceLocator& locator, const String& name, AssetType type, ResourceLoadPriority priority, HalleyAPI* api)
	: locator(locator)
	, name(name)
	, type(type)
	, priority(priority)
	, api(api)
{
	metadata = &locator.getMetaData(name, type);
}

std::unique_ptr<ResourceDataStatic> ResourceLoader::getStatic()
{
	auto result = locator.getStatic(name, type);
	if (result) {
		if (metadata->getString("asset_compression", "") == "deflate") {
			result->inflate();
		}
		loaded = true;
	}
	return result;
}

std::unique_ptr<ResourceDataStream> ResourceLoader::getStream()
{
	auto result = locator.getStream(name, type);
	if (result) {
		loaded = true;
	}
	return result;
}

Future<std::unique_ptr<ResourceDataStatic>> ResourceLoader::getAsync() const
{
	std::reference_wrapper<IResourceLocator> loc = locator;
	auto n = name;
	auto t = type;
	auto meta = getMeta();
	return Concurrent::execute(Executors::getDiskIO(), [meta, loc, n, t] () -> std::unique_ptr<ResourceDataStatic>
	{
		auto result = loc.get().getStatic(n, t);
		if (meta.getString("asset_compression", "") == "deflate") {
			result->inflate();
		}
		return result;
	});
}
<|endoftext|>


<commit_before>/*
 * CReader.cpp
 * save laser data to binary file
 *
 * Created on: 22.12.2014
 * Author: Markus
*/
#include <iostream>
#include <string>
#include "CReader.h"
#include <sstream>
#include <fstream>
#include <stdint.h>
#include <unistd.h>
#include <math.h>
#include <list>

#include <octomap/octomap.h>
#include <octomap/OcTree.h>
#include <octomap/Pointcloud.h>
#include "time.h"
#include "ip_connection.h"
#include "brick_imu.h"

#include <boost/chrono/thread_clock.hpp>

using namespace boost::chrono;

//
#define PI 3.14159265

#define CONFIG "/media/usb0/config.cfg"
#define HOST "localhost"
#define PORT 4223

#define DEBUG 1

std::fstream logfile;

boost::mutex mtx_da;

int data_av = 0;
bool is_imu_connected;

using std::string;
using namespace octomap;

IPConnection ipcon;
IMU imu;

// trim a string
const std::string trim( const std::string& s)
{
	std::string::size_type first = s.find_first_not_of( ' ');
	if( first == std::string::npos) {
		return std::string();
	}
	else {
		std::string::size_type last = s.find_last_not_of( ' '); /// must succeed
		return s.substr( first, last - first + 1);
	}
}

void debugMessage(int level, string message)
{
	if (level >= DEBUG)
		std::cerr << message << std::endl;
	return;
}

// constructor
CReader::CReader()
{
	scancycles = 0;
	is_imu_connected = false;

	ip_adress = "192.168.0.1";
	port = 12002;
	convergence = 0;

	// set angle filter
	angle_max = 0*PI/180; // scanner max 50
	angle_min = -60*PI/180; // scanner min -60

	maxmin = false;
	duration = false;
	writebt = false;
	writecsv = false;
	is_indoor = false;

	if (readConfig())
		debugMessage(2,"config successfully readed!");
	else
		debugMessage(2, "no config file!");

	return;
}

// read config file
int CReader::readConfig()
{
	std::ifstream fh;
	std::string line;
	size_t pos = 0;
	std::string key, val;

	fh.open(CONFIG, std::ios::in);

	if (!fh.is_open()) {
		fh.open("config.cfg", std::ios::in);
		if (!fh.is_open()) {
			return FALSE;
		}
	}

	debugMessage(2, "read config...");

	while (getline(fh,line)) {
		pos = line.find("=");
		key = trim(line.substr(0,pos));
		val = trim(line.substr(pos+1));

		try {
			if (key.compare("ip") == 0) {
				ip_adress = val;
			} else if (key.compare("port") == 0) {
				port = atoi(val.c_str());
			} else if (key.compare("maxmin") == 0) {
				if (val.compare("true") == 0)
					maxmin = true;
				else
					maxmin = false;
			} else if (key.compare("writebt") == 0) {
				if (val.compare("true") == 0)
					writebt = true;
			} else if (key.compare("btpath") == 0) {
				bt_path = val;
			} else if (key.compare("convergence") == 0) {
				convergence = atoi(val.c_str());
			} else if (key.compare("location") == 0) {
				if (val.compare("indoor") == 0) {
					is_indoor = true;
				}
			} else if (key.compare("writecsv") == 0) {
				if (val.compare("true") == 0) {
					writecsv = true;
				}
			} else if (key.compare("minangle") == 0) {
				angle_min = atoi(val.c_str())*PI/180.0;
			} else if (key.compare("maxangle") == 0) {
				angle_max = atoi(val.c_str())*PI/180.0;
			}

		} catch (...) {
			std::cout << "unkown parameter:" << key << std::endl;
		}
	}

	fh.close();

	return TRUE;
}

CReader::~CReader()
{
	// release sensor
	mtx_da.lock();
	releaseSensor();
	mtx_da.unlock();

	usleep(200);

	// turn off imu leds
	imu_leds_off(&imu);

	// release ipcon
	imu_set_quaternion_period(&imu, 0);
	imu_set_angular_velocity_period(&imu, 0);
	imu_destroy(&imu);
	ipcon_destroy(&ipcon); // Calls ipcon_disconnect internally
}

// TINKERFORGE

void cb_connected(uint8_t connect_reason, void *user_data)
{
    // ...then trigger enumerate
    ipcon_enumerate(&ipcon);
}

int imu_cb = 0;
double yaw = 0, pitch = 0, roll = 0;

void cb_angular_velocity(int16_t x, int16_t y, int16_t z, void *user_data)
{
	if (abs(x) > 3 || abs(y) || abs(z)) {
		imu_set_convergence_speed(&imu, 30);
	} else {
		imu_set_convergence_speed(&imu, 0);
	}
}

// print incoming enumeration information
void cb_enumerate(const char *uid, const char *connected_uid,
                  char position, uint8_t hardware_version[3],
                  uint8_t firmware_version[3], uint16_t device_identifier,
                  uint8_t enumeration_type, void *user_data)
{
    int is_indoor = *(int*)user_data;

    if(enumeration_type == IPCON_ENUMERATION_TYPE_DISCONNECTED) {
        printf("\n");
        return;
    }

    // check if device is an imu
    if(device_identifier == IMU_DEVICE_IDENTIFIER) {

		std::cout << "Found IMU with UID:" << uid << std::endl;

		if (is_imu_connected) {
			std::cout << "Es ist bereits eine IMU verbunden!" << std::endl;
			return;
		}

		imu_create(&imu, uid, &ipcon);

		imu_set_convergence_speed(&imu,60);

		if (!is_indoor) {

			imu_set_angular_velocity_period(&imu, 10);

			imu_register_callback(&imu,
								IMU_CALLBACK_ANGULAR_VELOCITY,
								(void *)cb_angular_velocity,
								NULL);
		}

		imu_leds_off(&imu);
		is_imu_connected = true;
	}
}

int CReader::init()
{
	// set bounding box filter
	bb_x_max = 70.0;
	bb_x_min = 0.0;
	bb_y_max = 200.0;
	bb_y_min = -200.0;

	// activate both filter
	filter_angle = true;
	filter_bbox = true;

	// init tinkerforge ------------------------------------------------
	// create IP connection

    ipcon_create(&ipcon);

    // Connect to brickd
    if(ipcon_connect(&ipcon, HOST, PORT) < 0) {
		std::cout << "Could not connect to brickd!" << std::endl;
        return false;
    }

	// Register connected callback to "cb_connected"
    ipcon_register_callback(&ipcon,
                            IPCON_CALLBACK_CONNECTED,
                            (void *)cb_connected,
                            &ipcon);

    // Register enumeration callback to "cb_enumerate"
    ipcon_register_callback(&ipcon,
                            IPCON_CALLBACK_ENUMERATE,
                            (void*)cb_enumerate,
                            &is_indoor);

	ipcon_enumerate(&ipcon);
	// sleep
	usleep(7000000);

	// check if imu is connected
	if (!is_imu_connected) {
		std::cout << "Keine Verbindung zur IMU!" << std::endl;
		return false;
	}

	// set convergence after initial stage
	imu_set_convergence_speed(&imu,convergence);

	usleep(50000);

	logfile.open("bin/rawdata.bin", std::ios::out | std::ios::trunc);
	logfile.close();

	logfile.open("bin/rawdata.bin", std::ios::app | std::ios::binary | std::ios::out);

	// init sensor
	if(!initSensor()) {
		std::cout << "Keine Verbindung zum Laserscanner!" << std::endl;
		return false;
	}

	imu_leds_on(&imu);

	return true;
}

int CReader::initSensor()
{
	if (!ibeo::ibeoLUX::IbeoLUX::getInstance()) {
		ibeo::ibeoLUX::IbeoLUX::initInstance(this->ip_adress, this->port, 1);
		std::cout << "Sensor searching..." << std::endl;

		laserscanner = ibeo::ibeoLUX::IbeoLUX::getInstance();

		try {
			laserscanner->connect();
			laserscanner->startMeasuring();
		} catch (...) {
			std::cout << "Sensor not found" << std::endl;
			return false;
		}
	}

	if (laserscanner->getConnectionStatus()) {
		std::cout << "Sensor connected" << std::endl;
	} else {
		return false;
	}

	if (!laserscanner->getMeasuringStatus())
		return false;

	laserscanner->ibeoLaserDataAvailable.connect(boost::bind(&CReader::newLaserData, this, _1));

	return true;
}
float xAngle, yAngle, zAngle;
void CReader::storeImuData()
{
	float x, y, z, w;
	//float x1 = 0.0, y1 = 0.0, z1 = 0.0, w1 = 0.0;

	imu_get_quaternion(&imu, &x, &y, &z, &w);

	/*
	// get avg of imu data
	for (int i = 0 ; i < 5 ; i++) {
		imu_get_quaternion(&imu, &x, &y, &z, &w);
		x1 += x;
		y1 += y;
		z1 += z;
		w1 += w;
		usleep(250);
	}
	x = x1 / 5;
	y = y1 / 5;
	z = z1 / 5;
	w = w1 / 5;
	*/
	// use octomath to calc quaternion
	// y, z, x
	octomath::Quaternion q(w,x,y,z);
	octomath::Vector3 v(0.0,0.0,0.0);
	octomath::Pose6D pp(v, q);

	xAngle = pp.roll();
	yAngle = pp.pitch();
	zAngle = pp.yaw()*-1; // invert to correct mirroring

	return;
}

float xmax  = 0.0, xmin  = 0.0, ymax  = 0.0, ymin = 0.0, zmax = 0.0, zmin = 0.0;

void CReader::newLaserData(ibeo::ibeoLaserDataAbstractSmartPtr dat)
{
	mtx_da.lock();

	unsigned char *scanPointRaw = NULL;
	unsigned int scanpoints = dat->getNumberOfScanpoints();
	//unsigned short scannumber = dat->getScannumber();
	short int angleTicksPerRotation = dat->getAngleTicksPerRotation();
	//ibeo::IbeoLaserScanpoint *scanPt;
	//thread_clock::time_point start = thread_clock::now();

	// get IMU data
	storeImuData();

	logfile.write(reinterpret_cast<const char*>(&scanpoints), sizeof(scanpoints));
	logfile.write(reinterpret_cast<const char*>(&xAngle), sizeof(xAngle));
	logfile.write(reinterpret_cast<const char*>(&yAngle), sizeof(yAngle));
	logfile.write(reinterpret_cast<const char*>(&zAngle), sizeof(zAngle));
	logfile.write(reinterpret_cast<const char*>(&angleTicksPerRotation), sizeof(angleTicksPerRotation));

	//std::cout << "NODE " << xAngle << " " << yAngle << " " << zAngle << std::endl;

	for (unsigned int i = 0; i < scanpoints ; i++) {

		scanPointRaw = dat->getScanPointRawAt(i);

		logfile.write((const char*)scanPointRaw,8);

		//scanPt = dat->getScanPointAt(i);
		//float xraw = scanPt->getXValue();
		//float yraw = scanPt->getYValue();
		//float zraw = scanPt->getZValue();
		//std::cout << xraw << " " << yraw << " " << zraw << std::endl;

		/*
		if (i == 128) {
			logfile.close();
			mtx_da.unlock();
			releaseSensor();
			exit(0);
		}*/
	}

	data_av = 1;

	// calc delay
	//thread_clock::time_point stop = thread_clock::now();

	//printf("Timestamp: %llu ", timestamp);
	//printf("| Scanpoints: %d", scanpoints);
	//printf("| Scannumber: %hu", scannumber);
	//printf("| Time elapsed: %ld ms \n", duration_cast<milliseconds>(stop - start).count());

	//releaseSensor();

	mtx_da.unlock();

	return;
}

// get octomap data for lds server
int CReader::getOctomap(std::stringstream& buff)
{

	return 0;

}

int CReader::writeDataBT()
{

	return 0;
}

void CReader::releaseSensor()
{
	// stop laserscanner
	laserscanner->stopMeasuring();
	usleep(1000);
	laserscanner->releaseInstance();

	return;
}

// get cpu load
int CReader::getCPULoad()
{
	int fd = 0;
	char buff[1024];
	float load;

	fd = open("/proc/loadavg", O_RDONLY);
	if (fd < 0)
		return -1;
	read(fd,buff,sizeof(buff)-1);
	sscanf(buff, "%f", &load);
	close(fd);

	return (int)(load*100);
}

// get ram load
int CReader::getRAMLoad(int* total, int* free)
{
	FILE* fp = NULL;
	char buff[256];
	char name[100], unit[16];

	if ((fp = fopen("/proc/meminfo","r")) == NULL) {
		perror("no file meminfo!");
		return 0;
	}

	fgets(buff, sizeof(buff), fp);
	sscanf(buff, "%s %d %s\n", name, total, unit);

	fgets(buff, sizeof(buff), fp);
	sscanf(buff, "%s %d %s\n", name, free, unit);

	//std::cout << "Total:" << *total << " Kb" << std::endl;
	//std::cout << "Free:"  << *free  << " Kb" <<  std::endl;
	//std::cout << "InUse:" << ((*total-*free)/1024) << " Mb"  << std::endl;

	fclose(fp);
	return 1;
}
<commit_msg>clean up<commit_after>/*
 * CReader.cpp
 * save laser data to binary file
 *
 * Created on: 22.12.2014
 * Author: Markus
*/
#include <iostream>
#include <string>
#include "CReader.h"
#include <sstream>
#include <fstream>
#include <stdint.h>
#include <unistd.h>
#include <math.h>
#include <list>

#include <octomap/octomap.h>
#include <octomap/OcTree.h>
#include <octomap/Pointcloud.h>
#include "time.h"
#include "ip_connection.h"
#include "brick_imu.h"

#include <boost/chrono/thread_clock.hpp>

using namespace boost::chrono;

//
#define PI 3.14159265

#define CONFIG "/media/usb0/config.cfg"
#define HOST "localhost"
#define PORT 4223

#define DEBUG 1

std::fstream logfile;

boost::mutex mtx_da;

int data_av = 0;
bool is_imu_connected;

using std::string;
using namespace octomap;

IPConnection ipcon;
IMU imu;

// trim a string
const std::string trim( const std::string& s)
{
	std::string::size_type first = s.find_first_not_of( ' ');
	if( first == std::string::npos) {
		return std::string();
	}
	else {
		std::string::size_type last = s.find_last_not_of( ' '); /// must succeed
		return s.substr( first, last - first + 1);
	}
}

void debugMessage(int level, string message)
{
	if (level >= DEBUG)
		std::cerr << message << std::endl;
	return;
}

// constructor
CReader::CReader()
{
	scancycles = 0;
	is_imu_connected = false;

	ip_adress = "192.168.0.1";
	port = 12002;
	convergence = 0;

	// set angle filter
	angle_max = 0*PI/180; // scanner max 50
	angle_min = -60*PI/180; // scanner min -60

	maxmin = false;
	duration = false;
	writebt = false;
	writecsv = false;
	is_indoor = false;

	if (readConfig())
		debugMessage(2,"config successfully readed!");
	else
		debugMessage(2, "no config file!");

	return;
}

// read config file
int CReader::readConfig()
{
	std::ifstream fh;
	std::string line;
	size_t pos = 0;
	std::string key, val;

	fh.open(CONFIG, std::ios::in);

	if (!fh.is_open()) {
		fh.open("config.cfg", std::ios::in);
		if (!fh.is_open()) {
			return FALSE;
		}
	}

	debugMessage(2, "read config...");

	while (getline(fh,line)) {
		pos = line.find("=");
		key = trim(line.substr(0,pos));
		val = trim(line.substr(pos+1));

		try {
			if (key.compare("ip") == 0) {
				ip_adress = val;
			} else if (key.compare("port") == 0) {
				port = atoi(val.c_str());
			} else if (key.compare("maxmin") == 0) {
				if (val.compare("true") == 0)
					maxmin = true;
				else
					maxmin = false;
			} else if (key.compare("writebt") == 0) {
				if (val.compare("true") == 0)
					writebt = true;
			} else if (key.compare("btpath") == 0) {
				bt_path = val;
			} else if (key.compare("convergence") == 0) {
				convergence = atoi(val.c_str());
			} else if (key.compare("location") == 0) {
				if (val.compare("indoor") == 0) {
					is_indoor = true;
				}
			} else if (key.compare("writecsv") == 0) {
				if (val.compare("true") == 0) {
					writecsv = true;
				}
			} else if (key.compare("minangle") == 0) {
				angle_min = atoi(val.c_str())*PI/180.0;
			} else if (key.compare("maxangle") == 0) {
				angle_max = atoi(val.c_str())*PI/180.0;
			}

		} catch (...) {
			std::cout << "unkown parameter:" << key << std::endl;
		}
	}

	fh.close();

	return TRUE;
}

CReader::~CReader()
{
	// release sensor
	mtx_da.lock();
	releaseSensor();
	mtx_da.unlock();

	usleep(200);

	// turn off imu leds
	imu_leds_off(&imu);

	// release ipcon
	imu_set_quaternion_period(&imu, 0);
	imu_set_angular_velocity_period(&imu, 0);
	imu_destroy(&imu);
	ipcon_destroy(&ipcon); // Calls ipcon_disconnect internally
}

// TINKERFORGE

void cb_connected(uint8_t connect_reason, void *user_data)
{
    // ...then trigger enumerate
    ipcon_enumerate(&ipcon);
}

int imu_cb = 0;
double yaw = 0, pitch = 0, roll = 0;

void cb_angular_velocity(int16_t x, int16_t y, int16_t z, void *user_data)
{
	if (abs(x) > 3 || abs(y) || abs(z)) {
		imu_set_convergence_speed(&imu, 30);
	} else {
		imu_set_convergence_speed(&imu, 0);
	}
}

// print incoming enumeration information
void cb_enumerate(const char *uid, const char *connected_uid,
                  char position, uint8_t hardware_version[3],
                  uint8_t firmware_version[3], uint16_t device_identifier,
                  uint8_t enumeration_type, void *user_data)
{
    int is_indoor = *(int*)user_data;

    if(enumeration_type == IPCON_ENUMERATION_TYPE_DISCONNECTED) {
        printf("\n");
        return;
    }

    // check if device is an imu
    if(device_identifier == IMU_DEVICE_IDENTIFIER) {

		std::cout << "Found IMU with UID:" << uid << std::endl;

		if (is_imu_connected) {
			std::cout << "Es ist bereits eine IMU verbunden!" << std::endl;
			return;
		}

		imu_create(&imu, uid, &ipcon);

		imu_set_convergence_speed(&imu,60);

		if (!is_indoor) {

			imu_set_angular_velocity_period(&imu, 10);

			imu_register_callback(&imu,
								IMU_CALLBACK_ANGULAR_VELOCITY,
								(void *)cb_angular_velocity,
								NULL);
		}

		imu_leds_off(&imu);
		is_imu_connected = true;
	}
}

int CReader::init()
{
	// set bounding box filter
	bb_x_max = 70.0;
	bb_x_min = 0.0;
	bb_y_max = 200.0;
	bb_y_min = -200.0;

	// activate both filter
	filter_angle = true;
	filter_bbox = true;

	// init tinkerforge ------------------------------------------------
	// create IP connection

    ipcon_create(&ipcon);

    // Connect to brickd
    if(ipcon_connect(&ipcon, HOST, PORT) < 0) {
		std::cout << "Could not connect to brickd!" << std::endl;
        return false;
    }

	// Register connected callback to "cb_connected"
    ipcon_register_callback(&ipcon,
                            IPCON_CALLBACK_CONNECTED,
                            (void *)cb_connected,
                            &ipcon);

    // Register enumeration callback to "cb_enumerate"
    ipcon_register_callback(&ipcon,
                            IPCON_CALLBACK_ENUMERATE,
                            (void*)cb_enumerate,
                            &is_indoor);

	ipcon_enumerate(&ipcon);
	// sleep
	usleep(7000000);

	// check if imu is connected
	if (!is_imu_connected) {
		std::cout << "Keine Verbindung zur IMU!" << std::endl;
		return false;
	}

	// set convergence after initial stage
	imu_set_convergence_speed(&imu,convergence);

	usleep(50000);

	// raw data file
	time_t t;
    struct tm *ts;
    char buff[128];
    std::stringstream ss;

    // build filename
    t = time(NULL);
    ts = localtime(&t);

    strftime(buff, 80, "rawdata_%Y_%m_%d-%H_%M_%S.bin", ts);

	ss << bt_path << buff;

	logfile.open(ss.str().c_str(), std::ios::out | std::ios::trunc);
	logfile.close();

	logfile.open(ss.str().c_str(), std::ios::app | std::ios::binary | std::ios::out);

	// init sensor
	if(!initSensor()) {
		std::cout << "Keine Verbindung zum Laserscanner!" << std::endl;
		return false;
	}

	imu_leds_on(&imu);

	return true;
}

int CReader::initSensor()
{
	if (!ibeo::ibeoLUX::IbeoLUX::getInstance()) {
		ibeo::ibeoLUX::IbeoLUX::initInstance(this->ip_adress, this->port, 1);
		std::cout << "Sensor searching..." << std::endl;

		laserscanner = ibeo::ibeoLUX::IbeoLUX::getInstance();

		try {
			laserscanner->connect();
			laserscanner->startMeasuring();
		} catch (...) {
			std::cout << "Sensor not found" << std::endl;
			return false;
		}
	}

	if (laserscanner->getConnectionStatus()) {
		std::cout << "Sensor connected" << std::endl;
	} else {
		return false;
	}

	if (!laserscanner->getMeasuringStatus())
		return false;

	laserscanner->ibeoLaserDataAvailable.connect(boost::bind(&CReader::newLaserData, this, _1));

	return true;
}
float xAngle, yAngle, zAngle;
void CReader::storeImuData()
{
	float x, y, z, w;

	imu_get_quaternion(&imu, &x, &y, &z, &w);

	// use octomath to calc quaternion
	// y, z, x
	octomath::Quaternion q(w,x,y,z);
	octomath::Vector3 v(0.0,0.0,0.0);
	octomath::Pose6D pp(v, q);

	xAngle = pp.roll();
	yAngle = pp.pitch();
	zAngle = pp.yaw()*-1; // invert to correct mirroring

	return;
}

float xmax  = 0.0, xmin  = 0.0, ymax  = 0.0, ymin = 0.0, zmax = 0.0, zmin = 0.0;

void CReader::newLaserData(ibeo::ibeoLaserDataAbstractSmartPtr dat)
{
	mtx_da.lock();

	unsigned char *scanPointRaw = NULL;
	unsigned int scanpoints = dat->getNumberOfScanpoints();
	short int angleTicksPerRotation = dat->getAngleTicksPerRotation();
	//thread_clock::time_point start = thread_clock::now();

	// get IMU data
	storeImuData();

	logfile.write(reinterpret_cast<const char*>(&scanpoints), sizeof(scanpoints));
	logfile.write(reinterpret_cast<const char*>(&xAngle), sizeof(xAngle));
	logfile.write(reinterpret_cast<const char*>(&yAngle), sizeof(yAngle));
	logfile.write(reinterpret_cast<const char*>(&zAngle), sizeof(zAngle));
	logfile.write(reinterpret_cast<const char*>(&angleTicksPerRotation), sizeof(angleTicksPerRotation));

	for (unsigned int i = 0; i < scanpoints ; i++) {

		scanPointRaw = dat->getScanPointRawAt(i);

		logfile.write((const char*)scanPointRaw,8);
	}

	data_av = 1;

	// calc delay
	//thread_clock::time_point stop = thread_clock::now();

	//printf("Timestamp: %llu ", timestamp);
	//printf("| Scanpoints: %d", scanpoints);
	//printf("| Scannumber: %hu", scannumber);
	//printf("| Time elapsed: %ld ms \n", duration_cast<milliseconds>(stop - start).count());

	mtx_da.unlock();

	return;
}

// get octomap data for lds server
int CReader::getOctomap(std::stringstream& buff)
{

	return 0;

}

int CReader::writeDataBT()
{

	return 0;
}

void CReader::releaseSensor()
{
	// stop laserscanner
	laserscanner->stopMeasuring();
	usleep(1000);
	laserscanner->releaseInstance();

	return;
}

// get cpu load
int CReader::getCPULoad()
{
	int fd = 0;
	char buff[1024];
	float load;

	fd = open("/proc/loadavg", O_RDONLY);
	if (fd < 0)
		return -1;
	read(fd,buff,sizeof(buff)-1);
	sscanf(buff, "%f", &load);
	close(fd);

	return (int)(load*100);
}

// get ram load
int CReader::getRAMLoad(int* total, int* free)
{
	FILE* fp = NULL;
	char buff[256];
	char name[100], unit[16];

	if ((fp = fopen("/proc/meminfo","r")) == NULL) {
		perror("no file meminfo!");
		return 0;
	}

	fgets(buff, sizeof(buff), fp);
	sscanf(buff, "%s %d %s\n", name, total, unit);

	fgets(buff, sizeof(buff), fp);
	sscanf(buff, "%s %d %s\n", name, free, unit);

	//std::cout << "Total:" << *total << " Kb" << std::endl;
	//std::cout << "Free:"  << *free  << " Kb" <<  std::endl;
	//std::cout << "InUse:" << ((*total-*free)/1024) << " Mb"  << std::endl;

	fclose(fp);
	return 1;
}
<|endoftext|>