|
1 | 1 | use rustc_hash::FxHashMap;
|
| 2 | +use std::collections::hash_map::OccupiedEntry; |
2 | 3 |
|
3 | 4 | use crate::key::DatabaseKeyIndex;
|
4 |
| -use crate::runtime::{BlockResult, ClaimTransferredResult, Running, WaitResult}; |
| 5 | +use crate::runtime::{BlockResult, ClaimTransferredResult, OtherThread, Running, WaitResult}; |
5 | 6 | use crate::sync::thread::{self};
|
6 | 7 | use crate::sync::Mutex;
|
7 | 8 | use crate::tracing;
|
@@ -54,64 +55,23 @@ impl SyncTable {
|
54 | 55 | ) -> ClaimResult<'me> {
|
55 | 56 | let mut write = self.syncs.lock();
|
56 | 57 | match write.entry(key_index) {
|
57 |
| - std::collections::hash_map::Entry::Occupied(mut occupied_entry) => { |
| 58 | + std::collections::hash_map::Entry::Occupied(occupied_entry) => { |
58 | 59 | let id = occupied_entry.get().id;
|
59 | 60 |
|
60 | 61 | let id = match id {
|
61 | 62 | SyncOwnerId::Thread(id) => id,
|
62 | 63 | SyncOwnerId::Transferred => {
|
63 |
| - let current_id = thread::current().id(); |
64 |
| - let database_key_index = DatabaseKeyIndex::new(self.ingredient, key_index); |
65 |
| - |
66 |
| - return match zalsa |
67 |
| - .runtime() |
68 |
| - .claim_transferred(database_key_index, allow_reentry) |
69 |
| - { |
70 |
| - ClaimTransferredResult::ClaimedBy(other_thread) => { |
71 |
| - occupied_entry.get_mut().anyone_waiting = true; |
72 |
| - |
73 |
| - match other_thread.block(write) { |
74 |
| - BlockResult::Cycle => ClaimResult::Cycle { inner: false }, |
75 |
| - BlockResult::Running(running) => ClaimResult::Running(running), |
76 |
| - } |
77 |
| - } |
78 |
| - ClaimTransferredResult::Reentrant => { |
79 |
| - let SyncState { |
80 |
| - id, claimed_twice, .. |
81 |
| - } = occupied_entry.into_mut(); |
82 |
| - |
83 |
| - if *claimed_twice { |
84 |
| - return ClaimResult::Cycle { inner: false }; |
85 |
| - } |
86 |
| - |
87 |
| - *id = SyncOwnerId::Thread(current_id); |
88 |
| - *claimed_twice = true; |
89 |
| - |
90 |
| - ClaimResult::Claimed(ClaimGuard { |
91 |
| - key_index, |
92 |
| - zalsa, |
93 |
| - sync_table: self, |
94 |
| - mode: ReleaseMode::SelfOnly, |
95 |
| - }) |
96 |
| - } |
97 |
| - ClaimTransferredResult::Cycle { inner: nested } => { |
98 |
| - ClaimResult::Cycle { inner: nested } |
99 |
| - } |
100 |
| - ClaimTransferredResult::Released => { |
101 |
| - occupied_entry.insert(SyncState { |
102 |
| - id: SyncOwnerId::Thread(thread::current().id()), |
103 |
| - anyone_waiting: false, |
104 |
| - is_transfer_target: false, |
105 |
| - claimed_twice: false, |
106 |
| - }); |
107 |
| - ClaimResult::Claimed(ClaimGuard { |
108 |
| - key_index, |
109 |
| - zalsa, |
110 |
| - sync_table: self, |
111 |
| - mode: ReleaseMode::Default, |
112 |
| - }) |
113 |
| - } |
114 |
| - }; |
| 64 | + return match self.try_claim_transferred( |
| 65 | + zalsa, |
| 66 | + occupied_entry, |
| 67 | + allow_reentry, |
| 68 | + ) { |
| 69 | + Ok(claimed) => claimed, |
| 70 | + Err(other_thread) => match other_thread.block(write) { |
| 71 | + BlockResult::Cycle => ClaimResult::Cycle { inner: false }, |
| 72 | + BlockResult::Running(running) => ClaimResult::Running(running), |
| 73 | + }, |
| 74 | + } |
115 | 75 | }
|
116 | 76 | };
|
117 | 77 |
|
@@ -153,6 +113,63 @@ impl SyncTable {
|
153 | 113 | }
|
154 | 114 | }
|
155 | 115 |
|
| 116 | + #[cold] |
| 117 | + fn try_claim_transferred<'me>( |
| 118 | + &'me self, |
| 119 | + zalsa: &'me Zalsa, |
| 120 | + mut entry: OccupiedEntry<Id, SyncState>, |
| 121 | + allow_reentry: bool, |
| 122 | + ) -> Result<ClaimResult<'me>, OtherThread<'me>> { |
| 123 | + let key_index = *entry.key(); |
| 124 | + let database_key_index = DatabaseKeyIndex::new(self.ingredient, key_index); |
| 125 | + |
| 126 | + match zalsa |
| 127 | + .runtime() |
| 128 | + .claim_transferred(database_key_index, allow_reentry) |
| 129 | + { |
| 130 | + ClaimTransferredResult::ClaimedBy(other_thread) => { |
| 131 | + entry.get_mut().anyone_waiting = true; |
| 132 | + Err(other_thread) |
| 133 | + } |
| 134 | + ClaimTransferredResult::Reentrant => { |
| 135 | + let SyncState { |
| 136 | + id, claimed_twice, .. |
| 137 | + } = entry.into_mut(); |
| 138 | + |
| 139 | + if *claimed_twice { |
| 140 | + return Ok(ClaimResult::Cycle { inner: false }); |
| 141 | + } |
| 142 | + |
| 143 | + *id = SyncOwnerId::Thread(thread::current().id()); |
| 144 | + *claimed_twice = true; |
| 145 | + |
| 146 | + Ok(ClaimResult::Claimed(ClaimGuard { |
| 147 | + key_index, |
| 148 | + zalsa, |
| 149 | + sync_table: self, |
| 150 | + mode: ReleaseMode::SelfOnly, |
| 151 | + })) |
| 152 | + } |
| 153 | + ClaimTransferredResult::Cycle { inner: nested } => { |
| 154 | + Ok(ClaimResult::Cycle { inner: nested }) |
| 155 | + } |
| 156 | + ClaimTransferredResult::Released => { |
| 157 | + entry.insert(SyncState { |
| 158 | + id: SyncOwnerId::Thread(thread::current().id()), |
| 159 | + anyone_waiting: false, |
| 160 | + is_transfer_target: false, |
| 161 | + claimed_twice: false, |
| 162 | + }); |
| 163 | + Ok(ClaimResult::Claimed(ClaimGuard { |
| 164 | + key_index, |
| 165 | + zalsa, |
| 166 | + sync_table: self, |
| 167 | + mode: ReleaseMode::Default, |
| 168 | + })) |
| 169 | + } |
| 170 | + } |
| 171 | + } |
| 172 | + |
156 | 173 | fn make_transfer_target(&self, key_index: Id) -> Option<SyncOwnerId> {
|
157 | 174 | let mut syncs = self.syncs.lock();
|
158 | 175 | syncs.get_mut(&key_index).map(|state| {
|
|
0 commit comments