diff options
author | Max Kellermann <max@musicpd.org> | 2021-08-05 15:17:07 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2021-08-05 15:17:07 +0200 |
commit | c97aabe43aee1e2a0ceeda00f9c9b75f66b4d36c (patch) | |
tree | 96c757c906ba115eb8d53140c21eb4680a6e1d11 /src/tag/Builder.cxx | |
parent | b77acd35f776171c11d6590e2252298db89e58b2 (diff) | |
parent | 17b0ac75ca9d8d81e4eabaa8f11bec68830eb9ba (diff) |
Merge branch 'v0.22.x'
Diffstat (limited to 'src/tag/Builder.cxx')
-rw-r--r-- | src/tag/Builder.cxx | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/src/tag/Builder.cxx b/src/tag/Builder.cxx index 5a60a6e78..b2887c903 100644 --- a/src/tag/Builder.cxx +++ b/src/tag/Builder.cxx @@ -36,10 +36,12 @@ TagBuilder::TagBuilder(const Tag &other) noexcept { items.reserve(other.num_items); - const std::lock_guard<Mutex> protect(tag_pool_lock); - - for (unsigned i = 0, n = other.num_items; i != n; ++i) - items.push_back(tag_pool_dup_item(other.items[i])); + const std::size_t n = other.num_items; + if (n > 0) { + const std::lock_guard<Mutex> protect(tag_pool_lock); + for (std::size_t i = 0; i != n; ++i) + items.push_back(tag_pool_dup_item(other.items[i])); + } } TagBuilder::TagBuilder(Tag &&other) noexcept @@ -63,12 +65,17 @@ TagBuilder::operator=(const TagBuilder &other) noexcept /* copy all attributes */ duration = other.duration; has_playlist = other.has_playlist; - items = other.items; - /* increment the tag pool refcounters */ - const std::lock_guard<Mutex> protect(tag_pool_lock); - for (auto i : items) - tag_pool_dup_item(i); + RemoveAll(); + + if (!other.items.empty()) { + items = other.items; + + /* increment the tag pool refcounters */ + const std::lock_guard<Mutex> protect(tag_pool_lock); + for (auto &i : items) + i = tag_pool_dup_item(i); + } return *this; } @@ -76,9 +83,14 @@ TagBuilder::operator=(const TagBuilder &other) noexcept TagBuilder & TagBuilder::operator=(TagBuilder &&other) noexcept { + using std::swap; + duration = other.duration; has_playlist = other.has_playlist; - items = std::move(other.items); + + /* swap the two TagItem lists so we don't need to touch the + tag pool just yet */ + swap(items, other.items); return *this; } @@ -92,7 +104,7 @@ TagBuilder::operator=(Tag &&other) noexcept /* move all TagItem pointers from the Tag object; we don't need to contact the tag pool, because all we do is move references */ - items.clear(); + RemoveAll(); items.reserve(other.num_items); std::copy_n(other.items, other.num_items, std::back_inserter(items)); @@ -174,11 +186,14 @@ TagBuilder::Complement(const Tag &other) noexcept items.reserve(items.size() + other.num_items); - const std::lock_guard<Mutex> protect(tag_pool_lock); - for (unsigned i = 0, n = other.num_items; i != n; ++i) { - TagItem *item = other.items[i]; - if (!present[item->type]) - items.push_back(tag_pool_dup_item(item)); + const std::size_t n = other.num_items; + if (n > 0) { + const std::lock_guard<Mutex> protect(tag_pool_lock); + for (std::size_t i = 0; i != n; ++i) { + TagItem *item = other.items[i]; + if (!present[item->type]) + items.push_back(tag_pool_dup_item(item)); + } } } @@ -238,6 +253,11 @@ TagBuilder::AddEmptyItem(TagType type) noexcept void TagBuilder::RemoveAll() noexcept { + if (items.empty()) + /* don't acquire the tag_pool_lock if we're not going + to call tag_pool_put_item() anyway */ + return; + { const std::lock_guard<Mutex> protect(tag_pool_lock); for (auto i : items) |