use arc to minimize critical section

pull/5/head
Mingwei Samuel 2019-10-14 21:29:32 -07:00
parent 346ef13ed4
commit dff8eb432d
2 changed files with 25 additions and 39 deletions

View File

@ -1,18 +1,15 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::future::Future; use std::future::Future;
use parking_lot::{ use std::sync::Arc;
RwLock,
RwLockReadGuard,
RwLockWriteGuard,
MappedRwLockReadGuard,
MappedRwLockWriteGuard,
};
use async_std::task; use async_std::task;
use reqwest::{ use reqwest::{
Client, Client,
StatusCode, StatusCode,
}; };
use parking_lot::{
Mutex,
};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use super::rate_limit::RateLimit; use super::rate_limit::RateLimit;
@ -29,10 +26,10 @@ pub struct RegionalRequester<'a> {
/// Represents the app rate limit. /// Represents the app rate limit.
app_rate_limit: RateLimit, app_rate_limit: RateLimit,
/// Represents method rate limits. /// Represents method rate limits.
method_rate_limits: RwLock<HashMap<&'a str, RateLimit>>, method_rate_limits: Mutex<HashMap<&'a str, Arc<RateLimit>>>,
} }
impl <'a> RegionalRequester<'a> { impl<'a> RegionalRequester<'a> {
/// Request header name for the Riot API key. /// Request header name for the Riot API key.
const RIOT_KEY_HEADER: &'static str = "X-Riot-Token"; const RIOT_KEY_HEADER: &'static str = "X-Riot-Token";
@ -40,12 +37,12 @@ impl <'a> RegionalRequester<'a> {
const NONE_STATUS_CODES: [u16; 3] = [ 204, 404, 422 ]; const NONE_STATUS_CODES: [u16; 3] = [ 204, 404, 422 ];
pub fn new(riot_api_config: &'a RiotApiConfig<'a>, client: &'a Client) -> RegionalRequester<'a> { pub fn new(riot_api_config: &'a RiotApiConfig<'a>, client: &'a Client) -> Self {
RegionalRequester { Self {
riot_api_config: riot_api_config, riot_api_config: riot_api_config,
client: client, client: client,
app_rate_limit: RateLimit::new(RateLimitType::Application), app_rate_limit: RateLimit::new(RateLimitType::Application),
method_rate_limits: RwLock::new(HashMap::new()), method_rate_limits: Mutex::new(HashMap::new()),
} }
} }
@ -59,8 +56,8 @@ impl <'a> RegionalRequester<'a> {
// Rate limiting. // Rate limiting.
while let Some(delay) = { while let Some(delay) = {
let method_rate_limit = &self.get_insert_rate_limit(method_id); let method_rate_limit = self.get_method_rate_limit(method_id);
RateLimit::get_both_or_delay(&self.app_rate_limit, method_rate_limit) RateLimit::get_both_or_delay(&self.app_rate_limit, &*method_rate_limit)
} { } {
task::sleep(delay).await; task::sleep(delay).await;
} }
@ -81,7 +78,7 @@ impl <'a> RegionalRequester<'a> {
// Update rate limits (if needed). // Update rate limits (if needed).
{ {
self.app_rate_limit.on_response(&response); self.app_rate_limit.on_response(&response);
self.method_rate_limits.read().get(method_id).unwrap().on_response(&response); self.get_method_rate_limit(method_id).on_response(&response);
} }
// Handle response. // Handle response.
@ -118,20 +115,10 @@ impl <'a> RegionalRequester<'a> {
self.get(method_id, relative_url, region, query) self.get(method_id, relative_url, region, query)
} }
fn get_insert_rate_limit(&self, method_id: &'a str) -> MappedRwLockReadGuard<RateLimit> { fn get_method_rate_limit(&self, method_id: &'a str) -> Arc<RateLimit> {
// This is really stupid? Arc::clone(self.method_rate_limits.lock()
{ .entry(method_id)
let map_guard = self.method_rate_limits.read(); .or_insert_with(|| Arc::new(RateLimit::new(RateLimitType::Method))))
if map_guard.contains_key(method_id) {
return RwLockReadGuard::map(map_guard, |mrl| mrl.get(method_id).unwrap());
}
}
let map_guard = self.method_rate_limits.write();
let val_write = RwLockWriteGuard::map(
map_guard, |mrl| mrl.entry(method_id)
.or_insert(RateLimit::new(RateLimitType::Method))
);
MappedRwLockWriteGuard::downgrade(val_write)
} }
fn is_none_status_code(status: &StatusCode) -> bool { fn is_none_status_code(status: &StatusCode) -> bool {

View File

@ -1,4 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc;
use reqwest::{ use reqwest::{
Client, Client,
@ -8,14 +9,12 @@ use super::regional_requester::RegionalRequester;
use crate::riot_api_config::RiotApiConfig; use crate::riot_api_config::RiotApiConfig;
use crate::consts::region::Region; use crate::consts::region::Region;
// pub struct RequesterManager<'a> { pub struct RequesterManager<'a> {
// /// Configuration settings. /// Configuration settings.
// riot_api_config: &'a RiotApiConfig<'a>, riot_api_config: &'a RiotApiConfig<'a>,
// /// Client for making requests. /// Client for making requests.
// client: &'a Client, client: &'a Client,
// /// Represents the app rate limit. /// Per-region requesters.
// app_rate_limit: RateLimit, regional_requesters: HashMap<&'a Region<'a>, Arc<RegionalRequester<'a>>>,
// /// Represents method rate limits. }
// method_rate_limits: HashMap<&'a str, RateLimit>,
// }