-
Notifications
You must be signed in to change notification settings - Fork 0
/
IOState.cpp
65 lines (56 loc) · 1.87 KB
/
IOState.cpp
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "IOState.h"
namespace virtualpy {
void IOState::ClearSince() {
keyboard_since_request.fill(0);
}
void IOState::UpdateWithNewState(std::array<BYTE, 256> src_state) {
keyboard_at_request = src_state;
for (int i = 0; i < 256; i++) {
keyboard_since_request[i] |= src_state[i];
}
}
IOStateBuffer::IOStateBuffer() {
state1primary = true;
}
IOState IOStateBuffer::ReadState() {
// Gets the primary state as of the time the GetPrimaryState function checks
auto read_state = GetPrimaryState();
// If the writer grabs the primary state this will block until it is released,
// if it is free grabs the lock forcing the writer to swap the primaries.
read_state->first.lock();
IOState latest_state_copy = read_state->second;
read_state->second.ClearSince();
read_state->first.unlock();
return latest_state_copy;
}
void IOStateBuffer::WriteState(std::array<BYTE, 256> new_state) {
auto primary_state = GetPrimaryState();
// Attempts to grab the primary state
if (primary_state->first.try_lock()) {
// Got the primary state locked, can freely write to it as the reader will block
primary_state->second.UpdateWithNewState(new_state);
primary_state->first.unlock();
}
else {
// The primary state was locked, will now grab the secondary and swap
// the two states. It is fine to determine the secondary state
// non-atomically with the primary state as this thread is the only one that
// should be swapping the two.
auto secondary_state = GetSecondaryState();
secondary_state->second.UpdateWithNewState(new_state);
state1primary = false;
}
}
std::pair<std::mutex, IOState>* IOStateBuffer::GetPrimaryState() {
if (state1primary) {
return &state1;
}
return &state2;
}
std::pair<std::mutex, IOState>* IOStateBuffer::GetSecondaryState() {
if (state1primary) {
return &state2;
}
return &state1;
}
} // virtualpy