Hello. I want to code a function that adds entries to COBOL table and keep the entries of the table, and other working storage intact between calls.
Below is a generic sample, but not sure when needs to be done to it. I know that I could use BY REF in calls but this will be limited to passed parameters not internal items of the function.
Calling program
WORKING-STORAGESECTION.01 WS-FUNCTION-RESULTPIC X(80).MOVEFUNCTIONUSER-FUNC-LIST-MANAGER(WS-ITEM,"ADD")TOWS-RESULT...MOVEFUNCTIONUSER-FUNC-LIST-MANAGER(WS-ITEM,"COUNT")TOWS-RESULT*> HERE I WANT TO GET NUMBER OF TIMES THE FUNCTION WAS CALLED.END-PROGRAM.
looks fine - use LOCAL STORAGE for stuff that is "local" to the function run (should be often most variables) and WORKING STORAGE for everything that should be persistent.
If you want to be able to set/read values in the program without calling the function you could use EXTERNAL variables, but this may be seen as "dirty" (or not, depends on the use case), or even use nested functions with GLOBAL variables, possibly even more dirty.
One technique I've used in the past is a program that has to stay in memory (should not be CANCELed) and that can be called from different programs (or functions) and keeps the variables in WORKING STORAGE, this way you even can limit "only the caller's a/b/c can set variables, the others only request).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Is this in a batch environment where there is only one instance of the calling program ?
The reason for asking is that if not and it is in an OLTP environment, then you would need to have some mechanism to ENQUEUE around the manipulated array so as to not corrupt the array and it associated data. In a Z/OS CICS environment, I've used a CICS ENQUE to accomplish this. In CICS you can have ENQUEUE's at a CICS region level or a SYSPLEX level.
I'm not sure how you would serialize access in a LINUX / WINDOWS server environment, perhaps Simon could address that.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If all processes work on the same machine shared memory can be used (calling into "C").
For possibly easier understanding if performance is not an issue: use a file to write that data to, file locking also prevents race conditions and the file can also (with a bit more performance penalty) be on a network share so you can also work with multiple computers and the same "shared" data.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you. It is a batch program. The function and the program will be in the same file. CICS ENQUEUE is like magic! I guess the file idea is tempting but I don't have the courage :)
Last edit: Emmad 2021-08-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
We have (old now) examples of using Linux kernel queues, and ZeroMQ. There is more C support code in those samples than I would use now, knowing more about how easily GnuCOBOL can interface with C ABI libraries.
Getting new frameworks, like RabbitMQ or MQSeries would not be that hard to code up, either as CALLables or User Defined Functions from GnuCOBOL.
Going into left field, the FUNCTION REXX code supports the system stack idea from mainframes. It is supported in Regina Rexx as an external process, but then provides similar work flows to what mainframers have grown up with.
GnuCOBOL can do queues, if and when needs be. Kernel queues are POSIX and Linux, but many of the others are cross-platform. :-)
(Or, as Simon and László have pointed out, there are other ways at serializing access via shared memory).
Drifting a little: There is even a new kernel feature in Linux, that can set regions of memory as private to process only pages. Not even root can access these regions. Planned for use in keeping secrets that are to remain secret. And of course, awaiting bad guys to find the right crowbar, but from initial glance, it seems the kernel developers involved were very cognizant of those potentials, and are keeping things as secure as human brains can manage.
Cheers,
Blue
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You could also used name pipes in a Windows environment.
On Windows "between calls" the data content will remain intact, presuming this is a
single PID / TCB. Also assuming you have not issued a cancel.
Why is it a function ? I guess because it can be.
A subroutine would work just fine.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello. I want to code a function that adds entries to COBOL table and keep the entries of the table, and other working storage intact between calls.
Below is a generic sample, but not sure when needs to be done to it. I know that I could use BY REF in calls but this will be limited to passed parameters not internal items of the function.
Calling program
Function program:
Last edit: Simon Sobisch 2021-08-26
looks fine - use
LOCAL STORAGEfor stuff that is "local" to the function run (should be often most variables) andWORKING STORAGEfor everything that should be persistent.If you want to be able to set/read values in the program without calling the function you could use
EXTERNALvariables, but this may be seen as "dirty" (or not, depends on the use case), or even use nested functions withGLOBALvariables, possibly even more dirty.One technique I've used in the past is a program that has to stay in memory (should not be
CANCELed) and that can be called from different programs (or functions) and keeps the variables inWORKING STORAGE, this way you even can limit "only the caller's a/b/c can set variables, the others only request).Thank you. Never heard of "Local Storage" before! :)
Is this in a batch environment where there is only one instance of the calling program ?
The reason for asking is that if not and it is in an OLTP environment, then you would need to have some mechanism to ENQUEUE around the manipulated array so as to not corrupt the array and it associated data. In a Z/OS CICS environment, I've used a CICS ENQUE to accomplish this. In CICS you can have ENQUEUE's at a CICS region level or a SYSPLEX level.
I'm not sure how you would serialize access in a LINUX / WINDOWS server environment, perhaps Simon could address that.
If all processes work on the same machine shared memory can be used (calling into "C").
For possibly easier understanding if performance is not an issue: use a file to write that data to, file locking also prevents race conditions and the file can also (with a bit more performance penalty) be on a network share so you can also work with multiple computers and the same "shared" data.
Thank you. It is a batch program. The function and the program will be in the same file. CICS ENQUEUE is like magic! I guess the file idea is tempting but I don't have the courage :)
Last edit: Emmad 2021-08-27
We have (old now) examples of using Linux kernel queues, and ZeroMQ. There is more C support code in those samples than I would use now, knowing more about how easily GnuCOBOL can interface with C ABI libraries.
Getting new frameworks, like RabbitMQ or MQSeries would not be that hard to code up, either as CALLables or User Defined Functions from GnuCOBOL.
Going into left field, the FUNCTION REXX code supports the system stack idea from mainframes. It is supported in Regina Rexx as an external process, but then provides similar work flows to what mainframers have grown up with.
GnuCOBOL can do queues, if and when needs be. Kernel queues are POSIX and Linux, but many of the others are cross-platform. :-)
(Or, as Simon and László have pointed out, there are other ways at serializing access via shared memory).
Drifting a little: There is even a new kernel feature in Linux, that can set regions of memory as private to process only pages. Not even root can access these regions. Planned for use in keeping secrets that are to remain secret. And of course, awaiting bad guys to find the right crowbar, but from initial glance, it seems the kernel developers involved were very cognizant of those potentials, and are keeping things as secure as human brains can manage.
Cheers,
Blue
You could also used name pipes in a Windows environment.
On Windows "between calls" the data content will remain intact, presuming this is a
single PID / TCB. Also assuming you have not issued a cancel.
Why is it a function ? I guess because it can be.
A subroutine would work just fine.
Thank you. Pipes is certainly above my tech. level :) - You are correct in this case it does not have to be a function.
For shared memory and parallel processing there is an example here:
https://sourceforge.net/p/gnucobol/contrib/HEAD/tree/trunk/samples/shared_mem
László