Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

When and how to use static or dynamic calls!

Status
Not open for further replies.

wahlers

Programmer
May 13, 2004
142
NL
When and how to use static or dynamic calls!

Information related to the discussion following:

- The main program with a static call is called: STATICCALL.
- The main program with a dynamic call is called: DYNAMICCALL.
- The called (sub)program is called: RETURNLOWEST.
- RETURNLOWEST takes 2 numbers (number1 and number2) as input fields and returns the lowest of the 2 numbers into an output field (called theLowest).



=======================================

IDENTIFICATION DIVISION.
PROGRAM-ID. STATICCALL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 workData.
05 number1 PIC s9(09) VALUE +1234.
05 number2 PIC s9(09) VALUE -9876.
05 theLowest PIC s9(09).

PROCEDURE DIVISION.

*// RETURNLOWEST is between quotes.
*// This means that the (sub)program called is hardcoded(!)
*// in this source (it is a constant).
*// All hardcoded(!) calls are static calls.

CALL 'RETURNLOWEST' USING
, by content number1
, by content number2
, by reference theLowest
END-CALL

DISPLAY 'The lowest of the 2 numbers is: ' theLowest

GOBACK
.

END PROGRAM. STATICCALL.

=======================================

IDENTIFICATION DIVISION.
PROGRAM-ID. DYNAMICCALL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 workData.
05 someProgram PIC X(30) VALUE 'RETURNLOWEST'.
05 number1 PIC s9(09) VALUE +1234.
05 number2 PIC s9(09) VALUE -9876.
05 theLowest PIC s9(09).

PROCEDURE DIVISION.

*// someProgram is a variable field.
*// This means that this field value must be 'loaded' with the
*// program name before actually calling the (sub)program.
*//
*// This can be done by an initial VALUE (as is the case here)
*// or by a hardcoded MOVE statement, like:
*//
*// MOVE 'RETURNLOWEST' TO someProgram
*//
*// Notice that PIC x(30) is used for the field someProgram.
*// That is OK!
*// This field should be at least as big as the value it must
*// contain.

CALL someProgram USING
, by content number1
, by content number2
, by reference theLowest
END-CALL

DISPLAY 'The lowest of the 2 numbers is: ' theLowest

GOBACK
.

END PROGRAM. DYNAMICCALL.

=======================================

IDENTIFICATION DIVISION.
PROGRAM-ID. RETURNLOWEST.
DATA DIVISION.
LINKAGE SECTION.

01 number1 PIC s9(09).
01 number2 PIC s9(09).
01 theLowest PIC s9(09).

PROCEDURE DIVISION USING number1, number2, theLowest.

IF number1 < number2 THEN
, MOVE number1 TO theLowest
ELSE
, MOVE number2 TO theLowest
END-IF

GOBACK
.

END PROGRAM. RETURNLOWEST.

=======================================


Tip:
Always use dynamic calls!
(as far as I can judge there could possibly one minor exception to this rule, which is:
Use static call only for returning a single static error message in case of a complete systems failure...which...as a rule and in practice...should never occur!).


How does a static call work?

Answer:
At compile time every statically called subprogram will be copied and statically linked into programs calling these statically called programs.
This means when you have 100 programs calling 'RETURNLOWEST' statically that the executable code of 'RETURNLOWEST' is copied 100 times and added to each and every one of these 100 (main)programs (to be more precise, in the linkage step of the whole compile proces).

Consequences:
It increases the loadmodule size of each and every one of these 100 programs.
And when you change and recompile the subprogram 'RETURNLOWEST' then you need to again re-link all the 100 programs that include this static call.

Advantage of a static link:
You are 100% sure that this code can always be executed.
This is because a copy of the static program is actually a part of the main program. Hence, when the main program is loaded into main storage (RAM) then the copy is also loaded. 100% guarantee!
This, and only this, is the reason why a static link is good for a 'fatal-error-message' in case of a complete systems failure. However, there are no other advantages (note: some may say that a static link is quicker, more performant, but in (most) real programming environments this is a non-issue and mostly it is not even true!).

Disadvantages of static link:
First (and very important): very maintenance intensive.
Secondly: Main storage may be overloaded with many copies of the same static executable code. Again, (advise) never use static calls (with the possible exception previously mentioned).


How does a dynamic call work?

Answer:
(With reference to the static call explanation) a dynamic call is resolved at execution time.
With the first call the subprogram module is loaded into main storage (RAM) and then executed.
With every second and subsequent call it is just executed from main storage (because it already is and stays loaded into main storage).
For every dynamically called (sub)program there is always only one loadmule in main storage. Regardless how many different users are calling it in regardless how many different ways.

Advantage of dynamic calls:
Only one copy in main storage (as said before).
You can change and recompile dynamic loadmodules anytime.
There is no need to relink or recompile any module that calls this loadmodule.
You can make changes immediately effective without stopping the system by just reloading the changed module (changed subprogram). As of that moment all running main programs will immediately use this new, modified, copy (note: this feature is nice...but it is not wise to use it directly in a production environment without testing the new or changed functionality first on a test system).


What does the 'by content' or 'by reference' mean, or what does it do, as used in the CALL statement?

Answer:
'by content' means that when the call is executed a copy is taken of this variable.
That is; the system will dynamically allocate some storage and physically take a copy and then and only then passes this copy to the called (sub)program. The dynamically allocated storage is freed upon return of the called (sub)program. This means that the original value is not changed, regardless how the copy of the storage area was used by the called (sub)program.
Using 'by content' can, and does, make your program more robust. This is definitely a good thing...however...using the 'by content' option abundently may affect your storage consumption.
'By reference' means that the address of the field involved is passed to the called (sub)program. This means that the called (sub)program can directly change the contents of this memory address location (note: the addresses, as discussed here, are automatically resolved by COBOL. The COBOL language also include some instructions to directly manipulate address locations...but that is a different issue!).

Be aware of the following rules for the 'by content' and 'by reference' option:
1. The default is 'by reference'.
2. When either the 'by content' or 'by reference' option is used explicitly then that will become the default.
The latter can best be explained using an example:

call-1:
CALL 'RETURNLOWEST' USING
, by content number1
, by content number2
, by reference theLowest
END-CALL

call-2:
CALL 'RETURNLOWEST' USING
, by content number1
, number2
, by reference theLowest
END-CALL

call-3: --- NOTE: CALL-3 IS NOT CORRECT!!! --->
CALL 'RETURNLOWEST' USING
, by content number1
, number2
, theLowest
END-CALL

call-4:
CALL 'RETURNLOWEST' USING
, number1
, number2
, theLowest
END-CALL

call-1 and call-2 are exactly(!) the same.
number1 in call-1 has the 'by content' phrase.
number2 in call-1 does not have the 'by content' or 'by reference' phrase. It will use whatever was used before in the call statement. Therefore, in this case, it uses the 'by content'.

If no 'by xxxxxxx' phrase was specified at all then the standard default is used.
The standard default is: 'by reference' (see call-4).

call-3 will never produce anything useful! Why?
answer: The 'by content' is used for the first field.
As of that moment the 'by content' becomes the default for that specific call.
theLowest field is supposed to be a return field. However, in this case the 'by content' is still default.
The called (sub)program will function perfectly well. But it works with copies only, including a copy of the return field. Upon return the storage is freed for all copies of the 'by content' fields and the original 'by content' fields will be unchanged. As a result the original theLowest field is unchanged.

call-4 will work.
In call-4 all fields are 'by reference', which is the default.
Though there is a danger here! number1 and number2 are supposed to be input only fields. However, nothing will prevent the called (sub)program for executing the following move statement:
MOVE ZEROS TO number1, number2
So, your main program may not automatically assume that these input fields are unchanged upon return of the called (sub)program.


I hope the explanation above was informative (to some)


Regards, Wim Ahlers.
 
Wim,

Of course it is useful...how about a FAQ (or two)?

I say "(or two)" because it may be useful to separate the issues of (1) dynamic vs. static, and (2) by content vs. by reference.

WRT dynamic vs. static: you might mention the use of ON EXCEPTION to mitigate some of the negative issues regarding dynamic calls.

Tom Morrison
 
wim -

I might add that in the IBM mainframe and HP-3000 environments (and perhaps others), CALL "literal" can be a dynamic call if the compile options are set appropriately.

Regards.

Glenn
 
To: K5tm (concerns 'on exception')

I know the 'ON EXCEPTION' and related 'NOT ON EXCEPTION' phrase. I actually used them myself!
However, the 'on exception' does not work when the program is called from within a CICS environment. This is documented but I did not want to complicate the example any further (the example programs were kept very trivial).
To tell you the truth...I do not know the reason(!) why it does not work in a CICS environment (and maybe some other environments), I know it doesn't (tried it anyway!) and it is documented. Maybe somebody else can fill in the technical reason...

I considered not to use the 'by content'/'by reference' options...However, I eventually considered them useful and belonging to the workings of the call mechanism. I do not agree to separate them, I know you feel different about this issue.

To tell you the truth...I know and described that passing input fields 'by content' makes the code more robust but in pratice I do not always code it myself! Reason: I don't do this for certain types of input fields that are relatively large and at the same time frequently used (frequent as in online multi-thread environments!). However, in such cases it is a design decision and I do document it in the source code.

To: 3gm (concerns compiler option to force dynamic call)

Now you mention it...I think I have seen this, but I was not conciously aware of it. Thanks for the tip, it was definitely worth mentioning this fact!

Regards, Wim.
 
My documentation (HP Tandem NonStop Server) says "[NOT] ON EXCEPTION" is ignored when the called program is not COBOL.

I know CICS does strange things [bigsmile] - is it possible that a CALL in CICS gets translated to an OS CALL which in turn fetches the called module?

Just a thought.
 
Static makes for better distribution programs. You copy the program to any other system and that is all you need.

Dynamic Links, like DLLs on PCs means if you want to make a copy of an executable program to run on multiple systems you have to know all of the modules and copy them also.

On some PC compilers with Static link options you can write a program or tool like a piped-filter and distribute to all users more easily.
 
To: WMK

Thanks!
I have glanced at it, but now I am confused!
I haven't been intemately in touch with CICS for a while but the sentence you mentioned suggest to me that it does work now?
Anyway...I am not in the position to test this...I leave this to others.

To: ProfessorSparkie

PC programming is not my thing. And I immediately accept that you are right, that is (and I quote):
"...if you want to make a copy of an executable program to run on multiple systems you have to know all of the modules and copy them also...".
This is also true for mainframe environments.

However, I fail to see the problem!
Is it not true that (most) software systems consists of many modules.

In my experience "to know all of the modules" is a necessity for any software system.
1, 2, or 100 modules more (or less) does not really matter assuming(!) you have a well organised (automatic) system.

Again, my experience with PC-based systems is limited. So, I may miss the point you are trying to make.


Regards, Wim.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top