annotate foosdk/sdk/foobar2000/helpers/readWriteLock.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 namespace fb2k {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 //! fb2k::readWriteLock: abortable readWriteLock, allowing multiple concurrent readers while not writing, or one writer while not reading. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 //! Safe to release locks in different threads than obtained, contrary to system object such as SRW locks.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 class readWriteLock {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 pfc::mutex m_guard;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 size_t m_readers = 0, m_writers = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 typedef std::shared_ptr < pfc::event> eventRef_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 eventRef_t m_currentEvent;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 void shutdown() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 for (;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 eventRef_t waitFor;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 PFC_INSYNC(m_guard);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 if (m_readers == 0 && m_writers == 0) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 PFC_ASSERT(m_currentEvent);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 waitFor = m_currentEvent;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 waitFor->wait_for(-1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 service_ptr beginRead(abort_callback& a) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 for (;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 a.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 eventRef_t waitFor;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 PFC_INSYNC(m_guard);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 if (m_writers == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 if (!m_currentEvent) m_currentEvent = std::make_shared<pfc::event>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 ++m_readers;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 return fb2k::callOnRelease([this] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 PFC_INSYNC(m_guard);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 PFC_ASSERT(m_currentEvent);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 PFC_ASSERT(m_readers > 0 && m_writers == 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 if (--m_readers == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 m_currentEvent->set_state(true); m_currentEvent = nullptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 });
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 PFC_ASSERT(m_currentEvent);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 waitFor = m_currentEvent;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 a.waitForEvent(*waitFor);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 service_ptr beginWrite(abort_callback& a) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 for (;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 a.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 eventRef_t waitFor;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 PFC_INSYNC(m_guard);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 if (m_readers == 0 && m_writers == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 m_currentEvent = std::make_shared<pfc::event>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 ++m_writers;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 return fb2k::callOnRelease([this] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 PFC_INSYNC(m_guard);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 PFC_ASSERT(m_currentEvent);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 PFC_ASSERT(m_readers == 0 && m_writers > 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 if (--m_writers == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 m_currentEvent->set_state(true); m_currentEvent = nullptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 });
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 PFC_ASSERT(m_currentEvent);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 waitFor = m_currentEvent;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 a.waitForEvent(*waitFor);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 }