TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
ttklockedfile_win.cpp
Go to the documentation of this file.
1 #include "ttklockedfile.h"
2 #include <qt_windows.h>
3 #include <QFileInfo>
4 
5 #define MUTEX_PREFIX "TTKLockedFile mutex "
6 // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
7 #define MAX_READERS MAXIMUM_WAIT_OBJECTS
8 
9 Qt::HANDLE TTKLockedFile::getMutexHandle(int idx, bool doCreate)
10 {
11  if (m_mutexname.isEmpty()) {
12  const QFileInfo fin(*this);
13  m_mutexname = QString::fromLatin1(MUTEX_PREFIX) + fin.absoluteFilePath().toLower();
14  }
15  QString mname(m_mutexname);
16  if (idx >= 0)
17  mname += QString::number(idx);
18 
19  Qt::HANDLE mutex;
20  if (doCreate) {
21  mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData());
22  if (!mutex) {
23  qErrnoWarning("TTKLockedFile::lock(): CreateMutex failed");
24  return 0;
25  }
26  }
27  else {
28  mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData());
29  if (!mutex) {
30  if (GetLastError() != ERROR_FILE_NOT_FOUND)
31  qErrnoWarning("TTKLockedFile::lock(): OpenMutex failed");
32  return 0;
33  }
34  }
35  return mutex;
36 }
37 
38 bool TTKLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
39 {
40  Q_ASSERT(mutex);
41  DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
42  switch (res) {
43  case WAIT_OBJECT_0:
44  case WAIT_ABANDONED:
45  return true;
46  break;
47  case WAIT_TIMEOUT:
48  break;
49  default:
50  qErrnoWarning("TTKLockedFile::lock(): WaitForSingleObject failed");
51  }
52  return false;
53 }
54 
55 bool TTKLockedFile::lock(LockMode mode, bool block)
56 {
57  if (!isOpen()) {
58  qWarning("TTKLockedFile::lock(): file is not opened");
59  return false;
60  }
61 
62  if (mode == NoLock)
63  return unlock();
64 
65  if (mode == m_lock_mode)
66  return true;
67 
68  if (m_lock_mode != NoLock)
69  unlock();
70 
71  if (!m_wmutex && !(m_wmutex = getMutexHandle(-1, true)))
72  return false;
73 
74  if (!waitMutex(m_wmutex, block))
75  return false;
76 
77  if (mode == ReadLock) {
78  int idx = 0;
79  for (; idx < MAX_READERS; idx++) {
80  m_rmutex = getMutexHandle(idx, false);
81  if (!m_rmutex || waitMutex(m_rmutex, false))
82  break;
83  CloseHandle(m_rmutex);
84  }
85  bool ok = true;
86  if (idx >= MAX_READERS) {
87  qWarning("TTKLockedFile::lock(): too many readers");
88  m_rmutex = 0;
89  ok = false;
90  }
91  else if (!m_rmutex) {
92  m_rmutex = getMutexHandle(idx, true);
93  if (!m_rmutex || !waitMutex(m_rmutex, false))
94  ok = false;
95  }
96  if (!ok && m_rmutex) {
97  CloseHandle(m_rmutex);
98  m_rmutex = 0;
99  }
100  ReleaseMutex(m_wmutex);
101  if (!ok)
102  return false;
103  }
104  else {
105  Q_ASSERT(m_rmutexes.isEmpty());
106  for (int i = 0; i < MAX_READERS; i++) {
107  Qt::HANDLE mutex = getMutexHandle(i, false);
108  if (mutex)
109  m_rmutexes.append(mutex);
110  }
111  if (!m_rmutexes.isEmpty()) {
112  DWORD res = WaitForMultipleObjects(m_rmutexes.count(), m_rmutexes.constData(), TRUE, block ? INFINITE : 0);
113  if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
114  if (res != WAIT_TIMEOUT)
115  qErrnoWarning("TTKLockedFile::lock(): WaitForMultipleObjects failed");
116  m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
117  unlock();
118  return false;
119  }
120  }
121  }
122 
123  m_lock_mode = mode;
124  return true;
125 }
126 
127 bool TTKLockedFile::unlock()
128 {
129  if (!isOpen()) {
130  qWarning("TTKLockedFile::unlock(): file is not opened");
131  return false;
132  }
133 
134  if (!isLocked())
135  return true;
136 
137  if (m_lock_mode == ReadLock) {
138  ReleaseMutex(m_rmutex);
139  CloseHandle(m_rmutex);
140  m_rmutex = 0;
141  }
142  else {
143  foreach(Qt::HANDLE mutex, m_rmutexes) {
144  ReleaseMutex(mutex);
145  CloseHandle(mutex);
146  }
147  m_rmutexes.clear();
148  ReleaseMutex(m_wmutex);
149  }
150 
151  m_lock_mode = TTKLockedFile::NoLock;
152  return true;
153 }
154 
155 TTKLockedFile::~TTKLockedFile()
156 {
157  if (isOpen())
158  unlock();
159  if (m_wmutex)
160  CloseHandle(m_wmutex);
161 }
#define MAX_READERS
#define MUTEX_PREFIX
const char int mode
Definition: ioapi.h:135