chromium/third_party/blink/renderer/build/scripts/templates/instrumenting_probes_impl.cc.tmpl

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

{% from 'macros.tmpl' import source_files_for_generated_file %}
{{source_files_for_generated_file(template_file, input_files)}}

{% set sink_class = (name | to_singular) + "Sink" %}
{% set sink_class_header = (header | to_singular) + "_sink" %}
{% for file in files|sort %}
#include "{{output_path_in_gen_dir}}{{file.name}}_inl.h"
{% endfor %}
#include "{{output_path_in_gen_dir}}{{sink_class_header}}.h"
{% for agent in agents|sort %}
#include "{{agent | agent_name_to_include}}"
{% endfor %}
#include "base/synchronization/lock.h"

namespace blink {

namespace {

base::Lock& AgentCountLock() {
  DEFINE_THREAD_SAFE_STATIC_LOCAL(base::Lock, lock, ());
  return lock;
}

}  // namespace

// static
std::atomic<unsigned> {{sink_class}}::s_existingAgents;

{{sink_class}}::{{sink_class}}() {}

{{sink_class}}::~{{sink_class}}() {
  base::AutoLock locker(AgentCountLock());
{% for agent in agents|sort %}
  if (Has{{agent}}s() && --s_numSinksWith{{agent}} == 0)
    s_existingAgents &= ~k{{agent}};
{% endfor %}
}

{% for agent in agents|sort %}
{% set class_name = agent | agent_name_to_class %}
{% set getter_name = agent | to_snake_case %}

// static
unsigned {{sink_class}}::s_numSinksWith{{agent}} = 0;

void {{sink_class}}::Add{{agent}}({{class_name}}* agent) {
  bool already_had_agent = Has{{agent}}s();
  {{getter_name}}s_.AddAgent(agent);

  if (!already_had_agent) {
    base::AutoLock locker(AgentCountLock());
    if (++s_numSinksWith{{agent}} == 1)
      s_existingAgents |= k{{agent}};
  }

  DCHECK(HasAgentsGlobal(k{{agent}}));
}

void {{sink_class}}::Remove{{agent}}({{class_name}}* agent) {
  if (!Has{{agent}}s())
    return;

  {{getter_name}}s_.RemoveAgent(agent);

  if (!Has{{agent}}s()) {
    base::AutoLock locker(AgentCountLock());
    if (--s_numSinksWith{{agent}} == 0)
      s_existingAgents &= ~k{{agent}};
  }

  if (Has{{agent}}s())
    DCHECK(HasAgentsGlobal(k{{agent}}));
}

{% endfor -%}

void {{sink_class}}::Trace(Visitor* visitor) const
{
{% for agent in agents|sort %}
{% set getter_name = agent | to_snake_case %}
  visitor->Trace({{getter_name}}s_);
{% endfor %}
}

namespace probe {
{% macro params_list(probe) -%}
{%- for param in probe.params %}
{%- if probe.is_scoped and param.is_reference %}
std::reference_wrapper<std::remove_reference_t<{{param.type}}>>
{%- else %}
{{param.type}}
{%- endif %}
 {{param.name}}
{%- if not loop.last %}, {% endif -%}
{%- endfor -%}
{%- endmacro %}

{% macro probe_body(probe, common_name) %}
{% set agent_probe_name = method_name(common_name or probe.name) %}
  if (!probe_sink)
    return;
{% for agent in probe.agents|sort %}
{% set class_name = agent | agent_name_to_class %}
  if (probe_sink->Has{{agent}}s()) {
    probe_sink->{{class_name}}s().ForEachAgent([&]({{class_name}}* agent) {
      agent->{{agent_probe_name}}({{caller()}});
    });
  }
{% endfor %}
{% endmacro -%}

{% for file in files|sort %}
{% for probe in file.declarations %}
{% if probe.is_scoped %}
{{probe.name}}::{{probe.name}}({{ params_list(probe) }}) :
{% for param in probe.params %}
    {{param.name}}({{param.name}})
{%- if not loop.last %},
{% endif %}
{% endfor %} {
  if (!{{sink_class}}::HasAgentsGlobal(
    {%- for agent in probe.agents|sort %}
    {% if not loop.first %} | {% endif -%}
    {{sink_class}}::k{{agent}}
    {%- endfor %}))
    return;
  probe_sink = To{{sink_class}}({{probe.params[0].name}});
{% call probe_body(probe, "Will") %}*this{% endcall %}
}

{{probe.name}}::~{{probe.name}}() {
{% call probe_body(probe, "Did") %}*this{% endcall %}
}

{% else -%}

void {{probe.name}}Impl({{ params_list(probe) }}) {
  {{sink_class}}* probe_sink = To{{sink_class}}({{probe.params[0].name}});
{% call probe_body(probe, "") %}
{%- for param in probe.params %}
{%- if not loop.first or "Keep" in param.options -%}
{{param.name}}
{%- if not loop.last %}, {% endif -%}
{%- endif -%}
{%- endfor %}
{%- endcall %}
}

{% endif %}
{% endfor %}
{% endfor %}

} // namespace probe
} // namespace blink