Best way to set up "once only" code ?

Best way to set up "once only" code ?

I have a subroutine where I only want to execute a block of statements the FIRST time it's called.

I tried to do it this way:

INTEGER  Once

DATA once/0/

IF(ONCE == 0)THEN

!  EXECUTES A BLOCK OF STATEMENTS

 

...

...

...

ONCE =1

ENDIF

For some reason, the compiler set it to Zero every time it was called.

How do I tell the compiler that an item is NOT supposed to be reinitialized every time?

I am not sure that the standard really addresses this issue.

13 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Give your flag the SAVE attribute.
 

The DATA statement implies SAVE. I would want to see an actual example that demonstrates the problem. My guess is that Bill is inadvertently leaving something out of his paraphrase.

Retired 12/31/2016

The following works.  Plus, it avoids DATA, which I must admit I've never used or understood.


	    logical,save :: initialized = .false.

	    

	    if (.not. initialized) then

	    

	        !EXECUTES A BLOCK OF STATEMENTS

	        !...

	        

	        initialized = .true.

	        

	    end if

	 

Jacob, your code is essentially the same as if DATA was used. Semantically, they are identical.

Retired 12/31/2016

I'm with Jacob, I use his exact approach often, never a problem (and I too do not use DATA initialization).

From the IVF documentation : "...a named variable has the SAVE attribute if any part of it is initialized in a DATA statement. You can confirm this property by specifying the variable in a SAVE statement or a type declaration statement containing the SAVE attribute"

Perhaps it is actually necessary (and not redundant) to explicitly "confirm" the SAVE attribute.

 

It is redundant to specify SAVE for variables given initial values either through DATA or an initializer. This wasn't the case in F90, but as of F95 it is.

Retired 12/31/2016

If you have a small routine that is heavily executed, then might be (performance wise) a good opportunity to consider GOTO to goto (out of line) to the bottom of the program, perform the initialization, then goto back to following the IF statement. If the initialization code is close enough, then this may eliminate a branch in your code, and shave a few clock ticks off each call. You would have to inspect the code generated, because program optimization undo what you were trying to do.

Jim Dempsey

 

I like to include the "save" even though it is redundant.  Partially as a reminder to myself.  Also: I tend to avoid using saved variables, so if I'm using one somewhere, I want to make it easy to locate if I need it find it again one day.  It doesn't hurt, right?

I take it that the DATA statement is considered to be obsolete ?

Or just old-fashioned ?

Both :)

(but not formally)

Old-fashioned, maybe. There are things you can do in DATA that are not easily done with initializers, regarding arrays. Use whichever one you prefer. Personally I like keeping things together, so I use initializers where I can. Spreading a variable's information over multiple statements can lead to errors.

Retired 12/31/2016

Bill,

I use the approach you are adopting in many applications and it works for me.

I'd suggest that you include a write (*,*) 'once =',once at the start and end of the routine and see what is happening. Make sure you put it at the end ! You might be using once elsewhere.
Is once= 1 being executed or is there a return somewhere in that code ?

John

Leave a Comment

Please sign in to add a comment. Not a member? Join today