🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.misc
Article #4395

Re: GOTO controversy

#4395
From: John Noland
Date: Tue, 12 Mar 1996 00:32
159 lines
5655 bytes
In article <DnwCxp.84C@clw.cs.man.ac.uk>, chl@clw.cs.man.ac.uk says...
>
>In <4hl8mt$4po@newshost.cyberramp.net> sinan@cyberramp.net (John Noland) writes:
>
>>>Robert C Shields (rcshlds@mailserv.mta.ca) wrote:
>
>>The above is NOT an example of a good use for the goto statement. 
>
>Well that is what I thougut when I first saw the example, and I was about to
>dash off an article like you have done. But then I looked again and saw
>*exactly* what it was doing.
>
>So if you believe there is a better way, please can we see it?
>
I saw *exactly* what it was doing. 

I only have one problem with this example. It looks to me like he's trying to avoid
duplicate code by using goto's. Yet, it seems to me that in the spot where he says:

/* Do some stuff here */
return TRUE;  /* We did okay */

really looks like this:

/* Do some stuff here */
NOTE>/* including this? */
NOTE>   free(ptr);
NOTE>   DosCloseMutexSem(hmtx);
NOTE>   DosCloseEventSem(hev3);
NOTE>   DosCloseEventSem(hev2);
NOTE>   DosCloseEventSem(hev1);
return TRUE; /* We did okay */

so the obvious change I would make is this:

HEV    hev1, hev2, hev3;     /* Event semaphores */
HMTX   hmtx;                 /* Mutex semaphore  */ 
void  *ptr;              
int    retval;   /* I'm assuming he's returning an int */

/* There should be explicit initialization of all locals here */

retval = TRUE;

if (!DosCreateEventSem(0, &hev1, 0, FALSE))
    retval = FALSE;
    goto hev1_failed

if (!DosCreateEventSem(0, &hev2, 0, FALSE))
    retval = FALSE;
    goto hev2_failed;

if (!DosCreateEventSem(0, &hev3, 0, FALSE))
    retval = FALSE;
    goto hev3_failed;

if (!DosCreateMutexSem(0, &hmtx, 0, FALSE))
    retval = FALSE;
    goto hmtx_failed;

if ((ptr = malloc(SOME_SIZE)) == NULL)
    retval = FALSE;
    goto malloc_failed;

/* Do some stuff here */
free(ptr);

malloc_failed:
   DosCloseMutexSem(hmtx);
hmtx_failed:
   DosCloseEventSem(hev3);
hev3_failed:
   DosCloseEventSem(hev2);
hev2_failed:
   DosCloseEventSem(hev1);
hev1_failed:
   return retval;


To code a proper alternative to the goto's, I would really require some more 
information. I'm not familiar w/ this particular semaphore implementation, 
so I have to make some assumptions. I assume HEV and HMTX are structures 
that contain something similar to the UNIX implementation, semaphore value 
(semval), the process id of the last process to use the semphore(sempid), 
etc... In the implementations I've seen (and I'm not terribly knowledgeable 
about IPC mechanisms in general), there is a function called semget(). I don't 
know much about this, but I do know it returns a semaphore ID. I can't tell 
if that's what DosCreateXXXXSem() is doing or not. The original author treats 
it as a boolean. Something like the following would work to eliminate the goto's, 
but, it would be difficult to prove this method's superiority in this instance.

typedef struct {
    int hev_return;
    HEV hev_struct;
} HEV_SEM;

typedef struct {
    int hmtx_return; 
    HMTX hmtx_struct;
} HMTX_SEM;

int alloc_fn_resources(HEV_SEM *hev1, HEV_SEM *hev2, HEV_SEM *hev3, HMTX_SEM *hmtx, void *ptr);
void free_fn_resources(HEV_SEM *hev1, HEV_SEM *hev2, HEV_SEM *hev3, HMTX_SEM *hmtx, void *ptr);

int some_function(void) {

int    retval;
HEV_SEM    hev1, hev2, hev3;     /* Event semaphores */
HMTX_SEM   hmtx;                 /* Mutex semaphore  */ 
void  *ptr;              
    
    retval = TRUE;
    memset((HEV_SEM *)&hev1, 0, sizeof (HEV_SEM));
    memset((HEV_SEM *)&hev2, 0, sizeof (HEV_SEM));
    memset((HEV_SEM *)&hev3, 0, sizeof (HEV_SEM));
    memset((HMTX_SEM *)&hmtx, 0, sizeof (HMTX_SEM));
    
    if (!alloc_fn_resources(&hev1, &hev2, &hev3, &hmtx, ptr)) {
	free_fn_resources(&hev1, &hev2, &hev3, &hmtx, ptr);
        return FALSE;
    }
    /* Do some stuff here */
    free_fn_resources(&hev1, &hev2, &hev3, &hmtx, ptr);
    return TRUE;
}

int alloc_fn_resources(HEV_SEM *hev1, HEV_SEM *hev2, HEV_SEM *hev3, HMTX_SEM *hmtx, void *ptr) {

    if ((hev1->hev_return = DosCreateEventSem(0, &hev1->hev_struct, 0, FALSE)) == 0)
        return FALSE;
    if ((hev2->hev_return = DosCreateEventSem(0, &hev2->hev_struct, 0, FALSE)) == 0)
	return FALSE;
    if ((hev3->hev_return = DosCreateEventSem(0, &hev3->hev_struct, 0, FALSE)) == 0)
        return FALSE;
    if ((hmtx->hmtx_return = DosCreateMutexSem(0, &hmtx->hev_struct, 0, FALSE)) == 0)
        return FALSE;
    if ((ptr = malloc(SOME_SIZE)) == NULL)
	return FALSE;
    return TRUE;
}

void free_fn_resources(HEV_SEM *hev1, HEV_SEM *hev2, HEV_SEM *hev3, HMTX_SEM *hmtx, void *ptr);

if (ptr != NULL)
    free(ptr);
if (hmtx->hmtx_return != 0)
    DosCloseMutexSem(hmtx->hmtx_struct);
if (hev1->hev_return != 0)
    DosCloseEventSem(hev3->hev_struct);
if (hev2->hev_return != 0)
    DosCloseEventSem(hev2->hev_struct);
if (hev3->hev_return != 0)
    DosCloseEventSem(hev1->hev_struct);

}

If I made any mistakes here, I apologize. This code is off the top of my head. 

-John 
Technical Details
Message-ID: <4i2gmv$ect@newshost.cyberramp.net>
Path: arc1-ca.pugleaf.net!newshost.cyberramp.net!news
References: <rcshlds.1.000A6705@mailserv.mta.ca> <Dn8pJ8.nqs@emi.net> <4grt4e$8fg@goanna.cs.rmit.EDU.AU> <4hl8mt$4po@newshost.cyberramp.net> <DnwCxp.84C@clw.cs.man.ac.uk>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!newshost.cyberramp.net!news
From: sinan@cyberramp.net (John Noland)
Newsgroups: comp.lang.misc,comp.lang.c,comp.lang.pl1
Subject: Re: GOTO controversy
Date: 12 Mar 1996 00:32:31 GMT
Organization: Prose Software
Message-ID: <4i2gmv$ect@newshost.cyberramp.net>
References: <rcshlds.1.000A6705@mailserv.mta.ca> <Dn8pJ8.nqs@emi.net> <4grt4e$8fg@goanna.cs.rmit.EDU.AU> <4hl8mt$4po@newshost.cyberramp.net> <DnwCxp.84C@clw.cs.man.ac.uk>
NNTP-Posting-Host: ramp1-12.cyberramp.net
X-Newsreader: WinVN 0.99.5