Skip to content

Channel that only stores latest message, blocking on Recv, but not Send #942

@austenadler

Description

@austenadler

Is it possible to implement a channel that only stores only the latest value and returns the owned latest value on .recv()? This would be roughly similar to:

  • The async tokio::sync::watch, but would be owned rather than borrowed and non-async
  • bounded(1), except senders would never block, since sent messages would just replace the latest message, if there is one
  • (Mutex<T>, CondVar), except senders and receivers are separate like they are in channels, so senders cannot read the value, etc
  • single_value_channel, except recv would block

Current Solution

// A similar effect can be achieved by draining a bounded/unbounded channel, but this channel would be more efficient
while let Ok(mut msg) = chan.recv() {
  // Drain all channel messages, and keep only the last
  while let Ok(m) = chan.try_recv() { msg = m; }

  // Do work with the latest message `msg`
}

Example API

// Some new channel type
let (tx, mut rx) = unbounded_watch_channel::<usize>();

// Set latest value to 0.
tx.send(0);
// Set latest value to 1. This won't block since it's updating the latest value only (would deadlock if using bounded(1))
tx.send(1);

assert_eq!(rx.recv(), Ok(1));

std::thread::spawn(move || {
  tx.send(2);
});

// This will block until the thread above sends 2
assert_eq!(rx.recv(), Ok(2));

// This will sit and wait forever (unlike the tokio::sync::watch api, which does not move values)
x.recv();

Example use-case

If doing a non-interruptable refresh task, and n>1 RefreshRequest messages arrive in the channel during the refresh, the refresh task only runs once more instead of n times more.


If this is something that could conceivably be added to crossbeam, I could try starting development on it. If not, I can fork the single_value_channel source and make it blocking

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions