2017-04-05 69 views
0

我试图实现基于TypedArena的内存池。下面是我的原代码的简化版本:关于锈蚀寿命的问题

#![feature(rustc_private)] 
extern crate arena; 
use arena::TypedArena; 

pub struct MemoryPool { 
    arena: TypedArena<Vec<u8>>, 
    bytes_allocated: usize, 
} 

impl MemoryPool { 
    pub fn consume(&mut self, buf: Vec<u8>) -> &[u8] { 
     self.bytes_allocated += buf.capacity(); 
     self.arena.alloc(buf) 
    } 
} 

pub struct ByteArray<'a> { 
    data: &'a [u8], 
} 

impl<'a> ByteArray<'a> { 
    pub fn set_data(&mut self, data: &'a [u8]) { 
     self.data = data; 
    } 
} 

pub struct S<'a> { 
    pool: &'a mut MemoryPool, 
} 

impl<'a> S<'a> { 
    pub fn write(&mut self, buffer: &mut ByteArray<'a>) { 
     let v = vec!(); 
     let data = self.pool.consume(v); 
     buffer.set_data(data); 
    } 
} 

然而,编译器抱怨行:let data = self.pool.consume(v);

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 
    --> <anon>:34:26 
    | 
34 |  let data = self.pool.consume(v); 
    |       ^^^^^^^ 
    | 
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 32:54... 
    --> <anon>:32:55 
    | 
32 |  pub fn write(&mut self, buffer: &mut ByteArray<'a>) { 
    | _______________________________________________________^ starting here... 
33 | |  let v = vec!(); 
34 | |  let data = self.pool.consume(v); 
35 | |  buffer.set_data(data); 
36 | | } 
    | |___^ ...ending here 
note: ...so that reference does not outlive borrowed content 
    --> <anon>:34:16 
    | 
34 |  let data = self.pool.consume(v); 
    |    ^^^^^^^^^ 
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 32:54... 
    --> <anon>:32:55 
    | 
32 |  pub fn write(&mut self, buffer: &mut ByteArray<'a>) { 
    | _______________________________________________________^ starting here... 
33 | |  let v = vec!(); 
34 | |  let data = self.pool.consume(v); 
35 | |  buffer.set_data(data); 
36 | | } 
    | |___^ ...ending here 
note: ...so that types are compatible (expected &mut ByteArray<'_>, found &mut ByteArray<'a>) 
    --> <anon>:35:12 
    | 
35 |  buffer.set_data(data); 
    |   ^^^^^^^^ 

我的问题是:

  1. 为什么data不有终身'a?我在想,由于pool的使用寿命为a,并且consume的返回寿命与self相同,因此应该有终生使用期限'a

  2. 使代码正常工作的最佳方式是什么?基本上我想分配新的字节并将其生存期调整为与内存池相同。我知道我可以直接使用TypedArena,因为alloc不需要mut参考。不过,我真的想跟踪其他信息,如bytes_allocated

回答

0

让我们一步解决此步骤:

cannot infer an appropriate lifetime for autoref 

“autoref”描述为建设一个方法的self说法正确的引用的过程。编译器无法找到具有正确的生命周期的引用来调用consume()。为什么它不能?

note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 32:54... 
    --> <anon>:32:55 
    | 
32 |  pub fn write(&mut self, buffer: &mut ByteArray<'a>) { 
    | _______________________________________________________^ starting here... 
33 | |  let v = vec!(); 
34 | |  let data = self.pool.consume(v); 
35 | |  buffer.set_data(data); 
36 | | } 
    | |___^ ...ending here 
note: ...so that reference does not outlive borrowed content 
    --> <anon>:34:16 
    | 
34 |  let data = self.pool.consume(v); 
    |    ^^^^^^^^^ 

“匿名生命周期#1”是指生命周期为&mut self。这个说明只是说:我们不能将寿命大于self的寿命的参考值传递给consume():那么consume()会认为它的参数寿命比实际寿命长。

note: but, the lifetime must be valid for the lifetime 'a 

这是您已经预期应用的规则。但现在问题在哪里?那么:&mut self(匿名生命#1)的寿命可以比生命'a!就这样!我们可以很容易地解决这个问题:

impl<'a> S<'a> { 
    pub fn write<'b: 'a>(&'b mut self, buffer: &mut ByteArray<'a>) { 
     //  ^^^^^^^^ ^^ 
     ... 
    } 
} 

这里我们仅举先前匿名终身#1能够约束它,称它有活得比'a(比'a寿命更长)。

+0

谢谢。我认为我的困惑是'self.pool'拥有'self'而不是'pool','pool'是可变的。这是不直观的,因为有一个生命周期注释“a”附加到“池”。为了修复代码,你有其他建议,而不是为'self'添加'b'吗?这对我的原始代码不起作用,因为结构“S”预计比“a”短。 –

+0

@ChaoSun这是不可能的。 'MemoryPool'不能返回一个比它自己寿命更长的引用,同样,'S'不能返回引用的东西比它自己长,并且'S :: pool'的寿命与'S'一样长。我不太清楚你想要达到的目标。 –

+0

感谢您的解释。我想我需要重新设计这个东西.. –