我无法在结构内部增加值。我遇到许多不同的编译错误。我对self
的引用是一成不变的,我无法使其变得可变。
这是我的结构:
/// Proposer factory.
pub struct ProposerFactory<C, A>
where
A: txpool::ChainApi,
{
/// The client instance.
pub client: Arc<C>,
/// The transaction pool.
pub transaction_pool: Arc<TransactionPool<A>>,
/// The inherents pool
pub inherents_pool: Arc<InherentsPool<<A::Block as BlockT>::Extrinsic>>,
/// Current queue number
cur_queue_no_ptr: Arc<u64>,
}
我想将cur_queue_no_ptr
加+1
我尝试了以下代码:
let old_value_ref = Arc::get_mut(&mut self.cur_queue_no_ptr).unwrap();
let old_value = *old_value_ref;
let new_value = old_value + 1;
但出现此错误:
152 | let old_value_ref=Arc::get_mut(&mut self.cur_queue_no_ptr).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
我尝试了以下代码:
let copied_arc = Arc::clone(&self.cur_queue_no_ptr);
let old_value = *Arc::make_mut(&mut copied_arc);
let new_value = old_value + 1;
另一个错误:
150 | let old_value = *Arc::make_mut(&mut copied_arc);
| ^^^^^^^^^^^^^^^ cannot borrow as mutable
我也尝试过RefCell
,但我得到了这个错误:
^^^^^ `std::cell::RefCell<u64>` cannot be shared between threads safely
显然,文档中的示例仅适用于变量,而不适用于结构,那么如何使用结构呢?
答案 0 :(得分:4)
Arc
仅允许在对Arc
对象本身具有可变引用的情况下获得对内容的可变引用。
这里您想要的是RefCell
的等价线程安全编码的等效项之一,即Mutex
或RwLock
。这些将在您借用内容时锁定对内容的访问,以便您可以安全地同时从多个线程访问它们:
// defining the counter variable
let counter = Arc::new(Mutex::new(0));
// lock the mutex to borrow
// it is automatically released when the borrow ends
let counter_lock = counter.lock();
*counter_lock = *counter_lock + 1;
Mutex
仅允许您可变地借用,这使其更简单,但有时还不够。 RwLock
还允许您不变地借用,这样您就可以拥有一个可变的借用或多个不变的借用。
或者,对于数字类型,最好使用atomic types。这些是专门为整数创建的,并且比Mutex
或RwLock
更快(因为它们不需要锁定任何东西,因此更改是原子发生的)。对于上述计数器,相应的示例如下:
// define the counter variable
let counter = Arc::new(AtomicU32::new(0));
// increment the counter
// no lock or mutable borrow is necessary
counter.fetch_add(1, Ordering::SeqCst);