2023-01-28 04:54:20 +00:00
|
|
|
// Copyright 2017 The Crashpad Authors
|
2022-04-02 01:21:55 +00:00
|
|
|
//
|
|
|
|
// 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 "client/annotation_list.h"
|
|
|
|
|
|
|
|
#include "base/check_op.h"
|
|
|
|
#include "client/crashpad_info.h"
|
|
|
|
|
|
|
|
namespace crashpad {
|
|
|
|
|
|
|
|
AnnotationList::AnnotationList()
|
|
|
|
: tail_pointer_(&tail_),
|
|
|
|
head_(Annotation::Type::kInvalid, nullptr, nullptr),
|
|
|
|
tail_(Annotation::Type::kInvalid, nullptr, nullptr) {
|
|
|
|
head_.link_node().store(&tail_);
|
|
|
|
}
|
|
|
|
|
|
|
|
AnnotationList::~AnnotationList() {}
|
|
|
|
|
|
|
|
// static
|
|
|
|
AnnotationList* AnnotationList::Get() {
|
|
|
|
return CrashpadInfo::GetCrashpadInfo()->annotations_list();
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
AnnotationList* AnnotationList::Register() {
|
|
|
|
AnnotationList* list = Get();
|
|
|
|
if (!list) {
|
|
|
|
list = new AnnotationList();
|
|
|
|
CrashpadInfo::GetCrashpadInfo()->set_annotations_list(list);
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnnotationList::Add(Annotation* annotation) {
|
|
|
|
Annotation* null = nullptr;
|
|
|
|
Annotation* head_next = head_.link_node().load(std::memory_order_relaxed);
|
|
|
|
if (!annotation->link_node().compare_exchange_strong(null, head_next)) {
|
|
|
|
// If |annotation|'s link node is not null, then it has been added to the
|
|
|
|
// list already and no work needs to be done.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that the annotation's name is less than the maximum size. This is
|
|
|
|
// done here, since the Annotation constructor must be constexpr and this
|
|
|
|
// path is taken once per annotation.
|
|
|
|
DCHECK_LT(strlen(annotation->name_), Annotation::kNameMaxLength);
|
|
|
|
|
|
|
|
// Update the head link to point to the new |annotation|.
|
|
|
|
while (!head_.link_node().compare_exchange_weak(head_next, annotation)) {
|
|
|
|
// Another thread has updated the head-next pointer, so try again with the
|
|
|
|
// re-loaded |head_next|.
|
|
|
|
annotation->link_node().store(head_next, std::memory_order_relaxed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AnnotationList::Iterator::Iterator(Annotation* head, const Annotation* tail)
|
|
|
|
: curr_(head), tail_(tail) {}
|
|
|
|
|
|
|
|
AnnotationList::Iterator::~Iterator() = default;
|
|
|
|
|
|
|
|
Annotation* AnnotationList::Iterator::operator*() const {
|
|
|
|
CHECK_NE(curr_, tail_);
|
|
|
|
return curr_;
|
|
|
|
}
|
|
|
|
|
|
|
|
AnnotationList::Iterator& AnnotationList::Iterator::operator++() {
|
|
|
|
CHECK_NE(curr_, tail_);
|
|
|
|
curr_ = curr_->link_node();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AnnotationList::Iterator::operator==(
|
|
|
|
const AnnotationList::Iterator& other) const {
|
|
|
|
return curr_ == other.curr_;
|
|
|
|
}
|
|
|
|
|
|
|
|
AnnotationList::Iterator AnnotationList::begin() {
|
|
|
|
return Iterator(head_.link_node(), tail_pointer_);
|
|
|
|
}
|
|
|
|
|
|
|
|
AnnotationList::Iterator AnnotationList::end() {
|
|
|
|
return Iterator(&tail_, tail_pointer_);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace crashpad
|