<commit_before>/* Copyright 2018 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/compiler/jit/flags.h"

#include <mutex>  // NOLINT

#include "absl/base/call_once.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"
#include "absl/strings/strip.h"
#include "tensorflow/compiler/xla/parse_flags_from_env.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/util/command_line_flags.h"

namespace tensorflow {
namespace {

BuildXlaOpsPassFlags* build_ops_flags;
MarkForCompilationPassFlags* mark_for_compilation_flags;
XlaDeviceFlags* device_flags;
XlaOpsCommonFlags* ops_flags;
IntroduceFloatingPointJitterPassFlags* jitter_flags;
MlirCommonFlags* mlir_flags;

std::vector<Flag>* flag_list;
absl::once_flag flags_init;

bool SetterForXlaAutoJitFlag(const string& value) {
  int32 opt_level;
  // We need to use the mark_for_compilation_flags directly here instead of
  // going via GetMarkForCompilationPassFlags() to avoid infinite recursion. The
  // latter will try to setup and parse flags, which would bring us back to this
  // setter.
  if (absl::SimpleAtoi(value, &opt_level)) {
    mark_for_compilation_flags->xla_auto_jit_flag
        .optimization_level_single_gpu = opt_level;
    mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_general =
        opt_level;
    return true;
  }

  if (value == "fusible") {
    mark_for_compilation_flags->xla_auto_jit_flag
        .optimization_level_single_gpu = 1;
    mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_general =
        1;
    mark_for_compilation_flags->tf_xla_ops_to_cluster = "FUSIBLE";
    return true;
  }

  absl::string_view value_sv(value);
  if (!absl::ConsumePrefix(&value_sv, "single-gpu(") ||
      !absl::ConsumeSuffix(&value_sv, ")") ||
      !absl::SimpleAtoi(value_sv, &opt_level)) {
    return false;
  }

  mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_single_gpu =
      opt_level;
  return true;
}

void AppendMarkForCompilationPassFlagsInternal(std::vector<Flag>* flag_list) {
  std::vector<Flag> new_flags = {
      Flag("tf_xla_auto_jit", SetterForXlaAutoJitFlag, "0",
           "Control compilation of operators into XLA computations on CPU and "
           "GPU devices.  0 = use ConfigProto setting; -1 = off; 1 = on for "
           "things very likely to be improved; 2 = on for everything; "
           "(experimental) fusible = only for Tensorflow operations that XLA "
           "knows how to fuse.  "
           "If set to single-gpu(<N>) then this resolves to <N> for single-GPU "
           "graphs (graphs that have at least one node placed on a GPU and no "
           "more than one GPU is in use through the entire graph) and 0 "
           "otherwise.  Experimental."),
      Flag("tf_xla_min_cluster_size",
           &mark_for_compilation_flags->tf_xla_min_cluster_size,
           "Minimum number of operators in an XLA compilation. Ignored for "
           "operators placed on an XLA device or operators explicitly marked "
           "for compilation."),
      Flag("tf_xla_max_cluster_size",
           &mark_for_compilation_flags->tf_xla_max_cluster_size,
           "Maximum number of operators in an XLA compilation."),
      Flag(
          "tf_xla_ops_to_cluster",
          &mark_for_compilation_flags->tf_xla_ops_to_cluster,
          "(experimental) "
          "Limit the operations clustered by XLA to these operations. "
          "If multiple, separate them with commas. Shortcuts: "
          " PW: All point-wise operations."
          " RED: All reduction operations."
          " MISC: Mixed operations."
          " PWRED: TF operations that get converted to PW+RED operation in XLA."
          " REDUCEWINDOW: TF operations like MaxPool/AvgPool that get "
          "converted to ReduceWindow in XLA."
          " REDUCEWINDOWPW: Operation that get converted to ReduceWindow + PW "
          "(LRN, LRNGrad)."
          " BN: TF FusedBatchNorm* operations."
          " FUSIBLE: All TF operations that XLA can fuse (All the above). "
          "You can also put any TF operation name, e.g. 'FUSIBLE,MatMul'."),
      Flag("tf_xla_clustering_debug",
           &mark_for_compilation_flags->tf_xla_clustering_debug,
           "Dump graphs during XLA compilation."),
      Flag("tf_xla_cpu_global_jit",
           &mark_for_compilation_flags->tf_xla_cpu_global_jit,
           "Enables global JIT compilation for CPU via SessionOptions."),
      Flag("tf_xla_clustering_fuel",
           &mark_for_compilation_flags->tf_xla_clustering_fuel,
           "Places an artificial limit on the number of ops marked as "
           "eligible for clustering."),
      Flag("tf_xla_disable_deadness_safety_checks_for_debugging",
           &mark_for_compilation_flags
                ->tf_xla_disable_deadness_safety_checks_for_debugging,
           "Disable deadness related safety checks when clustering (this is "
           "unsound)."),
      Flag("tf_xla_disable_resource_variable_safety_checks_for_debugging",
           &mark_for_compilation_flags
                ->tf_xla_disable_resource_variable_safety_checks_for_debugging,
           "Disable resource variables related safety checks when clustering "
           "(this is unsound).")};
  flag_list->insert(flag_list->end(), new_flags.begin(), new_flags.end());
}

void AllocateAndParseFlags() {
  build_ops_flags = new BuildXlaOpsPassFlags;
  build_ops_flags->tf_xla_enable_lazy_compilation = true;
  build_ops_flags->tf_xla_print_cluster_outputs = false;
  build_ops_flags->tf_xla_check_cluster_input_numerics = false;
  build_ops_flags->tf_xla_check_cluster_output_numerics = false;
  build_ops_flags->tf_xla_disable_constant_folding = false;

  mark_for_compilation_flags = new MarkForCompilationPassFlags;
  mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_single_gpu =
      0;
  mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_general = 0;
  mark_for_compilation_flags->tf_xla_min_cluster_size = 4;
  mark_for_compilation_flags->tf_xla_max_cluster_size =
      std::numeric_limits<int32>::max();
  mark_for_compilation_flags->tf_xla_clustering_debug = false;
  mark_for_compilation_flags->tf_xla_cpu_global_jit = false;
  mark_for_compilation_flags->tf_xla_clustering_fuel =
      std::numeric_limits<int64>::max();
  mark_for_compilation_flags
      ->tf_xla_disable_deadness_safety_checks_for_debugging = false;
  mark_for_compilation_flags
      ->tf_xla_disable_resource_variable_safety_checks_for_debugging = false;

  device_flags = new XlaDeviceFlags;
  device_flags->tf_xla_compile_on_demand = false;
  device_flags->tf_xla_enable_xla_devices = false;

  ops_flags = new XlaOpsCommonFlags;
  ops_flags->tf_xla_always_defer_compilation = false;

  jitter_flags = new IntroduceFloatingPointJitterPassFlags;
  jitter_flags->jitter_amount = 1e-5;

  bool enable_mlir_bridge = false;
  bool enable_mlir_bridge_flag_updated = false;

  auto setter_for_jitter_tensor_names = [](string sequence) {
    jitter_flags->tensor_names = absl::StrSplit(sequence, ',');
    return true;
  };

  flag_list = new std::vector<Flag>(
      {Flag("tf_xla_enable_lazy_compilation",
            &build_ops_flags->tf_xla_enable_lazy_compilation, ""),
       Flag("tf_xla_print_cluster_outputs",
            &build_ops_flags->tf_xla_print_cluster_outputs,
            "If true then insert Print nodes to print out values produced by "
            "XLA clusters."),
       Flag("tf_xla_check_cluster_input_numerics",
            &build_ops_flags->tf_xla_check_cluster_input_numerics,
            "If true then insert CheckNumerics nodes to to check all cluster "
            "inputs."),
       Flag("tf_xla_check_cluster_output_numerics",
            &build_ops_flags->tf_xla_check_cluster_output_numerics,
            "If true then insert CheckNumerics nodes to to check all cluster "
            "outputs."),
       Flag("tf_xla_disable_constant_folding",
            &build_ops_flags->tf_xla_disable_constant_folding,
            "If true then disables constant folding on TF graph before XLA "
            "compilation."),

       Flag("tf_xla_compile_on_demand", &device_flags->tf_xla_compile_on_demand,
            "Switch a device into 'on-demand' mode, where instead of "
            "autoclustering ops are compiled one by one just-in-time."),

       Flag("tf_xla_enable_xla_devices",
            &device_flags->tf_xla_enable_xla_devices,
            "Generate XLA_* devices, where placing a computation on such a "
            "device"
            "forces compilation by XLA. Deprecated."),

       Flag("tf_xla_always_defer_compilation",
            &ops_flags->tf_xla_always_defer_compilation, ""),

       Flag("tf_introduce_floating_point_jitter_to_tensors",
            setter_for_jitter_tensor_names, "",
            "The Tensors to add the jitter to.  The tensors are named in the "
            "TensorId format of <node name>:<output idx>."),
       Flag("tf_introduce_floating_point_jitter_amount",
            &jitter_flags->jitter_amount,
            "The amount of jitter to introduce.  This amount is added to each "
            "element in the tensors named in `tensor_names."),

       Flag("tf_mlir_enable_mlir_bridge", &enable_mlir_bridge,
            "Enables experimental MLIR-Based TensorFlow Compiler Bridge.",
            &enable_mlir_bridge_flag_updated)});

  AppendMarkForCompilationPassFlagsInternal(flag_list);
  xla::ParseFlagsFromEnvAndDieIfUnknown("TF_XLA_FLAGS", *flag_list);

  mlir_flags = new MlirCommonFlags;
  if (!enable_mlir_bridge_flag_updated) {
    mlir_flags->tf_mlir_enable_mlir_bridge =
        ConfigProto::Experimental::MLIR_BRIDGE_ROLLOUT_UNSPECIFIED;
  } else if (enable_mlir_bridge) {
    mlir_flags->tf_mlir_enable_mlir_bridge =
        ConfigProto::Experimental::MLIR_BRIDGE_ROLLOUT_ENABLED;
  } else {
    mlir_flags->tf_mlir_enable_mlir_bridge =
        ConfigProto::Experimental::MLIR_BRIDGE_ROLLOUT_DISABLED;
  }
}

}  // namespace

bool SetXlaAutoJitFlagFromFlagString(const string& value) {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return SetterForXlaAutoJitFlag(value);
}

BuildXlaOpsPassFlags* GetBuildXlaOpsPassFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return build_ops_flags;
}

MarkForCompilationPassFlags* GetMarkForCompilationPassFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return mark_for_compilation_flags;
}

XlaDeviceFlags* GetXlaDeviceFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return device_flags;
}

const XlaOpsCommonFlags& GetXlaOpsCommonFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return *ops_flags;
}

const IntroduceFloatingPointJitterPassFlags&
GetIntroduceFloatingPointJitterPassFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return *jitter_flags;
}

MlirCommonFlags* GetMlirCommonFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return mlir_flags;
}

void AppendMarkForCompilationPassFlags(std::vector<Flag>* flag_list) {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  AppendMarkForCompilationPassFlagsInternal(flag_list);
}

static std::atomic<bool> xla_compilation_disabled(false);

void DisableXlaCompilation() { xla_compilation_disabled = true; }

bool FailOnXlaCompilation() { return xla_compilation_disabled; }

}  // namespace tensorflow
<commit_msg>Update naming of MLIR bridge flag and add some documentation.<commit_after>/* Copyright 2018 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/compiler/jit/flags.h"

#include <mutex>  // NOLINT

#include "absl/base/call_once.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"
#include "absl/strings/strip.h"
#include "tensorflow/compiler/xla/parse_flags_from_env.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/util/command_line_flags.h"

namespace tensorflow {
namespace {

BuildXlaOpsPassFlags* build_ops_flags;
MarkForCompilationPassFlags* mark_for_compilation_flags;
XlaDeviceFlags* device_flags;
XlaOpsCommonFlags* ops_flags;
IntroduceFloatingPointJitterPassFlags* jitter_flags;
MlirCommonFlags* mlir_flags;

std::vector<Flag>* flag_list;
absl::once_flag flags_init;

bool SetterForXlaAutoJitFlag(const string& value) {
  int32 opt_level;
  // We need to use the mark_for_compilation_flags directly here instead of
  // going via GetMarkForCompilationPassFlags() to avoid infinite recursion. The
  // latter will try to setup and parse flags, which would bring us back to this
  // setter.
  if (absl::SimpleAtoi(value, &opt_level)) {
    mark_for_compilation_flags->xla_auto_jit_flag
        .optimization_level_single_gpu = opt_level;
    mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_general =
        opt_level;
    return true;
  }

  if (value == "fusible") {
    mark_for_compilation_flags->xla_auto_jit_flag
        .optimization_level_single_gpu = 1;
    mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_general =
        1;
    mark_for_compilation_flags->tf_xla_ops_to_cluster = "FUSIBLE";
    return true;
  }

  absl::string_view value_sv(value);
  if (!absl::ConsumePrefix(&value_sv, "single-gpu(") ||
      !absl::ConsumeSuffix(&value_sv, ")") ||
      !absl::SimpleAtoi(value_sv, &opt_level)) {
    return false;
  }

  mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_single_gpu =
      opt_level;
  return true;
}

void AppendMarkForCompilationPassFlagsInternal(std::vector<Flag>* flag_list) {
  std::vector<Flag> new_flags = {
      Flag("tf_xla_auto_jit", SetterForXlaAutoJitFlag, "0",
           "Control compilation of operators into XLA computations on CPU and "
           "GPU devices.  0 = use ConfigProto setting; -1 = off; 1 = on for "
           "things very likely to be improved; 2 = on for everything; "
           "(experimental) fusible = only for Tensorflow operations that XLA "
           "knows how to fuse.  "
           "If set to single-gpu(<N>) then this resolves to <N> for single-GPU "
           "graphs (graphs that have at least one node placed on a GPU and no "
           "more than one GPU is in use through the entire graph) and 0 "
           "otherwise.  Experimental."),
      Flag("tf_xla_min_cluster_size",
           &mark_for_compilation_flags->tf_xla_min_cluster_size,
           "Minimum number of operators in an XLA compilation. Ignored for "
           "operators placed on an XLA device or operators explicitly marked "
           "for compilation."),
      Flag("tf_xla_max_cluster_size",
           &mark_for_compilation_flags->tf_xla_max_cluster_size,
           "Maximum number of operators in an XLA compilation."),
      Flag(
          "tf_xla_ops_to_cluster",
          &mark_for_compilation_flags->tf_xla_ops_to_cluster,
          "(experimental) "
          "Limit the operations clustered by XLA to these operations. "
          "If multiple, separate them with commas. Shortcuts: "
          " PW: All point-wise operations."
          " RED: All reduction operations."
          " MISC: Mixed operations."
          " PWRED: TF operations that get converted to PW+RED operation in XLA."
          " REDUCEWINDOW: TF operations like MaxPool/AvgPool that get "
          "converted to ReduceWindow in XLA."
          " REDUCEWINDOWPW: Operation that get converted to ReduceWindow + PW "
          "(LRN, LRNGrad)."
          " BN: TF FusedBatchNorm* operations."
          " FUSIBLE: All TF operations that XLA can fuse (All the above). "
          "You can also put any TF operation name, e.g. 'FUSIBLE,MatMul'."),
      Flag("tf_xla_clustering_debug",
           &mark_for_compilation_flags->tf_xla_clustering_debug,
           "Dump graphs during XLA compilation."),
      Flag("tf_xla_cpu_global_jit",
           &mark_for_compilation_flags->tf_xla_cpu_global_jit,
           "Enables global JIT compilation for CPU via SessionOptions."),
      Flag("tf_xla_clustering_fuel",
           &mark_for_compilation_flags->tf_xla_clustering_fuel,
           "Places an artificial limit on the number of ops marked as "
           "eligible for clustering."),
      Flag("tf_xla_disable_deadness_safety_checks_for_debugging",
           &mark_for_compilation_flags
                ->tf_xla_disable_deadness_safety_checks_for_debugging,
           "Disable deadness related safety checks when clustering (this is "
           "unsound)."),
      Flag("tf_xla_disable_resource_variable_safety_checks_for_debugging",
           &mark_for_compilation_flags
                ->tf_xla_disable_resource_variable_safety_checks_for_debugging,
           "Disable resource variables related safety checks when clustering "
           "(this is unsound).")};
  flag_list->insert(flag_list->end(), new_flags.begin(), new_flags.end());
}

void AllocateAndParseFlags() {
  build_ops_flags = new BuildXlaOpsPassFlags;
  build_ops_flags->tf_xla_enable_lazy_compilation = true;
  build_ops_flags->tf_xla_print_cluster_outputs = false;
  build_ops_flags->tf_xla_check_cluster_input_numerics = false;
  build_ops_flags->tf_xla_check_cluster_output_numerics = false;
  build_ops_flags->tf_xla_disable_constant_folding = false;

  mark_for_compilation_flags = new MarkForCompilationPassFlags;
  mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_single_gpu =
      0;
  mark_for_compilation_flags->xla_auto_jit_flag.optimization_level_general = 0;
  mark_for_compilation_flags->tf_xla_min_cluster_size = 4;
  mark_for_compilation_flags->tf_xla_max_cluster_size =
      std::numeric_limits<int32>::max();
  mark_for_compilation_flags->tf_xla_clustering_debug = false;
  mark_for_compilation_flags->tf_xla_cpu_global_jit = false;
  mark_for_compilation_flags->tf_xla_clustering_fuel =
      std::numeric_limits<int64>::max();
  mark_for_compilation_flags
      ->tf_xla_disable_deadness_safety_checks_for_debugging = false;
  mark_for_compilation_flags
      ->tf_xla_disable_resource_variable_safety_checks_for_debugging = false;

  device_flags = new XlaDeviceFlags;
  device_flags->tf_xla_compile_on_demand = false;
  device_flags->tf_xla_enable_xla_devices = false;

  ops_flags = new XlaOpsCommonFlags;
  ops_flags->tf_xla_always_defer_compilation = false;

  jitter_flags = new IntroduceFloatingPointJitterPassFlags;
  jitter_flags->jitter_amount = 1e-5;

  // The `enable_mlir_bridge` flag allows the user to explicitly request that
  // their program is (or isn't) compiled using the MLIR-based TF-to-XLA bridge.
  //
  // The `enable_mlir_bridge_is_explicit` variable tracks whether or not the
  // user has made an explicit request. That is, if this variable is set to
  // true, the program honors the user's request as per `enable_mlir_bridge`; if
  // it's set to false, the default behavior is used (which may run either
  // bridge, on a per-graph basis).
  bool enable_mlir_bridge = false;
  bool enable_mlir_bridge_is_explicit = false;

  auto setter_for_jitter_tensor_names = [](string sequence) {
    jitter_flags->tensor_names = absl::StrSplit(sequence, ',');
    return true;
  };

  flag_list = new std::vector<Flag>(
      {Flag("tf_xla_enable_lazy_compilation",
            &build_ops_flags->tf_xla_enable_lazy_compilation, ""),
       Flag("tf_xla_print_cluster_outputs",
            &build_ops_flags->tf_xla_print_cluster_outputs,
            "If true then insert Print nodes to print out values produced by "
            "XLA clusters."),
       Flag("tf_xla_check_cluster_input_numerics",
            &build_ops_flags->tf_xla_check_cluster_input_numerics,
            "If true then insert CheckNumerics nodes to to check all cluster "
            "inputs."),
       Flag("tf_xla_check_cluster_output_numerics",
            &build_ops_flags->tf_xla_check_cluster_output_numerics,
            "If true then insert CheckNumerics nodes to to check all cluster "
            "outputs."),
       Flag("tf_xla_disable_constant_folding",
            &build_ops_flags->tf_xla_disable_constant_folding,
            "If true then disables constant folding on TF graph before XLA "
            "compilation."),

       Flag("tf_xla_compile_on_demand", &device_flags->tf_xla_compile_on_demand,
            "Switch a device into 'on-demand' mode, where instead of "
            "autoclustering ops are compiled one by one just-in-time."),

       Flag("tf_xla_enable_xla_devices",
            &device_flags->tf_xla_enable_xla_devices,
            "Generate XLA_* devices, where placing a computation on such a "
            "device"
            "forces compilation by XLA. Deprecated."),

       Flag("tf_xla_always_defer_compilation",
            &ops_flags->tf_xla_always_defer_compilation, ""),

       Flag("tf_introduce_floating_point_jitter_to_tensors",
            setter_for_jitter_tensor_names, "",
            "The Tensors to add the jitter to.  The tensors are named in the "
            "TensorId format of <node name>:<output idx>."),
       Flag("tf_introduce_floating_point_jitter_amount",
            &jitter_flags->jitter_amount,
            "The amount of jitter to introduce.  This amount is added to each "
            "element in the tensors named in `tensor_names."),

       Flag("tf_mlir_enable_mlir_bridge", &enable_mlir_bridge,
            "Enables experimental MLIR-Based TensorFlow Compiler Bridge.",
            &enable_mlir_bridge_is_explicit)});

  AppendMarkForCompilationPassFlagsInternal(flag_list);
  xla::ParseFlagsFromEnvAndDieIfUnknown("TF_XLA_FLAGS", *flag_list);

  mlir_flags = new MlirCommonFlags;
  if (!enable_mlir_bridge_is_explicit) {
    mlir_flags->tf_mlir_enable_mlir_bridge =
        ConfigProto::Experimental::MLIR_BRIDGE_ROLLOUT_UNSPECIFIED;
  } else if (enable_mlir_bridge) {
    mlir_flags->tf_mlir_enable_mlir_bridge =
        ConfigProto::Experimental::MLIR_BRIDGE_ROLLOUT_ENABLED;
  } else {
    mlir_flags->tf_mlir_enable_mlir_bridge =
        ConfigProto::Experimental::MLIR_BRIDGE_ROLLOUT_DISABLED;
  }
}

}  // namespace

bool SetXlaAutoJitFlagFromFlagString(const string& value) {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return SetterForXlaAutoJitFlag(value);
}

BuildXlaOpsPassFlags* GetBuildXlaOpsPassFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return build_ops_flags;
}

MarkForCompilationPassFlags* GetMarkForCompilationPassFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return mark_for_compilation_flags;
}

XlaDeviceFlags* GetXlaDeviceFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return device_flags;
}

const XlaOpsCommonFlags& GetXlaOpsCommonFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return *ops_flags;
}

const IntroduceFloatingPointJitterPassFlags&
GetIntroduceFloatingPointJitterPassFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return *jitter_flags;
}

MlirCommonFlags* GetMlirCommonFlags() {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  return mlir_flags;
}

void AppendMarkForCompilationPassFlags(std::vector<Flag>* flag_list) {
  absl::call_once(flags_init, &AllocateAndParseFlags);
  AppendMarkForCompilationPassFlagsInternal(flag_list);
}

static std::atomic<bool> xla_compilation_disabled(false);

void DisableXlaCompilation() { xla_compilation_disabled = true; }

bool FailOnXlaCompilation() { return xla_compilation_disabled; }

}  // namespace tensorflow
<|endoftext|>


<commit_before>/// @file
/// @version 3.2
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <hltypes/hltypesUtil.h>

#include "Buffer.h"
#include "Category.h"
#include "Player.h"
#include "Sound.h"

namespace xal
{
	Player::Player(Sound* sound) : gain(1.0f), pitch(1.0f), paused(false), looping(false), fadeSpeed(0.0f),
		fadeTime(0.0f), offset(0.0f), bufferIndex(0), processedByteCount(0), idleTime(0.0f)
	{
		this->sound = sound;
		this->buffer = sound->getBuffer();
		if (this->buffer->isStreamed()) // streamed buffers cannot be shared
		{
			this->buffer = xal::mgr->_createBuffer(this->sound);
		}
	}

	Player::~Player()
	{
		if (this->buffer->isStreamed()) // this buffer was created internally
		{
			xal::mgr->_destroyBuffer(this->buffer);
		}
	}

	float Player::getGain()
	{
		xal::mgr->_lock();
		float gain = this->_getGain();
		xal::mgr->_unlock();
		return gain;
	}

	float Player::_getGain()
	{
		return this->gain;
	}

	void Player::setGain(float value)
	{
		xal::mgr->_lock();
		this->_setGain(value);
		xal::mgr->_unlock();
	}

	void Player::_setGain(float value)
	{
		this->gain = hclamp(value, 0.0f, 1.0f);
		this->_systemUpdateGain();
	}

	float Player::getPitch()
	{
		xal::mgr->_lock();
		float pitch = this->_getPitch();
		xal::mgr->_unlock();
		return pitch;
	}

	float Player::_getPitch()
	{
		return this->pitch;
	}

	void Player::setPitch(float value)
	{
		xal::mgr->_lock();
		this->_setPitch(value);
		xal::mgr->_unlock();
	}

	void Player::_setPitch(float value)
	{
		this->pitch = hclamp(value, 0.01f, 100.0f);
		this->_systemUpdatePitch();
	}

	float Player::getTimePosition()
	{
		return ((float)this->getSamplePosition() / this->buffer->getSamplingRate());
	}

	unsigned int Player::getSamplePosition()
	{
		xal::mgr->_lock();
		unsigned int position = this->_systemGetBufferPosition();
		if (this->sound->isStreamed())
		{
			// corrects position by using number of processed bytes (circular)
			position = (position + (STREAM_BUFFER_COUNT - this->bufferIndex) * STREAM_BUFFER_SIZE) % STREAM_BUFFER;
			// adds streamed processed byte count
			position += this->processedByteCount;
		}
		position = hmin(position, (unsigned int)this->sound->getSize());
		unsigned int samplePosition = (unsigned int)(position /
			(this->buffer->getChannels() * this->buffer->getBitsPerSample() * 0.125f));
		xal::mgr->_unlock();
		return samplePosition;
	}

	hstr Player::getName()
	{
		return this->sound->getName();
	}

	hstr Player::getFilename()
	{
		return this->sound->getFilename();
	}

	hstr Player::getRealFilename()
	{
		return this->sound->getRealFilename();
	}

	float Player::getDuration()
	{
		return this->buffer->getDuration();
	}

	int Player::getSize()
	{
		return this->buffer->getSize();
	}

	bool Player::isPlaying()
	{
		return (!this->isFadingOut() && this->_systemIsPlaying());
	}

	bool Player::isPaused()
	{
		return (this->paused && !this->isFading());
	}

	bool Player::isFading()
	{
		return (this->fadeSpeed != 0.0f);
	}

	bool Player::isFadingIn()
	{
		return (this->fadeSpeed > 0.0f);
	}

	bool Player::isFadingOut()
	{
		return (this->fadeSpeed < 0.0f);
	}

	Category* Player::getCategory()
	{
		return this->sound->getCategory();
	}

	void Player::_update(float timeDelta)
	{
		if (this->_systemIsPlaying())
		{
			this->buffer->keepLoaded();
			if (this->sound->isStreamed())
			{
				this->processedByteCount += this->_systemUpdateStream();
			}
		}
		else if (this->paused)
		{
			this->buffer->keepLoaded();
		}
		if (this->isFading())
		{
			this->fadeTime += this->fadeSpeed * timeDelta;
			if (this->fadeTime >= 1.0f && this->fadeSpeed > 0.0f)
			{
				this->_systemUpdateGain();
				this->fadeTime = 1.0f;
				this->fadeSpeed = 0.0f;
			}
			else if (this->fadeTime <= 0.0f && this->fadeSpeed < 0.0f)
			{
				this->fadeTime = 0.0f;
				this->fadeSpeed = 0.0f;
				if (!this->paused)
				{
					this->_stop();
					return;
				}
				this->_pause();
			}
			else
			{
				this->_systemUpdateGain();
			}
		}
	}

	void Player::play(float fadeTime, bool looping)
	{
		xal::mgr->_lock();
		this->_play(fadeTime, looping);
		xal::mgr->_unlock();
	}

	void Player::stop(float fadeTime)
	{
		xal::mgr->_lock();
		this->_stop(fadeTime);
		xal::mgr->_unlock();
	}

	void Player::pause(float fadeTime)
	{
		xal::mgr->_lock();
		this->_pause(fadeTime);
		xal::mgr->_unlock();
	}

	void Player::_play(float fadeTime, bool looping)
	{
		if (!xal::mgr->isEnabled())
		{
			return;
		}
		if (xal::mgr->isSuspended())
		{
			if (!xal::mgr->suspendedPlayers.contains(this))
			{
				xal::mgr->suspendedPlayers += this;
				if (!this->paused)
				{
					this->looping = looping;
					this->paused = true;
				}
			}
			return;
		}
		if (!this->_systemPreparePlay())
		{
			return;
		}
		if (!this->paused)
		{
			this->looping = looping;
		}
		bool alreadyFading = this->isFading();
		if (!alreadyFading && !this->_systemIsPlaying())
		{
			this->buffer->prepare();
			this->_systemPrepareBuffer();
			if (this->paused)
			{
				this->_systemSetOffset(this->offset);
			}
			this->buffer->bind(this, this->paused);
		}
		if (fadeTime > 0.0f)
		{
			this->fadeSpeed = 1.0f / fadeTime;
		}
		else
		{
			this->fadeTime = 1.0f;
			this->fadeSpeed = 0.0f;
		}
		this->_systemUpdateGain();
		if (!alreadyFading)
		{
			this->_systemPlay();
		}
		this->paused = false;
	}

	void Player::_stop(float fadeTime)
	{
		if (xal::mgr->isSuspended() && xal::mgr->suspendedPlayers.contains(this))
		{
			xal::mgr->suspendedPlayers -= this;
		}
		this->paused = false;
		this->_stopSound(fadeTime);
		this->offset = 0.0f;
		this->processedByteCount = 0;
	}

	void Player::_pause(float fadeTime)
	{
		this->paused = true;
		this->_stopSound(fadeTime);
	}

	float Player::_calcGain()
	{
		float gain = this->gain * this->sound->getCategory()->getGain() * xal::mgr->getGlobalGain();
		if (this->isFading())
		{
			gain *= this->fadeTime;
		}
		return hclamp(gain, 0.0f, 1.0f);
	}

	void Player::_stopSound(float fadeTime)
	{
		if (fadeTime > 0.0f)
		{
			this->fadeSpeed = -1.0f / fadeTime;
			return;
		}
		this->offset = this->_systemGetOffset();
		this->processedByteCount += this->_systemStop();
		this->buffer->unbind(this, this->paused);
		this->fadeTime = 0.0f;
		this->fadeSpeed = 0.0f;
	}

}
<commit_msg>- fixed problems with pausing sounds before they are played initially<commit_after>/// @file
/// @version 3.2
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>

#include "Buffer.h"
#include "Category.h"
#include "Player.h"
#include "Sound.h"
#include "xal.h"

namespace xal
{
	Player::Player(Sound* sound) : gain(1.0f), pitch(1.0f), paused(false), looping(false), fadeSpeed(0.0f),
		fadeTime(0.0f), offset(0.0f), bufferIndex(0), processedByteCount(0), idleTime(0.0f)
	{
		this->sound = sound;
		this->buffer = sound->getBuffer();
		if (this->buffer->isStreamed()) // streamed buffers cannot be shared
		{
			this->buffer = xal::mgr->_createBuffer(this->sound);
		}
	}

	Player::~Player()
	{
		if (this->buffer->isStreamed()) // this buffer was created internally
		{
			xal::mgr->_destroyBuffer(this->buffer);
		}
	}

	float Player::getGain()
	{
		xal::mgr->_lock();
		float gain = this->_getGain();
		xal::mgr->_unlock();
		return gain;
	}

	float Player::_getGain()
	{
		return this->gain;
	}

	void Player::setGain(float value)
	{
		xal::mgr->_lock();
		this->_setGain(value);
		xal::mgr->_unlock();
	}

	void Player::_setGain(float value)
	{
		this->gain = hclamp(value, 0.0f, 1.0f);
		this->_systemUpdateGain();
	}

	float Player::getPitch()
	{
		xal::mgr->_lock();
		float pitch = this->_getPitch();
		xal::mgr->_unlock();
		return pitch;
	}

	float Player::_getPitch()
	{
		return this->pitch;
	}

	void Player::setPitch(float value)
	{
		xal::mgr->_lock();
		this->_setPitch(value);
		xal::mgr->_unlock();
	}

	void Player::_setPitch(float value)
	{
		this->pitch = hclamp(value, 0.01f, 100.0f);
		this->_systemUpdatePitch();
	}

	float Player::getTimePosition()
	{
		return ((float)this->getSamplePosition() / this->buffer->getSamplingRate());
	}

	unsigned int Player::getSamplePosition()
	{
		xal::mgr->_lock();
		unsigned int position = this->_systemGetBufferPosition();
		if (this->sound->isStreamed())
		{
			// corrects position by using number of processed bytes (circular)
			position = (position + (STREAM_BUFFER_COUNT - this->bufferIndex) * STREAM_BUFFER_SIZE) % STREAM_BUFFER;
			// adds streamed processed byte count
			position += this->processedByteCount;
		}
		position = hmin(position, (unsigned int)this->sound->getSize());
		unsigned int samplePosition = (unsigned int)(position /
			(this->buffer->getChannels() * this->buffer->getBitsPerSample() * 0.125f));
		xal::mgr->_unlock();
		return samplePosition;
	}

	hstr Player::getName()
	{
		return this->sound->getName();
	}

	hstr Player::getFilename()
	{
		return this->sound->getFilename();
	}

	hstr Player::getRealFilename()
	{
		return this->sound->getRealFilename();
	}

	float Player::getDuration()
	{
		return this->buffer->getDuration();
	}

	int Player::getSize()
	{
		return this->buffer->getSize();
	}

	bool Player::isPlaying()
	{
		return (!this->isFadingOut() && this->_systemIsPlaying());
	}

	bool Player::isPaused()
	{
		return (this->paused && !this->isFading());
	}

	bool Player::isFading()
	{
		return (this->fadeSpeed != 0.0f);
	}

	bool Player::isFadingIn()
	{
		return (this->fadeSpeed > 0.0f);
	}

	bool Player::isFadingOut()
	{
		return (this->fadeSpeed < 0.0f);
	}

	Category* Player::getCategory()
	{
		return this->sound->getCategory();
	}

	void Player::_update(float timeDelta)
	{
		if (this->_systemIsPlaying())
		{
			this->buffer->keepLoaded();
			if (this->sound->isStreamed())
			{
				this->processedByteCount += this->_systemUpdateStream();
			}
		}
		else if (this->paused)
		{
			this->buffer->keepLoaded();
		}
		if (this->isFading())
		{
			this->fadeTime += this->fadeSpeed * timeDelta;
			if (this->fadeTime >= 1.0f && this->fadeSpeed > 0.0f)
			{
				this->_systemUpdateGain();
				this->fadeTime = 1.0f;
				this->fadeSpeed = 0.0f;
			}
			else if (this->fadeTime <= 0.0f && this->fadeSpeed < 0.0f)
			{
				this->fadeTime = 0.0f;
				this->fadeSpeed = 0.0f;
				if (!this->paused)
				{
					this->_stop();
					return;
				}
				this->_pause();
			}
			else
			{
				this->_systemUpdateGain();
			}
		}
	}

	void Player::play(float fadeTime, bool looping)
	{
		xal::mgr->_lock();
		this->_play(fadeTime, looping);
		xal::mgr->_unlock();
	}

	void Player::stop(float fadeTime)
	{
		xal::mgr->_lock();
		this->_stop(fadeTime);
		xal::mgr->_unlock();
	}

	void Player::pause(float fadeTime)
	{
		xal::mgr->_lock();
		this->_pause(fadeTime);
		xal::mgr->_unlock();
	}

	void Player::_play(float fadeTime, bool looping)
	{
		if (!xal::mgr->isEnabled())
		{
			return;
		}
		if (xal::mgr->isSuspended())
		{
			if (!xal::mgr->suspendedPlayers.contains(this))
			{
				xal::mgr->suspendedPlayers += this;
				if (!this->paused)
				{
					this->looping = looping;
				}
			}
			return;
		}
		if (!this->_systemPreparePlay())
		{
			return;
		}
		if (!this->paused)
		{
			this->looping = looping;
		}
		bool alreadyFading = this->isFading();
		if (!alreadyFading && !this->_systemIsPlaying())
		{
			this->buffer->prepare();
			this->_systemPrepareBuffer();
			if (this->paused)
			{
				this->_systemSetOffset(this->offset);
			}
			this->buffer->bind(this, this->paused);
		}
		if (fadeTime > 0.0f)
		{
			this->fadeSpeed = 1.0f / fadeTime;
		}
		else
		{
			this->fadeTime = 1.0f;
			this->fadeSpeed = 0.0f;
		}
		this->_systemUpdateGain();
		if (!alreadyFading)
		{
			this->_systemPlay();
		}
		this->paused = false;
	}

	void Player::_stop(float fadeTime)
	{
		if (xal::mgr->isSuspended() && xal::mgr->suspendedPlayers.contains(this))
		{
			xal::mgr->suspendedPlayers -= this;
		}
		this->paused = false;
		this->_stopSound(fadeTime);
		this->offset = 0.0f;
		this->processedByteCount = 0;
	}

	void Player::_pause(float fadeTime)
	{
		if (!this->_systemIsPlaying() && !this->paused)
		{
			hlog::warn(xal::logTag, "Player cannot be paused, it's not playing: " + this->getName());
			return;
		}
		this->paused = true;
		this->_stopSound(fadeTime);
	}

	float Player::_calcGain()
	{
		float gain = this->gain * this->sound->getCategory()->getGain() * xal::mgr->getGlobalGain();
		if (this->isFading())
		{
			gain *= this->fadeTime;
		}
		return hclamp(gain, 0.0f, 1.0f);
	}

	void Player::_stopSound(float fadeTime)
	{
		if (fadeTime > 0.0f)
		{
			this->fadeSpeed = -1.0f / fadeTime;
			return;
		}
		this->offset = this->_systemGetOffset();
		this->processedByteCount += this->_systemStop();
		this->buffer->unbind(this, this->paused);
		this->fadeTime = 0.0f;
		this->fadeSpeed = 0.0f;
	}

}
<|endoftext|>


<commit_before>// RUN: clang-diff -ast-dump-json %s -- \
// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s

// CHECK: "begin": 299,
// CHECK: "type": "FieldDecl",
// CHECK: "end": 319,
// CHECK: "type": "CXXRecordDecl",
class A {
  int x;
};

// CHECK: "children": [
// CHECK-NEXT: {
// CHECK-NEXT: "begin":
// CHECK-NEXT: "children": []
// CHECK-NEXT: "end":
// CHECK-NEXT: "id":
// CHECK-NEXT: "type": "CharacterLiteral"
// CHECK-NEXT: }
// CHECK: ]
// CHECK: "type": "VarDecl",
char nl = '\n';

// CHECK: "value": "abc \n\t\u0000\u001f"
char s[] = "abc \n\t\0\x1f";

<commit_msg>Fix test clang-diff-json.cpp<commit_after>// RUN: clang-diff -ast-dump-json %s -- \
// RUN: | '%python' -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s

// CHECK: "begin": 301,
// CHECK: "type": "FieldDecl",
// CHECK: "end": 321,
// CHECK: "type": "CXXRecordDecl",
class A {
  int x;
};

// CHECK: "children": [
// CHECK-NEXT: {
// CHECK-NEXT: "begin":
// CHECK-NEXT: "children": []
// CHECK-NEXT: "end":
// CHECK-NEXT: "id":
// CHECK-NEXT: "type": "CharacterLiteral"
// CHECK-NEXT: }
// CHECK: ]
// CHECK: "type": "VarDecl",
char nl = '\n';

// CHECK: "value": "abc \n\t\u0000\u001f"
char s[] = "abc \n\t\0\x1f";

<|endoftext|>


<commit_before><commit_msg>forgot this file<commit_after><|endoftext|>


<commit_before>#include "common/config/watch_map.h"

namespace Envoy {
namespace Config {

Watch* WatchMap::addWatch(SubscriptionCallbacks& callbacks) {
  auto watch = std::make_unique<Watch>(callbacks);
  Watch* watch_ptr = watch.get();
  wildcard_watches_.insert(watch_ptr);
  watches_.insert(std::move(watch));
  return watch_ptr;
}

void WatchMap::removeWatch(Watch* watch) {
  wildcard_watches_.erase(watch); // may or may not be in there, but we want it gone.
  watches_.erase(watch);
}

AddedRemoved WatchMap::updateWatchInterest(Watch* watch,
                                           const std::set<std::string>& update_to_these_names) {
  if (update_to_these_names.empty()) {
    wildcard_watches_.insert(watch);
  } else {
    wildcard_watches_.erase(watch);
  }

  std::vector<std::string> newly_added_to_watch;
  std::set_difference(update_to_these_names.begin(), update_to_these_names.end(),
                      watch->resource_names_.begin(), watch->resource_names_.end(),
                      std::inserter(newly_added_to_watch, newly_added_to_watch.begin()));

  std::vector<std::string> newly_removed_from_watch;
  std::set_difference(watch->resource_names_.begin(), watch->resource_names_.end(),
                      update_to_these_names.begin(), update_to_these_names.end(),
                      std::inserter(newly_removed_from_watch, newly_removed_from_watch.begin()));

  watch->resource_names_ = update_to_these_names;

  return AddedRemoved(findAdditions(newly_added_to_watch, watch),
                      findRemovals(newly_removed_from_watch, watch));
}

absl::flat_hash_set<Watch*> WatchMap::watchesInterestedIn(const std::string& resource_name) {
  absl::flat_hash_set<Watch*> ret = wildcard_watches_;
  const auto watches_interested = watch_interest_.find(resource_name);
  if (watches_interested != watch_interest_.end()) {
    for (const auto& watch : watches_interested->second) {
      ret.insert(watch);
    }
  }
  return ret;
}

void WatchMap::onConfigUpdate(const Protobuf::RepeatedPtrField<ProtobufWkt::Any>& resources,
                              const std::string& version_info) {
  if (watches_.empty()) {
    return;
  }
  SubscriptionCallbacks& name_getter = (*watches_.begin())->callbacks_;

  // Build a map from watches, to the set of updated resources that each watch cares about. Each
  // entry in the map is then a nice little bundle that can be fed directly into the individual
  // onConfigUpdate()s.
  absl::flat_hash_map<Watch*, Protobuf::RepeatedPtrField<ProtobufWkt::Any>> per_watch_updates;
  for (const auto& r : resources) {
    const absl::flat_hash_set<Watch*>& interested_in_r =
        watchesInterestedIn(name_getter.resourceName(r));
    for (const auto& interested_watch : interested_in_r) {
      per_watch_updates[interested_watch].Add()->CopyFrom(r);
    }
  }

  const bool map_is_single_wildcard = (watches_.size() == 1 && wildcard_watches_.size() == 1);
  // We just bundled up the updates into nice per-watch packages. Now, deliver them.
  for (auto& watch : watches_) {
    const auto this_watch_updates = per_watch_updates.find(watch);
    if (this_watch_updates == per_watch_updates.end()) {
      // This update included no resources this watch cares about.
      // 1) If there is only a single, wildcard watch (i.e. Cluster or Listener), always call
      //    its onConfigUpdate even if just a no-op, to properly maintain state-of-the-world
      //    semantics and the update_empty stat.
      // 2) If this watch previously had some resources, it means this update is removing all
      //    of this watch's resources, so the watch must be informed with an onConfigUpdate.
      // 3) Otherwise, we can skip onConfigUpdate for this watch.
      if (map_is_single_wildcard || !watch->state_of_the_world_empty_) {
        watch->callbacks_.onConfigUpdate({}, version_info);
        watch->state_of_the_world_empty_ = true;
      }
    } else {
      watch->callbacks_.onConfigUpdate(this_watch_updates->second, version_info);
      watch->state_of_the_world_empty_ = false;
    }
  }
}

void WatchMap::onConfigUpdate(
    const Protobuf::RepeatedPtrField<envoy::api::v2::Resource>& added_resources,
    const Protobuf::RepeatedPtrField<std::string>& removed_resources,
    const std::string& system_version_info) {
  // Build a pair of maps: from watches, to the set of resources {added,removed} that each watch
  // cares about. Each entry in the map-pair is then a nice little bundle that can be fed directly
  // into the individual onConfigUpdate()s.
  absl::flat_hash_map<Watch*, Protobuf::RepeatedPtrField<envoy::api::v2::Resource>> per_watch_added;
  for (const auto& r : added_resources) {
    const absl::flat_hash_set<Watch*>& interested_in_r = watchesInterestedIn(r.name());
    for (const auto& interested_watch : interested_in_r) {
      per_watch_added[interested_watch].Add()->CopyFrom(r);
    }
  }
  absl::flat_hash_map<Watch*, Protobuf::RepeatedPtrField<std::string>> per_watch_removed;
  for (const auto& r : removed_resources) {
    const absl::flat_hash_set<Watch*>& interested_in_r = watchesInterestedIn(r);
    for (const auto& interested_watch : interested_in_r) {
      *per_watch_removed[interested_watch].Add() = r;
    }
  }

  // We just bundled up the updates into nice per-watch packages. Now, deliver them.
  for (const auto& added : per_watch_added) {
    const Watch* cur_watch = added.first;
    const auto removed = per_watch_removed.find(cur_watch);
    if (removed == per_watch_removed.end()) {
      // additions only, no removals
      cur_watch->callbacks_.onConfigUpdate(added.second, {}, system_version_info);
    } else {
      // both additions and removals
      cur_watch->callbacks_.onConfigUpdate(added.second, removed->second, system_version_info);
      // Drop the removals now, so the final removals-only pass won't use them.
      per_watch_removed.erase(removed);
    }
  }
  // Any removals-only updates will not have been picked up in the per_watch_added loop.
  for (auto& removed : per_watch_removed) {
    removed.first->callbacks_.onConfigUpdate({}, removed.second, system_version_info);
  }
}

void WatchMap::onConfigUpdateFailed(ConfigUpdateFailureReason reason, const EnvoyException* e) {
  for (auto& watch : watches_) {
    watch->callbacks_.onConfigUpdateFailed(reason, e);
  }
}

std::set<std::string> WatchMap::findAdditions(const std::vector<std::string>& newly_added_to_watch,
                                              Watch* watch) {
  std::set<std::string> newly_added_to_subscription;
  for (const auto& name : newly_added_to_watch) {
    auto entry = watch_interest_.find(name);
    if (entry == watch_interest_.end()) {
      newly_added_to_subscription.insert(name);
      watch_interest_[name] = {watch};
    } else {
      entry->second.insert(watch);
    }
  }
  return newly_added_to_subscription;
}

std::set<std::string>
WatchMap::findRemovals(const std::vector<std::string>& newly_removed_from_watch, Watch* watch) {
  std::set<std::string> newly_removed_from_subscription;
  for (const auto& name : newly_removed_from_watch) {
    auto entry = watch_interest_.find(name);
    RELEASE_ASSERT(
        entry != watch_interest_.end(),
        fmt::format("WatchMap: tried to remove a watch from untracked resource {}", name));

    entry->second.erase(watch);
    if (entry->second.empty()) {
      watch_interest_.erase(entry);
      newly_removed_from_subscription.insert(name);
    }
  }
  return newly_removed_from_subscription;
}

} // namespace Config
} // namespace Envoy
<commit_msg>add clarifying comment to watch_map.cc (#9253)<commit_after>#include "common/config/watch_map.h"

namespace Envoy {
namespace Config {

Watch* WatchMap::addWatch(SubscriptionCallbacks& callbacks) {
  auto watch = std::make_unique<Watch>(callbacks);
  Watch* watch_ptr = watch.get();
  wildcard_watches_.insert(watch_ptr);
  watches_.insert(std::move(watch));
  return watch_ptr;
}

void WatchMap::removeWatch(Watch* watch) {
  wildcard_watches_.erase(watch); // may or may not be in there, but we want it gone.
  watches_.erase(watch);
}

AddedRemoved WatchMap::updateWatchInterest(Watch* watch,
                                           const std::set<std::string>& update_to_these_names) {
  if (update_to_these_names.empty()) {
    wildcard_watches_.insert(watch);
  } else {
    wildcard_watches_.erase(watch);
  }

  std::vector<std::string> newly_added_to_watch;
  std::set_difference(update_to_these_names.begin(), update_to_these_names.end(),
                      watch->resource_names_.begin(), watch->resource_names_.end(),
                      std::inserter(newly_added_to_watch, newly_added_to_watch.begin()));

  std::vector<std::string> newly_removed_from_watch;
  std::set_difference(watch->resource_names_.begin(), watch->resource_names_.end(),
                      update_to_these_names.begin(), update_to_these_names.end(),
                      std::inserter(newly_removed_from_watch, newly_removed_from_watch.begin()));

  watch->resource_names_ = update_to_these_names;

  return AddedRemoved(findAdditions(newly_added_to_watch, watch),
                      findRemovals(newly_removed_from_watch, watch));
}

absl::flat_hash_set<Watch*> WatchMap::watchesInterestedIn(const std::string& resource_name) {
  absl::flat_hash_set<Watch*> ret = wildcard_watches_;
  const auto watches_interested = watch_interest_.find(resource_name);
  if (watches_interested != watch_interest_.end()) {
    for (const auto& watch : watches_interested->second) {
      ret.insert(watch);
    }
  }
  return ret;
}

void WatchMap::onConfigUpdate(const Protobuf::RepeatedPtrField<ProtobufWkt::Any>& resources,
                              const std::string& version_info) {
  if (watches_.empty()) {
    return;
  }
  SubscriptionCallbacks& name_getter = (*watches_.begin())->callbacks_;

  // Build a map from watches, to the set of updated resources that each watch cares about. Each
  // entry in the map is then a nice little bundle that can be fed directly into the individual
  // onConfigUpdate()s.
  absl::flat_hash_map<Watch*, Protobuf::RepeatedPtrField<ProtobufWkt::Any>> per_watch_updates;
  for (const auto& r : resources) {
    const absl::flat_hash_set<Watch*>& interested_in_r =
        watchesInterestedIn(name_getter.resourceName(r));
    for (const auto& interested_watch : interested_in_r) {
      per_watch_updates[interested_watch].Add()->CopyFrom(r);
    }
  }

  const bool map_is_single_wildcard = (watches_.size() == 1 && wildcard_watches_.size() == 1);
  // We just bundled up the updates into nice per-watch packages. Now, deliver them.
  for (auto& watch : watches_) {
    const auto this_watch_updates = per_watch_updates.find(watch);
    if (this_watch_updates == per_watch_updates.end()) {
      // This update included no resources this watch cares about.
      // 1) If there is only a single, wildcard watch (i.e. Cluster or Listener), always call
      //    its onConfigUpdate even if just a no-op, to properly maintain state-of-the-world
      //    semantics and the update_empty stat.
      // 2) If this watch previously had some resources, it means this update is removing all
      //    of this watch's resources, so the watch must be informed with an onConfigUpdate.
      // 3) Otherwise, we can skip onConfigUpdate for this watch.
      if (map_is_single_wildcard || !watch->state_of_the_world_empty_) {
        watch->callbacks_.onConfigUpdate({}, version_info);
        watch->state_of_the_world_empty_ = true;
      }
    } else {
      watch->callbacks_.onConfigUpdate(this_watch_updates->second, version_info);
      watch->state_of_the_world_empty_ = false;
    }
  }
}

void WatchMap::onConfigUpdate(
    const Protobuf::RepeatedPtrField<envoy::api::v2::Resource>& added_resources,
    const Protobuf::RepeatedPtrField<std::string>& removed_resources,
    const std::string& system_version_info) {
  // Build a pair of maps: from watches, to the set of resources {added,removed} that each watch
  // cares about. Each entry in the map-pair is then a nice little bundle that can be fed directly
  // into the individual onConfigUpdate()s.
  absl::flat_hash_map<Watch*, Protobuf::RepeatedPtrField<envoy::api::v2::Resource>> per_watch_added;
  for (const auto& r : added_resources) {
    const absl::flat_hash_set<Watch*>& interested_in_r = watchesInterestedIn(r.name());
    for (const auto& interested_watch : interested_in_r) {
      per_watch_added[interested_watch].Add()->CopyFrom(r);
    }
  }
  absl::flat_hash_map<Watch*, Protobuf::RepeatedPtrField<std::string>> per_watch_removed;
  for (const auto& r : removed_resources) {
    const absl::flat_hash_set<Watch*>& interested_in_r = watchesInterestedIn(r);
    for (const auto& interested_watch : interested_in_r) {
      *per_watch_removed[interested_watch].Add() = r;
    }
  }

  // We just bundled up the updates into nice per-watch packages. Now, deliver them.
  for (const auto& added : per_watch_added) {
    const Watch* cur_watch = added.first;
    const auto removed = per_watch_removed.find(cur_watch);
    if (removed == per_watch_removed.end()) {
      // additions only, no removals
      cur_watch->callbacks_.onConfigUpdate(added.second, {}, system_version_info);
    } else {
      // both additions and removals
      cur_watch->callbacks_.onConfigUpdate(added.second, removed->second, system_version_info);
      // Drop the removals now, so the final removals-only pass won't use them.
      per_watch_removed.erase(removed);
    }
  }
  // Any removals-only updates will not have been picked up in the per_watch_added loop.
  for (auto& removed : per_watch_removed) {
    removed.first->callbacks_.onConfigUpdate({}, removed.second, system_version_info);
  }
}

void WatchMap::onConfigUpdateFailed(ConfigUpdateFailureReason reason, const EnvoyException* e) {
  for (auto& watch : watches_) {
    watch->callbacks_.onConfigUpdateFailed(reason, e);
  }
}

std::set<std::string> WatchMap::findAdditions(const std::vector<std::string>& newly_added_to_watch,
                                              Watch* watch) {
  std::set<std::string> newly_added_to_subscription;
  for (const auto& name : newly_added_to_watch) {
    auto entry = watch_interest_.find(name);
    if (entry == watch_interest_.end()) {
      newly_added_to_subscription.insert(name);
      watch_interest_[name] = {watch};
    } else {
      // Add this watch to the already-existing set at watch_interest_[name]
      entry->second.insert(watch);
    }
  }
  return newly_added_to_subscription;
}

std::set<std::string>
WatchMap::findRemovals(const std::vector<std::string>& newly_removed_from_watch, Watch* watch) {
  std::set<std::string> newly_removed_from_subscription;
  for (const auto& name : newly_removed_from_watch) {
    auto entry = watch_interest_.find(name);
    RELEASE_ASSERT(
        entry != watch_interest_.end(),
        fmt::format("WatchMap: tried to remove a watch from untracked resource {}", name));

    entry->second.erase(watch);
    if (entry->second.empty()) {
      watch_interest_.erase(entry);
      newly_removed_from_subscription.insert(name);
    }
  }
  return newly_removed_from_subscription;
}

} // namespace Config
} // namespace Envoy
<|endoftext|>


<commit_before>// Ouzel by Elviss Strazdins

#ifndef OUZEL_GRAPHICS_RENDERDEVICE_HPP
#define OUZEL_GRAPHICS_RENDERDEVICE_HPP

#include <array>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <queue>
#include <set>
#include "Commands.hpp"
#include "Driver.hpp"
#include "SamplerFilter.hpp"
#include "Settings.hpp"
#include "Vertex.hpp"
#include "../math/Matrix.hpp"
#include "../math/Size.hpp"
#include "../utils/Log.hpp"

namespace ouzel::core
{
    class Window;
}

namespace ouzel::graphics
{
    class Graphics;

    struct ApiVersion final
    {
        constexpr ApiVersion() noexcept = default;
        constexpr ApiVersion(std::uint16_t majorVersion, std::uint16_t minorVersion) noexcept:
            v{majorVersion, minorVersion} {}

        constexpr bool operator==(const ApiVersion& other) const noexcept
        {
            return v[0] == other.v[0] && v[1] == other.v[1];
        }

        constexpr bool operator>(const ApiVersion& other) const noexcept
        {
            return (v[0] == other.v[0]) ? (v[1] > other.v[1]) : (v[0] > other.v[0]);
        }

        constexpr bool operator>=(const ApiVersion& other) const noexcept
        {
            return (v[0] == other.v[0]) ? (v[1] >= other.v[1]) : (v[0] > other.v[0]);
        }

        std::uint16_t v[2]{0, 0};
    };

    inline Log& operator<<(Log& log, const ApiVersion& val)
    {
        log << val.v[0] << '.' << val.v[1];
        return log;
    }

    class RenderDevice
    {
        friend Graphics;
    public:
        static constexpr std::array<Vertex::Attribute, 5> vertexAttributes{
            Vertex::Attribute{Vertex::Attribute::Usage::position, DataType::float32Vector3},
            Vertex::Attribute{Vertex::Attribute::Usage::color, DataType::unsignedByteVector4Norm},
            Vertex::Attribute{Vertex::Attribute::Usage::textureCoordinates0, DataType::float32Vector2},
            Vertex::Attribute{Vertex::Attribute::Usage::textureCoordinates1, DataType::float32Vector2},
            Vertex::Attribute{Vertex::Attribute::Usage::normal, DataType::float32Vector3}
        };

        struct Event final
        {
            enum class Type
            {
                frame
            };

            Type type;
        };

        RenderDevice(Driver initDriver,
                     const Settings& settings,
                     core::Window& initWindow,
                     const std::function<void(const Event&)>& initCallback);
        virtual ~RenderDevice() = default;

        RenderDevice(const RenderDevice&) = delete;
        RenderDevice& operator=(const RenderDevice&) = delete;

        RenderDevice(RenderDevice&&) = delete;
        RenderDevice& operator=(RenderDevice&&) = delete;

        auto getDriver() const noexcept { return driver; }

        virtual void process();

        auto getSampleCount() const noexcept { return sampleCount; }

        virtual std::vector<Size<std::uint32_t, 2>> getSupportedResolutions() const;

        void submitCommandBuffer(CommandBuffer&& commandBuffer)
        {
            std::unique_lock lock(commandQueueMutex);
            commandQueue.push(std::move(commandBuffer));
            lock.unlock();
            commandQueueCondition.notify_all();
        }

        auto getDrawCallCount() const noexcept { return drawCallCount; }

        auto getAPIMajorVersion() const noexcept { return apiVersion.v[0]; }
        auto getAPIMinorVersion() const noexcept { return apiVersion.v[1]; }

        auto isNPOTTexturesSupported() const noexcept { return npotTexturesSupported; }
        auto isAnisotropicFilteringSupported() const noexcept { return anisotropicFilteringSupported; }
        auto isRenderTargetsSupported() const noexcept { return renderTargetsSupported; }

        auto& getProjectionTransform(bool renderTarget) const noexcept
        {
            return renderTarget ? renderTargetProjectionTransform : projectionTransform;
        }

        float getFPS() const noexcept { return currentFPS; }
        float getAccumulatedFPS() const noexcept { return accumulatedFPS; }

        void executeOnRenderThread(const std::function<void()>& func);

        using ResourceId = std::size_t;
        class Resource final
        {
        public:
            Resource() = default;
            Resource(RenderDevice& initRenderDevice):
                renderDevice{&initRenderDevice}, id{initRenderDevice.createResourceId()}
            {
            }

            ~Resource()
            {
                if (renderDevice && id) renderDevice->deleteResourceId(id);
            }

            Resource(const Resource&) = delete;
            Resource& operator=(const Resource&) = delete;

            Resource(Resource&& other) noexcept:
                renderDevice{other.renderDevice}, id(other.id)
            {
                other.renderDevice = nullptr;
                other.id = 0;
            }

            Resource& operator=(Resource&& other) noexcept
            {
                if (&other == this) return *this;

                if (renderDevice && id) renderDevice->deleteResourceId(id);
                renderDevice = other.renderDevice;
                id = other.id;
                other.renderDevice = nullptr;
                other.id = 0;

                return *this;
            }

            operator ResourceId() const noexcept { return id; }

        private:
            RenderDevice* renderDevice = nullptr;
            ResourceId id = 0;
        };

    protected:
        void executeAll();

        virtual void generateScreenshot(const std::string& filename);

        Driver driver;
        core::Window& window;
        std::function<void(const Event&)> callback;

        ApiVersion apiVersion;

        std::uint32_t sampleCount = 1; // MSAA sample count

        bool verticalSync = true;
        bool srgb = false;
        bool depth = false;
        bool stencil = false;
        bool debugRenderer = false;

        // features
        bool npotTexturesSupported:1;
        bool anisotropicFilteringSupported:1;
        bool renderTargetsSupported:1;
        bool clampToBorderSupported:1;
        bool multisamplingSupported:1;
        bool uintIndicesSupported:1;

        Matrix<float, 4> projectionTransform = Matrix<float, 4>::identity();
        Matrix<float, 4> renderTargetProjectionTransform = Matrix<float, 4>::identity();

        std::uint32_t drawCallCount = 0;

        std::queue<CommandBuffer> commandQueue;
        std::mutex commandQueueMutex;
        std::condition_variable commandQueueCondition;

        std::atomic<float> currentFPS{0.0F};
        std::chrono::steady_clock::time_point previousFrameTime;

        float accumulatedTime = 0.0F;
        float currentAccumulatedFPS = 0.0F;
        std::atomic<float> accumulatedFPS{0.0F};

        std::queue<std::function<void()>> executeQueue;
        std::mutex executeMutex;

    private:
        ResourceId createResourceId()
        {
            if (const auto i = deletedResourceIds.begin(); i != deletedResourceIds.end())
            {
                std::size_t resourceId = *i;
                deletedResourceIds.erase(i);
                return resourceId;
            }
            else
                return ++lastResourceId;
        }

        void deleteResourceId(ResourceId id)
        {
            deletedResourceIds.insert(id);
        }

        ResourceId lastResourceId = 0;
        std::set<ResourceId> deletedResourceIds;
    };
}

#endif // OUZEL_GRAPHICS_RENDERDEVICE_HPP
<commit_msg>Use auto instead of size_t and make resourceId const<commit_after>// Ouzel by Elviss Strazdins

#ifndef OUZEL_GRAPHICS_RENDERDEVICE_HPP
#define OUZEL_GRAPHICS_RENDERDEVICE_HPP

#include <array>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <queue>
#include <set>
#include "Commands.hpp"
#include "Driver.hpp"
#include "SamplerFilter.hpp"
#include "Settings.hpp"
#include "Vertex.hpp"
#include "../math/Matrix.hpp"
#include "../math/Size.hpp"
#include "../utils/Log.hpp"

namespace ouzel::core
{
    class Window;
}

namespace ouzel::graphics
{
    class Graphics;

    struct ApiVersion final
    {
        constexpr ApiVersion() noexcept = default;
        constexpr ApiVersion(std::uint16_t majorVersion, std::uint16_t minorVersion) noexcept:
            v{majorVersion, minorVersion} {}

        constexpr bool operator==(const ApiVersion& other) const noexcept
        {
            return v[0] == other.v[0] && v[1] == other.v[1];
        }

        constexpr bool operator>(const ApiVersion& other) const noexcept
        {
            return (v[0] == other.v[0]) ? (v[1] > other.v[1]) : (v[0] > other.v[0]);
        }

        constexpr bool operator>=(const ApiVersion& other) const noexcept
        {
            return (v[0] == other.v[0]) ? (v[1] >= other.v[1]) : (v[0] > other.v[0]);
        }

        std::uint16_t v[2]{0, 0};
    };

    inline Log& operator<<(Log& log, const ApiVersion& val)
    {
        log << val.v[0] << '.' << val.v[1];
        return log;
    }

    class RenderDevice
    {
        friend Graphics;
    public:
        static constexpr std::array<Vertex::Attribute, 5> vertexAttributes{
            Vertex::Attribute{Vertex::Attribute::Usage::position, DataType::float32Vector3},
            Vertex::Attribute{Vertex::Attribute::Usage::color, DataType::unsignedByteVector4Norm},
            Vertex::Attribute{Vertex::Attribute::Usage::textureCoordinates0, DataType::float32Vector2},
            Vertex::Attribute{Vertex::Attribute::Usage::textureCoordinates1, DataType::float32Vector2},
            Vertex::Attribute{Vertex::Attribute::Usage::normal, DataType::float32Vector3}
        };

        struct Event final
        {
            enum class Type
            {
                frame
            };

            Type type;
        };

        RenderDevice(Driver initDriver,
                     const Settings& settings,
                     core::Window& initWindow,
                     const std::function<void(const Event&)>& initCallback);
        virtual ~RenderDevice() = default;

        RenderDevice(const RenderDevice&) = delete;
        RenderDevice& operator=(const RenderDevice&) = delete;

        RenderDevice(RenderDevice&&) = delete;
        RenderDevice& operator=(RenderDevice&&) = delete;

        auto getDriver() const noexcept { return driver; }

        virtual void process();

        auto getSampleCount() const noexcept { return sampleCount; }

        virtual std::vector<Size<std::uint32_t, 2>> getSupportedResolutions() const;

        void submitCommandBuffer(CommandBuffer&& commandBuffer)
        {
            std::unique_lock lock(commandQueueMutex);
            commandQueue.push(std::move(commandBuffer));
            lock.unlock();
            commandQueueCondition.notify_all();
        }

        auto getDrawCallCount() const noexcept { return drawCallCount; }

        auto getAPIMajorVersion() const noexcept { return apiVersion.v[0]; }
        auto getAPIMinorVersion() const noexcept { return apiVersion.v[1]; }

        auto isNPOTTexturesSupported() const noexcept { return npotTexturesSupported; }
        auto isAnisotropicFilteringSupported() const noexcept { return anisotropicFilteringSupported; }
        auto isRenderTargetsSupported() const noexcept { return renderTargetsSupported; }

        auto& getProjectionTransform(bool renderTarget) const noexcept
        {
            return renderTarget ? renderTargetProjectionTransform : projectionTransform;
        }

        float getFPS() const noexcept { return currentFPS; }
        float getAccumulatedFPS() const noexcept { return accumulatedFPS; }

        void executeOnRenderThread(const std::function<void()>& func);

        using ResourceId = std::size_t;
        class Resource final
        {
        public:
            Resource() = default;
            Resource(RenderDevice& initRenderDevice):
                renderDevice{&initRenderDevice}, id{initRenderDevice.createResourceId()}
            {
            }

            ~Resource()
            {
                if (renderDevice && id) renderDevice->deleteResourceId(id);
            }

            Resource(const Resource&) = delete;
            Resource& operator=(const Resource&) = delete;

            Resource(Resource&& other) noexcept:
                renderDevice{other.renderDevice}, id(other.id)
            {
                other.renderDevice = nullptr;
                other.id = 0;
            }

            Resource& operator=(Resource&& other) noexcept
            {
                if (&other == this) return *this;

                if (renderDevice && id) renderDevice->deleteResourceId(id);
                renderDevice = other.renderDevice;
                id = other.id;
                other.renderDevice = nullptr;
                other.id = 0;

                return *this;
            }

            operator ResourceId() const noexcept { return id; }

        private:
            RenderDevice* renderDevice = nullptr;
            ResourceId id = 0;
        };

    protected:
        void executeAll();

        virtual void generateScreenshot(const std::string& filename);

        Driver driver;
        core::Window& window;
        std::function<void(const Event&)> callback;

        ApiVersion apiVersion;

        std::uint32_t sampleCount = 1; // MSAA sample count

        bool verticalSync = true;
        bool srgb = false;
        bool depth = false;
        bool stencil = false;
        bool debugRenderer = false;

        // features
        bool npotTexturesSupported:1;
        bool anisotropicFilteringSupported:1;
        bool renderTargetsSupported:1;
        bool clampToBorderSupported:1;
        bool multisamplingSupported:1;
        bool uintIndicesSupported:1;

        Matrix<float, 4> projectionTransform = Matrix<float, 4>::identity();
        Matrix<float, 4> renderTargetProjectionTransform = Matrix<float, 4>::identity();

        std::uint32_t drawCallCount = 0;

        std::queue<CommandBuffer> commandQueue;
        std::mutex commandQueueMutex;
        std::condition_variable commandQueueCondition;

        std::atomic<float> currentFPS{0.0F};
        std::chrono::steady_clock::time_point previousFrameTime;

        float accumulatedTime = 0.0F;
        float currentAccumulatedFPS = 0.0F;
        std::atomic<float> accumulatedFPS{0.0F};

        std::queue<std::function<void()>> executeQueue;
        std::mutex executeMutex;

    private:
        ResourceId createResourceId()
        {
            if (const auto i = deletedResourceIds.begin(); i != deletedResourceIds.end())
            {
                const auto resourceId = *i;
                deletedResourceIds.erase(i);
                return resourceId;
            }
            else
                return ++lastResourceId;
        }

        void deleteResourceId(ResourceId id)
        {
            deletedResourceIds.insert(id);
        }

        ResourceId lastResourceId = 0;
        std::set<ResourceId> deletedResourceIds;
    };
}

#endif // OUZEL_GRAPHICS_RENDERDEVICE_HPP
<|endoftext|>


<commit_before>/**
 * register_file.cpp - Implementation of register file (RF) model
 * Define classes and methods to operate with RF of simulated architecture
 * Copyright 2009 MDSP team
 * Designed by Dmitry Korobov
 */

#include "register_file.h"

/* Constructor */
RegisterFileModel::RegisterFileModel( unsigned int number_of_registers,
									  unsigned int size_of_register_in_bytes)
{
    num_of_reg = number_of_registers;
    try
    {
        /* We try to allocate memory for the array of pointers to registers */
        reg_file = new RegVal*[ num_of_reg];
    } catch ( std::bad_alloc)
    {
	    cout << "Can't allocate memory for register file!\n";
        assert( 0);// Exit the program if we can't allocate memory.
    }

    for ( unsigned int i = 0; i < num_of_reg; i++)
    {
        try
        {
            /* We try to allocate memory for the register */
            reg_file[ i] = new RegVal( size_of_register_in_bytes);
        } catch ( std::bad_alloc)
        {
            /*
             * If allocation failed we report the number of the register
             * for which we can't allocate memory and then we exit the program.
             */
            cout << "Can't allocate memory for register number " << i << "\n";
            assert( 0);
        }
    }
}

/* Destructor */
RegisterFileModel::~RegisterFileModel()
{
    /* Deallocate memory of each register */
    for ( unsigned int i = 0; i < num_of_reg; i++)
    {
        delete reg_file[ i];
    }

    /* Deallocate memory of the array of registers */
    delete [] reg_file;
}

/* Read a logical set of bytes (RegVal) form physical register with number reg_num */
RegVal* RegisterFileModel::readReg( physRegNum reg_num)
{
    /*
     * We should check is 'reg_num' less than or equal to the greatest serial number
     * of elements of register value array. Because we can't read non-existent element.
     */
    if ( reg_num < num_of_reg)
    {
        return reg_file[ reg_num];
    } else
    {
        /* If 'reg_num' is incorrect report the error and exit the program */
        cout << "Error: number of register to be readed is out of range!\n";
        assert( 0);
    }
}

/* Write a logical set of bytes (RegVal) to physical register with number reg_num */
void RegisterFileModel::writeReg( physRegNum reg_num, RegVal& reg_value)
{
    /*
     * We should check is 'reg_num' less than or equal to the greatest serial number
     * of elements of register value array. Because we can't write to non-existent element.
     */
    if ( reg_num < num_of_reg)
    {
        *reg_file[ reg_num] = reg_value;
    } else
    {
        /* If 'reg_num' is incorrect report the error and exit the program */
        cout << "Error: number of register to be written is out of range!\n";
        assert( 0);
    }
}
<commit_msg>File endings fixed (register_file.cpp)<commit_after>/**
 * register_file.cpp - Implementation of register file (RF) model
 * Define classes and methods to operate with RF of simulated architecture
 * Copyright 2009 MDSP team
 * Designed by Dmitry Korobov
 */

#include "register_file.h"

/* Constructor */
RegisterFileModel::RegisterFileModel( unsigned int number_of_registers,
									  unsigned int size_of_register_in_bytes)
{
    num_of_reg = number_of_registers;
    try
    {
        /* We try to allocate memory for the array of pointers to registers */
        reg_file = new RegVal*[ num_of_reg];
    } catch ( std::bad_alloc)
    {
	    cout << "Can't allocate memory for register file!\n";
        assert( 0);// Exit the program if we can't allocate memory.
    }

    for ( unsigned int i = 0; i < num_of_reg; i++)
    {
        try
        {
            /* We try to allocate memory for the register */
            reg_file[ i] = new RegVal( size_of_register_in_bytes);
        } catch ( std::bad_alloc)
        {
            /*
             * If allocation failed we report the number of the register
             * for which we can't allocate memory and then we exit the program.
             */
            cout << "Can't allocate memory for register number " << i << "\n";
            assert( 0);
        }
    }
}

/* Destructor */
RegisterFileModel::~RegisterFileModel()
{
    /* Deallocate memory of each register */
    for ( unsigned int i = 0; i < num_of_reg; i++)
    {
        delete reg_file[ i];
    }

    /* Deallocate memory of the array of registers */
    delete [] reg_file;
}

/* Read a logical set of bytes (RegVal) form physical register with number reg_num */
RegVal* RegisterFileModel::readReg( physRegNum reg_num)
{
    /*
     * We should check is 'reg_num' less than or equal to the greatest serial number
     * of elements of register value array. Because we can't read non-existent element.
     */
    if ( reg_num < num_of_reg)
    {
        return reg_file[ reg_num];
    } else
    {
        /* If 'reg_num' is incorrect report the error and exit the program */
        cout << "Error: number of register to be readed is out of range!\n";
        assert( 0);
    }
}

/* Write a logical set of bytes (RegVal) to physical register with number reg_num */
void RegisterFileModel::writeReg( physRegNum reg_num, RegVal& reg_value)
{
    /*
     * We should check is 'reg_num' less than or equal to the greatest serial number
     * of elements of register value array. Because we can't write to non-existent element.
     */
    if ( reg_num < num_of_reg)
    {
        *reg_file[ reg_num] = reg_value;
    } else
    {
        /* If 'reg_num' is incorrect report the error and exit the program */
        cout << "Error: number of register to be written is out of range!\n";
        assert( 0);
    }
}

<|endoftext|>


<commit_before>//
// Created by Vitali Kurlovich on 5/4/16.
//

#ifndef RMPROPELLER_RMTRANSFORM_HPP
#define RMPROPELLER_RMTRANSFORM_HPP

#include "common/common.hpp"

namespace rmengine {

    namespace graphics {

        class RMTransform3d {
        protected:
            RMTransform3d* _parent;

            vec3 _translate;
            quaternion _rotation;
            vec3 _scale;

            affine_mat4x4 _localTransformMatrix;

            union {
                struct {
                    uint8 _localTranslateChanged:1;
                    uint8 _localRotationChanged:1;
                    uint8 _localScaleChanged:1;
                };
                uint8 _localTransformChanged:3;
            };

        public:

            const affine_mat4x4& getLocalTransformMatrix() const {

                if (_localTransformChanged == 0) {
                    return _localTransformMatrix;
                } else {
                    //_localTransformChanged = 0;
                }

                return _localTransformMatrix;
            }

            const affine_mat4x4& getWorldTransformMatrix() const {
                if (_parent == nullptr) {
                    return getLocalTransformMatrix();
                }

                return _parent->getWorldTransformMatrix()*getLocalTransformMatrix();
            }

            virtual void setParent(const RMTransform3d* parent = nullptr) {
                if (_parent != parent) {

                }
            }

            virtual void setLocalTranslate(const vec3 &translate) {
                if (_translate != translate) {
                    _translate = translate;
                    _translateChanged = true;
                }
            }

            virtual void setWorldTranslate(vec3 translate) {
                if (_parent == nullptr) {
                    setLocalTranslate(translate);
                } else {

                }
            }

        };

    }
}

#endif //RMPROPELLER_RMTRANSFORM_HPP
<commit_msg>update<commit_after>//
// Created by Vitali Kurlovich on 5/4/16.
//

#ifndef RMPROPELLER_RMTRANSFORM_HPP
#define RMPROPELLER_RMTRANSFORM_HPP

#include "common/common.hpp"

namespace rmengine {

    namespace graphics {

        class RMTransform3d {
        protected:
            RMTransform3d* _parent;

            quaternion _rotation;
            vec3 _scale;

            affine_mat4x4 _localTransformMatrix;

            union {
                struct {
                    uint8 _localTranslateChanged:1;
                    uint8 _localRotationChanged:1;
                    uint8 _localScaleChanged:1;
                };
                uint8 _localTransformChanged:3;
            };

        public:

            RMTransform3d()
            : _localTransformMatrix(affine_mat4x4::identity())
            {

            }

            const affine_mat4x4& getLocalTransformMatrix() const {

                if (_localTransformChanged == 0) {
                    return _localTransformMatrix;
                } else {
                    //_localTransformChanged = 0;
                }

                return _localTransformMatrix;
            }

            const affine_mat4x4& getWorldTransformMatrix() const {
                if (_parent == nullptr) {
                    return getLocalTransformMatrix();
                }

                return _parent->getWorldTransformMatrix()*getLocalTransformMatrix();
            }

            virtual void setParent(const RMTransform3d* parent = nullptr) {
                if (_parent != parent) {

                }
            }

            virtual void setLocalTranslate(const pos3 &translate) {
                if (_translate != translate) {
                    _translate = translate;
                    _translateChanged = true;
                    _localTransformMatrix.row[3] = translate.xyz;
                }
            }

            virtual void setWorldTranslate(vec3 translate) {
                if (_parent == nullptr) {
                    setLocalTranslate(translate);
                } else {

                }
            }

        };

    }
}

#endif //RMPROPELLER_RMTRANSFORM_HPP
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// 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 "Texture2D.h"
#include "Texture2D_ispc.h"

#include "../common/Data.h"

namespace ospray {

  std::string Texture2D::toString() const
  {
    return "ospray::Texture2D";
  }

  void Texture2D::commit()
  {
    auto size = getParam<vec2i>("size", vec2i(-1, -1));

    if (size.x < 0 || size.y < 0) {
      std::stringstream ss;
      ss << "'size' param on Texture2D must be positive! got " << size;
      throw std::runtime_error(ss.str());
    }

    auto texData = getParamData("data", nullptr);

    if (!texData->data)
      throw std::runtime_error("no texel data provided to Texture2D");

    type  = static_cast<OSPTextureFormat>(
      getParam1i("type", OSP_TEXTURE_FORMAT_INVALID)
    );
    flags = getParam1i("flags", 0);

    const size_t numBytesExpected = sizeOf(type) * size.x * size.y;

    if (numBytesExpected != texData->numBytes) {
      std::stringstream ss;
      ss << "'size' and 'data' parameters disagree on memory size!\n";
      ss << "expected #bytes: " << numBytesExpected;
      ss << "   given #bytes: " << texData->numBytes;
      throw std::runtime_error(ss.str());
    }

    this->type  = (OSPTextureFormat)type;
    this->flags = flags;

    this->ispcEquivalent = ispc::Texture2D_create((ispc::vec2i&)size,
                                                  texData->data, type, flags);
  }

  OSP_REGISTER_TEXTURE(Texture2D, texture2d);
  OSP_REGISTER_TEXTURE(Texture2D, texture2D);
  OSP_REGISTER_TEXTURE(Texture2D, image2d);
  OSP_REGISTER_TEXTURE(Texture2D, image2D);
  OSP_REGISTER_TEXTURE(Texture2D, 2d);
  OSP_REGISTER_TEXTURE(Texture2D, 2D);

} // ::ospray
<commit_msg>fix warnings<commit_after>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// 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 "Texture2D.h"
#include "Texture2D_ispc.h"

#include "../common/Data.h"

namespace ospray {

  std::string Texture2D::toString() const
  {
    return "ospray::Texture2D";
  }

  void Texture2D::commit()
  {
    auto size = getParam<vec2i>("size", vec2i(-1, -1));

    if (size.x < 0 || size.y < 0) {
      std::stringstream ss;
      ss << "'size' param on Texture2D must be positive! got " << size;
      throw std::runtime_error(ss.str());
    }

    auto texData = getParamData("data", nullptr);

    if (!texData->data)
      throw std::runtime_error("no texel data provided to Texture2D");

    type  = static_cast<OSPTextureFormat>(
      getParam1i("type", OSP_TEXTURE_FORMAT_INVALID)
    );
    flags = getParam1i("flags", 0);

    const size_t numBytesExpected = sizeOf(type) * size.x * size.y;

    if (numBytesExpected != texData->numBytes) {
      std::stringstream ss;
      ss << "'size' and 'data' parameters disagree on memory size!\n";
      ss << "expected #bytes: " << numBytesExpected;
      ss << "   given #bytes: " << texData->numBytes;
      throw std::runtime_error(ss.str());
    }

    this->ispcEquivalent = ispc::Texture2D_create((ispc::vec2i&)size,
                                                  texData->data, type, flags);
  }

  OSP_REGISTER_TEXTURE(Texture2D, texture2d);
  OSP_REGISTER_TEXTURE(Texture2D, texture2D);
  OSP_REGISTER_TEXTURE(Texture2D, image2d);
  OSP_REGISTER_TEXTURE(Texture2D, image2D);
  OSP_REGISTER_TEXTURE(Texture2D, 2d);
  OSP_REGISTER_TEXTURE(Texture2D, 2D);

} // ::ospray
<|endoftext|>


<commit_before>#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <unordered_map>

#include "cbor.h"

static size_t allocated_mem = 0;
static std::unordered_map<void*, size_t> allocated_len_map;
static constexpr size_t kMemoryLimit = 1 << 30;

void *limited_malloc(size_t size) {
    if (size + allocated_mem > kMemoryLimit) {
        return nullptr;
    }
    if (size == 0) {
        return nullptr;
    }
    void* m = malloc(size);
    if (m != nullptr) {
        allocated_mem += size;
        allocated_len_map[m] = size;
    }
    return m;
}

void limited_free(void *ptr) {
    if (ptr != NULL && allocated_len_map.find(ptr) == allocated_len_map.end()) {
        abort();
    }
    free(ptr);
    if (ptr != NULL) {
        allocated_mem -= allocated_len_map[ptr];
        allocated_len_map.erase(ptr);
    }
}

void *limited_realloc(void *ptr, size_t size) {
    if (ptr != NULL && allocated_len_map.find(ptr) == allocated_len_map.end()) {
        abort();
    }
    if (ptr == NULL) {
        return limited_malloc(size);
    }
    long delta = (long) size - allocated_len_map[ptr];
    if (delta + allocated_mem > kMemoryLimit) {
        return nullptr;
    }
    void* new_ptr = realloc(ptr, size);
    if (size > 0 && new_ptr == nullptr) {
        return nullptr;
    }
    allocated_mem += delta;
    allocated_len_map.erase(ptr);
    if (size > 0) {
        allocated_len_map[new_ptr] = size;
    }
    return new_ptr;
}

struct State {
    FILE* fout;

    State() : fout(fopen("/dev/null", "r")) {
        cbor_set_allocs(limited_malloc, limited_realloc, limited_free);
    }
};

static State kState;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
    cbor_load_result result;
    cbor_item_t *item = cbor_load(Data, Size, &result);
    if (result.error.code == CBOR_ERR_NONE) {
        cbor_describe(item, kState.fout);
        unsigned char *buffer;
        size_t buffer_size;
        cbor_serialize_alloc(item, &buffer, &buffer_size);
        free(buffer);
        cbor_item_t *copied = cbor_copy(item);
        cbor_decref(&copied);
        cbor_decref(&item);
    }
    return 0;
}
<commit_msg>Oss-fuzz: Revert to per-alloc size limit only<commit_after>#include <cstdint>
#include <cstdio>

#include "cbor.h"

void *limited_malloc(size_t size) {
    if (size > 1 << 24) {
        return nullptr;
    }
    return malloc(size);
}

struct State {
    FILE* fout;

    State() : fout(fopen("/dev/null", "r")) {
        cbor_set_allocs(limited_malloc, realloc, free);
    }
};

static State kState;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
    cbor_load_result result;
    cbor_item_t *item = cbor_load(Data, Size, &result);
    if (result.error.code == CBOR_ERR_NONE) {
        cbor_describe(item, kState.fout);
        unsigned char *buffer;
        size_t buffer_size;
        cbor_serialize_alloc(item, &buffer, &buffer_size);
        free(buffer);
        cbor_item_t *copied = cbor_copy(item);
        cbor_decref(&copied);
        cbor_decref(&item);
    }
    return 0;
}
<|endoftext|>