You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: rcu.rs
    path of file: ./repos/scryer-prolog/src
    
    the code of the file until where you have to start completion: use std::{
    cell::OnceCell,
    fmt::Debug,
    mem::ManuallyDrop,
    ops::Deref,
    ptr::NonNull,
    sync::{
        atomic::{AtomicPtr, AtomicU8},
        Arc, RwLock, Weak,
    },
};

// the epoch counters of all threads that have ever accessed an Rcu
// threads that have finished will have a dangling Weak reference and can be cleand up
// having this be shared between all Rcu's is a tradeof,
// writes will be slower as more epoch counters need to be waited for
// reads should be faster as a thread only needs to register itself once on the first read
//
static EPOCH_COUNTERS: RwLock<Vec<Weak<AtomicU8>>> = RwLock::new(Vec::new());

thread_local! {
    // odd value means the current thread is about to access the active_epoch of an Rcu
    // a thread has a single epoch counter for all Rcu it accesses,
    // as a thread can only access o
    
    pub fn replace(&self, new_value: T) {
        let arc_ptr = self.active_value.swap(
            Arc::into_raw(Arc::new(new_value)).cast_mut(),
            std::sync::atomic::Ordering::AcqRel,
        );

        // maually drop as we need to ensure not to drop the arc while
        // we have not witnest all threads to be or have been outside the read critical section
        // i.e. even epoch counter or different odd epoch counter
        // Safety:
        // - the ptr was created in Rcu::new or Rcu::replace with Arc::into_raw
        // - the Rcu itself holds one strong count
        let arc = unsafe { ManuallyDrop::new(Arc::from_raw(arc_ptr)) };

        let epochs = EPOCH_COUNTERS.read().unwrap().clone();
        let mut epochs = epochs
            .into_iter()
            .flat_map(|elem| {
                let arc = elem.upgrade()?;
                let init_val = arc.load(std::sync::atomic::Ordering::Acquire);
                if init_val % 2 == 0 {
                    // already even can be ignored
                    return None;
                }
                // odd initial value thread is in read critical section
                // need to wait for the value to change before we can drop the arc
                Some((init_val, elem))
            })
            .collect::<Vec<_>>();

        while !epochs.is_empty() {
            epochs.retain(|elem| {
                let Some(arc) = elem.1.upgrade() else {
                    // as the thread is dead it can't have a ref to old arc
                    return false;
                };
                // the epoch counter has not changed so the thread is still in the same instance of the critical section
                // any different value is ok as
                // - even values indicate the thread is outside the critical section
                // - a diffrent odd value indicates the thread has left the critical section and can subsequently only read the new active_value
                arc.load(std::sync::atomic::Ordering::Acquire) == elem.0
            })
        }

        // Safety:
        // - we have not dropped the arc another way
        // - we witnessed all threads either with an even epoch count or with a new odd count
        //   as such they must have left the critical section at some point
        ManuallyDrop::into_inner(arc);
    }