Index: base/synchronized.cc |
diff --git a/base/synchronized.cc b/base/synchronized.cc |
deleted file mode 100644 |
index d8a9b65c59e7eb33fa6bdeec0f84406f0f9b17a6..0000000000000000000000000000000000000000 |
--- a/base/synchronized.cc |
+++ /dev/null |
@@ -1,512 +0,0 @@ |
-// Copyright 2004-2009 Google Inc. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
-// ======================================================================== |
-// |
-// Defines methods of classes used to encapsulate |
-// the synchronization primitives. |
- |
-#include "omaha/base/synchronized.h" |
- |
-#include "omaha/base/debug.h" |
-#include "omaha/base/error.h" |
-#include "omaha/base/logging.h" |
-#include "omaha/base/system.h" |
-#include "omaha/base/system_info.h" |
-#include "omaha/base/user_info.h" |
-#include "omaha/base/utils.h" |
- |
-namespace omaha { |
- |
-typedef HANDLE WINAPI CreateMutexExFunction( |
- LPSECURITY_ATTRIBUTES attributes, |
- const WCHAR* name, |
- DWORD flags, |
- DWORD desired_access |
-); |
- |
-#define CREATE_EVENT_MANUAL_RESET 0x01 |
-typedef HANDLE WINAPI CreateEventExFunction( |
- LPSECURITY_ATTRIBUTES attributes, |
- const WCHAR* name, |
- DWORD flags, |
- DWORD desired_access |
-); |
- |
-CreateMutexExFunction* create_mutex_ex_function = NULL; |
-CreateEventExFunction* create_event_ex_function = NULL; |
- |
-void EnsureCreateEx() { |
- if ((create_mutex_ex_function && create_event_ex_function) || |
- !SystemInfo::IsRunningOnVistaOrLater()) { |
- return; |
- } |
- |
- HMODULE kernel32_module = ::GetModuleHandle(_T("kernel32.dll")); |
- if (!kernel32_module) { |
- ASSERT(kernel32_module, |
- (_T("[GetModuleHandle error 0x%x]"), ::GetLastError())); |
- return; |
- } |
- GPA(kernel32_module, "CreateMutexExW", &create_mutex_ex_function); |
- ASSERT(create_mutex_ex_function, |
- (_T("[GPA error 0x%x]"), ::GetLastError())); |
- |
- GPA(kernel32_module, "CreateEventExW", &create_event_ex_function); |
- ASSERT(create_event_ex_function, |
- (_T("[GPA error 0x%x]"), ::GetLastError())); |
-} |
- |
-HANDLE CreateMutexWithSyncAccess(const TCHAR* name, |
- LPSECURITY_ATTRIBUTES lock_attributes) { |
- EnsureCreateEx(); |
- if (create_mutex_ex_function) { |
- return create_mutex_ex_function(lock_attributes, name, 0, |
- SYNCHRONIZE | |
- MUTEX_MODIFY_STATE); // for ReleaseMutex |
- } |
- return ::CreateMutex(lock_attributes, false, name); |
-} |
- |
-HANDLE CreateEventWithSyncAccess(const TCHAR* name, |
- LPSECURITY_ATTRIBUTES event_attributes) { |
- EnsureCreateEx(); |
- if (create_event_ex_function) { |
- return create_event_ex_function(event_attributes, name, |
- CREATE_EVENT_MANUAL_RESET, |
- SYNCHRONIZE | |
- EVENT_MODIFY_STATE); // for Set/Reset, etc. |
- } |
- return ::CreateEvent(event_attributes, true, false, name); |
-} |
- |
-// c-tor will take mutex. |
-AutoSync::AutoSync(const Lockable *pLock) |
- : lock_(pLock), |
- first_time_(true) { |
- ASSERT(lock_, (L"")); |
- VERIFY(lock_->Lock(), (L"Failed to lock in constructor")); |
-} |
- |
-// c-tor will take mutex. |
-AutoSync::AutoSync(const Lockable &rLock) |
- : lock_(&rLock), |
- first_time_(true) { |
- ASSERT(lock_, (L"")); |
- VERIFY(lock_->Lock(), (L"Failed to lock in constructor")); |
-} |
- |
-// d-tor will release mutex. |
-AutoSync::~AutoSync() { |
- ASSERT(lock_, (L"")); |
- VERIFY(lock_->Unlock(), (L"Failed to unlock in denstructor")); |
-} |
- |
-// Allows to write the for loop of __mutexBlock macro |
-bool AutoSync::FirstTime() { |
- if (first_time_) { |
- first_time_ = false; |
- return true; |
- } |
- return false; |
-} |
- |
-// Constructor. |
-GLock::GLock() : mutex_(NULL) { |
-} |
- |
-bool GLock::InitializeWithSecAttr(const TCHAR* name, |
- LPSECURITY_ATTRIBUTES lock_attributes) { |
- ASSERT(!mutex_, (L"")); |
- |
-#if defined(DEBUG) || defined(ASSERT_IN_RELEASE) |
- name_ = name; |
-#endif |
- |
- mutex_ = CreateMutexWithSyncAccess(name, lock_attributes); |
- return mutex_ != NULL; |
-} |
- |
-// Create mutex return the status of creation. Sets to default DACL. |
-bool GLock::Initialize(const TCHAR* name) { |
- return InitializeWithSecAttr(name, NULL); |
-} |
- |
-// Clean up. |
-GLock::~GLock() { |
- if (mutex_) { |
- VERIFY(::CloseHandle(mutex_), (_T(""))); |
- } |
-}; |
- |
-// Wait until signaled. |
-bool GLock::Lock() const { |
- return Lock(INFINITE); |
-} |
- |
-bool GLock::Lock(DWORD dwMilliseconds) const { |
- ASSERT1(mutex_); |
- |
- DWORD ret = ::WaitForSingleObject(mutex_, dwMilliseconds); |
- if (ret == WAIT_OBJECT_0) { |
- return true; |
- } else if (ret == WAIT_ABANDONED) { |
- UTIL_LOG(LE, (_T("[GLock::Lock - mutex was abandoned %s]"), name_)); |
- return true; |
- } |
- return false; |
-} |
- |
-// Release. |
-bool GLock::Unlock() const { |
- ASSERT1(mutex_); |
- |
- bool ret = (false != ::ReleaseMutex(mutex_)); |
- ASSERT(ret, (_T("ReleaseMutex failed. Err=%i"), ::GetLastError())); |
- |
- return ret; |
-} |
- |
-LLock::LLock() { |
- InitializeCriticalSection(&critical_section_); |
-} |
- |
-LLock::~LLock() { |
- DeleteCriticalSection(&critical_section_); |
-} |
- |
-bool LLock::Lock() const { |
- EnterCriticalSection(&critical_section_); |
- return true; |
-} |
- |
-// not very precise funcion, but OK for our goals. |
-bool LLock::Lock(DWORD wait_ms) const { |
- if (::TryEnterCriticalSection(&critical_section_)) |
- return true; |
- DWORD ticks_at_the_begin_of_wait = GetTickCount(); |
- do { |
- ::Sleep(0); |
- if (::TryEnterCriticalSection(&critical_section_)) { |
- return true; |
- } |
- } while (::GetTickCount() - ticks_at_the_begin_of_wait < wait_ms); |
- return false; |
-} |
- |
-bool LLock::Unlock() const { |
- LeaveCriticalSection(&critical_section_); |
- return true; |
-} |
- |
-// LockCount is initialized to a value of -1; a value of 0 or greater indicates |
-// that the critical section is held or owned. When LockCount is not equal |
-// to -1, the OwningThread field contains the thread id that owns the section. |
-DWORD LLock::GetOwner() const { |
- return critical_section_.LockCount != -1 ? |
- reinterpret_cast<DWORD>(critical_section_.OwningThread) : 0; |
-} |
- |
-// Use this c-tor for interprocess gates. |
-Gate::Gate(const TCHAR * event_name) : gate_(NULL) { |
- VERIFY(Initialize(event_name), (_T(""))); |
-} |
- |
-// Use this c-tor for in-process gates. |
-Gate::Gate() : gate_(NULL) { |
- VERIFY(Initialize(NULL), (_T(""))); |
-} |
- |
-// clean up. |
-Gate::~Gate() { |
- VERIFY(CloseHandle(gate_), (_T(""))); |
-} |
- |
-bool Gate::Initialize(const TCHAR * event_name) { |
- // event_name may be NULL |
- ASSERT1(gate_ == NULL); |
- |
- // Create the event. The gate is initially closed. |
- // if this is in process gate we don't name event, otherwise we do. |
- // Created with default permissions. |
- gate_ = CreateEventWithSyncAccess(event_name, NULL); |
- return (NULL != gate_); |
-} |
- |
-// Open the gate. Anyone can go through. |
-bool Gate::Open() { |
- return FALSE != SetEvent(gate_); |
-} |
- |
-// Shut the gate closed. |
-bool Gate::Close() { |
- return FALSE != ResetEvent(gate_); |
-} |
- |
-bool Gate::Wait(DWORD msec) { |
- return WAIT_OBJECT_0 == WaitForSingleObject(gate_, msec); |
-} |
- |
-// Returns S_OK, and sets selected_gate to zero based index of the gate that |
-// was opened |
-// Returns E_FAIL if timeout occured or gate was abandoned. |
-HRESULT Gate::WaitAny(Gate const * const *gates, |
- int num_gates, |
- DWORD msec, |
- int *selected_gate) { |
- ASSERT1(selected_gate); |
- ASSERT1(gates); |
- |
- return WaitMultipleHelper(gates, num_gates, msec, selected_gate, false); |
-} |
- |
-// Returns S_OK if all gates were opened |
-// Returns E_FAIL if timeout occured or gate was abandoned. |
-HRESULT Gate::WaitAll(Gate const * const *gates, int num_gates, DWORD msec) { |
- ASSERT1(gates); |
- |
- return WaitMultipleHelper(gates, num_gates, msec, NULL, true); |
-} |
- |
-HRESULT Gate::WaitMultipleHelper(Gate const * const *gates, |
- int num_gates, |
- DWORD msec, |
- int *selected_gate, |
- bool wait_all) { |
- ASSERT1(gates); |
- ASSERT(num_gates > 0, (_T("There must be at least 1 gate"))); |
- |
- if ( num_gates <= 0 ) { |
- return E_FAIL; |
- } |
- HANDLE *gate_array = new HANDLE[ num_gates ]; |
- ASSERT1(gate_array); |
- for ( int i = 0 ; i < num_gates ; ++i ) { |
- gate_array[ i ] = gates[ i ]->gate_; |
- } |
- DWORD res = WaitForMultipleObjects(num_gates, |
- gate_array, |
- wait_all ? TRUE : FALSE, |
- msec); |
- delete[] gate_array; |
- |
-#pragma warning(disable : 4296) |
-// C4296: '>=' : expression is always true |
- if (WAIT_OBJECT_0 <= res && res < (WAIT_OBJECT_0 + num_gates)) { |
- if (selected_gate) { |
- *selected_gate = res - WAIT_OBJECT_0; |
- } |
- return S_OK; |
- } |
-#pragma warning(default : 4296) |
- return E_FAIL; |
-} |
- |
-bool WaitAllowRepaint(const Gate& gate, DWORD msec) { |
- DWORD wait = 0; |
- HANDLE gate_handle = gate; |
- while ((wait = ::MsgWaitForMultipleObjects(1, |
- &gate_handle, |
- FALSE, |
- msec, |
- QS_PAINT)) == WAIT_OBJECT_0 + 1) { |
- MSG msg; |
- if (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || |
- ::PeekMessage(&msg, NULL, WM_NCPAINT, WM_NCPAINT, PM_REMOVE)) { |
- ::TranslateMessage(&msg); |
- ::DispatchMessage(&msg); |
- } |
- } |
- return (wait == WAIT_OBJECT_0); |
-} |
- |
-// SimpleLock |
-// TODO(omaha): Replace InterlockedCompareExchange with |
-// InterlockedCompareExchangeAcquire |
-// and InterlockedDecrement with InterlockedDecrementRelease for Windows 2003 |
- |
-bool SimpleLock::Lock() const { |
- while (1 == ::InterlockedCompareExchange(&lock_, 1, 0)) |
- ::SleepEx(0, TRUE); |
- return true; |
-} |
- |
-bool SimpleLock::Unlock() const { |
- ::InterlockedDecrement(&lock_); |
- return true; |
-} |
- |
-// same with a delay in the loop to prevent CPU usage with significant |
-// contention |
- |
-bool SimpleLockWithDelay::Lock() const { |
- while (1 == ::InterlockedCompareExchange(&lock_, 1, 0)) |
- ::SleepEx(25, FALSE); |
- return true; |
-} |
- |
-bool SimpleLockWithDelay::Unlock() const { |
- ::InterlockedDecrement(&lock_); |
- return true; |
-} |
- |
- |
-CriticalSection::CriticalSection() |
-: number_entries_(0) { |
- InitializeCriticalSection(&critical_section_); |
-} |
- |
-// allow only one thread to hold a lock |
-CriticalSection::~CriticalSection() { |
- // we should not have to do anything in the destructor |
- ASSERT(!number_entries_, (_T("critical section destroyed while active"))); |
- while (number_entries_) { |
- LeaveCriticalSection(&critical_section_); |
- number_entries_--; |
- } |
- |
- DeleteCriticalSection(&critical_section_); |
-} |
- |
-// enter the critical section |
-// entries may be nested |
-void CriticalSection::Enter() { |
- EnterCriticalSection(&critical_section_); |
- number_entries_++; |
-} |
- |
-// exit the critical section |
-// number of exits must match number of entries |
-void CriticalSection::Exit() { |
- LeaveCriticalSection(&critical_section_); |
- number_entries_--; |
-} |
- |
-// Take a CriticalSection and lock it |
-SingleLock::SingleLock(CriticalSection * cs) { |
- ASSERT(cs, (L"")); |
- critical_section_ = cs; |
- critical_section_->Enter(); |
-} |
- |
-// If we haven't freed it yet, do so now since we fell out of scope |
-SingleLock::~SingleLock() { |
- if (critical_section_) { |
- critical_section_->Exit(); |
- critical_section_ = NULL; |
- } |
-} |
- |
-// Explicitly unlock |
-HRESULT SingleLock::Unlock() { |
- // If they did not |
- if (critical_section_ == NULL) |
- return S_FALSE; |
- |
- critical_section_->Exit(); |
- critical_section_ = NULL; |
- return S_OK; |
-} |
- |
-// Encapsulation for kernel Event. Initializes and destroys with it's lifetime |
-void EventObj::Init(const TCHAR * event_name) { |
- ASSERT(event_name, (L"")); |
- |
- h_ = ::CreateEvent(NULL, false, false, event_name); |
- ASSERT1(h_); |
-} |
- |
-EventObj::~EventObj() { |
- if (h_) { |
- VERIFY(CloseHandle(h_), (L"")); |
- h_ = NULL; |
- } |
-} |
- |
-BOOL EventObj::SetEvent() { |
- ASSERT(h_, (L"")); |
- return ::SetEvent(h_); |
-} |
- |
-// Is the given handle signaled? |
-// |
-// Typically used for events. |
-bool IsHandleSignaled(HANDLE h) { |
- ASSERT(h != NULL && |
- h != INVALID_HANDLE_VALUE, (_T(""))); |
- |
- DWORD result = ::WaitForSingleObject(h, 0); |
- if (result == WAIT_OBJECT_0) { |
- return true; |
- } |
- |
- ASSERT(result == WAIT_TIMEOUT, |
- (_T("unexpected result value: %u (hr=0x%x)"), |
- result, HRESULTFromLastError())); |
- return false; |
-} |
- |
- |
-// Create an id for the events/mutexes that can be used at the given scope. |
-// TODO(omaha): Error handling. |
-void CreateSyncId(const TCHAR* id, SyncScope scope, CString* sync_id) { |
- ASSERT1(id); |
- ASSERT1(sync_id); |
- |
- CString postfix; |
- switch (scope) { |
- default: |
- ASSERT1(false); |
- break; |
- |
- case SYNC_LOCAL: |
- sync_id->SetString(_T("Local\\")); |
- // no postfix for local ids |
- break; |
- |
- case SYNC_USER: |
- case SYNC_GLOBAL: |
- sync_id->SetString(_T("Global\\")); |
- |
- if (scope == SYNC_GLOBAL) { |
- // (MSDN insists that you can create objects with the same name with the |
- // prefixes "Global\" and "Local\" in a system "running Terminal |
- // Services". And it also assures that XP when running Fast User |
- // Switching uses Terminal Services. But when you try to create two |
- // objects with the same name but in the different namespaces on an |
- // XP Pro workstation NOT running Fast User Switching you can't - you |
- // get ERROR_ALREADY_EXISTS. And the reason is that in the Object table, |
- // Global and Local are both symlinks to the same object directory. |
- // Yet every technique that you can use to interrogate the system on |
- // whether or not the system is "running Terminal Services" says that |
- // the system is, in fact, running Terminal Services. |
- // Which is exactly what you'd expect, yet you can't create the |
- // two objects with the same name in different workspaces. So we change |
- // the name slightly.) |
- postfix.SetString(_T("_global")); |
- } else { |
- ASSERT1(scope == SYNC_USER); |
- // make the postfix the sid |
- VERIFY1(SUCCEEDED(omaha::user_info::GetProcessUser(NULL, |
- NULL, |
- &postfix))); |
- } |
- break; |
- } |
- |
- sync_id->Append(id); |
- sync_id->Append(postfix); |
-} |
- |
-} // namespace omaha |
- |