Skip to content

Instantly share code, notes, and snippets.

@niuk
Created July 20, 2011 20:02
Show Gist options
  • Save niuk/1095789 to your computer and use it in GitHub Desktop.
Save niuk/1095789 to your computer and use it in GitHub Desktop.
Resource Handling, PART II
/* The Hammer code for read_buf_from_file would look like this: */
void *read_buf_from_file(char *path) {
int ret = -1;
void *buf = malloc(512) <-
lambda(buf) {
if (ret < 0) free(buf);
};
int fd = open(path, O_RDONLY) <-
lambda(fd) {
if (close(fd) < 0) throw new FileCloseException();
};
ret = read(fd, buf, 512);
return buf;
}
/* The backwards arrow (<-) notation is used to "hook up" a "destructor" to
* the result of an expression, which gets executed at stack unwinding.
* Furthermore, the destructors are run in the reverse order of the execution
* of their associated expressions, even if the programmer himself has no
* information about the evaluation order. Also, since the destructor is
* attached to the results of expressions rather than variables, one could
* write the function in a more direct way, without allocating variables: */
void closeWrapper(int fd) {
if (close(fd) < 0) throw new FileCloseException();
}
void *read_buf_from_file(char *path) {
bool success = false;
void freeWrapper(void *buf) {
if (success) free(buf);
}
void *buf = malloc(512) <- freeWrapper;
read(open(path, O_RDONLY) <- closeWrapper, buf, 512);
success = true;
return buf;
}
/* Note that we have eliminated the file descriptor variable. Also, there is no
* fear in throwing a new exception in a destructor because, in Hammer,
* exceptions are aggregated and it is guaranteed that EVERY exception will
* either be caught or propagated to the toplevel (where it is usually printed
* verbatim to stderr) immediately after throwing. The main problem, now, is
* verbosity. Neither freeWrapper nor closeWrapper can be put into a library
* because it is conceivable that a function might want to preserve the opened
* file or the allocated buffer in the case of success. We want a generic way
* to let destructors know in what circumstances they were called. */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment