GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — feather/feather/server/src/player_count.rs at develop · aheart/feather Expand file tree/ Copy pathplayer_count.rsMore file actions 105 lines (88 loc) · 2.42 KB / Copy pathplayer_count.rsFile metadata and controls105 lines (88 loc) · 2.42 KB 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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 use std::sync::{ atomic::{AtomicU32, Ordering}, Arc, }; #[derive(Debug)] pub struct MaxPlayersReached; /// Maintains the server player count. /// /// Can be cloned to create a new handle. #[derive(Clone)] pub struct PlayerCount { inner: Arc<Inner>, } impl PlayerCount { pub fn new(max_players: u32) -> Self { Self { inner: Arc::new(Inner { count: AtomicU32::new(0), max_players, }), } } pub fn try_add_player(&self) -> Result<(), MaxPlayersReached> { loop { let current_count = self.inner.count.load(Ordering::SeqCst); let new_count = current_count + 1; if new_count > self.inner.max_players { return Err(MaxPlayersReached); } if self .inner .count .compare_exchange(current_count, new_count, Ordering::SeqCst, Ordering::SeqCst) .is_ok() { return Ok(()); } } } pub fn remove_player(&self) { self.inner.count.fetch_sub(1, Ordering::SeqCst); } pub fn get(&self) -> u32 { self.inner.count.load(Ordering::Acquire) } } struct Inner { count: AtomicU32, max_players: u32, } #[cfg(test)] mod tests { use crossbeam_utils::thread; use super::*; #[test] fn try_add() { let count = PlayerCount::new(1); assert_eq!(count.get(), 0); count.try_add_player().unwrap(); assert_eq!(count.get(), 1); for _ in 0..10 { count.try_add_player().unwrap_err(); assert_eq!(count.get(), 1); } } #[test] fn no_race_conditions() { let threads = 8; let players_per_thread = 100000; let max_players = threads * players_per_thread / 2; let count = PlayerCount::new(max_players); let num_added = AtomicU32::new(0); thread::scope(|s| { for _ in 0..threads { s.spawn(|_| { for _ in 0..players_per_thread { if count.try_add_player().is_ok() { num_added.fetch_add(1, Ordering::SeqCst); } } }); } }) .unwrap(); assert_eq!(num_added.load(Ordering::SeqCst), max_players); assert_eq!(count.get(), max_players); } } |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |