|
@@ -1,4 +1,5 @@
|
|
|
use async_std::sync::{Arc, Mutex};
|
|
use async_std::sync::{Arc, Mutex};
|
|
|
|
|
+use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
|
|
|
|
use futures::{
|
|
use futures::{
|
|
|
io::{ReadHalf, WriteHalf},
|
|
io::{ReadHalf, WriteHalf},
|
|
@@ -12,6 +13,7 @@ use url::Url;
|
|
|
|
|
|
|
|
use crate::{
|
|
use crate::{
|
|
|
system::{StoppableTask, StoppableTaskPtr, Subscriber, SubscriberPtr, Subscription},
|
|
system::{StoppableTask, StoppableTaskPtr, Subscriber, SubscriberPtr, Subscription},
|
|
|
|
|
+ util::time,
|
|
|
Error, Result,
|
|
Error, Result,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -29,7 +31,7 @@ struct ChannelInfo {
|
|
|
last_msg: String,
|
|
last_msg: String,
|
|
|
last_status: String,
|
|
last_status: String,
|
|
|
// Message log which is cleared on querying get_info
|
|
// Message log which is cleared on querying get_info
|
|
|
- log: Mutex<Vec<(String, String)>>,
|
|
|
|
|
|
|
+ log: Mutex<Vec<(u64, String, String)>>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl ChannelInfo {
|
|
impl ChannelInfo {
|
|
@@ -62,7 +64,7 @@ pub struct Channel {
|
|
|
message_subsystem: MessageSubsystem,
|
|
message_subsystem: MessageSubsystem,
|
|
|
stop_subscriber: SubscriberPtr<Error>,
|
|
stop_subscriber: SubscriberPtr<Error>,
|
|
|
receive_task: StoppableTaskPtr,
|
|
receive_task: StoppableTaskPtr,
|
|
|
- stopped: Mutex<bool>,
|
|
|
|
|
|
|
+ stopped: AtomicBool,
|
|
|
info: Mutex<ChannelInfo>,
|
|
info: Mutex<ChannelInfo>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -85,7 +87,7 @@ impl Channel {
|
|
|
message_subsystem,
|
|
message_subsystem,
|
|
|
stop_subscriber: Subscriber::new(),
|
|
stop_subscriber: Subscriber::new(),
|
|
|
receive_task: StoppableTask::new(),
|
|
receive_task: StoppableTask::new(),
|
|
|
- stopped: Mutex::new(false),
|
|
|
|
|
|
|
+ stopped: AtomicBool::new(false),
|
|
|
info: Mutex::new(ChannelInfo::new()),
|
|
info: Mutex::new(ChannelInfo::new()),
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
@@ -114,15 +116,13 @@ impl Channel {
|
|
|
/// the channel has been closed.
|
|
/// the channel has been closed.
|
|
|
pub async fn stop(&self) {
|
|
pub async fn stop(&self) {
|
|
|
debug!(target: "net", "Channel::stop() [START, address={}]", self.address());
|
|
debug!(target: "net", "Channel::stop() [START, address={}]", self.address());
|
|
|
- let mut stopped = self.stopped.lock().await;
|
|
|
|
|
- if !*stopped {
|
|
|
|
|
- *stopped = true;
|
|
|
|
|
- self.stop_subscriber.notify(Error::ChannelStopped).await;
|
|
|
|
|
- self.receive_task.stop().await;
|
|
|
|
|
- self.message_subsystem.trigger_error(Error::ChannelStopped).await;
|
|
|
|
|
- debug!(target: "net", "Channel::stop() [END, address={}]", self.address());
|
|
|
|
|
- }
|
|
|
|
|
- drop(stopped);
|
|
|
|
|
|
|
+ assert!(!self.stopped.load(Ordering::Relaxed));
|
|
|
|
|
+ // Changes memory ordering to relaxed. We don't need strict thread locking here.
|
|
|
|
|
+ self.stopped.store(false, Ordering::Relaxed);
|
|
|
|
|
+ self.stop_subscriber.notify(Error::ChannelStopped).await;
|
|
|
|
|
+ self.receive_task.stop().await;
|
|
|
|
|
+ self.message_subsystem.trigger_error(Error::ChannelStopped).await;
|
|
|
|
|
+ debug!(target: "net", "Channel::stop() [END, address={}]", self.address());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Creates a subscription to a stopped signal.
|
|
/// Creates a subscription to a stopped signal.
|
|
@@ -150,13 +150,8 @@ impl Channel {
|
|
|
M::name(),
|
|
M::name(),
|
|
|
self.address()
|
|
self.address()
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
- // TODO can we use RwLock here instead of Mutex
|
|
|
|
|
- {
|
|
|
|
|
- let stopped = *self.stopped.lock().await;
|
|
|
|
|
- if stopped {
|
|
|
|
|
- return Err(Error::ChannelStopped)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if self.stopped.load(Ordering::Relaxed) {
|
|
|
|
|
+ return Err(Error::ChannelStopped)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Catch failure and stop channel, return a net error
|
|
// Catch failure and stop channel, return a net error
|
|
@@ -191,10 +186,11 @@ impl Channel {
|
|
|
let mut payload = Vec::new();
|
|
let mut payload = Vec::new();
|
|
|
message.encode(&mut payload)?;
|
|
message.encode(&mut payload)?;
|
|
|
let packet = message::Packet { command: String::from(M::name()), payload };
|
|
let packet = message::Packet { command: String::from(M::name()), payload };
|
|
|
|
|
+ let time = time::unix_timestamp()?;
|
|
|
|
|
|
|
|
{
|
|
{
|
|
|
let info = &mut *self.info.lock().await;
|
|
let info = &mut *self.info.lock().await;
|
|
|
- info.log.lock().await.push(("send".to_string(), packet.command.clone()));
|
|
|
|
|
|
|
+ info.log.lock().await.push((time, "send".to_string(), packet.command.clone()));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let stream = &mut *self.writer.lock().await;
|
|
let stream = &mut *self.writer.lock().await;
|
|
@@ -276,7 +272,8 @@ impl Channel {
|
|
|
let info = &mut *self.info.lock().await;
|
|
let info = &mut *self.info.lock().await;
|
|
|
info.last_msg = packet.command.clone();
|
|
info.last_msg = packet.command.clone();
|
|
|
info.last_status = "recv".to_string();
|
|
info.last_status = "recv".to_string();
|
|
|
- info.log.lock().await.push(("recv".to_string(), packet.command.clone()));
|
|
|
|
|
|
|
+ let time = time::unix_timestamp()?;
|
|
|
|
|
+ info.log.lock().await.push((time, "recv".to_string(), packet.command.clone()));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Send result to our subscribers
|
|
// Send result to our subscribers
|