Skip to content

Commit

Permalink
impl Drop for MultiValue
Browse files Browse the repository at this point in the history
This action would automatically return container to the pool on drop (instead of doing it manually)
  • Loading branch information
khvzak committed Aug 1, 2023
1 parent 196c09a commit 4fff14a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 67 deletions.
12 changes: 5 additions & 7 deletions src/lua.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,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<MultiValue<'static>>,
multivalue_pool: Vec<Vec<Value<'static>>>,
// Pool of `Thread`s (coroutines) for async execution
#[cfg(feature = "async")]
thread_pool: Vec<c_int>,
Expand Down Expand Up @@ -2898,8 +2898,7 @@ impl Lua {
let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
let _guard = StateGuard::new(&lua.0, state);

let mut args = MultiValue::new_or_pooled(lua);
args.reserve(nargs as usize);
let mut args = MultiValue::with_lua_and_capacity(lua, nargs as usize);
for _ in 0..nargs {
args.push_front(lua.pop_value());
}
Expand Down Expand Up @@ -2943,7 +2942,6 @@ impl Lua {
for r in results.drain_all() {
lua.push_value(r)?;
}
MultiValue::return_to_pool(results, lua);
Ok(nresults as c_int + 1)
}
_ => {
Expand Down Expand Up @@ -3184,13 +3182,13 @@ impl LuaInner {
}

#[inline]
pub(crate) fn new_multivalue_from_pool(&self) -> MultiValue {
pub(crate) fn pop_multivalue_from_pool(&self) -> Option<Vec<Value>> {
let extra = unsafe { &mut *self.extra.get() };
extra.multivalue_pool.pop().unwrap_or_default()
extra.multivalue_pool.pop()
}

#[inline]
pub(crate) fn return_multivalue_to_pool(&self, mut multivalue: MultiValue) {
pub(crate) fn push_multivalue_to_pool(&self, mut multivalue: Vec<Value>) {
let extra = unsafe { &mut *self.extra.get() };
if extra.multivalue_pool.len() < MULTIVALUE_POOL_SIZE {
multivalue.clear();
Expand Down
25 changes: 9 additions & 16 deletions src/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ 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::new_or_pooled(lua);
let mut result = MultiValue::with_lua_and_capacity(lua, 2);
match self {
Ok(v) => result.push_front(v.into_lua(lua)?),
Err(e) => {
Expand All @@ -28,7 +28,7 @@ impl<'lua, T: IntoLua<'lua>, E: IntoLua<'lua>> IntoLuaMulti<'lua> for StdResult<
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::new_or_pooled(lua);
let mut v = MultiValue::with_lua_and_capacity(lua, 1);
v.push_front(self.into_lua(lua)?);
Ok(v)
}
Expand All @@ -43,9 +43,7 @@ impl<'lua, T: IntoLua<'lua>> IntoLuaMulti<'lua> for T {
impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for T {
#[inline]
fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
let res = T::from_lua(values.pop_front().unwrap_or(Nil), lua);
MultiValue::return_to_pool(values, lua);
res
T::from_lua(values.pop_front().unwrap_or(Nil), lua)
}

#[inline]
Expand All @@ -55,9 +53,7 @@ impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for T {
to: Option<&str>,
lua: &'lua Lua,
) -> Result<Self> {
let res = T::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua);
MultiValue::return_to_pool(args, lua);
res
T::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua)
}

#[inline]
Expand Down Expand Up @@ -170,7 +166,7 @@ impl<T> DerefMut for Variadic<T> {
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::new_or_pooled(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)))?;
Ok(values)
}
Expand All @@ -179,13 +175,11 @@ impl<'lua, T: IntoLua<'lua>> IntoLuaMulti<'lua> for Variadic<T> {
impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for Variadic<T> {
#[inline]
fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
let res = values
values
.drain_all()
.map(|e| T::from_lua(e, lua))
.collect::<Result<Vec<T>>>()
.map(Variadic);
MultiValue::return_to_pool(values, lua);
res
.map(Variadic)
}
}

Expand All @@ -194,7 +188,7 @@ macro_rules! impl_tuple {
impl<'lua> IntoLuaMulti<'lua> for () {
#[inline]
fn into_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
Ok(MultiValue::new_or_pooled(lua))
Ok(MultiValue::with_lua_and_capacity(lua, 0))
}

#[inline]
Expand All @@ -205,8 +199,7 @@ macro_rules! impl_tuple {

impl<'lua> FromLuaMulti<'lua> for () {
#[inline]
fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
MultiValue::return_to_pool(values, lua);
fn from_lua_multi(_values: MultiValue<'lua>, _lua: &'lua Lua) -> Result<Self> {
Ok(())
}

Expand Down
101 changes: 57 additions & 44 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::ops::Index;
use std::os::raw::{c_int, c_void};
use std::string::String as StdString;
use std::sync::Arc;
use std::{fmt, ptr, slice, str, vec};
use std::{fmt, mem, ptr, slice, str, vec};

#[cfg(feature = "serialize")]
use {
Expand Down Expand Up @@ -379,24 +379,43 @@ 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<Value<'lua>>);
pub struct MultiValue<'lua> {
vec: Vec<Value<'lua>>,
lua: Option<&'lua Lua>,
}

impl Drop for MultiValue<'_> {
fn drop(&mut self) {
if let Some(lua) = self.lua {
let vec = mem::replace(&mut self.vec, Vec::new());
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::new())
}

/// Similar to `new` but can return previously used container with allocated capacity.
#[inline]
pub(crate) fn new_or_pooled(lua: &'lua Lua) -> MultiValue<'lua> {
lua.new_multivalue_from_pool()
MultiValue {
vec: Vec::new(),
lua: None,
}
}

/// Clears and returns previously allocated multivalue container to the pool.
/// Similar to `new` but can reuse previously used container with allocated capacity.
#[inline]
pub(crate) fn return_to_pool(multivalue: Self, lua: &Lua) {
lua.return_multivalue_to_pool(multivalue);
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),
}
}
}

Expand All @@ -419,8 +438,10 @@ impl<'lua> IntoIterator for MultiValue<'lua> {
type IntoIter = iter::Rev<vec::IntoIter<Value<'lua>>>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter().rev()
fn into_iter(mut self) -> Self::IntoIter {
let vec = mem::replace(&mut self.vec, Vec::new());
mem::forget(self);
vec.into_iter().rev()
}
}

Expand All @@ -430,7 +451,7 @@ impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.iter().rev()
self.vec.iter().rev()
}
}

Expand All @@ -453,76 +474,72 @@ impl<'lua> Index<usize> for MultiValue<'lua> {

impl<'lua> MultiValue<'lua> {
#[inline]
pub fn from_vec(mut v: Vec<Value<'lua>>) -> MultiValue<'lua> {
v.reverse();
MultiValue(v)
pub fn from_vec(mut vec: Vec<Value<'lua>>) -> MultiValue<'lua> {
vec.reverse();
MultiValue { vec, lua: None }
}

#[inline]
pub fn into_vec(self) -> Vec<Value<'lua>> {
let mut v = self.0;
v.reverse();
v
pub fn into_vec(mut self) -> Vec<Value<'lua>> {
let mut vec = mem::replace(&mut self.vec, Vec::new());
mem::forget(self);
vec.reverse();
vec
}

#[inline]
pub fn get(&self, index: usize) -> Option<&Value<'lua>> {
if index < self.0.len() {
return self.0.get(self.0.len() - index - 1);
if index < self.vec.len() {
return self.vec.get(self.vec.len() - index - 1);
}
None
}

#[inline]
pub(crate) fn reserve(&mut self, size: usize) {
self.0.reserve(size);
}

#[inline]
pub fn pop_front(&mut self) -> Option<Value<'lua>> {
self.0.pop()
self.vec.pop()
}

#[inline]
pub fn push_front(&mut self, value: Value<'lua>) {
self.0.push(value);
self.vec.push(value);
}

#[inline]
pub fn clear(&mut self) {
self.0.clear();
self.vec.clear();
}

#[inline]
pub fn len(&self) -> usize {
self.0.len()
self.vec.len()
}

#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
self.vec.is_empty()
}

#[inline]
pub fn iter(&self) -> iter::Rev<slice::Iter<Value<'lua>>> {
self.0.iter().rev()
self.vec.iter().rev()
}

#[inline]
pub(crate) fn drain_all(&mut self) -> iter::Rev<vec::Drain<Value<'lua>>> {
self.0.drain(..).rev()
self.vec.drain(..).rev()
}

#[inline]
pub(crate) fn refill(
&mut self,
iter: impl IntoIterator<Item = Result<Value<'lua>>>,
) -> Result<()> {
self.0.clear();
self.vec.clear();
for value in iter {
self.0.push(value?);
self.vec.push(value?);
}
self.0.reverse();
self.vec.reverse();
Ok(())
}
}
Expand All @@ -543,15 +560,12 @@ pub trait IntoLuaMulti<'lua>: Sized {
unsafe fn push_into_stack_multi(self, lua: &'lua Lua) -> Result<c_int> {
let mut values = self.into_lua_multi(lua)?;
let len: c_int = values.len().try_into().unwrap();

unsafe {
check_stack(lua.state(), len + 1)?;
for v in values.drain_all() {
lua.push_value(v)?;
}
}
MultiValue::return_to_pool(values, lua);

Ok(len)
}
}
Expand Down Expand Up @@ -589,8 +603,7 @@ pub trait FromLuaMulti<'lua>: Sized {
#[doc(hidden)]
#[inline]
unsafe fn from_stack_multi(nvals: c_int, lua: &'lua Lua) -> Result<Self> {
let mut values = MultiValue::new_or_pooled(lua);
values.reserve(nvals as usize);
let mut values = MultiValue::with_lua_and_capacity(lua, nvals as usize);
for idx in 1..=nvals {
values.push_front(lua.stack_value(-idx));
}
Expand Down

0 comments on commit 4fff14a

Please sign in to comment.