Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "rw_lock_win.h"
     12 
     13 #include "critical_section_wrapper.h"
     14 #include "condition_variable_wrapper.h"
     15 #include "trace.h"
     16 
     17 // TODO (hellner) why not just use the rw_lock_generic.cc solution if
     18 //                           native is not supported? Unnecessary redundancy!
     19 
     20 namespace webrtc {
     21 bool RWLockWindows::_winSupportRWLockPrimitive = false;
     22 static HMODULE library = NULL;
     23 
     24 PInitializeSRWLock       _PInitializeSRWLock;
     25 PAcquireSRWLockExclusive _PAcquireSRWLockExclusive;
     26 PAcquireSRWLockShared    _PAcquireSRWLockShared;
     27 PReleaseSRWLockShared    _PReleaseSRWLockShared;
     28 PReleaseSRWLockExclusive _PReleaseSRWLockExclusive;
     29 
     30 RWLockWindows::RWLockWindows()
     31     : _critSectPtr(NULL),
     32       _readCondPtr(NULL),
     33       _writeCondPtr(NULL),
     34       _readersActive(0),
     35       _writerActive(false),
     36       _readersWaiting(0),
     37       _writersWaiting(0)
     38 {
     39 }
     40 
     41 RWLockWindows::~RWLockWindows()
     42 {
     43     delete _writeCondPtr;
     44     delete _readCondPtr;
     45     delete _critSectPtr;
     46 }
     47 
     48 int RWLockWindows::Init()
     49 {
     50     if(!library)
     51     {
     52         // Use native implementation if supported (i.e Vista+)
     53         library = LoadLibrary(TEXT("Kernel32.dll"));
     54         if(library)
     55         {
     56             WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
     57                          "Loaded Kernel.dll");
     58 
     59             _PInitializeSRWLock =
     60                 (PInitializeSRWLock)GetProcAddress(
     61                     library,
     62                     "InitializeSRWLock");
     63 
     64             _PAcquireSRWLockExclusive =
     65                (PAcquireSRWLockExclusive)GetProcAddress(
     66                    library,
     67                    "AcquireSRWLockExclusive");
     68             _PReleaseSRWLockExclusive =
     69                 (PReleaseSRWLockExclusive)GetProcAddress(
     70                     library,
     71                     "ReleaseSRWLockExclusive");
     72             _PAcquireSRWLockShared =
     73                 (PAcquireSRWLockShared)GetProcAddress(
     74                     library,
     75                     "AcquireSRWLockShared");
     76             _PReleaseSRWLockShared =
     77                 (PReleaseSRWLockShared)GetProcAddress(
     78                     library,
     79                     "ReleaseSRWLockShared");
     80 
     81             if( _PInitializeSRWLock &&
     82                 _PAcquireSRWLockExclusive &&
     83                 _PReleaseSRWLockExclusive &&
     84                 _PAcquireSRWLockShared &&
     85                 _PReleaseSRWLockShared )
     86             {
     87                 WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
     88                             "Loaded Simple RW Lock");
     89                 _winSupportRWLockPrimitive = true;
     90             }
     91         }
     92     }
     93     if(_winSupportRWLockPrimitive)
     94     {
     95         _PInitializeSRWLock(&_lock);
     96     } else {
     97         _critSectPtr  = CriticalSectionWrapper::CreateCriticalSection();
     98         _readCondPtr  = ConditionVariableWrapper::CreateConditionVariable();
     99         _writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
    100     }
    101     return 0;
    102 }
    103 
    104 void RWLockWindows::AcquireLockExclusive()
    105 {
    106     if (_winSupportRWLockPrimitive)
    107     {
    108         _PAcquireSRWLockExclusive(&_lock);
    109     } else {
    110         _critSectPtr->Enter();
    111 
    112         if (_writerActive || _readersActive > 0)
    113         {
    114             ++_writersWaiting;
    115             while (_writerActive || _readersActive > 0)
    116             {
    117                 _writeCondPtr->SleepCS(*_critSectPtr);
    118             }
    119             --_writersWaiting;
    120         }
    121         _writerActive = true;
    122         _critSectPtr->Leave();
    123     }
    124 }
    125 
    126 void RWLockWindows::ReleaseLockExclusive()
    127 {
    128     if(_winSupportRWLockPrimitive)
    129     {
    130         _PReleaseSRWLockExclusive(&_lock);
    131     } else {
    132         _critSectPtr->Enter();
    133         _writerActive = false;
    134         if (_writersWaiting > 0)
    135         {
    136             _writeCondPtr->Wake();
    137 
    138         }else if (_readersWaiting > 0) {
    139             _readCondPtr->WakeAll();
    140         }
    141         _critSectPtr->Leave();
    142     }
    143 }
    144 
    145 void RWLockWindows::AcquireLockShared()
    146 {
    147     if(_winSupportRWLockPrimitive)
    148     {
    149         _PAcquireSRWLockShared(&_lock);
    150     } else
    151     {
    152         _critSectPtr->Enter();
    153         if (_writerActive || _writersWaiting > 0)
    154         {
    155             ++_readersWaiting;
    156 
    157             while (_writerActive || _writersWaiting > 0)
    158             {
    159                 _readCondPtr->SleepCS(*_critSectPtr);
    160             }
    161             --_readersWaiting;
    162         }
    163         ++_readersActive;
    164         _critSectPtr->Leave();
    165     }
    166 }
    167 
    168 void RWLockWindows::ReleaseLockShared()
    169 {
    170     if(_winSupportRWLockPrimitive)
    171     {
    172         _PReleaseSRWLockShared(&_lock);
    173     } else
    174     {
    175         _critSectPtr->Enter();
    176 
    177         --_readersActive;
    178 
    179         if (_readersActive == 0 && _writersWaiting > 0)
    180         {
    181             _writeCondPtr->Wake();
    182         }
    183         _critSectPtr->Leave();
    184     }
    185 }
    186 } // namespace webrtc
    187