diff options
| author | Zeyla Hellyer <[email protected]> | 2017-10-10 20:08:11 -0700 |
|---|---|---|
| committer | Zeyla Hellyer <[email protected]> | 2017-10-10 20:08:11 -0700 |
| commit | 93e0a4215c915b98cf433ac6d0bcfbc60f0168ec (patch) | |
| tree | 727111506d1f89cd8a511b8b79c102131222421f /src | |
| parent | Resume on resumable session invalidations (diff) | |
| download | serenity-93e0a4215c915b98cf433ac6d0bcfbc60f0168ec.tar.xz serenity-93e0a4215c915b98cf433ac6d0bcfbc60f0168ec.zip | |
Switch to parking_lot::{Mutex, RwLock}
Switch to the `parking_lot` crate's implementations of
`std::sync::Mutex` and `std::sync::RwLock`, which are more efficient.
A writeup on why `parking_lot` is more efficient can be read here:
<https://github.com/Amanieu/parking_lot>
Upgrade path:
Modify `mutex.lock().unwrap()` usage to `mutex.lock()` (not needing to
unwrap or handle a result), and
`rwlock.read().unwrap()`/`rwlock.write().unwrap()` usage to
`rwlock.read()` and `rwlock.write()`.
For example, modify:
```rust
use serenity::CACHE;
println!("{}", CACHE.read().unwrap().user.id);
```
to:
```rust
use serenity::CACHE;
println!("{}", CACHE.read().user.id);
```
Diffstat (limited to 'src')
35 files changed, 401 insertions, 320 deletions
diff --git a/src/builder/create_embed.rs b/src/builder/create_embed.rs index a6b264c..f7dc0b1 100644 --- a/src/builder/create_embed.rs +++ b/src/builder/create_embed.rs @@ -249,20 +249,20 @@ impl CreateEmbed { /// impl EventHandler for Handler { /// fn on_guild_member_addition(&self, _: Context, guild_id: GuildId, member: Member) { /// use serenity::client::CACHE; - /// let cache = CACHE.read().unwrap(); + /// let cache = CACHE.read(); /// /// if let Some(guild) = cache.guild(guild_id) { - /// let guild = guild.read().unwrap(); + /// let guild = guild.read(); /// /// let channel_search = guild /// .channels /// .values() - /// .find(|c| c.read().unwrap().name == "join-log"); + /// .find(|c| c.read().name == "join-log"); /// /// if let Some(channel) = channel_search { - /// let user = member.user.read().unwrap(); + /// let user = member.user.read(); /// - /// let _ = channel.read().unwrap().send_message(|m| m + /// let _ = channel.read().send_message(|m| m /// .embed(|e| { /// let mut e = e /// .author(|a| a.icon_url(&user.face()).name(&user.name)) diff --git a/src/builder/create_invite.rs b/src/builder/create_invite.rs index 5f4f0bf..d719c17 100644 --- a/src/builder/create_invite.rs +++ b/src/builder/create_invite.rs @@ -21,7 +21,7 @@ use internal::prelude::*; /// fn on_message(&self, _: Context, msg: Message) { /// use serenity::client::CACHE; /// if msg.content == "!createinvite" { -/// let channel = match CACHE.read().unwrap().guild_channel(msg.channel_id) { +/// let channel = match CACHE.read().guild_channel(msg.channel_id) { /// Some(channel) => channel, /// None => { /// let _ = msg.channel_id.say("Error creating invite"); @@ -30,7 +30,7 @@ use internal::prelude::*; /// }, /// }; /// -/// let reader = channel.read().unwrap(); +/// let reader = channel.read(); /// /// let invite = match reader.create_invite(|i| i.max_age(3600).max_uses(10)) { /// Ok(invite) => invite, @@ -77,8 +77,8 @@ impl CreateInvite { /// # use std::error::Error; /// # /// # fn try_main() -> Result<(), Box<Error>> { - /// # let channel = CACHE.read().unwrap().guild_channel(81384788765712384).unwrap(); - /// # let channel = channel.read().unwrap(); + /// # let channel = CACHE.read().guild_channel(81384788765712384).unwrap(); + /// # let channel = channel.read(); /// # /// let invite = channel.create_invite(|i| i.max_age(3600))?; /// # Ok(()) @@ -111,8 +111,8 @@ impl CreateInvite { /// # use std::error::Error; /// # /// # fn try_main() -> Result<(), Box<Error>> { - /// # let channel = CACHE.read().unwrap().guild_channel(81384788765712384).unwrap(); - /// # let channel = channel.read().unwrap(); + /// # let channel = CACHE.read().guild_channel(81384788765712384).unwrap(); + /// # let channel = channel.read(); /// # /// let invite = channel.create_invite(|i| i.max_uses(5))?; /// # Ok(()) @@ -143,8 +143,8 @@ impl CreateInvite { /// # use std::error::Error; /// # /// # fn try_main() -> Result<(), Box<Error>> { - /// # let channel = CACHE.read().unwrap().guild_channel(81384788765712384).unwrap(); - /// # let channel = channel.read().unwrap(); + /// # let channel = CACHE.read().guild_channel(81384788765712384).unwrap(); + /// # let channel = channel.read(); /// # /// let invite = channel.create_invite(|i| i.temporary(true))?; /// # Ok(()) @@ -175,8 +175,8 @@ impl CreateInvite { /// # use std::error::Error; /// # /// # fn try_main() -> Result<(), Box<Error>> { - /// # let channel = CACHE.read().unwrap().guild_channel(81384788765712384).unwrap(); - /// # let channel = channel.read().unwrap(); + /// # let channel = CACHE.read().guild_channel(81384788765712384).unwrap(); + /// # let channel = channel.read(); /// # /// let invite = channel.create_invite(|i| i.unique(true))?; /// # Ok(()) diff --git a/src/cache/mod.rs b/src/cache/mod.rs index 9b43804..6b93d41 100644 --- a/src/cache/mod.rs +++ b/src/cache/mod.rs @@ -41,10 +41,12 @@ //! [`Role`]: ../model/struct.Role.html //! [`CACHE`]: ../struct.CACHE.html //! [`http`]: ../http/index.html + +use parking_lot::RwLock; use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::default::Default; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use model::*; mod cache_update; @@ -188,7 +190,7 @@ impl Cache { /// // seconds. /// thread::sleep(Duration::from_secs(5)); /// - /// println!("{} unknown members", CACHE.read().unwrap().unknown_members()); + /// println!("{} unknown members", CACHE.read().unknown_members()); /// } /// } /// @@ -202,7 +204,7 @@ impl Cache { let mut total = 0; for guild in self.guilds.values() { - let guild = guild.read().unwrap(); + let guild = guild.read(); let members = guild.members.len() as u64; @@ -227,7 +229,7 @@ impl Cache { /// ```rust,no_run /// use serenity::client::CACHE; /// - /// let amount = CACHE.read().unwrap().all_private_channels().len(); + /// let amount = CACHE.read().all_private_channels().len(); /// /// println!("There are {} private channels", amount); /// ``` @@ -260,7 +262,7 @@ impl Cache { /// struct Handler; /// impl EventHandler for Handler { /// fn on_ready(&self, _: Context, _: Ready) { - /// println!("Guilds in the Cache: {:?}", CACHE.read().unwrap().all_guilds()); + /// println!("Guilds in the Cache: {:?}", CACHE.read().all_guilds()); /// } /// } /// let mut client = Client::new("token", Handler); @@ -332,10 +334,8 @@ impl Cache { /// # fn try_main() -> Result<(), Box<Error>> { /// use serenity::client::CACHE; /// - /// let cache = CACHE.read()?; - /// - /// if let Some(guild) = cache.guild(7) { - /// println!("Guild name: {}", guild.read().unwrap().name); + /// if let Some(guild) = CACHE.read().guild(7) { + /// println!("Guild name: {}", guild.read().name); /// } /// # Ok(()) /// # } @@ -370,7 +370,7 @@ impl Cache { /// /// impl EventHandler for Handler { /// fn on_message(&self, ctx: Context, message: Message) { - /// let cache = CACHE.read().unwrap(); + /// let cache = CACHE.read(); /// /// let channel = match cache.guild_channel(message.channel_id) { /// Some(channel) => channel, @@ -417,10 +417,8 @@ impl Cache { /// # fn try_main() -> Result<(), Box<Error>> { /// use serenity::client::CACHE; /// - /// let cache = CACHE.read()?; - /// - /// if let Some(group) = cache.group(7) { - /// println!("Owner Id: {}", group.read().unwrap().owner_id); + /// if let Some(group) = CACHE.read().group(7) { + /// println!("Owner Id: {}", group.read().owner_id); /// } /// # Ok(()) /// # } @@ -448,7 +446,7 @@ impl Cache { /// ```rust,ignore /// use serenity::CACHE; /// - /// let cache = CACHE.read().unwrap(); + /// let cache = CACHE.read(); /// let member = { /// let channel = match cache.guild_channel(message.channel_id) { /// Some(channel) => channel, @@ -482,7 +480,7 @@ impl Cache { pub fn member<G, U>(&self, guild_id: G, user_id: U) -> Option<Member> where G: Into<GuildId>, U: Into<UserId> { self.guilds.get(&guild_id.into()).and_then(|guild| { - guild.read().unwrap().members.get(&user_id.into()).cloned() + guild.read().members.get(&user_id.into()).cloned() }) } @@ -502,10 +500,8 @@ impl Cache { /// # fn try_main() -> Result<(), Box<Error>> { /// use serenity::client::CACHE; /// - /// let cache = CACHE.read()?; - /// - /// if let Some(channel) = cache.private_channel(7) { - /// channel.read().unwrap().say("Hello there!"); + /// if let Some(channel) = CACHE.read().private_channel(7) { + /// channel.read().say("Hello there!"); /// } /// # Ok(()) /// # } @@ -539,9 +535,7 @@ impl Cache { /// # fn try_main() -> Result<(), Box<Error>> { /// use serenity::client::CACHE; /// - /// let cache = CACHE.read()?; - /// - /// if let Some(role) = cache.role(7, 77) { + /// if let Some(role) = CACHE.read().role(7, 77) { /// println!("Role with Id 77 is called {}", role.name); /// } /// # Ok(()) @@ -555,7 +549,7 @@ impl Cache { where G: Into<GuildId>, R: Into<RoleId> { self.guilds .get(&guild_id.into()) - .and_then(|g| g.read().unwrap().roles.get(&role_id.into()).cloned()) + .and_then(|g| g.read().roles.get(&role_id.into()).cloned()) } /// Retrieves a `User` from the cache's [`users`] map, if it exists. @@ -576,10 +570,8 @@ impl Cache { /// # fn try_main() -> Result<(), Box<Error>> { /// use serenity::client::CACHE; /// - /// let cache = CACHE.read()?; - /// - /// if let Some(user) = cache.user(7) { - /// println!("User with Id 7 is currently named {}", user.read().unwrap().name); + /// if let Some(user) = CACHE.read().user(7) { + /// println!("User with Id 7 is currently named {}", user.read().name); /// } /// # Ok(()) /// # } @@ -611,7 +603,7 @@ impl Cache { e.insert(Arc::new(RwLock::new(user.clone()))); }, Entry::Occupied(mut e) => { - e.get_mut().write().unwrap().clone_from(user); + e.get_mut().write().clone_from(user); }, } } diff --git a/src/client/bridge/gateway/shard_manager.rs b/src/client/bridge/gateway/shard_manager.rs index 2068bef..4a50b56 100644 --- a/src/client/bridge/gateway/shard_manager.rs +++ b/src/client/bridge/gateway/shard_manager.rs @@ -1,8 +1,8 @@ use internal::prelude::*; -use parking_lot::Mutex as ParkingLotMutex; +use parking_lot::Mutex; use std::collections::HashMap; use std::sync::mpsc::{self, Receiver, Sender}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::thread; use super::super::super::EventHandler; use super::{ @@ -19,7 +19,7 @@ use typemap::ShareMap; use framework::Framework; pub struct ShardManager { - pub runners: Arc<ParkingLotMutex<HashMap<ShardId, ShardRunnerInfo>>>, + pub runners: Arc<Mutex<HashMap<ShardId, ShardRunnerInfo>>>, /// The index of the first shard to initialize, 0-indexed. shard_index: u64, /// The number of shards to initialize. @@ -38,7 +38,7 @@ impl ShardManager { shard_total: u64, ws_url: Arc<Mutex<String>>, token: Arc<Mutex<String>>, - data: Arc<ParkingLotMutex<ShareMap>>, + data: Arc<Mutex<ShareMap>>, event_handler: Arc<H>, framework: Arc<Mutex<Option<Box<Framework + Send>>>>, threadpool: ThreadPool, @@ -46,7 +46,7 @@ impl ShardManager { let (thread_tx, thread_rx) = mpsc::channel(); let (shard_queue_tx, shard_queue_rx) = mpsc::channel(); - let runners = Arc::new(ParkingLotMutex::new(HashMap::new())); + let runners = Arc::new(Mutex::new(HashMap::new())); let mut shard_queuer = ShardQueuer { data: data.clone(), @@ -82,14 +82,14 @@ impl ShardManager { shard_total: u64, ws_url: Arc<Mutex<String>>, token: Arc<Mutex<String>>, - data: Arc<ParkingLotMutex<ShareMap>>, + data: Arc<Mutex<ShareMap>>, event_handler: Arc<H>, threadpool: ThreadPool, ) -> Self where H: EventHandler + Send + Sync + 'static { let (thread_tx, thread_rx) = mpsc::channel(); let (shard_queue_tx, shard_queue_rx) = mpsc::channel(); - let runners = Arc::new(ParkingLotMutex::new(HashMap::new())); + let runners = Arc::new(Mutex::new(HashMap::new())); let mut shard_queuer = ShardQueuer { data: data.clone(), diff --git a/src/client/bridge/gateway/shard_queuer.rs b/src/client/bridge/gateway/shard_queuer.rs index ea49de4..f75e35d 100644 --- a/src/client/bridge/gateway/shard_queuer.rs +++ b/src/client/bridge/gateway/shard_queuer.rs @@ -1,9 +1,9 @@ use gateway::Shard; use internal::prelude::*; -use parking_lot::Mutex as ParkingLotMutex; +use parking_lot::Mutex; use std::collections::HashMap; use std::sync::mpsc::{Receiver, Sender}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::thread; use std::time::{Duration, Instant}; use super::super::super::EventHandler; @@ -27,13 +27,13 @@ use framework::Framework; /// blocking nature of the loop itself as well as a 5 second thread sleep /// between shard starts. pub struct ShardQueuer<H: EventHandler + Send + Sync + 'static> { - pub data: Arc<ParkingLotMutex<ShareMap>>, + pub data: Arc<Mutex<ShareMap>>, pub event_handler: Arc<H>, #[cfg(feature = "framework")] pub framework: Arc<Mutex<Option<Box<Framework + Send>>>>, pub last_start: Option<Instant>, pub manager_tx: Sender<ShardManagerMessage>, - pub runners: Arc<ParkingLotMutex<HashMap<ShardId, ShardRunnerInfo>>>, + pub runners: Arc<Mutex<HashMap<ShardId, ShardRunnerInfo>>>, pub rx: Receiver<ShardQueuerMessage>, pub threadpool: ThreadPool, pub token: Arc<Mutex<String>>, @@ -81,7 +81,7 @@ impl<H: EventHandler + Send + Sync + 'static> ShardQueuer<H> { fn start(&mut self, shard_id: ShardId, shard_total: ShardId) -> Result<()> { let shard_info = [shard_id.0, shard_total.0]; let shard = Shard::new(self.ws_url.clone(), self.token.clone(), shard_info)?; - let locked = Arc::new(ParkingLotMutex::new(shard)); + let locked = Arc::new(Mutex::new(shard)); let mut runner = feature_framework! {{ ShardRunner::new( diff --git a/src/client/bridge/gateway/shard_runner.rs b/src/client/bridge/gateway/shard_runner.rs index 1b1de0e..53d4b80 100644 --- a/src/client/bridge/gateway/shard_runner.rs +++ b/src/client/bridge/gateway/shard_runner.rs @@ -1,7 +1,7 @@ use internal::prelude::*; use internal::ws_impl::ReceiverExt; use model::event::{Event, GatewayEvent}; -use parking_lot::Mutex as ParkingLotMutex; +use parking_lot::Mutex; use std::sync::mpsc::{self, Receiver, Sender}; use std::sync::Arc; use super::super::super::{EventHandler, dispatch}; @@ -12,11 +12,9 @@ use websocket::WebSocketError; #[cfg(feature = "framework")] use framework::Framework; -#[cfg(feature = "framework")] -use std::sync::Mutex; pub struct ShardRunner<H: EventHandler + Send + Sync + 'static> { - data: Arc<ParkingLotMutex<ShareMap>>, + data: Arc<Mutex<ShareMap>>, event_handler: Arc<H>, #[cfg(feature = "framework")] framework: Arc<Mutex<Option<Box<Framework + Send>>>>, @@ -34,7 +32,7 @@ impl<H: EventHandler + Send + Sync + 'static> ShardRunner<H> { shard: LockedShard, manager_tx: Sender<ShardManagerMessage>, framework: Arc<Mutex<Option<Box<Framework + Send>>>>, - data: Arc<ParkingLotMutex<ShareMap>>, + data: Arc<Mutex<ShareMap>>, event_handler: Arc<H>, threadpool: ThreadPool, ) -> Self { @@ -58,7 +56,7 @@ impl<H: EventHandler + Send + Sync + 'static> ShardRunner<H> { pub fn new( shard: LockedShard, manager_tx: Sender<ShardManagerMessage>, - data: Arc<ParkingLotMutex<ShareMap>>, + data: Arc<Mutex<ShareMap>>, event_handler: Arc<H>, threadpool: ThreadPool, ) -> Self { diff --git a/src/client/context.rs b/src/client/context.rs index 2288f28..18500d6 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -83,7 +83,7 @@ impl Context { feature_cache! { { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); map.insert("username".to_string(), Value::String(cache.user.name.clone())); diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index 709e34b..aec6283 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -15,8 +15,6 @@ use framework::Framework; use model::GuildId; #[cfg(feature = "cache")] use std::{thread, time}; -#[cfg(feature = "framework")] -use std::sync; #[cfg(feature = "cache")] use super::CACHE; @@ -26,7 +24,7 @@ macro_rules! update { { #[cfg(feature="cache")] { - CACHE.write().unwrap().update(&mut $event) + CACHE.write().update(&mut $event) } } }; @@ -44,7 +42,7 @@ fn context(conn: Arc<Mutex<Shard>>, data: Arc<Mutex<ShareMap>>) -> Context { #[cfg(feature = "framework")] pub fn dispatch<H: EventHandler + 'static>(event: Event, conn: Arc<Mutex<Shard>>, - framework: Arc<sync::Mutex<Option<Box<Framework + Send>>>>, + framework: Arc<Mutex<Option<Box<Framework + Send>>>>, data: Arc<Mutex<ShareMap>>, event_handler: Arc<H>) { match event { @@ -56,7 +54,7 @@ pub fn dispatch<H: EventHandler + 'static>(event: Event, event_handler, ); - if let Some(ref mut framework) = *framework.lock().unwrap() { + if let Some(ref mut framework) = *framework.lock() { framework.dispatch(context, event.message); } }, @@ -102,7 +100,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event, #[cfg(feature = "cache")] let wait_for_guilds = move || -> ::Result<()> { - let unavailable_guilds = CACHE.read().unwrap().unavailable_guilds.len(); + let unavailable_guilds = CACHE.read().unavailable_guilds.len(); while unavailable_guilds != 0 && (now!() < last_guild_create_time + 2000) { thread::sleep(time::Duration::from_millis(500)); @@ -173,7 +171,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event, let context = context(conn, data); feature_cache! {{ - let before = CACHE.read().unwrap().channel(event.channel.id()); + let before = CACHE.read().channel(event.channel.id()); event_handler.on_channel_update(context, before, event.channel); } else { event_handler.on_channel_update(context, event.channel); @@ -192,7 +190,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event, Event::GuildCreate(mut event) => { #[cfg(feature = "cache")] let _is_new = { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); !cache.unavailable_guilds.contains(&event.guild.id) }; @@ -203,7 +201,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event, { last_guild_create_time = now!(); - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); if cache.unavailable_guilds.is_empty() { let context = context(conn.clone(), data.clone()); @@ -274,7 +272,6 @@ fn handle_event<H: EventHandler + 'static>(event: Event, // the member if it did not exist. So, there is be _no_ way // that this could fail under any circumstance. let after = CACHE.read() - .unwrap() .member(event.guild_id, event.user.id) .unwrap() .clone(); @@ -332,7 +329,6 @@ fn handle_event<H: EventHandler + 'static>(event: Event, feature_cache! {{ let before = CACHE.read() - .unwrap() .guilds .get(&event.guild.id) .cloned(); diff --git a/src/client/event_handler.rs b/src/client/event_handler.rs index 6e3c78e..0c618c2 100644 --- a/src/client/event_handler.rs +++ b/src/client/event_handler.rs @@ -1,3 +1,4 @@ +use parking_lot::RwLock; use serde_json::Value; use std::collections::HashMap; use std::sync::Arc; @@ -5,8 +6,6 @@ use super::context::Context; use model::event::*; use model::*; -use std::sync::RwLock; - pub trait EventHandler { #[cfg(feature = "cache")] fn on_cached(&self, _: Context, _: Vec<GuildId>) {} diff --git a/src/client/mod.rs b/src/client/mod.rs index f2fb297..c17e284 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -39,7 +39,7 @@ pub use CACHE; use self::bridge::gateway::{ShardId, ShardManager, ShardRunnerInfo}; use self::dispatch::dispatch; -use std::sync::{self, Arc}; +use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; use parking_lot::Mutex; use std::collections::HashMap; @@ -192,7 +192,7 @@ pub struct Client<H: EventHandler + Send + Sync + 'static> { /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready /// [`on_ready`]: #method.on_ready event_handler: Arc<H>, - #[cfg(feature = "framework")] framework: Arc<sync::Mutex<Option<Box<Framework + Send>>>>, + #[cfg(feature = "framework")] framework: Arc<Mutex<Option<Box<Framework + Send>>>>, /// A HashMap of all shards instantiated by the Client. /// /// The key is the shard ID and the value is the shard itself. @@ -250,7 +250,7 @@ pub struct Client<H: EventHandler + Send + Sync + 'static> { /// Defaults to 5 threads, which should suffice small bots. Consider /// increasing this number as your bot grows. pub threadpool: ThreadPool, - token: Arc<sync::Mutex<String>>, + token: Arc<Mutex<String>>, } impl<H: EventHandler + Send + Sync + 'static> Client<H> { @@ -291,7 +291,7 @@ impl<H: EventHandler + Send + Sync + 'static> Client<H> { }; http::set_token(&token); - let locked = Arc::new(sync::Mutex::new(token)); + let locked = Arc::new(Mutex::new(token)); let name = "serenity client".to_owned(); let threadpool = ThreadPool::with_name(name, 5); @@ -300,7 +300,7 @@ impl<H: EventHandler + Send + Sync + 'static> Client<H> { Client { data: Arc::new(Mutex::new(ShareMap::custom())), event_handler: Arc::new(handler), - framework: Arc::new(sync::Mutex::new(None)), + framework: Arc::new(Mutex::new(None)), shard_runners: Arc::new(Mutex::new(HashMap::new())), threadpool, token: locked, @@ -417,7 +417,7 @@ impl<H: EventHandler + Send + Sync + 'static> Client<H> { /// [framework docs]: ../framework/index.html #[cfg(feature = "framework")] pub fn with_framework<F: Framework + Send + 'static>(&mut self, f: F) { - self.framework = Arc::new(sync::Mutex::new(Some(Box::new(f)))); + self.framework = Arc::new(Mutex::new(Some(Box::new(f)))); } /// Establish the connection and start listening for events. @@ -755,12 +755,12 @@ impl<H: EventHandler + Send + Sync + 'static> Client<H> { { let user = http::get_current_user()?; - if let Some(ref mut framework) = *self.framework.lock().unwrap() { + if let Some(ref mut framework) = *self.framework.lock() { framework.update_current_user(user.id, user.bot); } } - let gateway_url = Arc::new(sync::Mutex::new(url)); + let gateway_url = Arc::new(Mutex::new(url)); let mut manager = ShardManager::new( shard_data[0], diff --git a/src/framework/standard/help_commands.rs b/src/framework/standard/help_commands.rs index 9bae941..dbf25a9 100644 --- a/src/framework/standard/help_commands.rs +++ b/src/framework/standard/help_commands.rs @@ -51,7 +51,7 @@ fn remove_aliases(cmds: &HashMap<String, CommandOrAlias>) -> HashMap<&String, &I result } -/// Checks whether a user is member of required roles +/// Checks whether a user is member of required roles /// and given the required permissions. fn has_all_requirements(cmd: &Command, guild: &Guild, member: &Member, msg: &Message) -> bool { if cmd.allowed_roles.is_empty() { @@ -102,7 +102,8 @@ pub fn with_embeds(_: &mut Context, CommandOrAlias::Command(ref cmd) => { if !cmd.allowed_roles.is_empty() { if let Some(guild) = msg.guild() { - let guild = guild.read().unwrap(); + let guild = guild.read(); + if let Some(member) = guild.members.get(&msg.author.id) { if let Ok(permissions) = member.permissions() { if !permissions.administrator() && @@ -209,7 +210,8 @@ pub fn with_embeds(_: &mut Context, if cmd.help_available { if let Some(guild) = msg.guild() { - let guild = guild.read().unwrap(); + let guild = guild.read(); + if let Some(member) = guild.members.get(&msg.author.id) { if let Ok(permissions) = member.permissions() { if cmd.help_available && @@ -275,7 +277,8 @@ pub fn plain(_: &mut Context, CommandOrAlias::Command(ref cmd) => { if !cmd.allowed_roles.is_empty() { if let Some(guild) = msg.guild() { - let guild = guild.read().unwrap(); + let guild = guild.read(); + if let Some(member) = guild.members.get(&msg.author.id) { if let Ok(permissions) = member.permissions() { if !permissions.administrator() && @@ -362,7 +365,8 @@ pub fn plain(_: &mut Context, for name in command_names { let cmd = &commands[name]; if let Some(guild) = msg.guild() { - let guild = guild.read().unwrap(); + let guild = guild.read(); + if let Some(member) = guild.members.get(&msg.author.id) { if let Ok(permissions) = member.permissions() { if cmd.help_available && diff --git a/src/framework/standard/mod.rs b/src/framework/standard/mod.rs index a44c6e7..c3f0d70 100644 --- a/src/framework/standard/mod.rs +++ b/src/framework/standard/mod.rs @@ -400,7 +400,7 @@ impl StandardFramework { #[cfg(feature = "cache")] fn is_blocked_guild(&self, message: &Message) -> bool { - if let Some(Channel::Guild(channel)) = CACHE.read().unwrap().channel(message.channel_id) { + if let Some(Channel::Guild(channel)) = CACHE.read().channel(message.channel_id) { let guild_id = channel.with(|g| g.guild_id); if self.configuration.blocked_guilds.contains(&guild_id) { return true; @@ -510,7 +510,8 @@ impl StandardFramework { } else { if !command.allowed_roles.is_empty() { if let Some(guild) = message.guild() { - let guild = guild.read().unwrap(); + let guild = guild.read(); + if let Some(member) = guild.members.get(&message.author.id) { if let Ok(permissions) = member.permissions() { if !permissions.administrator() { diff --git a/src/gateway/shard.rs b/src/gateway/shard.rs index 7e81813..379d183 100644 --- a/src/gateway/shard.rs +++ b/src/gateway/shard.rs @@ -1,9 +1,10 @@ use chrono::Utc; +use parking_lot::Mutex; use serde_json::Value; use std::env::consts; use std::io::Write; use std::net::Shutdown; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::time::{Duration as StdDuration, Instant}; use super::{ConnectionStage, GatewayError}; use websocket::client::Url; @@ -108,25 +109,39 @@ impl Shard { /// Instantiating a new Shard manually for a bot with no shards, and /// then listening for events: /// - /// ```rust,ignore + /// ```rust,no_run + /// extern crate parking_lot; + /// extern crate serenity; + /// # + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// # + /// use parking_lot::Mutex; /// use serenity::gateway::Shard; /// use serenity::http; /// use std::env; + /// use std::sync::Arc; /// - /// let token = env::var("DISCORD_BOT_TOKEN").expect("Token in environment"); + /// let token = Arc::new(Mutex::new(env::var("DISCORD_BOT_TOKEN")?)); /// // retrieve the gateway response, which contains the URL to connect to - /// let gateway = http::get_gateway().expect("Valid gateway response").url; - /// let shard = Shard::new(&gateway, &token, None) - /// .expect("Working shard"); + /// let gateway = Arc::new(Mutex::new(http::get_gateway()?.url)); + /// let shard = Shard::new(gateway, token, [0, 1])?; /// /// // at this point, you can create a `loop`, and receive events and match /// // their variants + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` pub fn new(ws_url: Arc<Mutex<String>>, token: Arc<Mutex<String>>, shard_info: [u64; 2]) -> Result<Shard> { - let client = connect(&*ws_url.lock().unwrap())?; + let client = connect(&*ws_url.lock())?; let current_presence = (None, OnlineStatus::Online, false); let heartbeat_instants = (None, None); @@ -188,14 +203,26 @@ impl Shard { /// Retrieving the shard info for the second shard, out of two shards total: /// /// ```rust,no_run + /// # extern crate parking_lot; + /// # extern crate serenity; + /// # + /// # use parking_lot::Mutex; /// # use serenity::client::gateway::Shard; - /// # use std::sync::{Arc, Mutex}; + /// # use std::error::Error; + /// # use std::sync::Arc; /// # - /// # let mutex = Arc::new(Mutex::new("".to_string())); + /// # fn try_main() -> Result<(), Box<Error>> { + /// # let mutex = Arc::new(Mutex::new("".to_string())); /// # - /// # let shard = Shard::new(mutex.clone(), mutex, [1, 2]).unwrap(); + /// # let shard = Shard::new(mutex.clone(), mutex, [1, 2]).unwrap(); /// # /// assert_eq!(shard.shard_info(), [1, 2]); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` pub fn shard_info(&self) -> [u64; 2] { self.shard_info } @@ -218,16 +245,28 @@ impl Shard { /// Setting the current game to playing `"Heroes of the Storm"`: /// /// ```rust,no_run + /// # extern crate parking_lot; + /// # extern crate serenity; + /// # + /// # use parking_lot::Mutex; /// # use serenity::client::gateway::Shard; - /// # use std::sync::{Arc, Mutex}; + /// # use std::error::Error; + /// # use std::sync::Arc; /// # - /// # let mutex = Arc::new(Mutex::new("".to_string())); + /// # fn try_main() -> Result<(), Box<Error>> { + /// # let mutex = Arc::new(Mutex::new("".to_string())); /// # - /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); + /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); /// # /// use serenity::model::Game; /// /// shard.set_game(Some(Game::playing("Heroes of the Storm"))); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` pub fn set_game(&mut self, game: Option<Game>) { self.current_presence.0 = game; @@ -247,16 +286,28 @@ impl Shard { /// Setting the current online status for the shard to [`DoNotDisturb`]. /// /// ```rust,no_run + /// # extern crate parking_lot; + /// # extern crate serenity; + /// # + /// # use parking_lot::Mutex; /// # use serenity::client::gateway::Shard; - /// # use std::sync::{Arc, Mutex}; + /// # use std::error::Error; + /// # use std::sync::Arc; /// # - /// # let mutex = Arc::new(Mutex::new("".to_string())); + /// # fn try_main() -> Result<(), Box<Error>> { + /// # let mutex = Arc::new(Mutex::new("".to_string())); /// # - /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); + /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); /// # /// use serenity::model::OnlineStatus; /// /// shard.set_status(OnlineStatus::DoNotDisturb); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` /// /// [`DoNotDisturb`]: ../../model/enum.OnlineStatus.html#variant.DoNotDisturb @@ -282,17 +333,29 @@ impl Shard { /// and not being afk: /// /// ```rust,no_run + /// # extern crate parking_lot; + /// # extern crate serenity; + /// # + /// # use parking_lot::Mutex; /// # use serenity::client::gateway::Shard; - /// # use std::sync::{Arc, Mutex}; + /// # use std::error::Error; + /// # use std::sync::Arc; /// # - /// # let mutex = Arc::new(Mutex::new("".to_string())); + /// # fn try_main() -> Result<(), Box<Error>> { + /// # let mutex = Arc::new(Mutex::new("".to_string())); /// # - /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); + /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); /// # /// use serenity::model::{Game, OnlineStatus}; /// /// shard.set_presence(Some(Game::playing("Heroes of the Storm")), OnlineStatus::Online, /// false); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` pub fn set_presence(&mut self, game: Option<Game>, mut status: OnlineStatus, afk: bool) { if status == OnlineStatus::Offline { @@ -638,36 +701,60 @@ impl Shard { /// specifying a query parameter: /// /// ```rust,no_run + /// # extern crate parking_lot; + /// # extern crate serenity; + /// # + /// # use parking_lot::Mutex; /// # use serenity::client::gateway::Shard; - /// # use std::sync::{Arc, Mutex}; + /// # use std::error::Error; + /// # use std::sync::Arc; /// # - /// # let mutex = Arc::new(Mutex::new("".to_string())); + /// # fn try_main() -> Result<(), Box<Error>> { + /// # let mutex = Arc::new(Mutex::new("".to_string())); /// # - /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); + /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1])?; /// # /// use serenity::model::GuildId; /// /// let guild_ids = vec![GuildId(81384788765712384)]; /// /// shard.chunk_guilds(&guild_ids, Some(2000), None); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` /// /// Chunk a single guild by Id, limiting to 20 members, and specifying a /// query parameter of `"do"`: /// /// ```rust,no_run + /// # extern crate parking_lot; + /// # extern crate serenity; + /// # + /// # use parking_lot::Mutex; /// # use serenity::client::gateway::Shard; - /// # use std::sync::{Arc, Mutex}; + /// # use std::error::Error; + /// # use std::sync::Arc; /// # - /// # let mutex = Arc::new(Mutex::new("".to_string())); + /// # fn try_main() -> Result<(), Box<Error>> { + /// # let mutex = Arc::new(Mutex::new("".to_string())); /// # - /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); + /// # let mut shard = Shard::new(mutex.clone(), mutex, [0, 1])?; /// # /// use serenity::model::GuildId; /// /// let guild_ids = vec![GuildId(81384788765712384)]; /// /// shard.chunk_guilds(&guild_ids, Some(20), Some("do")); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` /// /// [`Event::GuildMembersChunk`]: @@ -702,24 +789,36 @@ impl Shard { /// Retrieve the number of guilds a shard is responsible for: /// /// ```rust,no_run + /// # extern crate parking_lot; + /// # extern crate serenity; + /// # + /// # use parking_lot::Mutex; /// # use serenity::client::gateway::Shard; - /// # use std::sync::{Arc, Mutex}; + /// # use std::error::Error; + /// # use std::sync::Arc; /// # - /// # let mutex = Arc::new(Mutex::new("will anyone read this".to_string())); + /// # fn try_main() -> Result<(), Box<Error>> { + /// # let mutex = Arc::new(Mutex::new("will anyone read this".to_string())); /// # - /// # let shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); + /// # let shard = Shard::new(mutex.clone(), mutex, [0, 1]).unwrap(); /// # /// let info = shard.shard_info(); /// let guilds = shard.guilds_handled(); /// /// println!("Shard {:?} is responsible for {} guilds", info, guilds); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } /// ``` /// /// [`Cache`]: ../ext/cache/struct.Cache.html /// [`Guild`]: ../model/struct.Guild.html #[cfg(feature = "cache")] pub fn guilds_handled(&self) -> u16 { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); let (shard_id, shard_count) = (self.shard_info[0], self.shard_info[1]); @@ -926,7 +1025,7 @@ impl Shard { "d": { "session_id": session_id, "seq": self.seq, - "token": &*self.token.lock().unwrap(), + "token": &*self.token.lock(), }, })) } @@ -947,7 +1046,7 @@ impl Shard { // This is used to accurately assess whether the state of the shard is // accurate when a Hello is received. self.stage = ConnectionStage::Connecting; - self.client = connect(&self.ws_url.lock().unwrap())?; + self.client = connect(&self.ws_url.lock())?; self.stage = ConnectionStage::Handshake; Ok(()) @@ -960,7 +1059,7 @@ impl Shard { "compression": true, "large_threshold": constants::LARGE_THRESHOLD, "shard": self.shard_info, - "token": &*self.token.lock().unwrap(), + "token": &*self.token.lock(), "v": constants::GATEWAY_VERSION, "properties": { "$browser": "serenity", @@ -1015,7 +1114,7 @@ impl Shard { #[cfg(feature = "cache")] { - let mut cache = CACHE.write().unwrap(); + let mut cache = CACHE.write(); let current_user_id = cache.user.id; cache.presences.get_mut(¤t_user_id).map(|presence| { diff --git a/src/http/mod.rs b/src/http/mod.rs index 2348794..d6b32f1 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -38,6 +38,7 @@ use hyper::net::HttpsConnector; use hyper::{header, Error as HyperError, Result as HyperResult, Url}; use hyper_native_tls::NativeTlsClient; use multipart::client::Multipart; +use parking_lot::Mutex; use self::ratelimiting::Route; use serde_json; use std::collections::BTreeMap; @@ -46,7 +47,7 @@ use std::fmt::Write as FmtWrite; use std::fs::File; use std::io::{ErrorKind as IoErrorKind, Read}; use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use constants; use internal::prelude::*; use model::*; @@ -98,7 +99,7 @@ lazy_static! { /// # fn main() { /// # try_main().unwrap(); /// # } -pub fn set_token(token: &str) { TOKEN.lock().unwrap().clone_from(&token.to_string()); } +pub fn set_token(token: &str) { TOKEN.lock().clone_from(&token.to_string()); } /// Adds a [`User`] as a recipient to a [`Group`]. /// @@ -793,7 +794,7 @@ pub fn edit_profile(map: &JsonMap) -> Result<CurrentUser> { let mut value = serde_json::from_reader::<HyperResponse, Value>(response)?; if let Some(map) = value.as_object_mut() { - if !TOKEN.lock().unwrap().starts_with("Bot ") { + if !TOKEN.lock().starts_with("Bot ") { if let Some(Value::String(token)) = map.remove("token") { set_token(&token); } @@ -1639,7 +1640,7 @@ pub fn send_files<'a, T, It: IntoIterator<Item=T>>(channel_id: u64, files: It, m let mut request = Request::with_connector(Method::Post, url, &connector)?; request .headers_mut() - .set(header::Authorization(TOKEN.lock().unwrap().clone())); + .set(header::Authorization(TOKEN.lock().clone())); request .headers_mut() .set(header::UserAgent(constants::USER_AGENT.to_string())); @@ -1798,7 +1799,7 @@ pub fn unpin_message(channel_id: u64, message_id: u64) -> Result<()> { fn request<'a, F>(route: Route, f: F) -> Result<HyperResponse> where F: Fn() -> RequestBuilder<'a> { let response = ratelimiting::perform(route, || { - f().header(header::Authorization(TOKEN.lock().unwrap().clone())) + f().header(header::Authorization(TOKEN.lock().clone())) .header(header::ContentType::json()) })?; diff --git a/src/http/ratelimiting.rs b/src/http/ratelimiting.rs index 93ca4f6..09c2527 100644 --- a/src/http/ratelimiting.rs +++ b/src/http/ratelimiting.rs @@ -44,8 +44,9 @@ use chrono::Utc; use hyper::client::{RequestBuilder, Response}; use hyper::header::Headers; use hyper::status::StatusCode; +use parking_lot::Mutex; use std::collections::HashMap; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::time::Duration; use std::{str, thread, i64}; use super::{HttpError, LightMethod}; @@ -80,10 +81,8 @@ lazy_static! { /// ```rust,no_run /// use serenity::http::ratelimiting::{ROUTES, Route}; /// - /// let routes = ROUTES.lock().unwrap(); - /// - /// if let Some(route) = routes.get(&Route::ChannelsId(7)) { - /// println!("Reset time at: {}", route.lock().unwrap().reset); + /// if let Some(route) = ROUTES.lock().get(&Route::ChannelsId(7)) { + /// println!("Reset time at: {}", route.lock().reset); /// } /// ``` /// @@ -352,7 +351,7 @@ pub(crate) fn perform<'a, F>(route: Route, f: F) -> Result<Response> loop { // This will block if another thread already has the global // unlocked already (due to receiving an x-ratelimit-global). - let _ = GLOBAL.lock().expect("global route lock poisoned"); + let _ = GLOBAL.lock(); // Perform pre-checking here: // @@ -364,7 +363,6 @@ pub(crate) fn perform<'a, F>(route: Route, f: F) -> Result<Response> // - then, perform the request let bucket = ROUTES .lock() - .expect("routes poisoned") .entry(route) .or_insert_with(|| { Arc::new(Mutex::new(RateLimit { @@ -375,7 +373,7 @@ pub(crate) fn perform<'a, F>(route: Route, f: F) -> Result<Response> }) .clone(); - let mut lock = bucket.lock().unwrap(); + let mut lock = bucket.lock(); lock.pre_hook(&route); let response = super::retry(&f)?; @@ -397,7 +395,7 @@ pub(crate) fn perform<'a, F>(route: Route, f: F) -> Result<Response> return Ok(response); } else { let redo = if response.headers.get_raw("x-ratelimit-global").is_some() { - let _ = GLOBAL.lock().expect("global route lock poisoned"); + let _ = GLOBAL.lock(); Ok( if let Some(retry_after) = parse_header(&response.headers, "retry-after")? { diff --git a/src/internal/rwlock_ext.rs b/src/internal/rwlock_ext.rs index 8266cdf..6235370 100644 --- a/src/internal/rwlock_ext.rs +++ b/src/internal/rwlock_ext.rs @@ -1,3 +1,4 @@ +use parking_lot::RwLock as ParkingLotRwLock; use std::sync::{Arc, RwLock}; pub trait RwLockExt<T> { @@ -16,3 +17,15 @@ impl<T> RwLockExt<T> for Arc<RwLock<T>> { f(&mut w) } } + +impl<T> RwLockExt<T> for Arc<ParkingLotRwLock<T>> { + fn with<Y, F: Fn(&T) -> Y>(&self, f: F) -> Y { + let r = self.read(); + f(&r) + } + + fn with_mut<Y, F: FnMut(&mut T) -> Y>(&self, mut f: F) -> Y { + let mut w = self.write(); + f(&mut w) + } +} @@ -107,6 +107,7 @@ extern crate serde_json; extern crate lazy_static; extern crate chrono; +extern crate parking_lot; extern crate serde; #[cfg(feature = "utils")] @@ -125,8 +126,6 @@ extern crate multipart; extern crate native_tls; #[cfg(feature = "voice")] extern crate opus; -#[cfg(feature = "client")] -extern crate parking_lot; #[cfg(feature = "voice")] extern crate sodiumoxide; #[cfg(feature = "threadpool")] @@ -172,7 +171,7 @@ pub use client::Client; #[cfg(feature = "cache")] use cache::Cache; #[cfg(feature = "cache")] -use std::sync::RwLock; +use parking_lot::RwLock; #[cfg(feature = "cache")] lazy_static! { @@ -197,16 +196,9 @@ lazy_static! { /// ```rust,ignore /// use serenity::CACHE; /// - /// println!("{}", CACHE.read().unwrap().user.id); + /// println!("{}", CACHE.read().user.id); /// ``` /// - /// By `unwrap()`ing, the thread managing an event dispatch will be blocked - /// until the guard can be opened. - /// - /// If you do not want to block the current thread, you may instead use - /// `RwLock::try_read`. Refer to `RwLock`'s documentation in the stdlib for - /// more information. - /// /// [`CurrentUser`]: model/struct.CurrentUser.html /// [`Cache`]: cache/struct.Cache.html /// [cache module documentation]: cache/index.html diff --git a/src/model/channel/channel_id.rs b/src/model/channel/channel_id.rs index f728191..4034fb9 100644 --- a/src/model/channel/channel_id.rs +++ b/src/model/channel/channel_id.rs @@ -224,14 +224,14 @@ impl ChannelId { /// Search the cache for the channel with the Id. #[cfg(feature = "cache")] - pub fn find(&self) -> Option<Channel> { CACHE.read().unwrap().channel(*self) } + pub fn find(&self) -> Option<Channel> { CACHE.read().channel(*self) } /// Search the cache for the channel. If it can't be found, the channel is /// requested over REST. pub fn get(&self) -> Result<Channel> { #[cfg(feature = "cache")] { - if let Some(channel) = CACHE.read().unwrap().channel(*self) { + if let Some(channel) = CACHE.read().channel(*self) { return Ok(channel); } } @@ -311,13 +311,13 @@ impl ChannelId { }; Some(match channel { - Guild(channel) => channel.read().unwrap().name().to_string(), - Group(channel) => match channel.read().unwrap().name() { + Guild(channel) => channel.read().name().to_string(), + Group(channel) => match channel.read().name() { Cow::Borrowed(name) => name.to_string(), Cow::Owned(name) => name, }, - Category(category) => category.read().unwrap().name().to_string(), - Private(channel) => channel.read().unwrap().name(), + Category(category) => category.read().name().to_string(), + Private(channel) => channel.read().name(), }) } diff --git a/src/model/channel/guild_channel.rs b/src/model/channel/guild_channel.rs index e2e5f09..cc74b9d 100644 --- a/src/model/channel/guild_channel.rs +++ b/src/model/channel/guild_channel.rs @@ -157,12 +157,12 @@ impl GuildChannel { /// kind: PermissionOverwriteType::Member(user_id), /// }; /// - /// let cache = CACHE.read().unwrap(); + /// let cache = CACHE.read(); /// let channel = cache /// .guild_channel(channel_id) /// .ok_or(ModelError::ItemMissing)?; /// - /// channel.read().unwrap().create_permission(&overwrite)?; + /// channel.read().create_permission(&overwrite)?; /// # Ok(()) /// # } /// # @@ -199,12 +199,12 @@ impl GuildChannel { /// kind: PermissionOverwriteType::Member(user_id), /// }; /// - /// let cache = CACHE.read().unwrap(); + /// let cache = CACHE.read(); /// let channel = cache /// .guild_channel(channel_id) /// .ok_or(ModelError::ItemMissing)?; /// - /// channel.read().unwrap().create_permission(&overwrite)?; + /// channel.read().create_permission(&overwrite)?; /// # Ok(()) /// # } /// # @@ -365,7 +365,7 @@ impl GuildChannel { /// **Note**: Right now this performs a clone of the guild. This will be /// optimized in the future. #[cfg(feature = "cache")] - pub fn guild(&self) -> Option<Arc<RwLock<Guild>>> { CACHE.read().unwrap().guild(self.guild_id) } + pub fn guild(&self) -> Option<Arc<RwLock<Guild>>> { CACHE.read().guild(self.guild_id) } /// Gets all of the channel's invites. /// @@ -436,12 +436,12 @@ impl GuildChannel { /// /// impl EventHandler for Handler { /// fn on_message(&self, _: Context, msg: Message) { - /// let channel = match CACHE.read().unwrap().guild_channel(msg.channel_id) { + /// let channel = match CACHE.read().guild_channel(msg.channel_id) { /// Some(channel) => channel, /// None => return, /// }; /// - /// let permissions = channel.read().unwrap().permissions_for(&msg.author).unwrap(); + /// let permissions = channel.read().permissions_for(&msg.author).unwrap(); /// /// println!("The user's permissions: {:?}", permissions); /// } @@ -464,14 +464,14 @@ impl GuildChannel { /// /// impl EventHandler for Handler { /// fn on_message(&self, _: Context, msg: Message) { - /// let channel = match CACHE.read().unwrap().guild_channel(msg.channel_id) { + /// let channel = match CACHE.read().guild_channel(msg.channel_id) { /// Some(channel) => channel, /// None => return, /// }; /// - /// let current_user_id = CACHE.read().unwrap().user.id; + /// let current_user_id = CACHE.read().user.id; /// let permissions = - /// channel.read().unwrap().permissions_for(current_user_id).unwrap(); + /// channel.read().permissions_for(current_user_id).unwrap(); /// /// if !permissions.contains(Permissions::ATTACH_FILES | /// Permissions::SEND_MESSAGES) { @@ -512,7 +512,7 @@ impl GuildChannel { pub fn permissions_for<U: Into<UserId>>(&self, user_id: U) -> Result<Permissions> { self.guild() .ok_or_else(|| Error::Model(ModelError::GuildNotFound)) - .map(|g| g.read().unwrap().permissions_for(self.id, user_id)) + .map(|g| g.read().permissions_for(self.id, user_id)) } /// Pins a [`Message`] to the channel. diff --git a/src/model/channel/message.rs b/src/model/channel/message.rs index 55f61ba..f6efd74 100644 --- a/src/model/channel/message.rs +++ b/src/model/channel/message.rs @@ -97,12 +97,12 @@ impl Message { /// /// command!(channel_name(_ctx, msg) { /// let _ = match msg.channel() { - /// Some(Channel::Category(c)) => msg.reply(&c.read().unwrap().name), - /// Some(Channel::Group(c)) => msg.reply(&c.read().unwrap().name()), - /// Some(Channel::Guild(c)) => msg.reply(&c.read().unwrap().name), + /// Some(Channel::Category(c)) => msg.reply(&c.read().name), + /// Some(Channel::Group(c)) => msg.reply(&c.read().name()), + /// Some(Channel::Guild(c)) => msg.reply(&c.read().name), /// Some(Channel::Private(c)) => { - /// let channel = c.read().unwrap(); - /// let user = channel.recipient.read().unwrap(); + /// let channel = c.read(); + /// let user = channel.recipient.read(); /// /// msg.reply(&format!("DM with {}", user.name.clone())) /// }, @@ -113,12 +113,12 @@ impl Message { /// ``` #[cfg(feature = "cache")] #[inline] - pub fn channel(&self) -> Option<Channel> { CACHE.read().unwrap().channel(self.channel_id) } + pub fn channel(&self) -> Option<Channel> { CACHE.read().channel(self.channel_id) } /// A util function for determining whether this message was sent by someone else, or the /// bot. #[cfg(all(feature = "cache", feature = "utils"))] - pub fn is_own(&self) -> bool { self.author.id == CACHE.read().unwrap().user.id } + pub fn is_own(&self) -> bool { self.author.id == CACHE.read().user.id } /// Deletes the message. /// @@ -138,7 +138,7 @@ impl Message { #[cfg(feature = "cache")] { let req = Permissions::MANAGE_MESSAGES; - let is_author = self.author.id == CACHE.read().unwrap().user.id; + let is_author = self.author.id == CACHE.read().user.id; let has_perms = utils::user_has_perms(self.channel_id, req)?; if !is_author && !has_perms { @@ -211,7 +211,7 @@ impl Message { where F: FnOnce(CreateMessage) -> CreateMessage { #[cfg(feature = "cache")] { - if self.author.id != CACHE.read().unwrap().user.id { + if self.author.id != CACHE.read().user.id { return Err(Error::Model(ModelError::InvalidUser)); } } @@ -335,7 +335,7 @@ impl Message { #[cfg(feature = "cache")] pub fn guild(&self) -> Option<Arc<RwLock<Guild>>> { self.guild_id() - .and_then(|guild_id| CACHE.read().unwrap().guild(guild_id)) + .and_then(|guild_id| CACHE.read().guild(guild_id)) } /// Retrieves the Id of the guild that the message was sent in, if sent in @@ -345,8 +345,8 @@ impl Message { /// cache. #[cfg(feature = "cache")] pub fn guild_id(&self) -> Option<GuildId> { - match CACHE.read().unwrap().channel(self.channel_id) { - Some(Channel::Guild(ch)) => Some(ch.read().unwrap().guild_id), + match CACHE.read().channel(self.channel_id) { + Some(Channel::Guild(ch)) => Some(ch.read().guild_id), _ => None, } } @@ -354,7 +354,7 @@ impl Message { /// True if message was sent using direct messages. #[cfg(feature = "cache")] pub fn is_private(&self) -> bool { - match CACHE.read().unwrap().channel(self.channel_id) { + match CACHE.read().channel(self.channel_id) { Some(Channel::Group(_)) | Some(Channel::Private(_)) => true, _ => false, } diff --git a/src/model/channel/mod.rs b/src/model/channel/mod.rs index 4ba0322..f7ecc0f 100644 --- a/src/model/channel/mod.rs +++ b/src/model/channel/mod.rs @@ -83,16 +83,16 @@ impl Channel { pub fn delete(&self) -> Result<()> { match *self { Channel::Group(ref group) => { - let _ = group.read().unwrap().leave()?; + let _ = group.read().leave()?; }, Channel::Guild(ref public_channel) => { - let _ = public_channel.read().unwrap().delete()?; + let _ = public_channel.read().delete()?; }, Channel::Private(ref private_channel) => { - let _ = private_channel.read().unwrap().delete()?; + let _ = private_channel.read().delete()?; }, Channel::Category(ref category) => { - category.read().unwrap().delete()?; + category.read().delete()?; }, } @@ -375,15 +375,15 @@ impl Display for Channel { /// [`PrivateChannel`]: struct.PrivateChannel.html fn fmt(&self, f: &mut Formatter) -> FmtResult { match *self { - Channel::Group(ref group) => Display::fmt(&group.read().unwrap().name(), f), - Channel::Guild(ref ch) => Display::fmt(&ch.read().unwrap().id.mention(), f), + Channel::Group(ref group) => Display::fmt(&group.read().name(), f), + Channel::Guild(ref ch) => Display::fmt(&ch.read().id.mention(), f), Channel::Private(ref ch) => { - let channel = ch.read().unwrap(); - let recipient = channel.recipient.read().unwrap(); + let channel = ch.read(); + let recipient = channel.recipient.read(); Display::fmt(&recipient.name, f) }, - Channel::Category(ref category) => Display::fmt(&category.read().unwrap().name, f), + Channel::Category(ref category) => Display::fmt(&category.read().name, f), } } } diff --git a/src/model/channel/private_channel.rs b/src/model/channel/private_channel.rs index d6ba781..01b387a 100644 --- a/src/model/channel/private_channel.rs +++ b/src/model/channel/private_channel.rs @@ -279,6 +279,6 @@ impl PrivateChannel { impl Display for PrivateChannel { /// Formats the private channel, displaying the recipient's username. fn fmt(&self, f: &mut Formatter) -> FmtResult { - f.write_str(&self.recipient.read().unwrap().name) + f.write_str(&self.recipient.read().name) } } diff --git a/src/model/channel/reaction.rs b/src/model/channel/reaction.rs index 8edc2e9..1a40ecb 100644 --- a/src/model/channel/reaction.rs +++ b/src/model/channel/reaction.rs @@ -48,7 +48,7 @@ impl Reaction { pub fn delete(&self) -> Result<()> { let user_id = feature_cache! { { - let user = if self.user_id == CACHE.read().unwrap().user.id { + let user = if self.user_id == CACHE.read().user.id { None } else { Some(self.user_id.0) diff --git a/src/model/event.rs b/src/model/event.rs index fe65269..8d949c7 100644 --- a/src/model/event.rs +++ b/src/model/event.rs @@ -61,7 +61,7 @@ impl CacheUpdate for ChannelCreateEvent { let channel_id = group.with_mut(|writer| { for (recipient_id, recipient) in &mut writer.recipients { - cache.update_user_entry(&recipient.read().unwrap()); + cache.update_user_entry(&recipient.read()); *recipient = cache.users[recipient_id].clone(); } @@ -110,7 +110,7 @@ impl CacheUpdate for ChannelCreateEvent { }, Channel::Category(ref category) => cache .categories - .insert(category.read().unwrap().id, category.clone()) + .insert(category.read().id, category.clone()) .map(Channel::Category), } } @@ -214,7 +214,7 @@ impl CacheUpdate for ChannelRecipientAddEvent { let user = cache.users[&self.user.id].clone(); cache.groups.get_mut(&self.channel_id).map(|group| { - group.write().unwrap().recipients.insert(self.user.id, user); + group.write().recipients.insert(self.user.id, user); }); None @@ -263,16 +263,16 @@ impl CacheUpdate for ChannelUpdateEvent { e.insert(group.clone()); }, Entry::Occupied(mut e) => { - let mut dest = e.get_mut().write().unwrap(); + let mut dest = e.get_mut().write(); if no_recipients { let recipients = mem::replace(&mut dest.recipients, HashMap::new()); - dest.clone_from(&group.read().unwrap()); + dest.clone_from(&group.read()); dest.recipients = recipients; } else { - dest.clone_from(&group.read().unwrap()); + dest.clone_from(&group.read()); } }, } @@ -289,13 +289,13 @@ impl CacheUpdate for ChannelUpdateEvent { Channel::Private(ref channel) => { cache .private_channels - .get_mut(&channel.read().unwrap().id) + .get_mut(&channel.read().id) .map(|private| private.clone_from(channel)); }, Channel::Category(ref category) => { cache .categories - .get_mut(&category.read().unwrap().id) + .get_mut(&category.read().id) .map(|c| c.clone_from(category)); }, } @@ -340,7 +340,7 @@ impl CacheUpdate for GuildCreateEvent { let mut guild = self.guild.clone(); for (user_id, member) in &mut guild.members { - cache.update_user_entry(&member.user.read().unwrap()); + cache.update_user_entry(&member.user.read()); let user = cache.users[user_id].clone(); member.user = user.clone(); @@ -375,7 +375,7 @@ impl CacheUpdate for GuildDeleteEvent { fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> { // Remove channel entries for the guild if the guild is found. cache.guilds.remove(&self.guild.id).map(|guild| { - for channel_id in guild.write().unwrap().channels.keys() { + for channel_id in guild.write().channels.keys() { cache.channels.remove(channel_id); } @@ -428,7 +428,7 @@ impl CacheUpdate for GuildMemberAddEvent { fn update(&mut self, cache: &mut Cache) -> Option<()> { let user_id = self.member.user.with(|u| u.id); - cache.update_user_entry(&self.member.user.read().unwrap()); + cache.update_user_entry(&self.member.user.read()); // Always safe due to being inserted above. self.member.user = cache.users[&user_id].clone(); @@ -498,7 +498,7 @@ impl CacheUpdate for GuildMemberUpdateEvent { cache.update_user_entry(&self.user); if let Some(guild) = cache.guilds.get_mut(&self.guild_id) { - let mut guild = guild.write().unwrap(); + let mut guild = guild.write(); let mut found = false; @@ -507,7 +507,7 @@ impl CacheUpdate for GuildMemberUpdateEvent { member.nick.clone_from(&self.nick); member.roles.clone_from(&self.roles); - member.user.write().unwrap().clone_from(&self.user); + member.user.write().clone_from(&self.user); found = true; @@ -550,7 +550,7 @@ impl CacheUpdate for GuildMembersChunkEvent { fn update(&mut self, cache: &mut Cache) -> Option<()> { for member in self.members.values() { - cache.update_user_entry(&member.user.read().unwrap()); + cache.update_user_entry(&member.user.read()); } cache.guilds.get_mut(&self.guild_id).map(|guild| { @@ -607,7 +607,6 @@ impl CacheUpdate for GuildRoleCreateEvent { cache.guilds.get_mut(&self.guild_id).map(|guild| { guild .write() - .unwrap() .roles .insert(self.role.id, self.role.clone()) }); @@ -683,7 +682,7 @@ impl CacheUpdate for GuildUpdateEvent { fn update(&mut self, cache: &mut Cache) -> Option<()> { cache.guilds.get_mut(&self.guild.id).map(|guild| { - let mut guild = guild.write().unwrap(); + let mut guild = guild.write(); guild.afk_timeout = self.guild.afk_timeout; guild.afk_channel_id.clone_from(&self.guild.afk_channel_id); @@ -766,13 +765,13 @@ impl CacheUpdate for PresenceUpdateEvent { let user_id = self.presence.user_id; if let Some(user) = self.presence.user.as_mut() { - cache.update_user_entry(&user.read().unwrap()); + cache.update_user_entry(&user.read()); *user = cache.users[&user_id].clone(); } if let Some(guild_id) = self.guild_id { if let Some(guild) = cache.guilds.get_mut(&guild_id) { - let mut guild = guild.write().unwrap(); + let mut guild = guild.write(); // If the member went offline, remove them from the presence list. if self.presence.status == OnlineStatus::Offline { @@ -918,7 +917,7 @@ impl CacheUpdate for ReadyEvent { for (user_id, presence) in &mut ready.presences { if let Some(ref user) = presence.user { - cache.update_user_entry(&user.read().unwrap()); + cache.update_user_entry(&user.read()); } presence.user = cache.users.get(user_id).cloned(); @@ -1002,7 +1001,7 @@ impl CacheUpdate for VoiceStateUpdateEvent { fn update(&mut self, cache: &mut Cache) -> Option<()> { if let Some(guild_id) = self.guild_id { if let Some(guild) = cache.guilds.get_mut(&guild_id) { - let mut guild = guild.write().unwrap(); + let mut guild = guild.write(); if self.voice_state.channel_id.is_some() { // Update or add to the voice state list diff --git a/src/model/gateway.rs b/src/model/gateway.rs index 4edc20e..ca846e8 100644 --- a/src/model/gateway.rs +++ b/src/model/gateway.rs @@ -1,6 +1,7 @@ +use parking_lot::RwLock; use serde::de::Error as DeError; use serde_json; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use super::utils::*; use super::*; diff --git a/src/model/guild/emoji.rs b/src/model/guild/emoji.rs index 4a2190f..7f332ae 100644 --- a/src/model/guild/emoji.rs +++ b/src/model/guild/emoji.rs @@ -151,8 +151,8 @@ impl Emoji { /// ``` #[cfg(feature = "cache")] pub fn find_guild_id(&self) -> Option<GuildId> { - for guild in CACHE.read().unwrap().guilds.values() { - let guild = guild.read().unwrap(); + for guild in CACHE.read().guilds.values() { + let guild = guild.read(); if guild.emojis.contains_key(&self.id) { return Some(guild.id); diff --git a/src/model/guild/guild_id.rs b/src/model/guild/guild_id.rs index 4b9a713..efda6a8 100644 --- a/src/model/guild/guild_id.rs +++ b/src/model/guild/guild_id.rs @@ -305,7 +305,7 @@ impl GuildId { /// Search the cache for the guild. #[cfg(feature = "cache")] - pub fn find(&self) -> Option<Arc<RwLock<Guild>>> { CACHE.read().unwrap().guild(*self) } + pub fn find(&self) -> Option<Arc<RwLock<Guild>>> { CACHE.read().guild(*self) } /// Requests the guild over REST. /// @@ -408,7 +408,7 @@ impl GuildId { /// [`utils::shard_id`]: ../utils/fn.shard_id.html #[cfg(all(feature = "cache", feature = "utils"))] #[inline] - pub fn shard_id(&self) -> u64 { ::utils::shard_id(self.0, CACHE.read().unwrap().shard_count) } + pub fn shard_id(&self) -> u64 { ::utils::shard_id(self.0, CACHE.read().shard_count) } /// Returns the Id of the shard associated with the guild. /// diff --git a/src/model/guild/member.rs b/src/model/guild/member.rs index 694de20..bca3ecb 100644 --- a/src/model/guild/member.rs +++ b/src/model/guild/member.rs @@ -88,7 +88,7 @@ impl Member { return Ok(()); } - match http::add_member_role(self.guild_id.0, self.user.read().unwrap().id.0, role_id.0) { + match http::add_member_role(self.guild_id.0, self.user.read().id.0, role_id.0) { Ok(()) => { self.roles.push(role_id); @@ -111,7 +111,7 @@ impl Member { let map = EditMember::default().roles(&self.roles).0; - match http::edit_member(self.guild_id.0, self.user.read().unwrap().id.0, &map) { + match http::edit_member(self.guild_id.0, self.user.read().id.0, &map) { Ok(()) => Ok(()), Err(why) => { self.roles.retain(|r| !role_ids.contains(r)); @@ -149,7 +149,7 @@ impl Member { http::ban_user( self.guild_id.0, - self.user.read().unwrap().id.0, + self.user.read().id.0, dmd, &*reason, ) @@ -158,9 +158,9 @@ impl Member { /// Determines the member's colour. #[cfg(all(feature = "cache", feature = "utils"))] pub fn colour(&self) -> Option<Colour> { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); let guild = match cache.guilds.get(&self.guild_id) { - Some(guild) => guild.read().unwrap(), + Some(guild) => guild.read(), None => return None, }; @@ -187,10 +187,10 @@ impl Member { None => return None, }; - let reader = guild.read().unwrap(); + let reader = guild.read(); for (cid, channel) in &reader.channels { - if reader.permissions_for(*cid, self.user.read().unwrap().id).read_messages() { + if reader.permissions_for(*cid, self.user.read().id).read_messages() { return Some(channel.clone()); } } @@ -206,7 +206,7 @@ impl Member { self.nick .as_ref() .map(Cow::Borrowed) - .unwrap_or_else(|| Cow::Owned(self.user.read().unwrap().name.clone())) + .unwrap_or_else(|| Cow::Owned(self.user.read().name.clone())) } /// Returns the DiscordTag of a Member, taking possible nickname into account. @@ -215,7 +215,7 @@ impl Member { format!( "{}#{}", self.display_name(), - self.user.read().unwrap().discriminator + self.user.read().discriminator ) } @@ -231,7 +231,7 @@ impl Member { pub fn edit<F: FnOnce(EditMember) -> EditMember>(&self, f: F) -> Result<()> { let map = f(EditMember::default()).0; - http::edit_member(self.guild_id.0, self.user.read().unwrap().id.0, &map) + http::edit_member(self.guild_id.0, self.user.read().id.0, &map) } /// Kick the member from the guild. @@ -274,17 +274,16 @@ impl Member { let has_perms = CACHE .read() - .unwrap() .guilds .get(&self.guild_id) - .map(|guild| guild.read().unwrap().has_perms(req)); + .map(|guild| guild.read().has_perms(req)); if let Some(Ok(false)) = has_perms { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } - self.guild_id.kick(self.user.read().unwrap().id) + self.guild_id.kick(self.user.read().id) } /// Returns the permissions for the member. @@ -314,18 +313,18 @@ impl Member { None => return Err(From::from(ModelError::GuildNotFound)), }; - let guild = guild.read().unwrap(); + let guild = guild.read(); - let default_channel = match guild.default_channel(self.user.read().unwrap().id) { + let default_channel = match guild.default_channel(self.user.read().id) { Some(dc) => dc, None => return Err(From::from(ModelError::ItemMissing)), }; - let default_channel_reader = default_channel.read().unwrap(); + let default_channel_reader = default_channel.read(); Ok( guild - .permissions_for(default_channel_reader.id, self.user.read().unwrap().id), + .permissions_for(default_channel_reader.id, self.user.read().id), ) } @@ -344,7 +343,7 @@ impl Member { return Ok(()); } - match http::remove_member_role(self.guild_id.0, self.user.read().unwrap().id.0, role_id.0) { + match http::remove_member_role(self.guild_id.0, self.user.read().id.0, role_id.0) { Ok(()) => { self.roles.retain(|r| r.0 != role_id.0); @@ -366,7 +365,7 @@ impl Member { let map = EditMember::default().roles(&self.roles).0; - match http::edit_member(self.guild_id.0, self.user.read().unwrap().id.0, &map) { + match http::edit_member(self.guild_id.0, self.user.read().id.0, &map) { Ok(()) => Ok(()), Err(why) => { self.roles.extend_from_slice(role_ids); @@ -385,19 +384,17 @@ impl Member { pub fn roles(&self) -> Option<Vec<Role>> { CACHE .read() - .unwrap() .guilds .values() .find(|guild| { - guild.read().unwrap().members.values().any(|m| { - m.user.read().unwrap().id == self.user.read().unwrap().id && + guild.read().members.values().any(|m| { + m.user.read().id == self.user.read().id && m.joined_at == self.joined_at }) }) .map(|guild| { guild .read() - .unwrap() .roles .values() .filter(|role| self.roles.contains(&role.id)) @@ -420,7 +417,7 @@ impl Member { /// [Ban Members]: permissions/constant.BAN_MEMBERS.html #[cfg(feature = "cache")] pub fn unban(&self) -> Result<()> { - http::remove_ban(self.guild_id.0, self.user.read().unwrap().id.0) + http::remove_ban(self.guild_id.0, self.user.read().id.0) } } @@ -436,6 +433,6 @@ impl Display for Member { /// // This is in the format of `<@USER_ID>`. fn fmt(&self, f: &mut Formatter) -> FmtResult { - Display::fmt(&self.user.read().unwrap().mention(), f) + Display::fmt(&self.user.read().mention(), f) } } diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs index 73dfa73..ea6cb17 100644 --- a/src/model/guild/mod.rs +++ b/src/model/guild/mod.rs @@ -155,17 +155,17 @@ impl Guild { #[cfg(feature = "cache")] fn has_perms(&self, mut permissions: Permissions) -> Result<bool> { - let member = match self.members.get(&CACHE.read().unwrap().user.id) { + let member = match self.members.get(&CACHE.read().user.id) { Some(member) => member, None => return Err(Error::Model(ModelError::ItemMissing)), }; - let default_channel = match self.default_channel(member.user.read().unwrap().id) { + let default_channel = match self.default_channel(member.user.read().id) { Some(dc) => dc, None => return Err(Error::Model(ModelError::ItemMissing)), }; - let perms = self.permissions_for(default_channel.read().unwrap().id, member.user.read().unwrap().id); + let perms = self.permissions_for(default_channel.read().id, member.user.read().id); permissions.remove(perms); Ok(permissions.is_empty()) @@ -406,7 +406,7 @@ impl Guild { pub fn delete(&self) -> Result<PartialGuild> { #[cfg(feature = "cache")] { - if self.owner_id != CACHE.read().unwrap().user.id { + if self.owner_id != CACHE.read().user.id { let req = Permissions::MANAGE_GUILD; return Err(Error::Model(ModelError::InvalidPermissions(req))); @@ -723,9 +723,9 @@ impl Guild { self.members .values() .find(|member| { - let name_matches = member.user.read().unwrap().name == name; + let name_matches = member.user.read().name == name; let discrim_matches = match discrim { - Some(discrim) => member.user.read().unwrap().discriminator == discrim, + Some(discrim) => member.user.read().discriminator == discrim, None => true, }; @@ -744,7 +744,7 @@ impl Guild { /// - "zey", "zeyla", "zey mei" /// If 'case_sensitive' is false, the following are not found: /// - "Zey", "ZEYla", "zeY mei" - /// + /// /// [`Member`]: struct.Member.html pub fn members_starting_with(&self, prefix: &str, case_sensitive: bool) -> Vec<&Member> { self.members @@ -752,11 +752,11 @@ impl Guild { .filter(|member| if case_sensitive { - member.user.read().unwrap().name.starts_with(prefix) + member.user.read().name.starts_with(prefix) } else { - starts_with_case_insensitive(&member.user.read().unwrap().name, &prefix) + starts_with_case_insensitive(&member.user.read().name, &prefix) } - + || member.nick.as_ref() .map_or(false, |nick| @@ -773,7 +773,7 @@ impl Guild { /// - "zeyla", "meiyla", "yladenisyla" /// If 'case_sensitive' is false, the following are not found: /// - "zeYLa", "meiyLa", "LYAdenislyA" - /// + /// /// [`Member`]: struct.Member.html pub fn members_containing(&self, substring: &str, case_sensitive: bool) -> Vec<&Member> { self.members @@ -781,11 +781,11 @@ impl Guild { .filter(|member| if case_sensitive { - member.user.read().unwrap().name.contains(substring) + member.user.read().name.contains(substring) } else { - contains_case_insensitive(&member.user.read().unwrap().name, &substring) + contains_case_insensitive(&member.user.read().name, &substring) } - + || member.nick.as_ref() .map_or(false, |nick| @@ -849,7 +849,7 @@ impl Guild { } else { warn!( "(╯°□°)╯︵ ┻━┻ {} on {} has non-existent role {:?}", - member.user.read().unwrap().id, + member.user.read().id, self.id, role ); @@ -862,7 +862,7 @@ impl Guild { } if let Some(channel) = self.channels.get(&channel_id) { - let channel = channel.read().unwrap(); + let channel = channel.read(); // If this is a text channel, then throw out voice permissions. if channel.kind == ChannelType::Text { @@ -1102,7 +1102,7 @@ impl Guild { /// impl EventHandler for Handler { /// fn on_message(&self, _: Context, msg: Message) { /// if let Some(arc) = msg.guild_id().unwrap().find() { - /// if let Some(role) = arc.read().unwrap().role_by_name("role_name") { + /// if let Some(role) = arc.read().role_by_name("role_name") { /// println!("{:?}", role); /// } /// } diff --git a/src/model/guild/role.rs b/src/model/guild/role.rs index 7ac7019..3ed718e 100644 --- a/src/model/guild/role.rs +++ b/src/model/guild/role.rs @@ -106,8 +106,8 @@ impl Role { /// [`ModelError::GuildNotFound`]: enum.ModelError.html#variant.GuildNotFound #[cfg(feature = "cache")] pub fn find_guild(&self) -> Result<GuildId> { - for guild in CACHE.read().unwrap().guilds.values() { - let guild = guild.read().unwrap(); + for guild in CACHE.read().guilds.values() { + let guild = guild.read(); if guild.roles.contains_key(&RoleId(self.id.0)) { return Ok(guild.id); @@ -168,10 +168,10 @@ impl RoleId { /// Search the cache for the role. #[cfg(feature = "cache")] pub fn find(&self) -> Option<Role> { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); for guild in cache.guilds.values() { - let guild = guild.read().unwrap(); + let guild = guild.read(); if !guild.roles.contains_key(self) { continue; diff --git a/src/model/mod.rs b/src/model/mod.rs index 0817094..64987e1 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -32,11 +32,12 @@ pub use self::voice::*; pub use self::webhook::*; use chrono::NaiveDateTime; +use parking_lot::RwLock; use self::utils::*; use serde::de::Visitor; use std::collections::HashMap; use std::fmt::{Display, Formatter, Result as FmtResult}; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use internal::prelude::*; #[cfg(feature = "utils")] @@ -67,7 +68,7 @@ macro_rules! id_u64 { self } } - + impl From<u64> for $name { fn from(id_as_u64: u64) -> $name { $name(id_as_u64) diff --git a/src/model/user.rs b/src/model/user.rs index 39efa10..bf5ee36 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -7,12 +7,14 @@ use model::misc::Mentionable; #[cfg(feature = "model")] use chrono::NaiveDateTime; +#[cfg(all(feature = "cache", feature = "model"))] +use parking_lot::RwLock; #[cfg(feature = "model")] use std::fmt::Write; #[cfg(feature = "model")] use std::mem; #[cfg(all(feature = "cache", feature = "model"))] -use std::sync::{Arc, RwLock}; +use std::sync::Arc; #[cfg(feature = "model")] use builder::{CreateMessage, EditProfile}; #[cfg(all(feature = "cache", feature = "model"))] @@ -46,7 +48,7 @@ impl CurrentUser { /// ```rust,no_run /// # use serenity::client::CACHE; /// # - /// # let cache = CACHE.read().unwrap(); + /// # let cache = CACHE.read(); /// # /// // assuming the cache has been unlocked /// let user = &cache.user; @@ -80,7 +82,7 @@ impl CurrentUser { /// /// let avatar = serenity::utils::read_image("./avatar.png").unwrap(); /// - /// CACHE.write().unwrap().user.edit(|p| p.avatar(Some(&avatar))); + /// CACHE.write().user.edit(|p| p.avatar(Some(&avatar))); /// ``` pub fn edit<F>(&mut self, f: F) -> Result<()> where F: FnOnce(EditProfile) -> EditProfile { @@ -123,7 +125,7 @@ impl CurrentUser { /// ```rust,no_run /// # use serenity::client::CACHE; /// # - /// # let cache = CACHE.read().unwrap(); + /// # let cache = CACHE.read(); /// # /// // assuming the cache has been unlocked /// let user = &cache.user; @@ -151,7 +153,7 @@ impl CurrentUser { /// ```rust,no_run /// # use serenity::client::CACHE; /// # - /// # let mut cache = CACHE.write().unwrap(); + /// # let mut cache = CACHE.write(); /// /// use serenity::model::permissions::Permissions; /// @@ -174,7 +176,7 @@ impl CurrentUser { /// ```rust,no_run /// # use serenity::client::CACHE; /// # - /// # let mut cache = CACHE.write().unwrap(); + /// # let mut cache = CACHE.write(); /// /// use serenity::model::Permissions; /// @@ -230,7 +232,7 @@ impl CurrentUser { /// ```rust,no_run /// # use serenity::client::CACHE; /// # - /// # let cache = CACHE.read().unwrap(); + /// # let cache = CACHE.read(); /// # /// // assuming the cache has been unlocked /// let user = &cache.user; @@ -254,7 +256,7 @@ impl CurrentUser { /// ```rust,no_run /// # use serenity::client::CACHE; /// # - /// # let cache = CACHE.read().unwrap(); + /// # let cache = CACHE.read(); /// # /// // assuming the cache has been unlocked /// println!("The current user's distinct identifier is {}", cache.user.tag()); @@ -410,25 +412,21 @@ impl User { /// impl EventHandler for Handler { /// fn on_message(&self, _: Context, msg: Message) { /// if msg.content == "~help" { - /// let url = match CACHE.read() { - /// Ok(v) => { - /// match v.user.invite_url(Permissions::empty()) { - /// Ok(v) => v, - /// Err(why) => { - /// println!("Error creating invite url: {:?}", why); - /// - /// return; - /// }, - /// } - /// }, + /// let cache = CACHE.read(); + /// + /// let url = match cache.user.invite_url(Permissions::empty()) { + /// Ok(v) => v, /// Err(why) => { - /// println!("Error reading from CACHE: {:?}", why); + /// println!("Error creating invite url: {:?}", why); /// /// return; - /// } + /// }, /// }; - /// let help = format!("Helpful info here. Invite me with this link: <{}>", - /// url); + /// + /// let help = format!( + /// "Helpful info here. Invite me with this link: <{}>", + /// url, + /// ); /// /// match msg.author.direct_message(|m| m.content(&help)) { /// Ok(_) => { @@ -480,12 +478,12 @@ impl User { let private_channel_id = feature_cache! { { let finding = { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); let finding = cache.private_channels .values() - .map(|ch| ch.read().unwrap()) - .find(|ch| ch.recipient.read().unwrap().id == self.id) + .map(|ch| ch.read()) + .find(|ch| ch.recipient.read().id == self.id) .map(|ch| ch.id); finding @@ -580,10 +578,9 @@ impl User { GuildContainer::Id(_guild_id) => { feature_cache! {{ CACHE.read() - .unwrap() .guilds .get(&_guild_id) - .map(|g| g.read().unwrap().roles.contains_key(&role_id)) + .map(|g| g.read().roles.contains_key(&role_id)) .unwrap_or(false) } else { true @@ -631,11 +628,11 @@ impl User { /// loop { /// thread::sleep(duration); /// - /// let cache = CACHE.read().unwrap(); + /// let cache = CACHE.read(); /// /// for id in &special_users { /// if let Some(user) = cache.user(*id) { - /// if let Err(why) = user.write().unwrap().refresh() { + /// if let Err(why) = user.write().refresh() { /// println!("Error refreshing {}: {:?}", id, why); /// } /// } @@ -721,7 +718,7 @@ impl UserId { /// Search the cache for the user with the Id. #[cfg(feature = "cache")] - pub fn find(&self) -> Option<Arc<RwLock<User>>> { CACHE.read().unwrap().user(*self) } + pub fn find(&self) -> Option<Arc<RwLock<User>>> { CACHE.read().user(*self) } /// Gets a user by its Id over the REST API. /// @@ -730,8 +727,8 @@ impl UserId { pub fn get(&self) -> Result<User> { #[cfg(feature = "cache")] { - if let Some(user) = CACHE.read().unwrap().user(*self) { - return Ok(user.read().unwrap().clone()); + if let Some(user) = CACHE.read().user(*self) { + return Ok(user.read().clone()); } } @@ -751,12 +748,12 @@ impl<'a> From<&'a CurrentUser> for UserId { impl From<Member> for UserId { /// Gets the Id of a `Member`. - fn from(member: Member) -> UserId { member.user.read().unwrap().id } + fn from(member: Member) -> UserId { member.user.read().id } } impl<'a> From<&'a Member> for UserId { /// Gets the Id of a `Member`. - fn from(member: &Member) -> UserId { member.user.read().unwrap().id } + fn from(member: &Member) -> UserId { member.user.read().id } } impl From<User> for UserId { diff --git a/src/model/utils.rs b/src/model/utils.rs index 719a472..62ecc4e 100644 --- a/src/model/utils.rs +++ b/src/model/utils.rs @@ -1,6 +1,7 @@ +use parking_lot::RwLock; use serde::de::Error as DeError; use std::collections::HashMap; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use super::*; #[cfg(feature = "cache")] @@ -44,7 +45,7 @@ pub fn deserialize_members<'de, D: Deserializer<'de>>( let mut members = HashMap::new(); for member in vec { - let user_id = member.user.read().unwrap().id; + let user_id = member.user.read().id; members.insert(user_id, member); } @@ -73,8 +74,8 @@ pub fn deserialize_private_channels<'de, D: Deserializer<'de>>( for private_channel in vec { let id = match private_channel { - Channel::Group(ref group) => group.read().unwrap().channel_id, - Channel::Private(ref channel) => channel.read().unwrap().id, + Channel::Group(ref group) => group.read().channel_id, + Channel::Private(ref channel) => channel.read().id, Channel::Guild(_) => unreachable!("Guild private channel decode"), Channel::Category(_) => unreachable!("Channel category private channel decode"), }; @@ -147,7 +148,7 @@ pub fn deserialize_voice_states<'de, D: Deserializer<'de>>( #[cfg(all(feature = "cache", feature = "model"))] pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Result<bool> { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); let current_user = &cache.user; let channel = match cache.channel(channel_id) { @@ -156,7 +157,7 @@ pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Re }; let guild_id = match channel { - Channel::Guild(channel) => channel.read().unwrap().guild_id, + Channel::Guild(channel) => channel.read().guild_id, Channel::Group(_) | Channel::Private(_) | Channel::Category(_) => { // Both users in DMs, and all users in groups and maybe all channels in categories will // have the same @@ -177,10 +178,7 @@ pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Re None => return Err(Error::Model(ModelError::ItemMissing)), }; - let perms = guild - .read() - .unwrap() - .permissions_for(channel_id, current_user.id); + let perms = guild.read().permissions_for(channel_id, current_user.id); permissions.remove(perms); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 4b36b73..c6d27c3 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -455,7 +455,7 @@ pub fn shard_id(guild_id: u64, shard_count: u64) -> u64 { (guild_id >> 22) % sha #[cfg(feature = "cache")] pub fn with_cache<T, F>(f: F) -> T where F: Fn(&Cache) -> T { - let cache = CACHE.read().unwrap(); + let cache = CACHE.read(); f(&cache) } @@ -476,6 +476,6 @@ pub fn with_cache<T, F>(f: F) -> T #[cfg(feature = "cache")] pub fn with_cache_mut<T, F>(mut f: F) -> T where F: FnMut(&mut Cache) -> T { - let mut cache = CACHE.write().unwrap(); + let mut cache = CACHE.write(); f(&mut cache) } diff --git a/src/voice/connection.rs b/src/voice/connection.rs index 3b31488..47b448c 100644 --- a/src/voice/connection.rs +++ b/src/voice/connection.rs @@ -1,4 +1,5 @@ use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; +use parking_lot::Mutex; use opus::{ packet as opus_packet, Application as CodingMode, @@ -11,7 +12,7 @@ use std::collections::HashMap; use std::io::Write; use std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; use std::sync::mpsc::{self, Receiver as MpscReceiver, Sender as MpscSender}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::thread::{self, Builder as ThreadBuilder, JoinHandle}; use std::time::Duration; use super::audio::{AudioReceiver, AudioSource, AudioType, HEADER_LEN, SAMPLE_RATE}; @@ -223,10 +224,7 @@ impl Connection { // Send the voice websocket keepalive if it's time if self.keepalive_timer.check() { - self.client - .lock() - .unwrap() - .send_json(&payload::build_keepalive())?; + self.client.lock().send_json(&payload::build_keepalive())?; } // Send UDP keepalive if it's time @@ -357,10 +355,7 @@ impl Connection { self.speaking = speaking; - self.client - .lock() - .unwrap() - .send_json(&payload::build_speaking(speaking)) + self.client.lock().send_json(&payload::build_speaking(speaking)) } } @@ -452,7 +447,7 @@ fn start_threads(client: Arc<Mutex<Client>>, udp: &UdpSocket) -> Result<ThreadIt let ws_thread = ThreadBuilder::new() .name(format!("{} WS", thread_name)) .spawn(move || loop { - while let Ok(Some(msg)) = client.lock().unwrap().recv_json(VoiceEvent::decode) { + while let Ok(Some(msg)) = client.lock().recv_json(VoiceEvent::decode) { if tx_clone.send(ReceiverStatus::Websocket(msg)).is_ok() { return; } |