Synchronization.cpp (2101B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include <AppInstallerSynchronization.h> 5 #include <AppInstallerStrings.h> 6 7 8 namespace AppInstaller::Synchronization 9 { 10 // The amount of time that we wait in between checking for cancellation 11 constexpr std::chrono::milliseconds s_CrossProcessInstallLock_WaitLoopTime = 250ms; 12 13 CrossProcessLock::CrossProcessLock(std::string_view name) : CrossProcessLock(Utility::ConvertToUTF16(name)) 14 { 15 } 16 17 CrossProcessLock::CrossProcessLock(const std::wstring& name) 18 { 19 m_mutex.create(name.c_str(), 0, SYNCHRONIZE); 20 } 21 22 CrossProcessLock::~CrossProcessLock() 23 { 24 Release(); 25 } 26 27 bool CrossProcessLock::Acquire(IProgressCallback& progress) 28 { 29 while (!progress.IsCancelledBy(CancelReason::Any)) 30 { 31 auto lock = m_mutex.acquire(nullptr, static_cast<DWORD>(std::chrono::duration_cast<std::chrono::milliseconds>(s_CrossProcessInstallLock_WaitLoopTime).count())); 32 33 if (lock) 34 { 35 m_lockThreadId = GetCurrentThreadId(); 36 m_lock = std::move(lock); 37 return true; 38 } 39 } 40 41 return false; 42 } 43 44 void CrossProcessLock::Release() 45 { 46 if (m_lock) 47 { 48 // Ensure that we are in fact always releasing on the same thread that acquired the lock. 49 // This is to force crashes rather than deadlocks in the event that we make a design error that leads to that. 50 FAIL_FAST_IF(m_lockThreadId != GetCurrentThreadId()); 51 m_lock.reset(); 52 } 53 } 54 55 bool CrossProcessLock::TryAcquireNoWait() 56 { 57 auto lock = m_mutex.acquire(nullptr, 0); 58 59 if (lock) 60 { 61 m_lockThreadId = GetCurrentThreadId(); 62 m_lock = std::move(lock); 63 return true; 64 } 65 66 return false; 67 } 68 69 CrossProcessLock::operator bool() const 70 { 71 return static_cast<bool>(m_lock); 72 } 73 }