summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-12-26 18:59:17 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-12-26 18:59:17 +0300
commitdee83d7a89c021f63b746681d11ab72381bdc472 (patch)
tree3fc7fe317945cdedc90eb7f67c9cdd087f67bf33 /protocols/Telegram/tdlib/td
parent2c566472e4d0fd77f33a873d1898d4cf094dc95c (diff)
fixes #3271 (Telegram: XP compatibility)
Diffstat (limited to 'protocols/Telegram/tdlib/td')
-rw-r--r--protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.cpp133
-rw-r--r--protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.h32
2 files changed, 156 insertions, 9 deletions
diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.cpp
new file mode 100644
index 0000000000..495856201e
--- /dev/null
+++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.cpp
@@ -0,0 +1,133 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#pragma once
+
+#include <assert.h>
+
+#include "td/utils/port/RwMutex.h"
+
+typedef void(WINAPI *srwlock_function)(winlock_t*);
+static srwlock_function srwlock_Init, srwlock_AcquireShared, srwlock_ReleaseShared, srwlock_AcquireExclusive, srwlock_ReleaseExclusive;
+
+static bool bInited = false;
+
+namespace td {
+ //----------------------------------------------------------------------------
+ // Stub for slim read-write lock
+ // Copyright (C) 1995-2002 Brad Wilson
+
+ static void WINAPI stub_srwlock_Init(winlock_t *srwl) {
+ srwl->readerCount = srwl->writerCount = 0;
+ }
+
+ static void WINAPI stub_srwlock_AcquireShared(winlock_t *srwl) {
+ while (true) {
+ assert(srwl->writerCount >= 0 && srwl->readerCount >= 0);
+
+ // If there's a writer already, spin without unnecessarily
+ // interlocking the CPUs
+ if (srwl->writerCount != 0) {
+ YieldProcessor();
+ continue;
+ }
+
+ // Add to the readers list
+ _InterlockedIncrement(&srwl->readerCount);
+
+ // Check for writers again (we may have been preempted). If
+ // there are no writers writing or waiting, then we're done.
+ if (srwl->writerCount == 0)
+ break;
+
+ // Remove from the readers list, spin, try again
+ _InterlockedDecrement(&srwl->readerCount);
+ YieldProcessor();
+ }
+ }
+
+ static void WINAPI stub_srwlock_ReleaseShared(winlock_t *srwl) {
+ assert(srwl->readerCount > 0);
+ _InterlockedDecrement(&srwl->readerCount);
+ }
+
+ static void WINAPI stub_srwlock_AcquireExclusive(winlock_t *srwl) {
+ while (true) {
+ assert(srwl->writerCount >= 0 && srwl->readerCount >= 0);
+
+ // If there's a writer already, spin without unnecessarily
+ // interlocking the CPUs
+ if (srwl->writerCount != 0) {
+ YieldProcessor();
+ continue;
+ }
+
+ // See if we can become the writer (expensive, because it inter-
+ // locks the CPUs, so writing should be an infrequent process)
+ if (_InterlockedExchange(&srwl->writerCount, 1) == 0)
+ break;
+ }
+
+ // Now we're the writer, but there may be outstanding readers.
+ // Spin until there aren't any more; new readers will wait now
+ // that we're the writer.
+ while (srwl->readerCount != 0) {
+ assert(srwl->writerCount >= 0 && srwl->readerCount >= 0);
+ YieldProcessor();
+ }
+ }
+
+ static void WINAPI stub_srwlock_ReleaseExclusive(winlock_t *srwl) {
+ assert(srwl->writerCount == 1 && srwl->readerCount >= 0);
+ srwl->writerCount = 0;
+ }
+
+ void InitializeLock(winlock_t &lock)
+ {
+ if (!bInited) {
+ HINSTANCE hKernel32dll = GetModuleHandleA("kernel32.dll");
+
+ const srwlock_function init = (srwlock_function)GetProcAddress(hKernel32dll, "InitializeSRWLock");
+ if (init != NULL) {
+ srwlock_Init = init;
+ srwlock_AcquireShared = (srwlock_function)GetProcAddress(hKernel32dll, "AcquireSRWLockShared");
+ srwlock_ReleaseShared = (srwlock_function)GetProcAddress(hKernel32dll, "ReleaseSRWLockShared");
+ srwlock_AcquireExclusive = (srwlock_function)GetProcAddress(hKernel32dll, "AcquireSRWLockExclusive");
+ srwlock_ReleaseExclusive = (srwlock_function)GetProcAddress(hKernel32dll, "ReleaseSRWLockExclusive");
+ } else {
+ srwlock_Init = stub_srwlock_Init;
+ srwlock_AcquireShared = stub_srwlock_AcquireShared;
+ srwlock_ReleaseShared = stub_srwlock_ReleaseShared;
+ srwlock_AcquireExclusive = stub_srwlock_AcquireExclusive;
+ srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive;
+ }
+
+ bInited = true;
+ }
+
+ srwlock_Init(&lock);
+ }
+
+ void AcquireLockShared(winlock_t &lock)
+ {
+ srwlock_AcquireShared(&lock);
+ }
+
+ void AcquireLockExclusive(winlock_t &lock)
+ {
+ srwlock_AcquireExclusive(&lock);
+ }
+
+ void ReleaseLockShared(winlock_t &lock)
+ {
+ srwlock_ReleaseShared(&lock);
+ }
+
+ void ReleaseLockExclusive(winlock_t &lock)
+ {
+ srwlock_ReleaseExclusive(&lock);
+ }
+} // namespace td
diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.h
index 01de499bd0..1d88caceee 100644
--- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.h
+++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/RwMutex.h
@@ -15,6 +15,17 @@
#include <pthread.h>
#endif
+#if TD_PORT_WINDOWS
+union winlock_t {
+ struct {
+ long volatile readerCount;
+ long volatile writerCount;
+ };
+
+ SRWLOCK rwlock;
+};
+#endif
+
#include <memory>
namespace td {
@@ -83,18 +94,23 @@ class RwMutex {
#if TD_PORT_POSIX
pthread_rwlock_t mutex_;
#elif TD_PORT_WINDOWS
- unique_ptr<SRWLOCK> mutex_;
+ winlock_t mutex_;
#endif
};
+void InitializeLock(winlock_t&);
+void AcquireLockShared(winlock_t&);
+void AcquireLockExclusive(winlock_t&);
+void ReleaseLockShared(winlock_t&);
+void ReleaseLockExclusive(winlock_t&);
+
inline void RwMutex::init() {
CHECK(empty());
is_valid_ = true;
#if TD_PORT_POSIX
pthread_rwlock_init(&mutex_, nullptr);
#elif TD_PORT_WINDOWS
- mutex_ = make_unique<SRWLOCK>();
- InitializeSRWLock(mutex_.get());
+ InitializeLock(mutex_);
#endif
}
@@ -102,8 +118,6 @@ inline void RwMutex::clear() {
if (is_valid_) {
#if TD_PORT_POSIX
pthread_rwlock_destroy(&mutex_);
-#elif TD_PORT_WINDOWS
- mutex_.release();
#endif
is_valid_ = false;
}
@@ -115,7 +129,7 @@ inline void RwMutex::lock_read_unsafe() {
#if TD_PORT_POSIX
pthread_rwlock_rdlock(&mutex_);
#elif TD_PORT_WINDOWS
- AcquireSRWLockShared(mutex_.get());
+ AcquireLockShared(mutex_);
#endif
}
@@ -124,7 +138,7 @@ inline void RwMutex::lock_write_unsafe() {
#if TD_PORT_POSIX
pthread_rwlock_wrlock(&mutex_);
#elif TD_PORT_WINDOWS
- AcquireSRWLockExclusive(mutex_.get());
+ AcquireLockExclusive(mutex_);
#endif
}
@@ -133,7 +147,7 @@ inline void RwMutex::unlock_read_unsafe() {
#if TD_PORT_POSIX
pthread_rwlock_unlock(&mutex_);
#elif TD_PORT_WINDOWS
- ReleaseSRWLockShared(mutex_.get());
+ ReleaseLockShared(mutex_);
#endif
}
@@ -142,7 +156,7 @@ inline void RwMutex::unlock_write_unsafe() {
#if TD_PORT_POSIX
pthread_rwlock_unlock(&mutex_);
#elif TD_PORT_WINDOWS
- ReleaseSRWLockExclusive(mutex_.get());
+ ReleaseLockExclusive(mutex_);
#endif
}