swctx

Check-in Differences
Login

Check-in Differences

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Difference From swctx-0.1.0 To swctx-0.1.1

2023-08-10
15:15
Merge. check-in: b2f56db268 user: jan tags: trunk
2023-08-09
13:30
Experimenting with generalized SetCtx state. check-in: e69956c141 user: jan tags: generalized-setctx-state
2023-08-08
07:22
Release maintenance. check-in: 580e75c17c user: jan tags: swctx-0.1.1, trunk
07:19
Add try_get() as a non-blocking alternative to wait(). check-in: c6619994a8 user: jan tags: trunk
2023-07-30
21:09
Add exclude list. Don't use full features for tokio. check-in: 03825e43b4 user: jan tags: swctx-0.1.0, trunk
20:56
Move project from brainstorming repo. check-in: 9b3e6e5ca3 user: jan tags: trunk

Changes to Cargo.toml.

1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







[package]
name = "swctx"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
license = "0BSD"
categories = [ "concurrency", "asynchronous" ]
keywords = [ "channel", "threads", "sync", "message-passing" ]
repository = "https://repos.qrnch.tech/pub/swctx"
description = "One-shot channel with some special semantics."
rust-version = "1.56"

Changes to src/lib.rs.

67
68
69
70
71
72
73


























74
75
76
77
78
79
80
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  Err(Error<E>)
}

struct Inner<T, E> {
  state: State<T, E>,
  waker: Option<Waker>
}

impl<T, E> Inner<T, E> {
  fn try_get(&mut self) -> Result<Option<T>, Error<E>> {
    match self.state {
      State::Inactive | State::Waiting => Ok(None),
      State::Data(_) => {
        let old = std::mem::replace(&mut self.state, State::Finalized);
        let State::Data(data) = old else {
          panic!("Unable to extract data");
        };
        Ok(Some(data))
      }
      State::Err(_) => {
        let old = std::mem::replace(&mut self.state, State::Finalized);
        let State::Err(err) = old else {
          panic!("Unable to extract error");
        };
        Err(err)
      }
      _ => {
        panic!("Unexpected state");
      }
    }
  }
}


struct Shared<T, E> {
  inner: Mutex<Inner<T, E>>,
  signal: Condvar
}

impl<T, E> Shared<T, E> {

Changes to src/wctx.rs.

39
40
41
42
43
44
45













46
47
48
49



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81


82
83
84
85
86
87















88




89
90
91
92
93







+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
















-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-





        }
        _ => {
          panic!("Unexpected state");
        }
      }
    }
  }

  /// Non-blocking attempt to get the get the stored value.
  ///
  /// Returns `Ok(Some(T))` if a value has been stored.  Returns `Ok(None)` if
  /// no value has been stored.
  ///
  /// # Panic
  /// This function will panic if called again after it has resolved to either
  /// data or error.
  pub fn try_get(&self) -> Result<Option<T>, Error<E>> {
    let mut inner = self.0.inner.lock();
    inner.try_get()
  }

  /// Return a `Future` that will wait for either data to be set or an error to
  /// occur.
  ///
  /// # Cancel safety
  /// This method is cancel safe.
  ///
  /// # Panic
  /// This function will panic if called again after it has resolved to either
  /// data or error.
  pub fn wait_async(&self) -> WaitFuture<T, E> {
    WaitFuture(Arc::clone(&self.0))
  }
}


#[repr(transparent)]
pub struct WaitFuture<T, E>(Arc<Shared<T, E>>);

impl<T, E> Future for WaitFuture<T, E> {
  type Output = Result<T, Error<E>>;
  fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
    let mut inner = self.0.inner.lock();
    match inner.state {
      State::Inactive | State::Waiting => {
    match inner.try_get() {
      Ok(Some(v)) => Poll::Ready(Ok(v)),
      Ok(None) => {
        inner.waker = Some(ctx.waker().clone());
        Poll::Pending
      }
      State::Data(_) => {
        let State::Data(data) =
          std::mem::replace(&mut inner.state, State::Finalized)
        else {
          panic!("Unexpected state; not State::Data()");
        };
        Poll::Ready(Ok(data))
      }
      State::Err(_) => {
        let State::Err(err) =
          std::mem::replace(&mut inner.state, State::Finalized)
        else {
          panic!("Unexpected state; not State::Err()");
        };
        Poll::Ready(Err(err))
      Err(e) => Poll::Ready(Err(e))
      }
      State::Finalized => {
        panic!("Unexpected state");
      }
    }
  }
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :

Changes to www/changelog.md.

1
2
3
4
5
6
7
8
9
10







11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22










+
+
+
+
+
+
+





# Change Log

## [Unreleased]

### Added

### Changed

### Removed


## [0.1.1] - 2023-08-08

### Added

- Add a `try_get()` as a non-blocking alternative to `wait()`.


## [0.1.0] - 2023-07-30

- First release.