Menu

Could a function keep state?

Anonymous
2021-08-26
2021-08-28
  • Anonymous

    Anonymous - 2021-08-26

    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-STORAGE SECTION.
    01 WS-FUNCTION-RESULT PIC X(80).
                    MOVE FUNCTION USER-FUNC-LIST-MANAGER(WS-ITEM, "ADD") TO WS-RESULT
                    ...
                      MOVE FUNCTION USER-FUNC-LIST-MANAGER(WS-ITEM, "COUNT") TO WS-RESULT
                      *> HERE I WANT TO GET NUMBER OF TIMES THE FUNCTION WAS CALLED.
    
    END-PROGRAM.
    

    Function program:

    WORKING-STORAGE SECTION
    01 CALLED-TIMES PIC S99 VALUE ZERO
    LINKAGE-SECTION
    01 LS ITEM PIC X(80).
    01 LS-OPERATION PIC X(10).
    01 LS-RESULT PIC X(80).
    PROCDURE DIVISION USING  LS-ITEM, LS-OPERATION RETURNING LS-RESULT
    ADD 1 TO CALLED-TIMES
    IF LS-OPERATION = "COUNT" THEN MOVE CALLED-TIMES TO LS-RESULT END-IF
    ...
    END-FUNCTION ...
    
     

    Last edit: Simon Sobisch 2021-08-26
  • Simon Sobisch

    Simon Sobisch - 2021-08-26

    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).

     
    • Emmad

      Emmad - 2021-08-27

      Thank you. Never heard of "Local Storage" before! :)

       
  • Chuck Haatvedt

    Chuck Haatvedt - 2021-08-26

    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.

     
    • Simon Sobisch

      Simon Sobisch - 2021-08-26

      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.

       
    • Emmad

      Emmad - 2021-08-27

      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
    • Brian Tiffin

      Brian Tiffin - 2021-08-28

      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

       
  • Ralph Linkletter

    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.

     
    • Emmad

      Emmad - 2021-08-27

      Thank you. Pipes is certainly above my tech. level :) - You are correct in this case it does not have to be a function.

       

Anonymous
Anonymous

Add attachments
Cancel