Automatic or Static Storage?
August 27, 2008 Susan Gantner
If you write RPG subprocedures, you should know about the differences between automatic and static storage. (If you don’t write subprocedures, shame on you!) I’ve found that many writers and/or users of subprocedures don’t fully understand the differences. So let’s start at the beginning. By default, fields (i.e., stand-alone fields, data structures, arrays, etc.) defined inside a subprocedure (a.k.a. local fields) use automatic storage. This means that the storage doesn’t exist until the procedure is called and it is cleaned up when the procedure returns to its caller. Of course, since the storage goes away between calls to the procedure, that means the values are reinitialized between each call to the procedure (and the status of the LR indicator has no impact.) This differs from fields defined outside of subprocedures (i.e., in the main part of the program–or before the first P spec in the source member) that use static storage. Static storage exists from the time the program is called until the activation group where it is running ends, or until the job ends. Notice, though, that the values in static fields defined outside the P specs are re-initialized on return if the LR indicator was turned on; with LR off, the values remain the same between multiple calls to the program. You have no choice for the type of storage used for the global fields, but for the local fields in your procedures, you do have the option of making them static by coding the STATIC keyword. This makes them behave almost the same as the global fields. They will retain their values between multiple calls to the procedure. However, there is still a difference in behavior between local static fields in a procedure and global fields. The local static fields are not impacted by the status of the LR indicator, so they retain their values between calls to the program even if LR was set on before the return. To see if you’ve got the idea, study the following code and then try to answer the following questions. H DftActGrp(*NO) ActGrp('QILE') Option(*SrcStmt) D ProcAuto PR D I S 5U 0 D GlobalCount S 3 0 Inz /FREE For I = 1 to 3; // Call the subprocedure 3 times ProcAuto(); EndFor; *INLR = *On; /END-FREE P ProcAuto B D PI D AutoCount S 3 0 D StatCount S 3 0 Static /FREE StatCount += 1; AutoCount += 1; GlobalCount += 1; Dsply (' AutoCount=' + %Char(AutoCount) + ', StatCount=' + %Char(StatCount) + ', GlobalCount=' + %Char(GlobalCount)); /END-FREE P ProcAuto E
If you answered the following for question 1… AutoCount=1, StatCount=1, GlobalCount=1 AutoCount=1, StatCount=2, GlobalCount=2 AutoCount=1, StatCount=3, GlobalCount=3 …and the following for question 2… AutoCount=1, StatCount=4, GlobalCount=1 AutoCount=1, StatCount=5, GlobalCount=2 AutoCount=1, StatCount=6, GlobalCount=3 …and the following for question 3… AutoCount=1, StatCount=1, GlobalCount=1 AutoCount=1, StatCount=2, GlobalCount=2 AutoCount=1, StatCount=3, GlobalCount=3 Congratulations, you’ve got it! Of course, all this begs the question of how to initialize or re-initialize static values in a procedure when you need to? The simple answer is to do it manually in the logic, with something like a CLEAR or EVAL operation. But how do you signal the subprocedure when to re-initialize the static fields? Presumably since you made them static, they should not be initialized on every call. This requires a bit of thought and there are many potential solutions. Many people have a special parameter that is passed to tell the procedure to initialize. It might be a *NoPass parameter at the end of the list that is only used when initialization is required. Another popular option is to make all the parameters *NoPass and when the procedure is called with %Parms = 0, it is the signal to reinitialize. There are many other options that could be used. The ones you use will likely be different for internal subprocedures vs. procedures in a Service Program. But the important thing to remember is that you’ll need to accommodate this in your design if you need to use static fields in a subprocedure. Susan Gantner is one of the most respected System i gurus in the world and is one of the co-founders of System i Developer, an organization dedicated to RPG, DB2, and other relevant software technologies for the System i platform. Gantner, who has worked in IBM’s Rochester and Toronto labs, left IBM to focus on training OS/400 and i5/OS shops on the latest programming technologies. She is also a regular speaker at COMMON and other user groups. Send your questions or comments for Susan to Ted Holt via the IT Jungle Contact page.
|