On Wednesday, 10 May 2017 at 05:26:11 UTC, H. S. Teoh wrote:
int myfunc(blah_t *blah, bleh_t *bleh, bluh_t *bluh) {
void *resource1, *resource2, *resource3;
int ret = RET_ERROR;
/* Vet arguments */
if (!blah || !bleh || !bluh)
return ret;
/* Acquire resources */
resource1 = acquire_resource(blah->blah);
if (!resource1) goto EXIT;
resource2 = acquire_resource(bleh->bleh);
if (!resource1) goto EXIT;
resource3 = acquire_resource(bluh->bluh);
if (!resource1) goto EXIT;
/* Do actual work */
if (do_step1(blah, resource1) == RET_ERROR)
goto EXIT;
if (do_step2(blah, resource1) == RET_ERROR)
goto EXIT;
if (do_step3(blah, resource1) == RET_ERROR)
goto EXIT;
ret = RET_OK;
EXIT:
/* Cleanup everything */
if (resource3) release(resource3);
if (resource2) release(resource2);
if (resource1) release(resource1);
return ret;
}
In modern C and with GLib (which makes use of a gcc/clang
extension) you can write this as:
gboolean myfunc(blah_t *blah, bleh_t *bleh, bluh_t *bluh) {
/* Cleanup everything automatically at the end */
g_autoptr(GResource) resource1 = NULL, resource2 = NULL,
resource3 = NULL;
gboolean ok;
/* Vet arguments */
g_return_if_fail(blah != NULL, FALSE);
g_return_if_fail(bleh != NULL, FALSE);
g_return_if_fail(bluh != NULL, FALSE);
/* Acquire resources */
ok = acquire_resource(resource1, blah->blah);
g_return_if_fail(ok, FALSE);
ok = acquire_resource(resource2, bleh->bleh);
g_return_if_fail(ok, FALSE);
ok = acquire_resource(resource3, bluh->bluh);
g_return_if_fail(ok, FALSE);
/* Do actual work */
ok = do_step1(blah, resource1);
g_return_if_fail(ok, FALSE);
ok = do_step2(blah, resource1);
g_return_if_fail(ok, FALSE);
return do_step3(blah, resource1);
}
Some random example of this style of coding:
https://github.com/flatpak/flatpak/blob/master/common/flatpak-db.c