fn update(&self, poll: &Poll, token: Token, interest: Ready, opt: PollOpt) -> io::Result<()> {
        // Ensure poll instances match
        if !self.queue.identical(&poll.readiness_queue) {
            return Err(io::Error::new(io::ErrorKind::Other, "registration registered with another instance of Poll"));
        }

        // The `update_lock` atomic is used as a flag ensuring only a single
        // thread concurrently enters the `update` critical section. Any
        // concurrent calls to update are discarded. If coordinated updates are
        // required, the Mio user is responsible for handling that.
        //
        // Acquire / Release ordering is used on `update_lock` to ensure that
        // data access to the `token_*` variables are scoped to the critical
        // section.

        // Acquire the update lock.
        if self.update_lock.compare_and_swap(false, true, Acquire) {
            // The lock is already held. Discard the update
            return Ok(());
        }

        // Relaxed ordering is acceptable here as the only memory that needs to
        // be visible as part of the update are the `token_*` variables, and
        // ordering has already been handled by the `update_lock` access.
        let mut state = self.state.load(Relaxed);
        let mut next;

        // Read the current token, again this memory has been ordered by the
        // acquire on `update_lock`.
        let curr_token_pos = state.token_write_pos();
        let curr_token = unsafe { self::token(self, curr_token_pos) };

        let mut next_token_pos = curr_token_pos;

        // If the `update` call is changing the token, then compute the next
        // available token slot and write the token there.
        //
        // Note that this computation is happening *outside* of the
        // compare-and-swap loop. The update lock ensures that only a single
        // thread could be mutating the write_token_position, so the
        // `next_token_pos` will never need to be recomputed even if
        // `token_read_pos` concurrently changes. This is because
        // `token_read_pos` can ONLY concurrently change to the current value of
        // `token_write_pos`, so `next_token_pos` will always remain valid.
        if token != curr_token {
            next_token_pos = state.next_token_pos();

            // Update the token
            match next_token_pos {
                0 => unsafe { *self.token_0.get() = token },
                1 => unsafe { *self.token_1.get() = token },
                2 => unsafe { *self.token_2.get() = token },
                _ => unreachable!(),
            }
        }

        // Now enter the compare-and-swap loop
        loop {
            next = state;

            // The node is only dropped once all `Registration` handles are
            // dropped. Only `Registration` can call `update`.
            debug_assert!(!state.is_dropped());

            // Update the write token position, this will also release the token
            // to Poll::poll.
            next.set_token_write_pos(next_token_pos);

            // Update readiness and poll opts
            next.set_interest(interest);
            next.set_poll_opt(opt);

            // If there is effective readiness, the node will need to be queued
            // for processing. This exact behavior is still TBD, so we are
            // conservative for now and always fire.
            //
            // See https://github.com/carllerche/mio/issues/535.
            if next.effective_readiness().is_some() {
                next.set_queued();
            }

            // compare-and-swap the state values. Only `Release` is needed here.
            // The `Release` ensures that `Poll::poll` will see the token
            // update and the update function doesn't care about any other
            // memory visibility.
            let actual = self.state.compare_and_swap(state, next, Release);

            if actual == state {
                break;
            }

            // CAS failed, but `curr_token_pos` should not have changed given
            // that we still hold the update lock.
            debug_assert_eq!(curr_token_pos, actual.token_write_pos());

            state = actual;
        }

        // Release the lock
        self.update_lock.store(false, Release);

        if !state.is_queued() && next.is_queued() {
            // We are responsible for enqueing the node.
            try!(self.queue.enqueue_node_with_wakeup(self));
        }

        Ok(())
    }
/// Update the registration details associated with the node
Update the registration details associated with the node
Update the registration details associated with the node
fn update(&self, poll: &Poll, token: Token, interest: Ready, opt: PollOpt) -> io::Result<()> {
        // Ensure poll instances match
        if !self.queue.identical(&poll.readiness_queue) {
            return Err(io::Error::new(io::ErrorKind::Other, "registration registered with another instance of Poll"));
        }
        // The `update_lock` atomic is used as a flag ensuring only a single
        // thread concurrently enters the `update` critical section. Any
        // concurrent calls to update are discarded. If coordinated updates are
        // required, the Mio user is responsible for handling that.
        //
        // Acquire / Release ordering is used on `update_lock` to ensure that
        // data access to the `token_*` variables are scoped to the critical
        // section.
        // Acquire the update lock.
        if self.update_lock.compare_and_swap(false, true, Acquire) {
            // The lock is already held. Discard the update
            return Ok(());
        }
        // Relaxed ordering is acceptable here as the only memory that needs to
        // be visible as part of the update are the `token_*` variables, and
        // ordering has already been handled by the `update_lock` access.
        let mut state = self.state.load(Relaxed);
        let mut next;
        // Read the current token, again this memory has been ordered by the
        // acquire on `update_lock`.
        let curr_token_pos = state.token_write_pos();
        let curr_token = unsafe { self::token(self, curr_token_pos) };
        let mut next_token_pos = curr_token_pos;
        // If the `update` call is changing the token, then compute the next
        // available token slot and write the token there.
        //
        // Note that this computation is happening *outside* of the
        // compare-and-swap loop. The update lock ensures that only a single
        // thread could be mutating the write_token_position, so the
        // `next_token_pos` will never need to be recomputed even if
        // `token_read_pos` concurrently changes. This is because
        // `token_read_pos` can ONLY concurrently change to the current value of
        // `token_write_pos`, so `next_token_pos` will always remain valid.
        if token != curr_token {
            next_token_pos = state.next_token_pos();
            // Update the token
            match next_token_pos {
                0 => unsafe { *self.token_0.get() = token },
                1 => unsafe { *self.token_1.get() = token },
                2 => unsafe { *self.token_2.get() = token },
                _ => unreachable!(),
            }
        }
        // Now enter the compare-and-swap loop
        loop {
            next = state;
            // The node is only dropped once all `Registration` handles are
            // dropped. Only `Registration` can call `update`.
            debug_assert!(!state.is_dropped());
            // Update the write token position, this will also release the token
            // to Poll::poll.
            next.set_token_write_pos(next_token_pos);
            // Update readiness and poll opts
            next.set_interest(interest);
            next.set_poll_opt(opt);
            // If there is effective readiness, the node will need to be queued
            // for processing. This exact behavior is still TBD, so we are
            // conservative for now and always fire.
            //
            // See https://github.com/carllerche/mio/issues/535.
            if next.effective_readiness().is_some() {
                next.set_queued();
            }
            // compare-and-swap the state values. Only `Release` is needed here.
            // The `Release` ensures that `Poll::poll` will see the token
            // update and the update function doesn't care about any other
            // memory visibility.
            let actual = self.state.compare_and_swap(state, next, Release);
            if actual == state {
                break;
            }
            // CAS failed, but `curr_token_pos` should not have changed given
            // that we still hold the update lock.
            debug_assert_eq!(curr_token_pos, actual.token_write_pos());
            state = actual;
        }
        // Release the lock
        self.update_lock.store(false, Release);
        if !state.is_queued() && next.is_queued() {
            // We are responsible for enqueing the node.
            try!(self.queue.enqueue_node_with_wakeup(self));
        }
        Ok(())
    }
fn update ( & self , poll : & Poll , token : Token , interest : Ready , opt : PollOpt ) -> io :: Result < ( ) > { // Ensure poll instances match if ! self . queue . identical ( & poll . readiness_queue ) { return Err ( io :: Error :: new ( io :: ErrorKind :: Other , " " ) ) ; } // The `update_lock` atomic is used as a flag ensuring only a single // thread concurrently enters the `update` critical section. Any // concurrent calls to update are discarded. If coordinated updates are // required, the Mio user is responsible for handling that. // // Acquire / Release ordering is used on `update_lock` to ensure that // data access to the `token_*` variables are scoped to the critical // section. // Acquire the update lock. if self . update_lock . compare_and_swap ( false , true , Acquire ) { // The lock is already held. Discard the update return Ok ( ( ) ) ; } // Relaxed ordering is acceptable here as the only memory that needs to // be visible as part of the update are the `token_*` variables, and // ordering has already been handled by the `update_lock` access. let mut state = self . state . load ( Relaxed ) ; let mut next ; // Read the current token, again this memory has been ordered by the // acquire on `update_lock`. let curr_token_pos = state . token_write_pos ( ) ; let curr_token = unsafe { self :: token ( self , curr_token_pos ) } ; let mut next_token_pos = curr_token_pos ; // If the `update` call is changing the token, then compute the next // available token slot and write the token there. // // Note that this computation is happening *outside* of the // compare-and-swap loop. The update lock ensures that only a single // thread could be mutating the write_token_position, so the // `next_token_pos` will never need to be recomputed even if // `token_read_pos` concurrently changes. This is because // `token_read_pos` can ONLY concurrently change to the current value of // `token_write_pos`, so `next_token_pos` will always remain valid. if token != curr_token { next_token_pos = state . next_token_pos ( ) ; // Update the token match next_token_pos { 0 => unsafe { * self . token_0 . get ( ) = token } , 1 => unsafe { * self . token_1 . get ( ) = token } , 2 => unsafe { * self . token_2 . get ( ) = token } , _ => unreachable ! ( ) , } } // Now enter the compare-and-swap loop loop { next = state ; // The node is only dropped once all `Registration` handles are // dropped. Only `Registration` can call `update`. debug_assert ! ( state is_dropped ( ) ) ; // Update the write token position, this will also release the token // to Poll::poll. next . set_token_write_pos ( next_token_pos ) ; // Update readiness and poll opts next . set_interest ( interest ) ; next . set_poll_opt ( opt ) ; // If there is effective readiness, the node will need to be queued // for processing. This exact behavior is still TBD, so we are // conservative for now and always fire. // // See https://github.com/carllerche/mio/issues/535. if next . effective_readiness ( ) . is_some ( ) { next . set_queued ( ) ; } // compare-and-swap the state values. Only `Release` is needed here. // The `Release` ensures that `Poll::poll` will see the token // update and the update function doesn't care about any other // memory visibility. let actual = self . state . compare_and_swap ( state , next , Release ) ; if actual == state { break ; } // CAS failed, but `curr_token_pos` should not have changed given // that we still hold the update lock. debug_assert_eq ! ( curr_token_pos actual token_write_pos ( ) ) ; state = actual ; } // Release the lock self . update_lock . store ( false , Release ) ; if ! state . is_queued ( ) && next . is_queued ( ) { // We are responsible for enqueing the node. try ! ( self queue enqueue_node_with_wakeup ( self ) ) ; } Ok ( ( ) ) }
Update the registration details associated with the node
Update the registration details associated with the node
&self
poll
&Poll
token
Token
interest
Ready
opt
PollOpt