@@ -422,9 +422,13 @@ returncode_t libtocksync_sensor_read(int* val) {
422422### More Complicated Example:
423423
424424Drivers 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 function (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