Pārlūkot izejas kodu

improve performance of Critical lock and unlock

Kolja Strohm 1 nedēļu atpakaļ
vecāks
revīzija
f9a6c0a7d2
6 mainītis faili ar 67 papildinājumiem un 93 dzēšanām
  1. 26 53
      Critical.cpp
  2. 18 22
      Critical.h
  3. 1 0
      Global.cpp
  4. 1 0
      Globals.h
  5. 6 8
      Thread.cpp
  6. 15 10
      Thread.h

+ 26 - 53
Critical.cpp

@@ -13,9 +13,7 @@ using namespace Framework;
 Critical::Critical()
 {
     InitializeCriticalSection(&cs);
-    owner = 0;
     lockCount = 0;
-    id = (int)time(0);
 }
 
 // Destructor
@@ -24,21 +22,11 @@ Critical::~Critical()
     DeleteCriticalSection(&cs);
 }
 
-pthread_t CachedCurrentThread()
-{
-    volatile thread_local static pthread_t t = GetCurrentThread();
-    return (pthread_t)t;
-}
-
 // locks the object
 void Critical::lock()
 {
-    getThreadRegister()->lock();
-    Thread* tmp = getThreadRegister()->zThread(CachedCurrentThread());
-    if (tmp) tmp->addCriticalLock();
-    getThreadRegister()->unlock();
+    currentThreadLockCount++;
     EnterCriticalSection(&cs);
-    if (!owner) owner = tmp;
     lockCount++;
 }
 
@@ -46,12 +34,8 @@ void Critical::lock()
 bool Critical::tryLock()
 {
     if (lockCount > 0) return false;
-    getThreadRegister()->lock();
-    Thread* tmp = getThreadRegister()->zThread(CachedCurrentThread());
-    if (tmp) tmp->addCriticalLock();
-    getThreadRegister()->unlock();
+    currentThreadLockCount++;
     EnterCriticalSection(&cs);
-    if (!owner) owner = tmp;
     lockCount++;
     return true;
 }
@@ -59,23 +43,13 @@ bool Critical::tryLock()
 // unlocks the object
 void Critical::unlock()
 {
-    getThreadRegister()->lock();
-    Thread* tmp = 0;
-    if (getThreadRegister()->isThread(owner))
+    if (lockCount <= 0)
     {
-        if (owner
-            && GetThreadId(owner->getThreadHandle())
-                   != GetThreadId(CachedCurrentThread()))
-            throw std::runtime_error("A Thread that does not own a Critical "
-                                     "Object trys to unlock it");
-        tmp = owner;
+        throw "A Thread tried to unlock a critical that was not locked before";
     }
-    getThreadRegister()->unlock();
-    if (!--lockCount) owner = 0;
+    lockCount--;
     LeaveCriticalSection(&cs);
-    getThreadRegister()->lock();
-    if (tmp && getThreadRegister()->isThread(tmp)) tmp->removeCriticalLock();
-    getThreadRegister()->unlock();
+    currentThreadLockCount--;
 }
 
 // returns true if the object is locked
@@ -84,12 +58,6 @@ bool Critical::isLocked() const
     return lockCount > 0;
 }
 
-// returns a pointer to the thread that locked the object
-const Thread* Critical::zOwner() const
-{
-    return owner;
-}
-
 Synchronizer::Synchronizer()
     : numWaiting(0),
       skip(0)
@@ -153,32 +121,31 @@ int Synchronizer::getNumberOfWaitingThreads() const
     return numWaiting;
 }
 
-Framework::CriticalLock::CriticalLock(
-    std::initializer_list<Critical*> criticals)
+Framework::StackLock::StackLock(std::initializer_list<Lock*> locks)
 {
-    this->criticals = new Critical*[criticals.size()];
+    this->locks = new Lock*[locks.size()];
     int i = 0;
-    for (Critical* c : criticals)
+    for (Lock* c : locks)
     {
-        this->criticals[i] = c;
+        this->locks[i] = c;
         i++;
     }
-    size = (int)criticals.size();
+    size = (int)locks.size();
     if (size > 0)
     {
-        this->criticals[0]->lock();
+        this->locks[0]->lock();
         int index = 1;
         while (index < size)
         {
-            if (!this->criticals[index]->tryLock())
+            if (!this->locks[index]->tryLock())
             {
                 for (int i = 0; i < index; i++)
                 {
-                    this->criticals[i]->unlock();
+                    this->locks[i]->unlock();
                 }
-                this->criticals[index]->lock();
-                this->criticals[index]->unlock();
-                this->criticals[0]->lock();
+                this->locks[index]->lock();
+                this->locks[index]->unlock();
+                this->locks[0]->lock();
                 index = 1;
             }
             else
@@ -187,13 +154,13 @@ Framework::CriticalLock::CriticalLock(
     }
 }
 
-Framework::CriticalLock::~CriticalLock()
+Framework::StackLock::~StackLock()
 {
     for (int i = 0; i < size; i++)
     {
-        criticals[i]->unlock();
+        locks[i]->unlock();
     }
-    delete[] criticals;
+    delete[] locks;
 }
 
 class Framework::InternalReadLock : public Lock
@@ -287,6 +254,7 @@ void Framework::ReadWriteLock::lockRead()
         cs.lock();
         waitingReaders--;
     }
+    currentThreadLockCount++;
     int index = -1;
     for (int i = 0; i < readerThreadCount; i++)
     {
@@ -334,6 +302,7 @@ void Framework::ReadWriteLock::lockWrite()
         cs.lock();
         waitingWriters--;
     }
+    currentThreadLockCount++;
     writerThread = currentThreadId;
     writerCount++;
     cs.unlock();
@@ -367,6 +336,7 @@ void Framework::ReadWriteLock::unlockRead()
     {
         writerBlock.notify();
     }
+    currentThreadLockCount--;
     cs.unlock();
 }
 
@@ -390,6 +360,7 @@ void Framework::ReadWriteLock::unlockWrite()
             readerBlock.notify(waitingReaders);
         }
     }
+    currentThreadLockCount--;
     cs.unlock();
 }
 
@@ -401,6 +372,7 @@ bool Framework::ReadWriteLock::tryLockRead()
         cs.unlock();
         return false;
     }
+    currentThreadLockCount++;
     int index = -1;
     for (int i = 0; i < readerThreadCount; i++)
     {
@@ -445,6 +417,7 @@ bool Framework::ReadWriteLock::tryLockWrite()
         cs.unlock();
         return false;
     }
+    currentThreadLockCount++;
     writerThread = currentThreadId;
     writerCount++;
     cs.unlock();

+ 18 - 22
Critical.h

@@ -9,13 +9,19 @@ namespace Framework
 {
     class Thread;
 
-    class Critical
+    class Lock
+    {
+    public:
+        virtual void lock() = 0;
+        virtual bool tryLock() = 0;
+        virtual void unlock() = 0;
+    };
+
+    class Critical : public Lock
     {
     private:
         CRITICAL_SECTION cs;
-        Thread* owner;
         int lockCount;
-        int id;
 
     public:
         //! Constructor
@@ -23,31 +29,29 @@ namespace Framework
         //! Destructor
         DLLEXPORT ~Critical();
         //! Locks the object
-        DLLEXPORT void lock();
+        DLLEXPORT void lock() override;
         //! Tries to lock the object
-        DLLEXPORT bool tryLock();
+        DLLEXPORT bool tryLock() override;
         //! Unlocks the object
-        DLLEXPORT void unlock();
+        DLLEXPORT void unlock() override;
 
         //! Returns true if the object is locked
         DLLEXPORT bool isLocked() const;
-        //! Returns a pointer to the thread that locked the object
-        DLLEXPORT const Thread* zOwner() const;
     };
 
-    class CriticalLock
+    class StackLock
     {
     private:
-        Critical** criticals;
+        Lock** locks;
         int size;
 
     public:
-        DLLEXPORT CriticalLock(std::initializer_list<Critical*> criticals);
-        DLLEXPORT ~CriticalLock();
+        DLLEXPORT StackLock(std::initializer_list<Lock*> locks);
+        DLLEXPORT ~StackLock();
     };
 
-#define LOCK(x)     CriticalLock _lock(x)
-#define LOCKN(x, i) CriticalLock _lock_##i(x)
+#define LOCK(x)     Framework::StackLock _lock(x)
+#define LOCKN(x, i) Framework::StackLock _lock_##i(x)
 
     class Synchronizer
     {
@@ -70,14 +74,6 @@ namespace Framework
         DLLEXPORT int getNumberOfWaitingThreads() const;
     };
 
-    class Lock
-    {
-    public:
-        virtual void lock() = 0;
-        virtual bool tryLock() = 0;
-        virtual void unlock() = 0;
-    };
-
     class InternalReadLock;
     class InternalWriteLock;
 

+ 1 - 0
Global.cpp

@@ -26,6 +26,7 @@
 void Framework::initFramework(HINSTANCE__* hInst)
 {
     if (isInitialized) return;
+    currentThreadLockCount = 0;
 #ifdef WIN32
     currentThreadId = GetCurrentThreadId();
 #else

+ 1 - 0
Globals.h

@@ -44,6 +44,7 @@ namespace Framework
     Global bool cursorVisible;
     Global Logging::LoggingHandler* loggingHandler;
     Global thread_local int currentThreadId;
+    Global thread_local int currentThreadLockCount;
 
 #ifdef WIN32
     //! Returns the mouse coordinates on the screen

+ 6 - 8
Thread.cpp

@@ -67,7 +67,7 @@ void Thread::ende() // terminates the thread
 {
     if (run)
     {
-        while (lockCount > 0)
+        while (lockCount && *lockCount > 0)
             Sleep(100);
         bool rel = run;
 #ifdef WIN32
@@ -97,6 +97,7 @@ void Thread::thread() // Thread
 void Thread::threadEnd()
 {
     run = 0;
+    lockCount = 0;
     release();
 }
 
@@ -155,14 +156,9 @@ const char* Thread::getName() const
     return name ? name : typeid(*this).name();
 }
 
-void Thread::addCriticalLock()
-{
-    lockCount++;
-}
-
-void Thread::removeCriticalLock()
+void Thread::setLockCount(int* lockCount)
 {
-    lockCount--;
+    this->lockCount = lockCount;
 }
 
 // functions
@@ -172,6 +168,7 @@ unsigned long __stdcall Framework::threadStart(void* param)
     currentThreadId = GetCurrentThreadId();
     if (isThreadOk((Thread*)param))
     {
+        ((Thread*)param)->setLockCount(&currentThreadLockCount);
         const char* name = ((Thread*)param)->getName();
         wchar_t* wc = new wchar_t[textLength(name) + 1];
         size_t l;
@@ -191,6 +188,7 @@ void* Framework::threadStart(void* param)
     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
     if (isThreadOk((Thread*)param))
     {
+        ((Thread*)param)->setLockCount(&currentThreadLockCount);
         pthread_setname_np(
             ((Thread*)param)->getThreadHandle(), ((Thread*)param)->getName());
         ((Thread*)param)->setSystemHandlePointer(&handle);

+ 15 - 10
Thread.h

@@ -11,12 +11,20 @@ namespace Framework
     class Thread;
     class Critical;
 
+#ifdef WIN32
+    //! This function is used by the Thread class to start a thread
+    DLLEXPORT unsigned long __stdcall threadStart(void* param);
+#else
+    //! This function is used by the Thread class to start a thread
+    void* threadStart(void* param); //! starts thread
+#endif
+
     //! A new thread similar to the Thread class from Java
     class Thread : public virtual ReferenceCounter
     {
     private:
         pthread_t* threadHandleSys;
-        int lockCount;
+        int* lockCount;
         const char* name;
 
     protected:
@@ -63,19 +71,16 @@ namespace Framework
         DLLEXPORT const char* getName() const;
 
     private:
-        void addCriticalLock();
-        void removeCriticalLock();
-
-        friend Critical;
-    };
+        void setLockCount(int* lockCount);
 
 #ifdef WIN32
-    //! This function is used by the Thread class to start a thread
-    DLLEXPORT unsigned long __stdcall threadStart(void* param);
+        //! This function is used by the Thread class to start a thread
+        friend DLLEXPORT unsigned long __stdcall threadStart(void* param);
 #else
-    //! This function is used by the Thread class to start a thread
-    void* threadStart(void* param); //! starts thread
+        //! This function is used by the Thread class to start a thread
+        friend void* threadStart(void* param); //! starts thread
 #endif
+    };
 
     //! A class that stores all currently running Thread objects
     class ThreadRegister