Skip to content

Instantly share code, notes, and snippets.

@adrienthebo
Created April 25, 2017 20:41
Show Gist options
  • Save adrienthebo/26bd37d524fc410eb2dc3247cfee2ab5 to your computer and use it in GitHub Desktop.
Save adrienthebo/26bd37d524fc410eb2dc3247cfee2ab5 to your computer and use it in GitHub Desktop.
void Reader::teardown() {
if (_read_ptr) {
/* This provides some basic RAII functionality for the pants on head logic that is libpng.
* libpng provides a single function for releasing structs allocated for reading a
* png and uses multiple arguments for destroying these structs.
*
* Here's the story on what's actually happening here.
*
* 1. If `_read_ptr` is null then nothing has been initialized at all so we have
* nothing to tear down. Life is simple.
* 2. If `_read_ptr` has been set, then we might have multiple values to tear down.
* 3. The examples invoking this function show that if there is no info ptr to tear
* down then the nullptr should be provided, and if a nullptr is provided then the
* info object will be ignored.
* 4. If there is an info ptr (`_info_ptr`) then we can pass it, and both structs
* will be torn down.
*
* The fact that there's a single teardown function that requires nullptrs to be passed
* for unset objects is really odd, and a lot of the example code that I've seen does
* some really awkward dances around this. My best guess is that there's a lot of
* special handling for cases where `_info_ptr` was defined but left uninitialized,
* so always destroying the various png structs in tandem could be unsafe.
*
* HOWEVER, we can make this dramatically simpler by taking the revolutionary state of
* initializing our pointers to null by default. This brilliant idea means that the
* `_info_ptr` struct is nulled, and thus safe to destroy, or properly initialized,
* and thus safe to destroy.
*
* So long story short, given sane initialization and default values of our struct
* members teardown is pretty simple. However because we're relying on some implicit
* behavior with struct initialization and defaults, it's worth explaining carefully.
*
* Given that this comment is several times the size of the actual struct teardown code
* I could have just written some gross conditionals and continued the cargo culting,
* but given the opportunity to do something just a touch cleaner, I'm going to take
* it.
*
* In addition it's possible that `png_destroy_read_struct()` can safely handle the
* case where `_read_ptr` is also null and safely do nothing. However there are better
* things that one can do with their life, such as drinking away the pain that stems
* from wading into libraries and constructs like this.
*/
png_destroy_read_struct(&_read_ptr, &_info_ptr, (png_infopp) nullptr);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment