• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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