× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.




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-2024 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 [javascript protected email address].

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