@@ -47,7 +47,7 @@ use std::sync::Arc;
47
47
/// }
48
48
/// ```
49
49
///
50
- /// ## Limit the number of simultaneously opened files in your program.
50
+ /// ## Limit the number of simultaneously opened files in your program
51
51
///
52
52
/// Most operating systems have limits on the number of open file
53
53
/// handles. Even in systems without explicit limits, resource constraints
@@ -76,7 +76,7 @@ use std::sync::Arc;
76
76
/// }
77
77
/// ```
78
78
///
79
- /// ## Limit the number of incoming requests being handled at the same time.
79
+ /// ## Limit the number of incoming requests being handled at the same time
80
80
///
81
81
/// Similar to limiting the number of simultaneously opened files, network handles
82
82
/// are a limited resource. Allowing an unbounded amount of requests to be processed
@@ -125,19 +125,23 @@ use std::sync::Arc;
125
125
///
126
126
/// ## Prevent tests from running in parallel
127
127
///
128
- /// By default, Rust runs tests in the same file in parallel. However, in some cases, running two tests in parallel may lead to problems.
129
- /// For example, this can happen when tests use the same database.
128
+ /// By default, Rust runs tests in the same file in parallel. However, in some
129
+ /// cases, running two tests in parallel may lead to problems. For example, this
130
+ /// can happen when tests use the same database.
130
131
///
131
132
/// Consider the following scenario:
132
- /// 1. `test_insert`: Inserts a key-value pair into the database, then retrieves the value using the same key to verify the insertion.
133
- /// 2. `test_update`: Inserts a key, then updates the key to a new value and verifies that the value has been accurately updated.
134
- /// 3. `test_others`: A third test that doesn't modify the database state. It can run in parallel with the other tests.
133
+ /// 1. `test_insert`: Inserts a key-value pair into the database, then retrieves
134
+ /// the value using the same key to verify the insertion.
135
+ /// 2. `test_update`: Inserts a key, then updates the key to a new value and
136
+ /// verifies that the value has been accurately updated.
137
+ /// 3. `test_others`: A third test that doesn't modify the database state. It
138
+ /// can run in parallel with the other tests.
135
139
///
136
- /// In this example, `test_insert` and `test_update` need to run in sequence to work, but it doesn't matter which test runs first.
137
- /// We can leverage a semaphore with a single permit to address this challenge.
140
+ /// In this example, `test_insert` and `test_update` need to run in sequence to
141
+ /// work, but it doesn't matter which test runs first. We can leverage a
142
+ /// semaphore with a single permit to address this challenge.
138
143
///
139
144
/// ```
140
- /// use tokio::sync::Semaphore;
141
145
/// # use tokio::sync::Mutex;
142
146
/// # use std::collections::BTreeMap;
143
147
/// # struct Database {
@@ -164,6 +168,7 @@ use std::sync::Arc;
164
168
/// # *self.map.lock().await.get(key).unwrap()
165
169
/// # }
166
170
/// # }
171
+ /// use tokio::sync::Semaphore;
167
172
///
168
173
/// // Initialize a static semaphore with only one permit, which is used to
169
174
/// // prevent test_insert and test_update from running in parallel.
@@ -173,7 +178,7 @@ use std::sync::Arc;
173
178
/// static DB: Database = Database::setup();
174
179
///
175
180
/// #[tokio::test]
176
- /// # async fn fake_test () {}
181
+ /// # async fn fake_test_insert () {}
177
182
/// async fn test_insert() {
178
183
/// // Acquire permit before proceeding. Since the semaphore has only one permit,
179
184
/// // the test will wait if the permit is already acquired by other tests.
@@ -196,7 +201,7 @@ use std::sync::Arc;
196
201
/// }
197
202
///
198
203
/// #[tokio::test]
199
- /// # async fn fake_test () {}
204
+ /// # async fn fake_test_update () {}
200
205
/// async fn test_update() {
201
206
/// // Acquire permit before proceeding. Since the semaphore has only one permit,
202
207
/// // the test will wait if the permit is already acquired by other tests.
@@ -221,12 +226,12 @@ use std::sync::Arc;
221
226
/// }
222
227
///
223
228
/// #[tokio::test]
224
- /// # async fn fake_test () {}
229
+ /// # async fn fake_test_others () {}
225
230
/// async fn test_others() {
226
231
/// // This test can run in parallel with test_insert and test_update,
227
232
/// // so it does not use PERMIT.
228
233
/// }
229
- /// # #[tokio::main]
234
+ /// # #[tokio::main(flavor = "current_thread") ]
230
235
/// # async fn main() {
231
236
/// # test_insert().await;
232
237
/// # test_update().await;
@@ -236,6 +241,8 @@ use std::sync::Arc;
236
241
///
237
242
/// ## Rate limiting using a token bucket
238
243
///
244
+ /// This example showcases the [`add_permits`] and [`SemaphorePermit::forget`] methods.
245
+ ///
239
246
/// Many applications and systems have constraints on the rate at which certain
240
247
/// operations should occur. Exceeding this rate can result in suboptimal
241
248
/// performance or even errors.
@@ -256,6 +263,8 @@ use std::sync::Arc;
256
263
/// lot of cpu constantly looping and sleeping.
257
264
///
258
265
/// [token bucket]: https://en.wikipedia.org/wiki/Token_bucket
266
+ /// [`add_permits`]: crate::sync::Semaphore::add_permits
267
+ /// [`SemaphorePermit::forget`]: crate::sync::SemaphorePermit::forget
259
268
/// ```
260
269
/// use std::sync::Arc;
261
270
/// use tokio::sync::Semaphore;
@@ -292,8 +301,11 @@ use std::sync::Arc;
292
301
///
293
302
/// async fn acquire(&self) {
294
303
/// // This can return an error if the semaphore is closed, but we
295
- /// // never close it, so just ignore errors.
296
- /// let _ = self.sem.acquire().await;
304
+ /// // never close it, so this error can never happen.
305
+ /// let permit = self.sem.acquire().await.unwrap();
306
+ /// // To avoid releasing the permit back to the semaphore, we use
307
+ /// // the `SemaphorePermit::forget` method.
308
+ /// permit.forget();
297
309
/// }
298
310
/// }
299
311
///
0 commit comments