Lock/Unlock multiple locks at once function / class
[lsnes.git] / src / library / threads.cpp
blobfdec1fd3382487a7945076c5136fc1a8838aeb98
1 #include "threads.hpp"
2 #include <cstdint>
4 namespace threads
6 void lock_multiple(std::initializer_list<lock*> locks)
8 uintptr_t next = 0;
9 while(true) {
10 uintptr_t minaddr = 0;
11 lock* minlock = NULL;
12 for(auto i : locks) {
13 uintptr_t addr = reinterpret_cast<uintptr_t>(i);
14 if(addr < minaddr && addr > next) {
15 minaddr = addr;
16 minlock = i;
19 //If no more locks, exit.
20 if(!minlock) return;
21 //Lock minlock.
22 try {
23 minlock->lock();
24 next = minaddr;
25 } catch(...) {
26 //Unlock all locks we got.
27 for(auto i : locks) {
28 uintptr_t addr = reinterpret_cast<uintptr_t>(i);
29 if(addr < next)
30 i->unlock();
32 throw;
37 template<typename T> void _unlock_multiple(T locks)
39 uintptr_t next = 0;
40 while(true) {
41 uintptr_t minaddr = 0;
42 lock* minlock = NULL;
43 for(auto i : locks) {
44 uintptr_t addr = reinterpret_cast<uintptr_t>(i);
45 if(addr < minaddr && addr > next) {
46 minaddr = addr;
47 minlock = i;
50 //If no more locks, exit.
51 if(!minlock) return;
52 //Unlock minlock.
53 minlock->unlock();
54 next = minaddr;
58 void unlock_multiple(std::initializer_list<lock*> locks) { _unlock_multiple(locks); }
59 void unlock_multiple(std::vector<lock*> locks) { _unlock_multiple(locks); }