shared_mutex deadlock

Hello.
I've written a code from Anthony Williams's book - "Concurrency in action". It's a lookup table and sometimes there is a deadlock. If I replace shared_mutex into just mutex when there is no deadlock. I've tested it on gcc 7.2 and clang 5.0.

link to the project: https://bitbucket.org/OmegaDoom/threadsafelookuptable

I'm frustrated now, why this simple code doesn't work. Any help with it would be greatly appreciated.

I have found the problem. It happens only in MSYS2/mingw. There are no any problems in linux, cygwin or boost. It happens only with c++17 shared_mutex on MSYS2/mingw.
Last edited on
You do not use the lock correctly. You need to apply the lock whenever the protected object (m_list) is accessed. This includes find_value(...).

The special thing about shared_mutex is that you can have read access from multiple thread but whenever the object is modified it is blocked. For an example see:

http://en.cppreference.com/w/cpp/thread/shared_mutex
I'm sure I use lock correctly. I call "find_value" only when lock is held.
This code from the Anthony Williams's book - "Concurrency in action" with small and unimportant details. Do you have doubts about the code of former boost maintainer? :) And I can assure you I know what shared_mutex is about. Read this post carefully I have already found what causes the deadlock - it's a bug in MSYS2/mingw. I just don't know what to do with it.
Last edited on
Even this simple example causes a deadlock in MSYS2.
There should be more than one shared_mutex. The more mutexes the faster deadlock appears.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <shared_mutex>
#include <thread>
#include <chrono>
#include <array>

#define DURATION 500
#define MUTEX_COUNT 128

std::array<std::shared_mutex, MUTEX_COUNT> mutexes;

void lock()
{
	auto duration = std::chrono::milliseconds(DURATION);
	auto start = std::chrono::system_clock::now();

	unsigned long long index = 0;
	while (duration > std::chrono::system_clock::now() - start)
	{
		std::lock_guard<std::shared_mutex> lock(mutexes[++index % MUTEX_COUNT]);
	}
}

void shared_lock()
{
	auto duration = std::chrono::milliseconds(DURATION);
	auto start = std::chrono::system_clock::now();

	unsigned long long index = 0;
	while (duration > std::chrono::system_clock::now() - start)
	{
		std::shared_lock<std::shared_mutex> lock(mutexes[++index % MUTEX_COUNT]);
	}
}

int main(int argc, char* argv[])
{
	std::thread thr3(shared_lock);
	std::thread thr1(lock);
	std::thread thr2(lock);

	thr1.join();
	thr2.join();
	thr3.join();

	std::cout << "OK" << std::endl;
}
Topic archived. No new replies allowed.