Permalink
Browse files

Refs #10311. Reimplements RefererenceCounter using QAtomicInt for loc…

…kless reference counting.

This also renames AddRef to IncrRef and DownRef to DecrRef. This is solely for the benefit of any plugins that might be using the reference counters in MythUI when this is extended to those objects. The MythUI reference counters start at zero instead of one so anything using those will need to remove the UpRef/AddRef immediately post creation.
  • Loading branch information...
daniel-kristjansson committed May 28, 2012
1 parent 6911895 commit 517a34867563021abd084490dd367e78e98d3b60
@@ -679,13 +679,13 @@ void CommandLineArg::SetParentOf(CommandLineArg *other, bool forward)
{
int i;
bool replaced = false;
- other->UpRef();
+ other->IncrRef();
for (i = 0; i < m_children.size(); i++)
{
if (m_children[i]->m_name == other->m_name)
{
- m_children[i]->DownRef();
+ m_children[i]->DecrRef();
m_children.replace(i, other);
replaced = true;
break;
@@ -708,13 +708,13 @@ void CommandLineArg::SetChildOf(CommandLineArg *other, bool forward)
{
int i;
bool replaced = false;
- other->UpRef();
+ other->IncrRef();
for (i = 0; i < m_parents.size(); i++)
{
if (m_parents[i]->m_name == other->m_name)
{
- m_parents[i]->DownRef();
+ m_parents[i]->DecrRef();
m_parents.replace(i, other);
replaced = true;
break;
@@ -737,13 +737,13 @@ void CommandLineArg::SetRequires(CommandLineArg *other, bool forward)
{
int i;
bool replaced = false;
- other->UpRef();
+ other->IncrRef();
for (i = 0; i < m_requires.size(); i++)
{
if (m_requires[i]->m_name == other->m_name)
{
- m_requires[i]->DownRef();
+ m_requires[i]->DecrRef();
m_requires.replace(i, other);
replaced = true;
break;
@@ -767,13 +767,13 @@ void CommandLineArg::SetBlocks(CommandLineArg *other, bool forward)
{
int i;
bool replaced = false;
- other->UpRef();
+ other->IncrRef();
for (i = 0; i < m_blocks.size(); i++)
{
if (m_blocks[i]->m_name == other->m_name)
{
- m_blocks[i]->DownRef();
+ m_blocks[i]->DecrRef();
m_blocks.replace(i, other);
replaced = true;
break;
@@ -808,7 +808,7 @@ void CommandLineArg::AllowOneOf(QList<CommandLineArg*> args)
}
if ((*i1)->m_type == QVariant::Invalid)
- (*i1)->DownRef();
+ (*i1)->DecrRef();
}
}
@@ -970,19 +970,19 @@ void CommandLineArg::CleanupLinks(void)
{
// clear out interdependent pointers in preparation for deletion
while (!m_parents.isEmpty())
- m_parents.takeFirst()->DownRef();
+ m_parents.takeFirst()->DecrRef();
while (!m_children.isEmpty())
- m_children.takeFirst()->DownRef();
+ m_children.takeFirst()->DecrRef();
while (!m_blocks.isEmpty())
- m_blocks.takeFirst()->DownRef();
+ m_blocks.takeFirst()->DecrRef();
while (!m_requires.isEmpty())
- m_requires.takeFirst()->DownRef();
+ m_requires.takeFirst()->DecrRef();
while (!m_requiredby.isEmpty())
- m_requiredby.takeFirst()->DownRef();
+ m_requiredby.takeFirst()->DecrRef();
}
/** \brief Internal use. Print processed input in verbose mode.
@@ -1140,14 +1140,14 @@ MythCommandLineParser::~MythCommandLineParser()
while (i != m_namedArgs.end())
{
(*i)->CleanupLinks();
- (*i)->DownRef();
+ (*i)->DecrRef();
i = m_namedArgs.erase(i);
}
i = m_optionedArgs.begin();
while (i != m_optionedArgs.end())
{
- (*i)->DownRef();
+ (*i)->DecrRef();
i = m_optionedArgs.erase(i);
}
}
@@ -1206,7 +1206,7 @@ CommandLineArg* MythCommandLineParser::add(QStringList arglist,
cerr << "Adding " << (*i).toLocal8Bit().constData()
<< " as taking type '" << QVariant::typeToName(type)
<< "'" << endl;
- arg->UpRef();
+ arg->IncrRef();
m_optionedArgs.insert(*i, arg);
}
}
@@ -1717,7 +1717,7 @@ bool MythCommandLineParser::ReconcileLinks(void)
}
}
- (*i2)->DownRef();
+ (*i2)->DecrRef();
i2 = (*i1)->m_requiredby.erase(i2);
}
@@ -1732,7 +1732,7 @@ bool MythCommandLineParser::ReconcileLinks(void)
if (!m_namedArgs.contains((*i2)->m_name))
{
- (*i2)->DownRef();
+ (*i2)->DecrRef();
i2 = (*i1)->m_blocks.erase(i2);
continue; // if it doesnt exist, it cant block this command
}
@@ -1,54 +1,42 @@
// -*- Mode: c++ -*-
#include <QString>
-#include <QMutexLocker>
#include "referencecounter.h"
#include "mythlogging.h"
-ReferenceCounter::ReferenceCounter(void) :
- m_refCount(1)
+ReferenceCounter::ReferenceCounter(void) : m_referenceCount(1)
{
}
-void ReferenceCounter::UpRef(void)
+ReferenceCounter::~ReferenceCounter(void)
{
- QMutexLocker mlock(&m_refLock);
- m_refCount++;
- LOG(VB_REFCOUNT, LOG_DEBUG, QString("%1(0x%2)::UpRef() -> %3")
- .arg(metaObject()->className())
- .arg((uint64_t)this,0,16)
- .arg(QString::number(m_refCount)));
+ if (0 != m_referenceCount)
+ {
+ LOG(VB_GENERAL, LOG_ERR,
+ "Object deleted with non-zero reference count!");
+ }
}
-bool ReferenceCounter::DownRef(void)
+void ReferenceCounter::IncrRef(void)
{
- m_refLock.lock();
- m_refCount--;
- LOG(VB_REFCOUNT, LOG_DEBUG, QString("%1(0x%2)::DownRef() -> %3")
- .arg(metaObject()->className())
- .arg((uint64_t)this,0,16)
- .arg(QString::number(m_refCount)));
-
- if (m_refCount == 0)
+ int val = m_referenceCount.fetchAndAddRelease(1);
+
+ LOG(VB_REFCOUNT, LOG_DEBUG, QString("(0x%2)::IncrRef() -> %3")
+ .arg(reinterpret_cast<intptr_t>(this),0,16).arg(val));
+}
+
+bool ReferenceCounter::DecrRef(void)
+{
+ int val = m_referenceCount.fetchAndAddRelaxed(-1);
+
+ LOG(VB_REFCOUNT, LOG_DEBUG, QString("(0x%2)::DecrRef() -> %3")
+ .arg(reinterpret_cast<intptr_t>(this),0,16).arg(val));
+
+ if (0 == val)
{
- m_refLock.unlock();
delete this;
return true;
}
- m_refLock.unlock();
return false;
}
-
-ReferenceLocker::ReferenceLocker(ReferenceCounter *counter, bool upref) :
- m_refObject(counter)
-{
- if (upref)
- m_refObject->UpRef();
-}
-
-ReferenceLocker::~ReferenceLocker(void)
-{
- m_refObject->DownRef();
- m_refObject = NULL;
-}
@@ -3,31 +3,53 @@
#ifndef MYTHREFCOUNT_H_
#define MYTHREFCOUNT_H_
-#include <QObject>
-#include <QMutex>
+#include <QAtomicInt>
#include "mythbaseexp.h"
-class MBASE_PUBLIC ReferenceCounter : public QObject
+/** \brief General purpose reference counter.
+ *
+ * This class uses QAtomicInt for lockless reference counting.
+ *
+ */
+class MBASE_PUBLIC ReferenceCounter
{
- Q_OBJECT
public:
+ /// Creates reference counter with an initial value of 1.
ReferenceCounter(void);
- ~ReferenceCounter(void) {};
- virtual void UpRef(void);
- virtual bool DownRef(void);
+ /// Increments reference count.
+ void IncrRef(void);
+
+ /// Decrements reference count and deletes on 0.
+ /// \return true if object is deleted
+ bool DecrRef(void);
+
+ protected:
+ /// Called on destruction, will warn if object deleted with
+ /// references in place. Set breakpoint here for debugging.
+ virtual ~ReferenceCounter(void);
+
private:
- QMutex m_refLock;
- uint m_refCount;
+ QAtomicInt m_referenceCount;
};
+/** \brief This decrements the reference on destruction.
+ *
+ * This can be used to ensure a reference to an object is decrimented
+ * at the end of the scope containing ReferenceLocker.
+ *
+ */
class MBASE_PUBLIC ReferenceLocker
{
public:
- ReferenceLocker(ReferenceCounter *counter, bool upref=true);
- ~ReferenceLocker();
+ ReferenceLocker(ReferenceCounter *counter) : m_counter(counter) { }
+ ~ReferenceLocker()
+ {
+ if (m_counter)
+ m_counter->DecrRef();
+ }
private:
- ReferenceCounter *m_refObject;
+ ReferenceCounter *m_counter;
};
#endif
@@ -123,7 +123,7 @@ void MythSocketManager::AddSocketHandler(SocketHandler *sock)
if (m_socketMap.contains(sock->GetSocket()))
return;
- sock->UpRef();
+ sock->IncrRef();
m_socketMap.insert(sock->GetSocket(), sock);
}
@@ -134,7 +134,7 @@ SocketHandler *MythSocketManager::GetConnectionBySocket(MythSocket *sock)
return NULL;
SocketHandler *handler = m_socketMap[sock];
- handler->UpRef();
+ handler->IncrRef();
return handler;
}
@@ -166,7 +166,7 @@ void MythSocketManager::connectionClosed(MythSocket *sock)
if (m_socketMap.contains(sock))
{
SocketHandler *handler = m_socketMap.take(sock);
- handler->DownRef();
+ handler->DecrRef();
}
}
}
@@ -301,7 +301,7 @@ void MythSocketManager::ProcessRequestWork(MythSocket *sock)
}
SocketHandler *handler = GetConnectionBySocket(sock);
- ReferenceLocker hlock(handler, false);
+ ReferenceLocker hlock(handler);
QMap<QString, SocketRequestHandler*>::const_iterator i
= m_handlerMap.constBegin();
@@ -46,7 +46,7 @@ bool BaseRequestHandler::HandleAnnounce(MythSocket *socket,
QStringList sl; sl << "OK";
handler->SendStringList(sl);
- handler->DownRef();
+ handler->DecrRef();
handler = NULL;
LOG(VB_GENERAL, LOG_DEBUG, QString("MainServer::ANN %1")
@@ -52,7 +52,7 @@ void DeleteThread::run(void)
// this will only happen if the program is closing, so fast
// deletion is not a problem
QList<DeleteHandler*>::iterator i;
- (*i)->DownRef();
+ (*i)->DecrRef();
}
else
LOG(VB_FILE, LOG_DEBUG, "Delete thread self-terminating due to idle.");
@@ -75,7 +75,7 @@ bool DeleteThread::AddFile(QString path)
bool DeleteThread::AddFile(DeleteHandler *handler)
{
- handler->UpRef();
+ handler->IncrRef();
QMutexLocker lock(&m_newlock);
m_newfiles << handler;
return true;
@@ -124,7 +124,7 @@ void DeleteThread::ProcessNew(void)
QString("Error deleting '%1' -> '%2': ")
.arg(handler->m_path).arg(tmppath) + ENO);
handler->DeleteFailed();
- handler->DownRef();
+ handler->DecrRef();
continue;
}
@@ -155,7 +155,7 @@ void DeleteThread::ProcessNew(void)
else
handler->DeleteFailed();
- handler->DownRef();
+ handler->DecrRef();
continue;
}
}
@@ -170,7 +170,7 @@ void DeleteThread::ProcessNew(void)
QString("Error deleting '%1': could not open ")
.arg(handler->m_path) + ENO);
handler->DeleteFailed();
- handler->DownRef();
+ handler->DecrRef();
continue;
}
@@ -183,7 +183,7 @@ void DeleteThread::ProcessNew(void)
.arg(path) + ENO);
handler->DeleteFailed();
close(fd);
- handler->DownRef();
+ handler->DecrRef();
continue;
}
@@ -236,7 +236,7 @@ void DeleteThread::ProcessOld(void)
{
handler->Close();
m_files.removeFirst();
- handler->DownRef();
+ handler->DecrRef();
}
// fast delete can close out all, but slow delete needs
Oops, something went wrong.

0 comments on commit 517a348

Please sign in to comment.