{"id":282711,"date":"2016-12-19T17:40:04","date_gmt":"2016-12-19T14:40:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=282711"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=282711","title":{"rendered":"\u041f\u043e\u0440\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u0439 RWLock \u0434\u043b\u044f Windows"},"content":{"rendered":"<p>RWLock \u2014 \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u0438 \u044d\u043a\u0441\u043a\u043b\u044e\u0437\u0438\u0432\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. \u0422.\u0435. \u0447\u0442\u0435\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c, \u043d\u043e \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0440\u0435\u0434\u043e\u0432, \u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435.<br \/>  <a name=\"habracut\"><\/a><br \/>  \u0422\u0430\u043a \u0432\u043e\u0442, \u044d\u0442\u043e\u0442 \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432 posix threads \u0438 \u0432 Windows \u043e\u0442 Vista \u0438 \u0434\u0430\u043b\u0435\u0435. \u0414\u043b\u044f Windows XP\/2003 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0437\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0439, \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439, \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u0438\u0437 \u0434\u0432\u0443\u0445 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u0435\u043a\u0446\u0438\u0439 \u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f.<\/p>\n<p>  \u041f\u043e\u043a\u0430\u0436\u0435\u043c \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 (\u043a\u043e\u0434 \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d StackOverflow \u0438 \u0441\u043b\u0435\u0433\u043a\u0430 \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d \u0441 C \u043d\u0430 C++):<\/p>\n<pre><code class=\"cpp\">class RWLockXP \/\/ Implementation for Windows XP { public:     RWLockXP()         : countsLock(),           writerLock(),           noReaders(),           readerCount(0),           waitingWriter(FALSE)     {         InitializeCriticalSection(&writerLock);         InitializeCriticalSection(&countsLock);         \/*         * Could use a semaphore as well.  There can only be one waiter ever,         * so I'm showing an auto-reset event here.         *\/         noReaders = CreateEvent (NULL, FALSE, FALSE, NULL);     }      ~RWLockXP()     {         writerLock.destroy();         readerCountLock.destroy();         noReaders.destroy();     }      void readLock()     {         \/**          * We need to lock the writerLock too, otherwise a writer could          * do the whole of rwlock_wrlock after the readerCount changed          * from 0 to 1, but before the event was reset.          *\/          EnterCriticalSection(&writerLock);         EnterCriticalSection(&countsLock);         ++readerCount;         LeaveCriticalSection(&countsLock);         LeaveCriticalSection(&writerLock);     }     void readUnLock()     {         EnterCriticalSection(&countsLock);         assert (readerCount &gt; 0);         if (--readerCount == 0)         {             if (waitingWriter)             {                 \/*                  * Clear waitingWriter here to avoid taking countsLock                  * again in wrlock.                  *\/                 waitingWriter = FALSE;                 SetEvent(noReaders);             }         }         LeaveCriticalSection(&countsLock);     }      void writeLock()     {         EnterCriticalSection(&writerLock);         \/*          * readerCount cannot become non-zero within the writerLock CS,          * but it can become zero...          *\/         if (readerCount &gt; 0)         {             EnterCriticalSection(&countsLock);              \/* ... so test it again.  *\/             if (readerCount &gt; 0)             {                 waitingWriter = TRUE;                 LeaveCriticalSection(&countsLock);                 WaitForSingleObject(noReaders, INFINITE);             }             else             {                 \/* How lucky, no need to wait.  *\/                 LeaveCriticalSection(&countsLock);             }         }         \/* writerLock remains locked.  *\/     }      void writeUnLock()     {         LeaveCriticalSection(&writerLock);     }  private:     CRITICAL_SECTION countsLock;     CRITICAL_SECTION writerLock;     HANDLE noReaders;     int readerCount;     BOOL waitingWriter; }; <\/code><\/pre>\n<p>  \u0410 \u0432\u043e\u0442 \u043a\u0430\u043a \u044d\u0442\u0430 \u0436\u0435 \u043a\u0440\u0430\u0441\u043e\u0442\u0430 \u043c\u043e\u0433\u043b\u0430 \u0431\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e Vista+ \u0441\u0438\u0441\u0442\u0435\u043c:<\/p>\n<pre><code class=\"cpp\">class RWLockSRW \/\/ For Windows Vista+ based on Slim RWLock { public:     RWLockSRW()         : srwLock()     {         InitializeSRWLock(&srwLock);     }      ~RWLockSRW()     {     }      void readLock()     {         AcquireSRWLockShared(&srwLock);     }      void readUnLock()     {         ReleaseSRWLockShared(&srwLock);     }      void writeLock()     {         AcquireSRWLockExclusive(&srwLock);     }      void writeUnLock()     {         ReleaseSRWLockExclusive(&srwLock);     }  private:     RTL_SRWLOCK srwLock; }; <\/code><\/pre>\n<p>  \u041c\u0430\u043b\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u043e \u0431\u0435\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e, \u0435\u0449\u0435 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0431\u044b\u0441\u0442\u0440\u0435\u0435. \u041d\u043e, \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u043e \u043d\u043e, \u043a\u0430\u043a \u0432\u0441\u0435\u0433\u0434\u0430\u2026 \u041f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 (\u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043c\u044b \u0443\u043c\u043d\u044b\u0435 \u0440\u0435\u0431\u044f\u0442\u0430, \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438 \u0434\u043b\u044f XP \u0445\u043e\u0442\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0430 \u0434\u043b\u044f \u043d\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u2014 \u0432\u0442\u043e\u0440\u043e\u0439), \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430: \u00ab\u043e\u0439, \u0430 \u0432\u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 InitializeSRWLock \u0447\u0442\u043e-\u0442\u043e \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0432 kernel32\u00bb \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0431\u0438\u0442\u043e.<\/p>\n<p>  \u0412\u044b\u0445\u043e\u0434 \u2014 \u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Slim RWLock \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 LoadLibrary, \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u044d\u0442\u043e\u0433\u043e \u0432\u0441\u0435\u0433\u043e:<\/p>\n<pre><code class=\"cpp\">typedef void(__stdcall *SRWLock_fptr)(PSRWLOCK);  class RWLockSRW \/\/ For Windows Vista+ based on Slim RWLock { public:     RWLockSRW()         : hGetProcIDDLL(NULL),          AcquireSRWLockShared_func(NULL),         ReleaseSRWLockShared_func(NULL),         AcquireSRWLockExclusive_func(NULL),         ReleaseSRWLockExclusive_func(NULL),         srwLock()     {         wchar_t path[MAX_PATH] = { 0 };         GetSystemDirectory(path, sizeof(path));         std::wstring dllPath = std::wstring(path) + L&quot;\\\\kernel32.dll&quot;;         HINSTANCE hGetProcIDDLL = LoadLibrary(dllPath.c_str());         if (!hGetProcIDDLL)         {             throw std::exception(&quot;SRWLock Error loading kernel32.dll&quot;);         }          AcquireSRWLockShared_func = (SRWLock_fptr)GetProcAddress(hGetProcIDDLL, &quot;AcquireSRWLockShared&quot;);         if (!AcquireSRWLockShared_func)         {             throw std::exception(&quot;SRWLock Error loading AcquireSRWLockShared&quot;);         }          ReleaseSRWLockShared_func = (SRWLock_fptr)GetProcAddress(hGetProcIDDLL, &quot;ReleaseSRWLockShared&quot;);         if (!ReleaseSRWLockShared_func)         {             throw std::exception(&quot;SRWLock Error loading ReleaseSRWLockShared&quot;);         }          AcquireSRWLockExclusive_func = (SRWLock_fptr)GetProcAddress(hGetProcIDDLL, &quot;AcquireSRWLockExclusive&quot;);         if (!AcquireSRWLockExclusive_func)         {             throw std::exception(&quot;SRWLock Error loading AcquireSRWLockExclusive&quot;);         }          ReleaseSRWLockExclusive_func = (SRWLock_fptr)GetProcAddress(hGetProcIDDLL, &quot;ReleaseSRWLockExclusive&quot;);         if (!ReleaseSRWLockExclusive_func)         {             throw std::exception(&quot;SRWLock Error loading ReleaseSRWLockExclusive&quot;);         }          SRWLock_fptr InitializeSRWLock_func = (SRWLock_fptr)GetProcAddress(hGetProcIDDLL, &quot;InitializeSRWLock&quot;);         if (!InitializeSRWLock_func)         {             throw std::exception(&quot;SRWLock Error loading InitializeSRWLock&quot;);         }          InitializeSRWLock_func(&srwLock);     }      ~RWLockSRW()     {         if (hGetProcIDDLL)         {             FreeLibrary(hGetProcIDDLL);         }     }      void readLock()     {         if (AcquireSRWLockShared_func)         {             AcquireSRWLockShared_func(&srwLock);         }     }      void readUnLock()     {         if (ReleaseSRWLockShared_func)         {             ReleaseSRWLockShared_func(&srwLock);         }     }      void writeLock()     {         if (AcquireSRWLockExclusive_func)         {             AcquireSRWLockExclusive_func(&srwLock);         }     }      void writeUnLock()     {         if (ReleaseSRWLockExclusive_func)         {             ReleaseSRWLockExclusive_func(&srwLock);         }     }  private:     HINSTANCE hGetProcIDDLL;      SRWLock_fptr AcquireSRWLockShared_func;     SRWLock_fptr ReleaseSRWLockShared_func;     SRWLock_fptr AcquireSRWLockExclusive_func;     SRWLock_fptr ReleaseSRWLockExclusive_func;      RTL_SRWLOCK srwLock; }; <\/code><\/pre>\n<p>  \u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0443\u0447\u0435\u0440\u044f\u0432\u0435\u0439, \u0437\u0430\u0442\u043e \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u0440\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0440\u0430\u043f\u043f\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0449\u0438\u0439 \u043d\u0443\u0436\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0435\u0440\u0441\u0438\u0438 Windows:<\/p>\n<pre><code class=\"cpp\">class RWLock \/\/ Wrapper { public:      RWLock()          : rwLockXP(NULL), rwLockSRW(NULL), isVistaPlus(IsWindowsVistaOrGreater())      {           if (isVistaPlus)           {                rwLockSRW = new RWLockSRW();           }           else           {                rwLockXP = new RWLockXP();           }      }       ~RWLock()      {           if (isVistaPlus)           {                delete rwLockSRW;           }           else           {                delete rwLockXP;           }      }      void readLock()      {           if (isVistaPlus)           {                rwLockSRW-&gt;readLock();           }           else           {                rwLockXP-&gt;readLock();           }      }      void readUnLock()      {           if (isVistaPlus)           {                rwLockSRW-&gt;readUnLock();           }           else           {                rwLockXP-&gt;readUnLock();           }      }       void writeLock()      {           if (isVistaPlus)           {                rwLockSRW-&gt;writeLock();           }           else           {                rwLockXP-&gt;writeLock();           }      }      void writeUnLock()      {           if (isVistaPlus)           {                rwLockSRW-&gt;writeUnLock();           }           else           {                rwLockXP-&gt;writeUnLock();           }      }  private:      RWLockXP  *rwLockXP;      RWLockSRW *rwLockSRW;      bool isVistaPlus; }; <\/code><\/pre>\n<p>  \u0418 \u0432 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0430\u0432\u0442\u043e\u043b\u043e\u043a\u0435\u0440:<\/p>\n<pre><code class=\"cpp\">class ScopedRWLock { public:     ScopedRWLock(RWLock *lc_, bool write_ = false)         : lc(*lc_), write(write_)     {         if (write)         {             lc.writeLock();         }         else         {             lc.readLock();         }     }      ~ScopedRWLock()     {         if (write)         {             lc.writeUnLock();         }         else         {             lc.readUnLock();         }     } private:     RWLock &lc;     bool write;      \/\/ Non copyable!     static void *operator new(size_t);     static void operator delete(void *);     ScopedRWLock(const ScopedRWLock&);     void operator=(const ScopedRWLock&); }; <\/code><\/pre>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c pthread \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 SRWLock \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u0445 \u0438\u043c\u0435\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439.<br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/317958\/\"> https:\/\/habrahabr.ru\/post\/317958\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>RWLock \u2014 \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u0438 \u044d\u043a\u0441\u043a\u043b\u044e\u0437\u0438\u0432\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. \u0422.\u0435. \u0447\u0442\u0435\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c, \u043d\u043e \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0440\u0435\u0434\u043e\u0432, \u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-282711","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/282711","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=282711"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/282711\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=282711"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=282711"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=282711"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}