#![cfg(feature = "threadsafe")]
use std::sync::Arc;
use std::fmt;
use std::sync::RwLock;
use send_wrapper::SendWrapper;
use crate::list_item::*;
use crate::list_iterator::*;
use crate::thread_facilities::*;
use crate::threadsafe_context::*;
#[derive(Clone)]
pub struct ThreadSafeListIterator {
list_iter: Arc<RwLock<Option<SendWrapper<ListIterator>>>>,
}
unsafe impl Send for ThreadSafeListIterator {}
unsafe impl Sync for ThreadSafeListIterator {}
impl ThreadSafeListIterator {
pub (crate)
fn create(list_iter: ListIterator) -> Self {
Self {
list_iter: Arc::new(RwLock::new(Some(SendWrapper::new(list_iter))))
}
}
pub fn new(name: &str) -> Result<Self, ListError> {
use ListError::*;
let cname = name.to_string();
main_thread(move |_| {
ListIterator::new(&cname).map(|list|
ThreadSafeListIterator {
list_iter:
Arc::new(RwLock::new(Some(SendWrapper::new(list))))
})}
).get()
.map_or_else(
|err| Err(ThreadSafeOperationFailed(err.to_string())),
|res| res.map_or_else(|| Err(UnknownList(name.into())), Ok))
}
pub fn get_field_names(&self) -> Result<Vec<String>, ListError> {
use ListError::*;
let me = self.clone();
main_thread(move |_| {
Ok(me.list_iter.read().unwrap().as_ref()
.ok_or_else(
|| ListIteratorDropped("ListIterator dropped from \
threadsafe context.".into()))?
.get_field_names().to_vec())
}).get()
.map_or_else(|err| Err(ThreadSafeOperationFailed(err.to_string())),
|res| res)
}
pub fn to_vec(&self) -> Result<Vec<ListItem>, ListError> {
use ListError::*;
let me = self.clone();
main_thread(move |_| {
Ok(me.list_iter.read().unwrap().as_ref()
.ok_or_else(
||ListIteratorDropped("ListIterator dropped from \
threadsafe context.".into()))?
.to_vec())
}).get()
.map_or_else(|err| Err(ThreadSafeOperationFailed(err.to_string())),
|res| res)
}
pub fn get_item(&self) -> Result<ListItem, ListError> {
use ListError::*;
let me = self.clone();
main_thread(move |_| {
Ok(me.list_iter.read().unwrap().as_ref()
.ok_or_else(
||ListIteratorDropped("ListIterator dropped from \
threadsafe context.".into()))?
.get_item())
}).get()
.map_or_else(|err| Err(ThreadSafeOperationFailed(err.to_string())),
|res| res)
}
pub fn get_field(&self,
name: &str
) -> Result<ThreadSafeFieldValue, ListError>
{
use ListError::*;
use FieldValue as FV;
use ThreadSafeFieldValue as TSFV;
let name = name.to_string();
let me = self.clone();
main_thread(move |_| {
if let Some(iter) = me.list_iter.read().unwrap().as_ref() {
match iter.get_field(&name) {
Ok(field_val) => {
match field_val {
FV::StringVal(s) => {
Ok(TSFV::StringVal(s))
},
FV::IntVal(i) => {
Ok(TSFV::IntVal(i))
},
FV::PointerVal(pv) => {
Ok(TSFV::PointerVal(pv))
},
FV::ContextVal(ctx) => {
Ok(TSFV::ContextVal(
ThreadSafeContext::new(ctx)
))
},
FV::TimeVal(time) => {
Ok(TSFV::TimeVal(time))
}
}
},
Err(err) => {
Err(err)
},
}
} else {
Err(ListError::ListIteratorDropped(
"ListIterator dropped from threadsafe context."
.to_string()))
}
}).get()
.map_or_else(|err| Err(ThreadSafeOperationFailed(err.to_string())),
|res| res)
}
}
impl Iterator for ThreadSafeListIterator {
type Item = Self;
fn next(&mut self) -> Option<Self::Item> {
let me = self.clone();
main_thread(move |_| {
if let Some(iter) = me.list_iter.write().unwrap().as_mut() {
iter.next().map(|it| ThreadSafeListIterator::create(it.clone()))
} else {
None
}
}).get().unwrap_or(None)
}
}
impl Iterator for &ThreadSafeListIterator {
type Item = Self;
fn next(&mut self) -> Option<Self::Item> {
let me = self.clone();
let has_more = main_thread(move |_| {
me.list_iter.write().unwrap().as_mut()
.map_or(false, |it| it.next().is_some())
}).get().unwrap_or(false);
if has_more {
Some(self)
} else {
None
}
}
}
impl Drop for ThreadSafeListIterator {
fn drop(&mut self) {
if Arc::strong_count(&self.list_iter) <= 1
&& self.list_iter.read().unwrap().is_some() {
let me = self.clone();
main_thread(move |_| {
me.list_iter.write().unwrap().take();
});
}
}
}
#[derive(Debug, Clone)]
pub enum ThreadSafeFieldValue {
StringVal (String),
IntVal (i32),
PointerVal (u64),
ContextVal (ThreadSafeContext),
TimeVal (i64),
}
unsafe impl Send for ThreadSafeFieldValue {}
unsafe impl Sync for ThreadSafeFieldValue {}
impl fmt::Display for ThreadSafeFieldValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ThreadSafeFieldValue::*;
match self {
StringVal(s) => { write!(f, "{}", s) },
IntVal(i) => { write!(f, "{:?}", i) },
PointerVal(p) => { write!(f, "{:?}", p) },
TimeVal(t) => { write!(f, "{:?}", t) },
ContextVal(c) => { write!(f, "ContextVal({})", c) },
}
}
}