Repository: paritytech/substrate
File: client/rpc-spec-v2/src/chain_head/subscription/inner.rs (Rust)

Code before:
	fn new(max_operations: usize) -> Self {
		LimitOperations { semaphore: Arc::new(tokio::sync::Semaphore::new(max_operations)) }
	}

	/// Reserves capacity to execute at least one operation and at most the requested items.
	///
	/// Dropping [`PermitOperations`] without executing an operation will release
	/// the reserved capacity.
	///
	/// Returns nothing if there's no space available, else returns a permit
	/// that guarantees that at least one operation can be executed.
	fn reserve_at_most(&self, to_reserve: usize) -> Option<PermitOperations> {
		if to_reserve == 0 {
			return None
		}

		let mut permit = Arc::clone(&self.semaphore).try_acquire_owned().ok()?;
		let mut num_ops = 1;

		while num_ops < to_reserve {
			let Ok(new_permit) = Arc::clone(&self.semaphore).try_acquire_owned() else { break };
			permit.merge(new_permit);
			num_ops += 1;
		}

		Some(PermitOperations { num_ops, _permit: permit })
	}
}

/// Permits a number of operations to be executed.
///
/// [`PermitOperations`] are returned by [`LimitOperations::reserve()`] and are used
/// to guarantee the RPC server can execute the number of operations.
///
/// The number of reserved items are given back to the [`LimitOperations`] on drop.
struct PermitOperations {
	/// The number of operations permitted (reserved).
	num_ops: usize,
	/// The permit for these operations.
	_permit: tokio::sync::OwnedSemaphorePermit,
}

impl PermitOperations {
	/// Returns the number of reserved elements for this permit.
	///
	/// This can be smaller than the number of items requested via [`LimitOperations::reserve()`].
	fn num_reserved(&self) -> usize {
		self.num_ops
	}
}


Review comment (refactor):
I think it would be safe to simplify this. As I understand, everything here is behind an RwLock anyway.
```suggestion
		let num_ops = std::cmp::min(self.semaphore.available_permits(), to_reserve);

		if num_ops == 0 {
			return None
		}

		let permits = Arc::clone(&self.semaphore)
			.try_acquire_many_owned(num_ops.try_into().ok()?)
			.ok()?;

		Some(PermitOperations { num_ops, _permit: permits })
```
Edit: Ah I missed the other discussion, but should still work.

Code after:
	fn new(max_operations: usize) -> Self {
		LimitOperations { semaphore: Arc::new(tokio::sync::Semaphore::new(max_operations)) }
	}

	/// Reserves capacity to execute at least one operation and at most the requested items.
	///
	/// Dropping [`PermitOperations`] without executing an operation will release
	/// the reserved capacity.
	///
	/// Returns nothing if there's no space available, else returns a permit
	/// that guarantees that at least one operation can be executed.
	fn reserve_at_most(&self, to_reserve: usize) -> Option<PermitOperations> {
		let num_ops = std::cmp::min(self.semaphore.available_permits(), to_reserve);

		if num_ops == 0 {
			return None
		}

		let permits = Arc::clone(&self.semaphore)
			.try_acquire_many_owned(num_ops.try_into().ok()?)
			.ok()?;

		Some(PermitOperations { num_ops, _permit: permits })
	}
}

/// Permits a number of operations to be executed.
///
/// [`PermitOperations`] are returned by [`LimitOperations::reserve()`] and are used
/// to guarantee the RPC server can execute the number of operations.
///
/// The number of reserved items are given back to the [`LimitOperations`] on drop.
struct PermitOperations {
	/// The number of operations permitted (reserved).
	num_ops: usize,
	/// The permit for these operations.
	_permit: tokio::sync::OwnedSemaphorePermit,
}

impl PermitOperations {
	/// Returns the number of reserved elements for this permit.
	///
	/// This can be smaller than the number of items requested via [`LimitOperations::reserve()`].
	fn num_reserved(&self) -> usize {
		self.num_ops
	}
}

struct BlockState {
	/// The state machine of this block.
	state_machine: BlockStateMachine,