Implement capability HTTP and downloads (#54)
All checks were successful
Native code generation / deterministic (push) Successful in 11m59s
Imaging and meshing gate / native (push) Successful in 3m55s
JPEG 2000 feature / linux (push) Successful in 2m26s
Native Rust workspace compile / compile (push) Successful in 3m58s
Skia feature / linux (push) Successful in 31m44s
All checks were successful
Native code generation / deterministic (push) Successful in 11m59s
Imaging and meshing gate / native (push) Successful in 3m55s
JPEG 2000 feature / linux (push) Successful in 2m26s
Native Rust workspace compile / compile (push) Successful in 3m58s
Skia feature / linux (push) Successful in 31m44s
This commit is contained in:
@@ -356,6 +356,45 @@ impl CancellationToken {
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers an executor-neutral callback and removes it when the returned
|
||||
/// guard is dropped.
|
||||
#[must_use = "dropping the guard immediately unregisters the callback"]
|
||||
pub fn register_callback(&self, callback: Arc<dyn Fn() + Send + Sync>) -> Subscription {
|
||||
if self.is_cancellation_requested() {
|
||||
callback();
|
||||
return Subscription::detached();
|
||||
}
|
||||
let id = self.0.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
self.0
|
||||
.callbacks
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.insert(id, callback);
|
||||
if self.is_cancellation_requested() {
|
||||
if let Some(callback) = self
|
||||
.0
|
||||
.callbacks
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.remove(&id)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
return Subscription::detached();
|
||||
}
|
||||
let state = Arc::downgrade(&self.0);
|
||||
Subscription::new(move || {
|
||||
let Some(state) = state.upgrade() else {
|
||||
return;
|
||||
};
|
||||
state
|
||||
.callbacks
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.remove(&id);
|
||||
})
|
||||
}
|
||||
|
||||
fn register(&self, callback: Arc<dyn Fn() + Send + Sync>) -> CancellationRegistration {
|
||||
if self.is_cancellation_requested() {
|
||||
callback();
|
||||
@@ -528,7 +567,31 @@ pub struct DictionaryKeys<TKey, TValue>(pub Vec<TKey>, pub PhantomData<fn(TValue
|
||||
|
||||
pub struct DictionaryEntry(pub Object, pub Object);
|
||||
|
||||
pub struct RateLimitLease;
|
||||
/// Result of a mapped rate-limit acquisition.
|
||||
///
|
||||
/// Token-bucket leases do not return a token when dropped; the value records
|
||||
/// whether a token was acquired or the bounded waiting queue was already full.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct RateLimitLease {
|
||||
acquired: bool,
|
||||
}
|
||||
|
||||
impl RateLimitLease {
|
||||
#[must_use]
|
||||
pub const fn acquired() -> Self {
|
||||
Self { acquired: true }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn rejected() -> Self {
|
||||
Self { acquired: false }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn is_acquired(self) -> bool {
|
||||
self.acquired
|
||||
}
|
||||
}
|
||||
|
||||
struct CancellationSourceState {
|
||||
token: CancellationToken,
|
||||
@@ -641,7 +704,160 @@ pub struct Thread;
|
||||
|
||||
pub struct Task<T>(pub PhantomData<fn() -> T>);
|
||||
|
||||
pub struct TaskCompletionSource<T>(pub PhantomData<fn(T)>);
|
||||
struct TaskCompletionState<T> {
|
||||
next_id: AtomicU64,
|
||||
result: Mutex<Option<Result<T, crate::Error>>>,
|
||||
waiters: Mutex<BTreeMap<u64, Waker>>,
|
||||
}
|
||||
|
||||
/// Cloneable completion source used by mapped task-returning APIs.
|
||||
#[derive(Clone)]
|
||||
pub struct TaskCompletionSource<T>(Arc<TaskCompletionState<T>>);
|
||||
|
||||
impl<T> TaskCompletionSource<T> {
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self(Arc::new(TaskCompletionState {
|
||||
next_id: AtomicU64::new(1),
|
||||
result: Mutex::new(None),
|
||||
waiters: Mutex::new(BTreeMap::new()),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Completes the task once and wakes every waiter.
|
||||
#[must_use]
|
||||
pub fn try_set_result(&self, value: T) -> bool {
|
||||
self.try_complete(Ok(value))
|
||||
}
|
||||
|
||||
/// Completes the task with a typed failure once.
|
||||
#[must_use]
|
||||
pub fn try_set_error(&self, error: crate::Error) -> bool {
|
||||
self.try_complete(Err(error))
|
||||
}
|
||||
|
||||
/// Completes the task with mapped cancellation once.
|
||||
#[must_use]
|
||||
pub fn try_set_cancelled(&self) -> bool {
|
||||
self.try_set_error(crate::Error::Cancelled)
|
||||
}
|
||||
|
||||
fn try_complete(&self, value: Result<T, crate::Error>) -> bool {
|
||||
let mut result = self
|
||||
.0
|
||||
.result
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if result.is_some() {
|
||||
return false;
|
||||
}
|
||||
*result = Some(value);
|
||||
drop(result);
|
||||
for (_, waiter) in std::mem::take(
|
||||
&mut *self
|
||||
.0
|
||||
.waiters
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner),
|
||||
) {
|
||||
waiter.wake();
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn future(&self) -> TaskCompletionFuture<T> {
|
||||
TaskCompletionFuture {
|
||||
state: Arc::clone(&self.0),
|
||||
waiter_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_completed(&self) -> bool {
|
||||
self.0
|
||||
.result
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for TaskCompletionSource<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for TaskCompletionSource<T> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("TaskCompletionSource")
|
||||
.field("completed", &self.is_completed())
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
/// Future associated with a [`TaskCompletionSource`].
|
||||
pub struct TaskCompletionFuture<T> {
|
||||
state: Arc<TaskCompletionState<T>>,
|
||||
waiter_id: Option<u64>,
|
||||
}
|
||||
|
||||
impl<T: Clone> Future for TaskCompletionFuture<T> {
|
||||
type Output = Result<T, crate::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if let Some(result) = self
|
||||
.state
|
||||
.result
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.clone()
|
||||
{
|
||||
return Poll::Ready(result);
|
||||
}
|
||||
let id = self.waiter_id.unwrap_or_else(|| {
|
||||
let id = self.state.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
self.waiter_id = Some(id);
|
||||
id
|
||||
});
|
||||
self.state
|
||||
.waiters
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.insert(id, context.waker().clone());
|
||||
let ready = self
|
||||
.state
|
||||
.result
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.clone();
|
||||
if let Some(result) = ready {
|
||||
self.state
|
||||
.waiters
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.remove(&id);
|
||||
self.waiter_id = None;
|
||||
Poll::Ready(result)
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for TaskCompletionFuture<T> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(id) = self.waiter_id {
|
||||
self.state
|
||||
.waiters
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.remove(&id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Cloneable clock boundary used by runtime-neutral client code.
|
||||
#[derive(Clone)]
|
||||
@@ -741,7 +957,19 @@ pub struct HttpMethod(pub String);
|
||||
|
||||
pub struct AuthenticationHeaderValue(pub String);
|
||||
|
||||
pub trait IProgress<T>: Send + Sync {}
|
||||
/// Executor-neutral progress sink used by mapped upload/download APIs.
|
||||
pub trait IProgress<T>: Send + Sync {
|
||||
fn report(&self, value: T);
|
||||
}
|
||||
|
||||
impl<T, F> IProgress<T> for F
|
||||
where
|
||||
F: Fn(T) + Send + Sync,
|
||||
{
|
||||
fn report(&self, value: T) {
|
||||
self(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IEnumerator;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user