Great discussion.  We are having similar problems when a user switches from
1 current library to another and the service programs continue to use the
files from the previous library
That's one of many reasons why the "always keep files open" approach 
doesn't always work.  Another one is that when you're writing modular 
software, the caller shouldn't need to know how you're storing your data.
It shouldn't have to tell you to open or close your files because it 
shouldn't necesarily know that you're using files!  Maybe you're using 
text files in the IFS.  Maybe instead of database files, you're using an 
XML document.  Or connecting to a web service somewhere on the internet. 
Or maybe you've decided to use a user space or user index or something 
else besides a file.
The point is... the caller shouldn't know or care.  As soon as the caller 
has to understand the mechasism that you're using to save data, you lose 
one of the major advantages of making it modular...  If you ever want to 
change a program to use something besides database files, you shouldn't 
have to tell every caller to change to call an "connect to webservice" 
routine instead of an "open database file" routine.  The caller shouldn't 
know or care.
Activation groups make a great way to solve this problem.  They provide an 
environment in which you can load lots of programs and service programs 
that together make up an application.  And give you the ability to close 
them all at once.
This is precisely what they're for.

Granted, there's some time involved in creating and destroying an activation group. My benchmarks showed this to be about 1/100 of a second. That's a long time for a computer operation! But, that time is only a big deal if you do it in a loop.
You don't want to incur a 1/100 second penalty for each record in a 1 
million record file, for example.  That would be an insane amount of extra 
delay.
On the other hand, creating and destroying an activation group ONCE when a 
user selects an option off of a menu is nothing.  Who cares if that user 
has to wait an additional 1/100 of a second. He wastes more time breathing 
and blinking his eyes.

Would it work to create only a "Close" procedure that closes all files used
in the service program and call it whenever you exit the calling program
(via LR or return).

you could then put a %open test a the top of each procedure to open any
files used by the procedure.
The way I do it is to have an "OpenFiles" subprocedure that opens all of 
the files needed by the program.  This routine first opens all of the 
files. Then it registers a CleanUp subprocedure with CEE4RAGE.  Then it 
sets an indicator that says "I'm done opening files".  If the subprocedure 
gets called again, it checks that indicator to see if it's already opened 
the files -- if it has, it simply returns harmlessly.
Every exported subprocedure in my service program calls the OpenFiles 
routine as it's first line of code.
When the activation group ends, CEE4RAGE automatically calls my cleanup 
procedure which closes the files.
Granted, it's not (strictly speaking) neessary for the CleanUp procedure 
to close the files, since reclaiming the activation group will do that 
automatically, but I like having it in my code where I can see that it's 
being done.  It's also useful for cleaning up some things that aren't 
necessarily restricted to the activation group, such as deleting temporary 
files or user spaces from QTEMP.
I usually make the openFiles() and CleanUp() subprocedures EXPORTed so 
that a caller can run them manually if it absolutely needs to -- that way 
the files CAN be opened and closed without reclaiming the activation group 
if it's needed.  However, I only call them manually for testing purposes 
or in situations where performance is absolutely critical.  Otherwise, I 
prefer to let the service program open and close it's own files, that way 
the caller doesn't have to know anything about how the mechanism works.
I usually use ACTGRP(*NEW) as the first program off of a menu, and 
ACTGRP(*CALLER) for anything in calls.  That way, everything is 
automatically cleaned up for me when the program returns to the menu.
There are exceptions.... I don't do EVERYTHING the same way.  The 
important thing is to understand what activation groups do, and use them 
to maximum benefit.
Didn't we just have this conversation recently?

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2025 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact copyright@midrange.com.

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.