Как изменить значение дугив структуре? - PullRequest
0 голосов
/ 21 мая 2019

Я не могу увеличить значение внутри структуры.Я получаю много разных ошибок компиляции.У меня есть неизменяемая ссылка на 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

Видимо, примеры в документах будут работать только для переменных, но не для структур, так как высделать это со структурами?

1 Ответ

4 голосов
/ 21 мая 2019

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 позволяет вам также иметь неизменный заем, так что вы можете иметь либо один изменяемый заем, либо несколько неизменных заимствований.


В качестве альтернативы, для числовых типов может быть предпочтительным использование атомарных типов . Они специально созданы для целых чисел и быстрее, чем 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...