Skip to content

Commit f66cc2f

Browse files
committed
doc: update guide to use defer block for un-allows
1 parent 2c7f874 commit f66cc2f

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

doc/guide.md

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -422,9 +422,13 @@ returncode_t libtocksync_sensor_read(int* val) {
422422
### More Complicated Example:
423423
424424
Drivers that use allow buffers must un-allow the buffers after the operation
425-
finishes.
425+
finishes. To ease authoring of cleanup code, Tock provides a macro-based
426+
implementation of the `defer {}` feature that will be included with a future
427+
version of `C`.
426428
427429
```c
430+
#include <libtock/defer.h>
431+
428432
#include "digest.h"
429433
#include "syscalls/digest_syscalls.h"
430434
@@ -437,28 +441,27 @@ returncode_t libtocksync_digest_compute(uint8_t* input_buffer,
437441
// First allow for input. If it fails, return.
438442
ret = libtock_digest_set_readonly_allow(input_buffer, input_buffer_len);
439443
if (ret != RETURNCODE_SUCCESS) return ret;
440-
441-
// Second allow for output. If it fails, unallow first buffer then return.
444+
// Now that this buffer has been allowed, set up a `defer` block to
445+
// ensure that it will be unallowed before this function returns
446+
// (regardless of exit location out of the function).
447+
//
448+
// Note the return value of this "un-allow" operation is ignored in favor
449+
// of returning the disposition of the library funciton (i.e., `ret`).
450+
defer { libtock_digest_set_readonly_allow(NULL, 0); }
451+
452+
// Second allow for output.
442453
ret = libtock_digest_set_readwrite_allow(output_buffer, output_buffer_len);
443-
if (ret != RETURNCODE_SUCCESS) goto exit1;
454+
if (ret != RETURNCODE_SUCCESS) return ret;
455+
// Set up the output unallow.
456+
defer { libtock_digest_set_readwrite_allow(NULL, 0); }
444457
445458
// Attempt the command. If it fails, unallow both buffers.
446459
ret = libtock_digest_command_compute_digest();
447-
if (err != RETURNCODE_SUCCESS) goto exit2;
460+
if (err != RETURNCODE_SUCCESS) return ret;
448461
449462
// Wait for the digest to compute.
450463
ret = libtock_digest_yield_wait_for(val);
451464
452-
exit2:
453-
// Do the input unallow. We have to ignore the return value to 1) return the
454-
// correct error of the actual failing operation if something happened, and
455-
// 2) do the second unallow unconditionally.
456-
libtock_digest_set_readonly_allow(NULL, 0);
457-
458-
exit1:
459-
// Do the output unallow.
460-
libtock_digest_set_readonly_allow(NULL, 0);
461-
462465
return ret;
463466
}
464467
```

0 commit comments

Comments
 (0)