Created
April 25, 2017 20:41
-
-
Save adrienthebo/26bd37d524fc410eb2dc3247cfee2ab5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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