blob: 0de8a7a557eaeb8b693e8f4f35772aa99c09d1a8 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/media/codec_impl/codec_admission_control.h>
#include <stdint.h>
#include <zircon/assert.h>
#include <mutex>
void CodecAdmissionControl::TryAddCodec(
bool multi_instance,
fit::function<void(std::unique_ptr<CodecAdmission>)>
continue_after_previously_started_channel_closes_done) {
PostAfterPreviouslyStartedClosesDone(
[this, multi_instance,
callback =
std::move(continue_after_previously_started_channel_closes_done)] {
callback(TryAddCodecInternal(multi_instance));
});
}
void CodecAdmissionControl::PostAfterPreviouslyStartedClosesDone(
fit::closure to_run) {
// TODO(dustingreen): This post is a partial simulation of more robust fencing
// of previously initiated closes before newly initiated create. See TODO in
// the header file.
zx_status_t result =
async::PostTask(shared_fidl_dispatcher_, std::move(to_run));
ZX_ASSERT(result == ZX_OK);
}
std::unique_ptr<CodecAdmission> CodecAdmissionControl::TryAddCodecInternal(
bool multi_instance) {
std::lock_guard<std::mutex> lock(lock_);
if (multi_instance) {
if (single_instance_codec_count_ > 0) {
printf(
"CodecAdmissionControl::AddCodec(): we've already got a "
"single-instance codec\n");
return nullptr;
}
multi_instance_codec_count_++;
} else {
if (multi_instance_codec_count_ > 0 || single_instance_codec_count_ > 0) {
printf(
"CodecAdmissionControl::AddCodec(): we've already got an existing "
"codec. multi_instance_codec_count: %u single_instance_codec_count: "
"%u\n",
multi_instance_codec_count_, single_instance_codec_count_);
return nullptr;
}
single_instance_codec_count_++;
}
// private constructor so have to explicitly new, since friending
// std::make_unique<> would allow any class to create one.
return std::unique_ptr<CodecAdmission>(
new CodecAdmission(this, multi_instance));
}
CodecAdmissionControl::CodecAdmissionControl(
async_dispatcher_t* shared_fidl_dispatcher)
: shared_fidl_dispatcher_(shared_fidl_dispatcher) {
ZX_DEBUG_ASSERT(shared_fidl_dispatcher_);
}
void CodecAdmissionControl::RemoveCodec(bool multi_instance) {
std::lock_guard<std::mutex> lock(lock_);
// Else bug in caller.
if (multi_instance) {
ZX_DEBUG_ASSERT(multi_instance_codec_count_ > 0);
multi_instance_codec_count_--;
} else {
ZX_DEBUG_ASSERT(single_instance_codec_count_ == 1);
single_instance_codec_count_--;
}
}
CodecAdmission::~CodecAdmission() {
codec_admission_control_->RemoveCodec(multi_instance_);
}
CodecAdmission::CodecAdmission(CodecAdmissionControl* codec_admission_control,
bool multi_instance)
: codec_admission_control_(codec_admission_control),
multi_instance_(multi_instance) {
ZX_DEBUG_ASSERT(codec_admission_control_);
}