Commit edbd7213 authored by Igor Kushnir's avatar Igor Kushnir

Introduce and use DUChainReferenceCountingEnabler

parent 24ca16b1
......@@ -135,12 +135,13 @@ void DUChainBase::makeDynamic()
if (!d_func()->m_dynamic) {
Q_ASSERT(d_func()->classId);
DUChainBaseData* newData = DUChainItemSystem::self().cloneData(*d_func());
const auto referenceCountingSize = DUChainItemSystem::self().dynamicSize(*static_cast<DUChainBaseData*>(d_ptr));
enableDUChainReferenceCounting(d_ptr, referenceCountingSize);
//We don't delete the previous data, because it's embedded in the top-context when it isn't dynamic.
//However we do call the destructor, to keep semantic stuff like reference-counting within the data class working correctly.
KDevelop::DUChainItemSystem::self().callDestructor(static_cast<DUChainBaseData*>(d_ptr));
disableDUChainReferenceCounting(d_ptr, referenceCountingSize);
{
auto* const baseData = static_cast<DUChainBaseData*>(d_ptr);
const DUChainReferenceCountingEnabler rcEnabler(d_ptr, DUChainItemSystem::self().dynamicSize(*baseData));
//We don't delete the previous data, because it's embedded in the top-context when it isn't dynamic.
//However we do call the destructor, to keep semantic stuff like reference-counting within the data class working correctly.
DUChainItemSystem::self().callDestructor(baseData);
}
d_ptr = newData;
Q_ASSERT(d_ptr);
Q_ASSERT(d_func()->m_dynamic);
......
......@@ -77,14 +77,12 @@ void saveDUChainItem(QVector<TopDUContextDynamicData::ArrayWithPosition>& data,
if (item.d_func()->isDynamic()) {
//Change from dynamic data to constant data
enableDUChainReferenceCounting(data.back().array.data(), data.back().array.size());
const DUChainReferenceCountingEnabler rcEnabler(data.back().array.data(), data.back().array.size());
DUChainItemSystem::self().copy(*item.d_func(), target, true);
Q_ASSERT(!target.isDynamic());
if (!isSharedDataItem) {
item.setData(&target);
}
disableDUChainReferenceCounting(data.back().array.data(), data.back().array.size());
} else {
//Just copy the data into another place, expensive copy constructors are not needed
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 800)
......
......@@ -1189,9 +1189,8 @@ void StringSetRepository::itemRemovedFromSets(uint index)
///Call the IndexedString destructor with enabled reference-counting
KDevelop::IndexedString string = KDevelop::IndexedString::fromIndex(index);
KDevelop::enableDUChainReferenceCounting(&string, sizeof(KDevelop::IndexedString));
const KDevelop::DUChainReferenceCountingEnabler rcEnabler(&string, sizeof(KDevelop::IndexedString));
string.~IndexedString(); //Call destructor with enabled reference-counting
KDevelop::disableDUChainReferenceCounting(&string, sizeof(KDevelop::IndexedString));
}
void StringSetRepository::itemAddedToSets(uint index)
......@@ -1202,8 +1201,7 @@ void StringSetRepository::itemAddedToSets(uint index)
char data[sizeof(KDevelop::IndexedString)];
KDevelop::enableDUChainReferenceCounting(data, sizeof(KDevelop::IndexedString));
const KDevelop::DUChainReferenceCountingEnabler rcEnabler(data, sizeof(KDevelop::IndexedString));
new (data) KDevelop::IndexedString(string); //Call constructor with enabled reference-counting
KDevelop::disableDUChainReferenceCounting(data, sizeof(KDevelop::IndexedString));
}
}
......@@ -296,6 +296,11 @@ public:
unsigned short index = m_objectMap[localHash];
unsigned short insertedAt = 0;
const auto createInsertedItem = [&]() {
const OptionalDUChainReferenceCountingEnabler<markForReferenceCounting> optionalRc(m_data, dataSize());
request.createItem(reinterpret_cast<Item*>(m_data + insertedAt));
};
unsigned short follower = 0;
//Walk the chain of items with the same local hash
while (index && (follower = followerIndex(index)) && !(request.equals(itemFromIndex(index))))
......@@ -320,16 +325,7 @@ public:
setFollowerIndex(insertedAt, 0);
Q_ASSERT(m_objectMap[localHash] == 0);
m_objectMap[localHash] = insertedAt;
const auto referenceCountingSize = dataSize();
if (markForReferenceCounting)
enableDUChainReferenceCounting(m_data, referenceCountingSize);
request.createItem(reinterpret_cast<Item*>(m_data + insertedAt));
if (markForReferenceCounting)
disableDUChainReferenceCounting(m_data, referenceCountingSize);
createInsertedItem();
return insertedAt;
}
......@@ -437,14 +433,7 @@ public:
#endif
//Last thing we do, because createItem may recursively do even more transformation of the repository
const auto referenceCountingSize = dataSize();
if (markForReferenceCounting)
enableDUChainReferenceCounting(m_data, referenceCountingSize);
request.createItem(reinterpret_cast<Item*>(m_data + insertedAt));
if (markForReferenceCounting)
disableDUChainReferenceCounting(m_data, referenceCountingSize);
createInsertedItem();
#ifdef DEBUG_CREATEITEM_EXTENTS
if (m_available >= 8) {
......@@ -561,14 +550,10 @@ public:
Item* item = const_cast<Item*>(itemFromIndex(index));
const auto referenceCountingSize = dataSize();
if (markForReferenceCounting)
enableDUChainReferenceCounting(m_data, referenceCountingSize);
ItemRequest::destroy(item, repository);
if (markForReferenceCounting)
disableDUChainReferenceCounting(m_data, referenceCountingSize);
{
const OptionalDUChainReferenceCountingEnabler<markForReferenceCounting> optionalRc(m_data, dataSize());
ItemRequest::destroy(item, repository);
}
#ifndef QT_NO_DEBUG
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 800)
......@@ -1043,38 +1028,20 @@ private:
///stored in the repository. It is needed to correctly track the reference counting
///within disk-storage.
template <class Item, bool markForReferenceCounting>
class DynamicItem
class DynamicItem : public OptionalDUChainReferenceCountingEnabler<markForReferenceCounting>
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
Q_DISABLE_COPY_MOVE(DynamicItem)
#else
Q_DISABLE_COPY(DynamicItem)
#endif
public:
explicit DynamicItem(Item* i, const void* start, unsigned size) : m_item(i)
, m_start(start)
, m_size{size}
explicit DynamicItem(Item* i, const void* start, unsigned size)
: OptionalDUChainReferenceCountingEnabler<markForReferenceCounting>(start, size)
, m_item{i}
{
if (markForReferenceCounting)
enableDUChainReferenceCounting(m_start, m_size);
// qDebug() << "enabling" << i << "to" << (void*)(((char*)i)+size);
}
~DynamicItem()
{
if (m_start) {
// qDebug() << "destructor-disabling" << m_item;
if (markForReferenceCounting)
disableDUChainReferenceCounting(m_start, m_size);
}
}
Item* operator->() const { return m_item; }
private:
Item* const m_item;
const void* const m_start;
const unsigned m_size;
};
///@tparam Item See ExampleItem
......
......@@ -110,6 +110,43 @@ KDEVPLATFORMSERIALIZATION_EXPORT void enableDUChainReferenceCounting(const void*
///@param size Size of the area where the reference-counting was started in bytes
KDEVPLATFORMSERIALIZATION_EXPORT void disableDUChainReferenceCounting(const void* start, unsigned size);
class DUChainReferenceCountingEnabler
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
Q_DISABLE_COPY_MOVE(DUChainReferenceCountingEnabler)
#else
Q_DISABLE_COPY(DUChainReferenceCountingEnabler)
#endif
public:
explicit DUChainReferenceCountingEnabler(const void* start, unsigned size)
: m_start{start}
, m_size{size}
{
enableDUChainReferenceCounting(m_start, m_size);
}
~DUChainReferenceCountingEnabler()
{
disableDUChainReferenceCounting(m_start, m_size);
}
private:
const void* const m_start;
const unsigned m_size;
};
template <bool markForReferenceCounting>
struct OptionalDUChainReferenceCountingEnabler
{
explicit OptionalDUChainReferenceCountingEnabler(const void*, unsigned) {}
};
template<>
struct OptionalDUChainReferenceCountingEnabler<true> : DUChainReferenceCountingEnabler
{
using DUChainReferenceCountingEnabler::DUChainReferenceCountingEnabler;
};
///Use this as local variable within the object that maintains the reference-count,
///and use
struct ReferenceCountManager
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment