<commit_before>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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 "perfetto/ext/tracing/core/startup_trace_writer_registry.h"

#include <algorithm>
#include <cmath>
#include <functional>

#include "perfetto/base/logging.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/tracing/core/startup_trace_writer.h"
#include "src/tracing/core/shared_memory_arbiter_impl.h"

using ChunkHeader = perfetto::SharedMemoryABI::ChunkHeader;

namespace perfetto {

StartupTraceWriterRegistryHandle::StartupTraceWriterRegistryHandle(
    StartupTraceWriterRegistry* registry)
    : registry_(registry) {}

void StartupTraceWriterRegistryHandle::ReturnWriterToRegistry(
    std::unique_ptr<StartupTraceWriter> writer) {
  std::lock_guard<std::mutex> lock(lock_);
  if (registry_)
    registry_->ReturnTraceWriter(std::move(writer));
}

void StartupTraceWriterRegistryHandle::OnRegistryDestroyed() {
  std::lock_guard<std::mutex> lock(lock_);
  registry_ = nullptr;
}

StartupTraceWriterRegistry::StartupTraceWriterRegistry()
    : handle_(std::make_shared<StartupTraceWriterRegistryHandle>(this)) {}

StartupTraceWriterRegistry::~StartupTraceWriterRegistry() {
  handle_->OnRegistryDestroyed();
}

// static
constexpr size_t StartupTraceWriterRegistry::kDefaultMaxBufferSizeBytes;

std::unique_ptr<StartupTraceWriter>
StartupTraceWriterRegistry::CreateUnboundTraceWriter(
    BufferExhaustedPolicy buffer_exhausted_policy,
    size_t max_buffer_size_bytes) {
  std::lock_guard<std::mutex> lock(lock_);
  PERFETTO_DCHECK(!arbiter_);  // Should only be called while unbound.
  std::unique_ptr<StartupTraceWriter> writer(new StartupTraceWriter(
      handle_, buffer_exhausted_policy, max_buffer_size_bytes));
  unbound_writers_.push_back(writer.get());
  return writer;
}

void StartupTraceWriterRegistry::ReturnTraceWriter(
    std::unique_ptr<StartupTraceWriter> trace_writer) {
  std::unique_lock<std::mutex> lock(lock_);

  // We can only bind the writer on task_runner_.
  if (task_runner_ && !task_runner_->RunsTasksOnCurrentThread()) {
    // We shouldn't post tasks while holding a lock. |task_runner_| is only set
    // once, so will remain valid.
    lock.release();
    auto weak_this = weak_ptr_factory_->GetWeakPtr();
    auto* trace_writer_raw = trace_writer.get();
    task_runner_->PostTask([weak_this, trace_writer_raw]() {
      std::unique_ptr<StartupTraceWriter> owned_writer(trace_writer_raw);
      if (weak_this)<commit_msg>startup writers: Release unique_ptr/lock correctly in ReturnTraceWriter<commit_after>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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 "perfetto/ext/tracing/core/startup_trace_writer_registry.h"

#include <algorithm>
#include <cmath>
#include <functional>

#include "perfetto/base/logging.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/tracing/core/startup_trace_writer.h"
#include "src/tracing/core/shared_memory_arbiter_impl.h"

using ChunkHeader = perfetto::SharedMemoryABI::ChunkHeader;

namespace perfetto {

StartupTraceWriterRegistryHandle::StartupTraceWriterRegistryHandle(
    StartupTraceWriterRegistry* registry)
    : registry_(registry) {}

void StartupTraceWriterRegistryHandle::ReturnWriterToRegistry(
    std::unique_ptr<StartupTraceWriter> writer) {
  std::lock_guard<std::mutex> lock(lock_);
  if (registry_)
    registry_->ReturnTraceWriter(std::move(writer));
}

void StartupTraceWriterRegistryHandle::OnRegistryDestroyed() {
  std::lock_guard<std::mutex> lock(lock_);
  registry_ = nullptr;
}

StartupTraceWriterRegistry::StartupTraceWriterRegistry()
    : handle_(std::make_shared<StartupTraceWriterRegistryHandle>(this)) {}

StartupTraceWriterRegistry::~StartupTraceWriterRegistry() {
  handle_->OnRegistryDestroyed();
}

// static
constexpr size_t StartupTraceWriterRegistry::kDefaultMaxBufferSizeBytes;

std::unique_ptr<StartupTraceWriter>
StartupTraceWriterRegistry::CreateUnboundTraceWriter(
    BufferExhaustedPolicy buffer_exhausted_policy,
    size_t max_buffer_size_bytes) {
  std::lock_guard<std::mutex> lock(lock_);
  PERFETTO_DCHECK(!arbiter_);  // Should only be called while unbound.
  std::unique_ptr<StartupTraceWriter> writer(new StartupTraceWriter(
      handle_, buffer_exhausted_policy, max_buffer_size_bytes));
  unbound_writers_.push_back(writer.get());
  return writer;
}

void StartupTraceWriterRegistry::ReturnTraceWriter(
    std::unique_ptr<StartupTraceWriter> trace_writer) {
  std::unique_lock<std::mutex> lock(lock_);

  // We can only bind the writer on task_runner_.
  if (task_runner_ && !task_runner_->RunsTasksOnCurrentThread()) {
    // We shouldn't post tasks while holding a lock. |task_runner_| is only set
    // once, so will remain valid.
    lock.unlock();
    auto weak_this = weak_ptr_factory_->GetWeakPtr();
    auto* trace_writer_raw = trace_writer.release();
    task_runner_->PostTask([weak_this, trace_writer_raw]() {
      std::unique_ptr<StartupTraceWriter> owned_writer(trace_writer_raw);
      if (weak_this)
{'fraction_non_alphanumeric': 0.10093396690152384, 'fraction_numerical': 0.002621661477961658, 'mean_word_length': 5.9363636363636365, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5038213', 'n_tokens_mistral': 1813, 'n_tokens_neox': 1799, 'n_words': 417}