Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "logger.h"
24 : #include "eidregister.h"
25 : #include "log.h"
26 :
27 : #include "dom/mscore.h"
28 :
29 : using namespace mu::engraving;
30 :
31 70162 : EID EIDRegister::newEIDForItem(const EngravingObject* item)
32 : {
33 70162 : EID eid = MScore::testMode ? EID::newUniqueTestMode(m_maxValTestMode) : EID::newUnique();
34 70162 : registerItemEID(eid, const_cast<EngravingObject*>(item));
35 70162 : return eid;
36 : }
37 :
38 102289 : void EIDRegister::registerItemEID(const EID& eid, const EngravingObject* item)
39 : {
40 102289 : std::lock_guard lock(m_mutex);
41 102289 : IF_ASSERT_FAILED(eid.isValid() && item) {
42 0 : return;
43 : }
44 :
45 102289 : bool inserted = m_eidToItem.emplace(eid, const_cast<EngravingObject*>(item)).second;
46 102289 : assert(inserted);
47 :
48 102289 : inserted = m_itemToEid.emplace(const_cast<EngravingObject*>(item), eid).second;
49 102289 : assert(inserted);
50 :
51 102289 : if (MScore::testMode) {
52 102289 : EID::updateMaxValTestMode(eid, m_maxValTestMode);
53 : }
54 :
55 : #ifdef NDEBUG
56 : UNUSED(inserted);
57 : #endif
58 102289 : }
59 :
60 0 : void EIDRegister::removeItem(const EngravingObject* item)
61 : {
62 0 : std::lock_guard lock(m_mutex);
63 : // NOTE: needed only when elements are removed during read (e.g. broken spanners)
64 :
65 0 : auto itemIter = m_itemToEid.find(const_cast<EngravingObject*>(item));
66 0 : IF_ASSERT_FAILED(itemIter != m_itemToEid.end()) {
67 0 : return;
68 : }
69 :
70 0 : EID eid = (*itemIter).second;
71 0 : DO_ASSERT(eid.isValid());
72 :
73 0 : m_itemToEid.erase(itemIter);
74 :
75 0 : auto eidIter = m_eidToItem.find(eid);
76 0 : IF_ASSERT_FAILED(eidIter != m_eidToItem.end()) {
77 0 : return;
78 : }
79 :
80 0 : m_eidToItem.erase(eidIter);
81 0 : }
82 :
83 260634 : void EIDRegister::onItemDestroyed(const EngravingObject* item)
84 : {
85 260634 : std::lock_guard lock(m_mutex);
86 : // NOTE: most items never get an EID assigned, so a missing entry is the normal case.
87 : // Items that do have one must be unregistered here: a later allocation can reuse
88 : // the freed address, and a stale entry would corrupt the register.
89 :
90 260634 : auto itemIter = m_itemToEid.find(const_cast<EngravingObject*>(item));
91 260634 : if (itemIter == m_itemToEid.end()) {
92 249646 : return;
93 : }
94 :
95 10988 : m_eidToItem.erase(itemIter->second);
96 10988 : m_itemToEid.erase(itemIter);
97 260634 : }
98 :
99 4209 : EngravingObject* EIDRegister::itemFromEID(const EID& eid) const
100 : {
101 4209 : std::shared_lock lock(m_mutex);
102 4209 : auto iter = m_eidToItem.find(eid);
103 4209 : if (iter == m_eidToItem.end()) {
104 0 : return nullptr;
105 : }
106 4209 : return iter->second;
107 4209 : }
108 :
109 108192 : EID EIDRegister::EIDFromItem(const EngravingObject* item) const
110 : {
111 108192 : std::shared_lock lock(m_mutex);
112 108192 : auto iter = m_itemToEid.find(const_cast<EngravingObject*>(item));
113 216384 : return iter == m_itemToEid.end() ? EID::invalid() : iter->second;
114 108192 : }
|