mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Switch MultiValue to use VecDeque under the hood.
This commit is contained in:
+4
-3
@@ -1,5 +1,6 @@
|
||||
use std::any::TypeId;
|
||||
use std::cell::{Cell, RefCell, UnsafeCell};
|
||||
use std::collections::VecDeque;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
@@ -105,7 +106,7 @@ pub(crate) struct ExtraData {
|
||||
// Pool of `WrappedFailure` enums in the ref thread (as userdata)
|
||||
wrapped_failure_pool: Vec<c_int>,
|
||||
// Pool of `MultiValue` containers
|
||||
multivalue_pool: Vec<Vec<Value<'static>>>,
|
||||
multivalue_pool: Vec<VecDeque<Value<'static>>>,
|
||||
// Pool of `Thread`s (coroutines) for async execution
|
||||
#[cfg(feature = "async")]
|
||||
thread_pool: Vec<c_int>,
|
||||
@@ -3255,13 +3256,13 @@ impl LuaInner {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn pop_multivalue_from_pool(&self) -> Option<Vec<Value>> {
|
||||
pub(crate) fn pop_multivalue_from_pool(&self) -> Option<VecDeque<Value>> {
|
||||
let extra = unsafe { &mut *self.extra.get() };
|
||||
extra.multivalue_pool.pop()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn push_multivalue_to_pool(&self, mut multivalue: Vec<Value>) {
|
||||
pub(crate) fn push_multivalue_to_pool(&self, mut multivalue: VecDeque<Value>) {
|
||||
let extra = unsafe { &mut *self.extra.get() };
|
||||
if extra.multivalue_pool.len() < MULTIVALUE_POOL_SIZE {
|
||||
multivalue.clear();
|
||||
|
||||
+11
-33
@@ -12,28 +12,17 @@ use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil
|
||||
impl<'lua, T: IntoLua<'lua>, E: IntoLua<'lua>> IntoLuaMulti<'lua> for StdResult<T, E> {
|
||||
#[inline]
|
||||
fn into_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
let mut result = MultiValue::with_lua_and_capacity(lua, 2);
|
||||
match self {
|
||||
Ok(v) => result.push_front(v.into_lua(lua)?),
|
||||
Err(e) => {
|
||||
result.push_front(e.into_lua(lua)?);
|
||||
result.push_front(Nil);
|
||||
}
|
||||
Ok(val) => (val,).into_lua_multi(lua),
|
||||
Err(err) => (Nil, err).into_lua_multi(lua),
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn push_into_stack_multi(self, lua: &'lua Lua) -> Result<c_int> {
|
||||
match self {
|
||||
Ok(v) => v.push_into_stack(lua).map(|_| 1),
|
||||
Err(e) => {
|
||||
let state = lua.state();
|
||||
check_stack(state, 3)?;
|
||||
ffi::lua_pushnil(state);
|
||||
e.push_into_stack(lua)?;
|
||||
Ok(2)
|
||||
}
|
||||
Ok(val) => (val,).push_into_stack_multi(lua),
|
||||
Err(err) => (Nil, err).push_into_stack_multi(lua),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,13 +31,8 @@ impl<'lua, E: IntoLua<'lua>> IntoLuaMulti<'lua> for StdResult<(), E> {
|
||||
#[inline]
|
||||
fn into_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
match self {
|
||||
Ok(_) => return Ok(MultiValue::new()),
|
||||
Err(e) => {
|
||||
let mut result = MultiValue::with_lua_and_capacity(lua, 2);
|
||||
result.push_front(e.into_lua(lua)?);
|
||||
result.push_front(Nil);
|
||||
Ok(result)
|
||||
}
|
||||
Ok(_) => Ok(MultiValue::new()),
|
||||
Err(err) => (Nil, err).into_lua_multi(lua),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,13 +40,7 @@ impl<'lua, E: IntoLua<'lua>> IntoLuaMulti<'lua> for StdResult<(), E> {
|
||||
unsafe fn push_into_stack_multi(self, lua: &'lua Lua) -> Result<c_int> {
|
||||
match self {
|
||||
Ok(_) => Ok(0),
|
||||
Err(e) => {
|
||||
let state = lua.state();
|
||||
check_stack(state, 3)?;
|
||||
ffi::lua_pushnil(state);
|
||||
e.push_into_stack(lua)?;
|
||||
Ok(2)
|
||||
}
|
||||
Err(err) => (Nil, err).push_into_stack_multi(lua),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +49,7 @@ impl<'lua, T: IntoLua<'lua>> IntoLuaMulti<'lua> for T {
|
||||
#[inline]
|
||||
fn into_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
let mut v = MultiValue::with_lua_and_capacity(lua, 1);
|
||||
v.push_front(self.into_lua(lua)?);
|
||||
v.push_back(self.into_lua(lua)?);
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
@@ -209,7 +187,7 @@ impl<'lua, T: IntoLua<'lua>> IntoLuaMulti<'lua> for Variadic<T> {
|
||||
#[inline]
|
||||
fn into_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
let mut values = MultiValue::with_lua_and_capacity(lua, self.0.len());
|
||||
values.refill(self.0.into_iter().map(|e| e.into_lua(lua)))?;
|
||||
values.extend_from_values(self.0.into_iter().map(|val| val.into_lua(lua)))?;
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
@@ -218,8 +196,8 @@ impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for Variadic<T> {
|
||||
#[inline]
|
||||
fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
|
||||
values
|
||||
.drain_all()
|
||||
.map(|e| T::from_lua(e, lua))
|
||||
.drain(..)
|
||||
.map(|val| T::from_lua(val, lua))
|
||||
.collect::<Result<Vec<T>>>()
|
||||
.map(Variadic)
|
||||
}
|
||||
|
||||
+69
-129
@@ -1,12 +1,11 @@
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashSet;
|
||||
use std::iter;
|
||||
use std::ops::Index;
|
||||
use std::collections::{vec_deque, HashSet, VecDeque};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::os::raw::{c_int, c_void};
|
||||
use std::string::String as StdString;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, mem, ptr, slice, str, vec};
|
||||
use std::{fmt, mem, ptr, str};
|
||||
|
||||
use num_traits::FromPrimitive;
|
||||
|
||||
@@ -751,45 +750,19 @@ pub trait FromLua<'lua>: Sized {
|
||||
/// Multiple Lua values used for both argument passing and also for multiple return values.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MultiValue<'lua> {
|
||||
vec: Vec<Value<'lua>>,
|
||||
deque: VecDeque<Value<'lua>>,
|
||||
lua: Option<&'lua Lua>,
|
||||
}
|
||||
|
||||
impl Drop for MultiValue<'_> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(lua) = self.lua {
|
||||
let vec = mem::take(&mut self.vec);
|
||||
let vec = mem::take(&mut self.deque);
|
||||
lua.push_multivalue_to_pool(vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> MultiValue<'lua> {
|
||||
/// Creates an empty `MultiValue` containing no values.
|
||||
pub const fn new() -> MultiValue<'lua> {
|
||||
MultiValue {
|
||||
vec: Vec::new(),
|
||||
lua: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to `new` but can reuse previously used container with allocated capacity.
|
||||
#[inline]
|
||||
pub(crate) fn with_lua_and_capacity(lua: &'lua Lua, capacity: usize) -> MultiValue<'lua> {
|
||||
let vec = lua
|
||||
.pop_multivalue_from_pool()
|
||||
.map(|mut vec| {
|
||||
vec.reserve(capacity);
|
||||
vec
|
||||
})
|
||||
.unwrap_or_else(|| Vec::with_capacity(capacity));
|
||||
MultiValue {
|
||||
vec,
|
||||
lua: Some(lua),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> Default for MultiValue<'lua> {
|
||||
#[inline]
|
||||
fn default() -> MultiValue<'lua> {
|
||||
@@ -797,121 +770,88 @@ impl<'lua> Default for MultiValue<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> Deref for MultiValue<'lua> {
|
||||
type Target = VecDeque<Value<'lua>>;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.deque
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> DerefMut for MultiValue<'lua> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.deque
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> MultiValue<'lua> {
|
||||
/// Creates an empty `MultiValue` containing no values.
|
||||
pub const fn new() -> MultiValue<'lua> {
|
||||
MultiValue {
|
||||
deque: VecDeque::new(),
|
||||
lua: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to `new` but can reuse previously used container with allocated capacity.
|
||||
#[inline]
|
||||
pub(crate) fn with_lua_and_capacity(lua: &'lua Lua, capacity: usize) -> MultiValue<'lua> {
|
||||
let deque = lua
|
||||
.pop_multivalue_from_pool()
|
||||
.map(|mut deque| {
|
||||
if capacity > 0 {
|
||||
deque.reserve(capacity);
|
||||
}
|
||||
deque
|
||||
})
|
||||
.unwrap_or_else(|| VecDeque::with_capacity(capacity));
|
||||
MultiValue {
|
||||
deque,
|
||||
lua: Some(lua),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn extend_from_values(
|
||||
&mut self,
|
||||
iter: impl IntoIterator<Item = Result<Value<'lua>>>,
|
||||
) -> Result<()> {
|
||||
for value in iter {
|
||||
self.push_back(value?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromIterator<Value<'lua>> for MultiValue<'lua> {
|
||||
#[inline]
|
||||
fn from_iter<I: IntoIterator<Item = Value<'lua>>>(iter: I) -> Self {
|
||||
MultiValue::from_vec(Vec::from_iter(iter))
|
||||
let deque = VecDeque::from_iter(iter);
|
||||
MultiValue { deque, lua: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoIterator for MultiValue<'lua> {
|
||||
type Item = Value<'lua>;
|
||||
type IntoIter = iter::Rev<vec::IntoIter<Value<'lua>>>;
|
||||
type IntoIter = vec_deque::IntoIter<Value<'lua>>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(mut self) -> Self::IntoIter {
|
||||
let vec = mem::take(&mut self.vec);
|
||||
let deque = mem::take(&mut self.deque);
|
||||
mem::forget(self);
|
||||
vec.into_iter().rev()
|
||||
deque.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
|
||||
type Item = &'a Value<'lua>;
|
||||
type IntoIter = iter::Rev<slice::Iter<'a, Value<'lua>>>;
|
||||
type IntoIter = vec_deque::Iter<'a, Value<'lua>>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.vec.iter().rev()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> Index<usize> for MultiValue<'lua> {
|
||||
type Output = Value<'lua>;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
if let Some(result) = self.get(index) {
|
||||
result
|
||||
} else {
|
||||
panic!(
|
||||
"index out of bounds: the len is {} but the index is {}",
|
||||
self.len(),
|
||||
index
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> MultiValue<'lua> {
|
||||
#[inline]
|
||||
pub fn from_vec(mut vec: Vec<Value<'lua>>) -> MultiValue<'lua> {
|
||||
vec.reverse();
|
||||
MultiValue { vec, lua: None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_vec(mut self) -> Vec<Value<'lua>> {
|
||||
let mut vec = mem::take(&mut self.vec);
|
||||
mem::forget(self);
|
||||
vec.reverse();
|
||||
vec
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, index: usize) -> Option<&Value<'lua>> {
|
||||
if index < self.vec.len() {
|
||||
return self.vec.get(self.vec.len() - index - 1);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pop_front(&mut self) -> Option<Value<'lua>> {
|
||||
self.vec.pop()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn push_front(&mut self, value: Value<'lua>) {
|
||||
self.vec.push(value);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
self.vec.clear();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.vec.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.vec.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter(&self) -> iter::Rev<slice::Iter<Value<'lua>>> {
|
||||
self.vec.iter().rev()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn drain_all(&mut self) -> iter::Rev<vec::Drain<Value<'lua>>> {
|
||||
self.vec.drain(..).rev()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn refill(
|
||||
&mut self,
|
||||
iter: impl IntoIterator<Item = Result<Value<'lua>>>,
|
||||
) -> Result<()> {
|
||||
self.vec.clear();
|
||||
for value in iter {
|
||||
self.vec.push(value?);
|
||||
}
|
||||
self.vec.reverse();
|
||||
Ok(())
|
||||
self.deque.iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -975,8 +915,8 @@ pub trait FromLuaMulti<'lua>: Sized {
|
||||
#[inline]
|
||||
unsafe fn from_stack_multi(nvals: c_int, lua: &'lua Lua) -> Result<Self> {
|
||||
let mut values = MultiValue::with_lua_and_capacity(lua, nvals as usize);
|
||||
for idx in 1..=nvals {
|
||||
values.push_front(lua.stack_value(-idx));
|
||||
for idx in 0..nvals {
|
||||
values.push_back(lua.stack_value(-nvals + idx));
|
||||
}
|
||||
if nvals > 0 {
|
||||
// It's safe to clear the stack as all references moved to ref thread
|
||||
|
||||
Reference in New Issue
Block a user