1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //! Asynchronous counting semaphore. 15 16 use crate::sync::semaphore_inner::{SemaphoreError, SemaphoreInner}; 17 18 /// Asynchronous counting semaphore. It allows more than one caller to access 19 /// the shared resource. Semaphore contains a set of permits. Call `acquire` 20 /// method and get a permit to access the shared resource. When permits are used 21 /// up, new requests to acquire permit will wait until `release` method 22 /// is called. When no request is waiting, calling `release` method will add a 23 /// permit to semaphore. 24 /// 25 /// The difference between [`AutoRelSemaphore`] and [`Semaphore`] is that permit 26 /// acquired from [`Semaphore`] will be consumed. When permit from 27 /// [`AutoRelSemaphore`] is dropped, it will be assigned to another acquiring 28 /// request or returned to the semaphore. 29 /// 30 /// # Examples 31 /// 32 /// ``` 33 /// use std::sync::Arc; 34 /// 35 /// use ylong_runtime::sync::semaphore::Semaphore; 36 /// 37 /// async fn io_func() { 38 /// let sem = Arc::new(Semaphore::new(2).unwrap()); 39 /// let sem2 = sem.clone(); 40 /// let _permit1 = sem.try_acquire(); 41 /// ylong_runtime::spawn(async move { 42 /// let _permit2 = sem2.acquire().await.unwrap(); 43 /// }); 44 /// } 45 /// ``` 46 pub struct Semaphore { 47 inner: SemaphoreInner, 48 } 49 50 /// Asynchronous counting semaphore. It allows more than one caller to access 51 /// the shared resource. semaphore contains a set of permits. Call `acquire` 52 /// method and get a permit to access the shared resource. The total number of 53 /// permits is fixed. When no permits are available, new request to 54 /// acquire permit will wait until another permit is dropped. When no request is 55 /// waiting and one permit is **dropped**, the permit will be return to 56 /// semaphore so that the number of permits in semaphore will increase. 57 /// 58 /// The difference between [`AutoRelSemaphore`] and [`Semaphore`] is that permit 59 /// acquired from [`Semaphore`] will be consumed. When permit from 60 /// [`AutoRelSemaphore`] is dropped, it will be assigned to another acquiring 61 /// request or returned to the semaphore, in other words, permit will 62 /// be automatically released when it is dropped. 63 /// 64 /// # Examples 65 /// 66 /// ``` 67 /// use std::sync::Arc; 68 /// 69 /// use ylong_runtime::sync::semaphore::AutoRelSemaphore; 70 /// 71 /// async fn io_func() { 72 /// let sem = Arc::new(AutoRelSemaphore::new(2).unwrap()); 73 /// let sem2 = sem.clone(); 74 /// let _permit1 = sem.try_acquire(); 75 /// ylong_runtime::spawn(async move { 76 /// let _permit2 = sem2.acquire().await.unwrap(); 77 /// }); 78 /// } 79 /// ``` 80 pub struct AutoRelSemaphore { 81 inner: SemaphoreInner, 82 } 83 84 /// Permit acquired from `Semaphore`. 85 /// Consumed when dropped. 86 pub struct SemaphorePermit; 87 88 /// Permit acquired from `AutoRelSemaphore`. 89 /// Recycled when dropped. 90 pub struct AutoRelSemaphorePermit<'a> { 91 sem: &'a AutoRelSemaphore, 92 } 93 94 impl Semaphore { 95 /// Creates a `Semaphore` with an initial permit value. 96 /// 97 /// # Examples 98 /// 99 /// ``` 100 /// use ylong_runtime::sync::Semaphore; 101 /// 102 /// let sem = Semaphore::new(4).unwrap(); 103 /// ``` new(permits: usize) -> Result<Semaphore, SemaphoreError>104 pub fn new(permits: usize) -> Result<Semaphore, SemaphoreError> { 105 match SemaphoreInner::new(permits) { 106 Ok(inner) => Ok(Semaphore { inner }), 107 Err(e) => Err(e), 108 } 109 } 110 111 /// Gets the number of remaining permits. 112 /// 113 /// # Examples 114 /// 115 /// ``` 116 /// use ylong_runtime::sync::Semaphore; 117 /// let sem = Semaphore::new(4).unwrap(); 118 /// assert_eq!(sem.current_permits(), 4); 119 /// ``` current_permits(&self) -> usize120 pub fn current_permits(&self) -> usize { 121 self.inner.current_permits() 122 } 123 124 /// Adds a permit to the semaphore. 125 /// 126 /// # Examples 127 /// 128 /// ``` 129 /// use ylong_runtime::sync::Semaphore; 130 /// 131 /// let sem = Semaphore::new(4).unwrap(); 132 /// assert_eq!(sem.current_permits(), 4); 133 /// sem.release(); 134 /// assert_eq!(sem.current_permits(), 5); 135 /// ``` release(&self)136 pub fn release(&self) { 137 self.inner.release(); 138 } 139 140 /// Attempts to acquire a permit from semaphore. 141 /// 142 /// # Return value 143 /// The function returns: 144 /// * `Ok(SemaphorePermit)` if acquiring a permit successfully. 145 /// * `Err(PermitError::Empty)` if no permit remaining in semaphore. 146 /// * `Err(PermitError::Closed)` if semaphore is closed. 147 /// 148 /// # Examples 149 /// 150 /// ``` 151 /// use ylong_runtime::sync::Semaphore; 152 /// 153 /// let sem = Semaphore::new(4).unwrap(); 154 /// assert_eq!(sem.current_permits(), 4); 155 /// let permit = sem.try_acquire().unwrap(); 156 /// assert_eq!(sem.current_permits(), 3); 157 /// drop(permit); 158 /// assert_eq!(sem.current_permits(), 3); 159 /// ``` try_acquire(&self) -> Result<SemaphorePermit, SemaphoreError>160 pub fn try_acquire(&self) -> Result<SemaphorePermit, SemaphoreError> { 161 match self.inner.try_acquire() { 162 Ok(_) => Ok(SemaphorePermit), 163 Err(e) => Err(e), 164 } 165 } 166 167 /// Asynchronously acquires a permit from semaphore. 168 /// 169 /// # Return value 170 /// The function returns: 171 /// * `Ok(SemaphorePermit)` if acquiring a permit successfully. 172 /// * `Err(PermitError::Closed)` if semaphore is closed. 173 /// 174 /// # Examples 175 /// 176 /// ``` 177 /// use ylong_runtime::sync::Semaphore; 178 /// async fn io_func() { 179 /// let sem = Semaphore::new(2).unwrap(); 180 /// ylong_runtime::spawn(async move { 181 /// let _permit2 = sem.acquire().await.unwrap(); 182 /// }); 183 /// } 184 /// ``` acquire(&self) -> Result<SemaphorePermit, SemaphoreError>185 pub async fn acquire(&self) -> Result<SemaphorePermit, SemaphoreError> { 186 self.inner.acquire().await?; 187 Ok(SemaphorePermit) 188 } 189 190 /// Checks whether semaphore is closed. If so, the semaphore could not be 191 /// acquired anymore. 192 /// 193 /// # Examples 194 /// 195 /// ``` 196 /// use ylong_runtime::sync::semaphore::Semaphore; 197 /// 198 /// let sem = Semaphore::new(4).unwrap(); 199 /// assert!(!sem.is_closed()); 200 /// sem.close(); 201 /// assert!(sem.is_closed()); 202 /// ``` is_closed(&self) -> bool203 pub fn is_closed(&self) -> bool { 204 self.inner.is_closed() 205 } 206 207 /// Closes the semaphore so that it could not be acquired anymore, 208 /// and it notifies all requests in the waiting list. 209 /// 210 /// # Examples 211 /// 212 /// ``` 213 /// use ylong_runtime::sync::Semaphore; 214 /// 215 /// let sem = Semaphore::new(4).unwrap(); 216 /// assert!(!sem.is_closed()); 217 /// sem.close(); 218 /// assert!(sem.is_closed()); 219 /// ``` close(&self)220 pub fn close(&self) { 221 self.inner.close(); 222 } 223 } 224 225 impl AutoRelSemaphore { 226 /// Creates a semaphore with an initial capacity. 227 /// 228 /// # Examples 229 /// 230 /// ``` 231 /// use ylong_runtime::sync::AutoRelSemaphore; 232 /// 233 /// let sem = AutoRelSemaphore::new(4).unwrap(); 234 /// ``` new(number: usize) -> Result<AutoRelSemaphore, SemaphoreError>235 pub fn new(number: usize) -> Result<AutoRelSemaphore, SemaphoreError> { 236 match SemaphoreInner::new(number) { 237 Ok(inner) => Ok(AutoRelSemaphore { inner }), 238 Err(e) => Err(e), 239 } 240 } 241 242 /// Gets the number of remaining permits. 243 /// 244 /// # Examples 245 /// 246 /// ``` 247 /// use ylong_runtime::sync::AutoRelSemaphore; 248 /// let sem = AutoRelSemaphore::new(4).unwrap(); 249 /// assert_eq!(sem.current_permits(), 4); 250 /// ``` current_permits(&self) -> usize251 pub fn current_permits(&self) -> usize { 252 self.inner.current_permits() 253 } 254 255 /// Attempts to acquire an auto-release-permit from semaphore. 256 /// 257 /// # Return value 258 /// The function returns: 259 /// * `Ok(OneTimeSemaphorePermit)` if acquiring a permit successfully. 260 /// * `Err(PermitError::Empty)` if no permit remaining in semaphore. 261 /// * `Err(PermitError::Closed)` if semaphore is closed. 262 /// 263 /// # Examples 264 /// 265 /// ``` 266 /// use ylong_runtime::sync::AutoRelSemaphore; 267 /// 268 /// let sem = AutoRelSemaphore::new(4).unwrap(); 269 /// assert_eq!(sem.current_permits(), 4); 270 /// let permit = sem.try_acquire().unwrap(); 271 /// assert_eq!(sem.current_permits(), 3); 272 /// drop(permit); 273 /// assert_eq!(sem.current_permits(), 4); 274 /// ``` try_acquire(&self) -> Result<AutoRelSemaphorePermit<'_>, SemaphoreError>275 pub fn try_acquire(&self) -> Result<AutoRelSemaphorePermit<'_>, SemaphoreError> { 276 match self.inner.try_acquire() { 277 Ok(_) => Ok(AutoRelSemaphorePermit { sem: self }), 278 Err(e) => Err(e), 279 } 280 } 281 282 /// Asynchronously acquires an auto-release-permit from semaphore. 283 /// 284 /// # Return value 285 /// The function returns: 286 /// * `Ok(OneTimeSemaphorePermit)` if acquiring a permit successfully. 287 /// * `Err(PermitError::Closed)` if semaphore is closed. 288 /// 289 /// # Examples 290 /// 291 /// ``` 292 /// use ylong_runtime::sync::AutoRelSemaphore; 293 /// 294 /// async fn io_func() { 295 /// let sem = AutoRelSemaphore::new(2).unwrap(); 296 /// ylong_runtime::spawn(async move { 297 /// let _permit2 = sem.acquire().await.unwrap(); 298 /// }); 299 /// } 300 /// ``` acquire(&self) -> Result<AutoRelSemaphorePermit<'_>, SemaphoreError>301 pub async fn acquire(&self) -> Result<AutoRelSemaphorePermit<'_>, SemaphoreError> { 302 self.inner.acquire().await?; 303 Ok(AutoRelSemaphorePermit { sem: self }) 304 } 305 306 /// Checks whether the state of semaphore is closed, if so, the semaphore 307 /// could not acquire permits anymore. 308 /// 309 /// # Examples 310 /// 311 /// ``` 312 /// use ylong_runtime::sync::AutoRelSemaphore; 313 /// 314 /// let sem = AutoRelSemaphore::new(4).unwrap(); 315 /// assert!(!sem.is_closed()); 316 /// sem.close(); 317 /// assert!(sem.is_closed()); 318 /// ``` is_closed(&self) -> bool319 pub fn is_closed(&self) -> bool { 320 self.inner.is_closed() 321 } 322 323 /// Turns the state of semaphore to be closed so that semaphore could not 324 /// acquire permits anymore, and notify all request in the waiting list. 325 /// 326 /// # Examples 327 /// 328 /// ``` 329 /// use ylong_runtime::sync::AutoRelSemaphore; 330 /// 331 /// let sem = AutoRelSemaphore::new(4).unwrap(); 332 /// assert!(!sem.is_closed()); 333 /// sem.close(); 334 /// assert!(sem.is_closed()); 335 /// ``` close(&self)336 pub fn close(&self) { 337 self.inner.close(); 338 } 339 } 340 341 impl Drop for AutoRelSemaphorePermit<'_> { drop(&mut self)342 fn drop(&mut self) { 343 self.sem.inner.release(); 344 } 345 } 346