2017-04-05 32 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

感謝您的解釋。我想我需要重新設計這個東西.. –