Skip to main content

I want to create utility X.  I want to call utility X in program A and program B.  Program A runs, calls X, does work, then calls B.  B will also call program X.  This new X needs to start fresh and preserve state (file status, working storage) separate from the first instance. while B uses it.  Eventually B will shut down X #2, and return to A, which needs X #1 to remember it's file state and working storage.

 

The manual says that you only have one instance of X in memory, and therefore only state, unless it is called in two different threads.  I don't want to run A and B as separate threads.  I could run X in it's own separate thread, but then I cannot call that instance again, because it's now in a separate thread - I would have to send messages back & forth instead of using the linkage area to pass back & forth. 

Anyone know how to call a specific instance of X?  (I was hoping the call would allow calling with thread handle already set, but that's not what the manual says)


#CALLSUBPROGRAMINSTANCESTATETHREAD

I want to create utility X.  I want to call utility X in program A and program B.  Program A runs, calls X, does work, then calls B.  B will also call program X.  This new X needs to start fresh and preserve state (file status, working storage) separate from the first instance. while B uses it.  Eventually B will shut down X #2, and return to A, which needs X #1 to remember it's file state and working storage.

 

The manual says that you only have one instance of X in memory, and therefore only state, unless it is called in two different threads.  I don't want to run A and B as separate threads.  I could run X in it's own separate thread, but then I cannot call that instance again, because it's now in a separate thread - I would have to send messages back & forth instead of using the linkage area to pass back & forth. 

Anyone know how to call a specific instance of X?  (I was hoping the call would allow calling with thread handle already set, but that's not what the manual says)


#CALLSUBPROGRAMINSTANCESTATETHREAD

You can't do what you want. But there is a simple workaround.

Start program B in a thread, and from program A, immediately wait for a message from B (effectively not using threads). When B is finished, send that message to A, allowing A to continue. In that way, X is running two separate instances.

Note that I have not tried this, but it should work.


I want to create utility X.  I want to call utility X in program A and program B.  Program A runs, calls X, does work, then calls B.  B will also call program X.  This new X needs to start fresh and preserve state (file status, working storage) separate from the first instance. while B uses it.  Eventually B will shut down X #2, and return to A, which needs X #1 to remember it's file state and working storage.

 

The manual says that you only have one instance of X in memory, and therefore only state, unless it is called in two different threads.  I don't want to run A and B as separate threads.  I could run X in it's own separate thread, but then I cannot call that instance again, because it's now in a separate thread - I would have to send messages back & forth instead of using the linkage area to pass back & forth. 

Anyone know how to call a specific instance of X?  (I was hoping the call would allow calling with thread handle already set, but that's not what the manual says)


#CALLSUBPROGRAMINSTANCESTATETHREAD

Hi

Sometimes we need the same and we use this workaround:

- Write the X utility

- Compile the X utility and have the X object (for now I call XOBJ)

- Copy the XOBJ in YOBJ

- Program A calls XOBJ

- Program B call YOBJ

Finally, if you're working in Linux environment, you can also use symbolic link instead of the copy of the object:

- Install the XOBJ file

- Link the XOBJ to the YOBJ

Since now, every time you update the XOBJ, the system updates also the YOBJ, so you don't need to do it by yourself


I want to create utility X.  I want to call utility X in program A and program B.  Program A runs, calls X, does work, then calls B.  B will also call program X.  This new X needs to start fresh and preserve state (file status, working storage) separate from the first instance. while B uses it.  Eventually B will shut down X #2, and return to A, which needs X #1 to remember it's file state and working storage.

 

The manual says that you only have one instance of X in memory, and therefore only state, unless it is called in two different threads.  I don't want to run A and B as separate threads.  I could run X in it's own separate thread, but then I cannot call that instance again, because it's now in a separate thread - I would have to send messages back & forth instead of using the linkage area to pass back & forth. 

Anyone know how to call a specific instance of X?  (I was hoping the call would allow calling with thread handle already set, but that's not what the manual says)


#CALLSUBPROGRAMINSTANCESTATETHREAD

Thank you both.  I simplified the plan for my example, it could go beyond two instances, but both ideas could be used with a bit of work.

I plan to use the thread idea.  The manual says that variables passed by reference are shared between caller and called.  So I just have to, as suggested, call the program which should then go into a loop waiting for an incoming message.  The caller then sends a message, eg the string "CALL", to the sub-program then immediately does a receive to wait for the subprogram to finish/exit.  The subprogram gets the "call" message,  does it's thing and sends back "DONE", and loops back to it's receive command.  The caller can then resume and any changes the subprogram made to the using variables will be available.  Cancel gets replaced by close thread.

The trick PiGi mentioned could become a managed thing - have a copy library that calls a utility to get the next "unused" version of the program name for the program being called.  If that file doesn't exist yet, then the manager would link (or copy) the original to that name (XXXX, then XXXX1, then XXXX2 etc).  Main program can call that unique name.  Just remember to call a routine from the library to "cancel" the linked program so it can be marked as not-used.  This has the advantage that each called program is unique and you can use the "USING" to pass parameters.  The manager utility would leave the copies sitting around so they "cache".  I would probbably put them into a work folder, so an update can purge the old copies of the updated programs, and the manager can just rebuild the cache.


I want to create utility X.  I want to call utility X in program A and program B.  Program A runs, calls X, does work, then calls B.  B will also call program X.  This new X needs to start fresh and preserve state (file status, working storage) separate from the first instance. while B uses it.  Eventually B will shut down X #2, and return to A, which needs X #1 to remember it's file state and working storage.

 

The manual says that you only have one instance of X in memory, and therefore only state, unless it is called in two different threads.  I don't want to run A and B as separate threads.  I could run X in it's own separate thread, but then I cannot call that instance again, because it's now in a separate thread - I would have to send messages back & forth instead of using the linkage area to pass back & forth. 

Anyone know how to call a specific instance of X?  (I was hoping the call would allow calling with thread handle already set, but that's not what the manual says)


#CALLSUBPROGRAMINSTANCESTATETHREAD

Try this: program test_co_test runs two different istances of co_test. Limitation: the working-storage of co_test must be defined under a unique level 01 item

The "main" program test_co_test:

 identification division.
 program-id.     test_co_test.
 environment division.
 configuration section.
 source-computer. Lebedev_MESM.
 object-computer. Lebedev_MESM.
 special-names.     
 data division.
 working-storage section.
 
 78  main-pic            value 65536.
 01  par-size            pic 9(08).
 01  num-param           pic 9(06) comp-1.
 
 01  testHandle-a        pointer.
 01  testHandle-b        pointer.
 01  testHandle-c        pointer.

 01  buringoA            pic x(32).
 01  buringoB            pic x(64).
 01  buringoC            pic x(128).
                     
 
 linkage section.  
 
 procedure division.                              
 declaratives.
   setup section.  use at program start.
   setup-ex.  exit.      
   tearDown section.  use at program end.
   tearDown-ex.  exit
 end declaratives.

 main-line.
         stop " "                    
         
         move  "A"  to  buringoA
         move  "B"  to  buringoB
         move  "C"  to  buringoC
                  
         call  "co_test"         using testHandle-a  | out new handle
         call  "co_test"         using testHandle-b  | out new handle
         call  "co_test"         using testHandle-c  | out new handle
         
         
         call  "co_test.setStringA"  using testHandle-a
                                           buringoA                                           
         call  "co_test.setStringA"  using testHandle-b
                                           buringoB                                           
         call  "co_test.setStringA"  using testHandle-c
                                           buringoC
                                           
         move  spaces  to buringoA                                            
         move  spaces  to buringoB                                            
         move  spaces  to buringoC                                                                                       
                                           
         call  "co_test.getStringA"  using testHandle-a
                                           buringoA
         call  "co_test.getStringA"  using testHandle-b
                                           buringoB
         call  "co_test.getStringA"  using testHandle-c
                                           buringoC
         
         call  "co_test.dispose"      using testHandle-a
         call  "co_test.dispose"      using testHandle-b
         call  "co_test.dispose"      using testHandle-c
                                       
                  
         stop " "
 
     goback.

The subprogram co_test:

 identification division.
 program-id.     co_test.
 environment division.
 configuration section.
 source-computer. Lebedev_MESM.
 object-computer. Lebedev_MESM.
 special-names.     
 data division.
 working-storage section.
 
 78  main-pic            value 65536.
 01  par-size            pic 9(08).
 01  num-param           pic 9(06) comp-1.
 
 01  currentInstancePTR  pointer.

 01  propertyArea.
     05  pa-stringA      pic x(256).
     05  pa-stringB      pic x(256).
     
 78  k-ll-propertyArea   value length of propertyArea.               
 
 linkage section.  
 01  lk-instancePtr      pointer.
 01  lk-string           pic x(main-pic).
 
 procedure division using lk-instancePtr. | out per main (costruttore)                               
 declaratives.
   setup section.  use at program start.
   setup-ex.  exit.      
   tearDown section.  use at program end.
   tearDown-ex.  exit
 end declaratives.

 newInstance.
        set  lk-instancePtr to null
        perform p-saveCurrentInstance
        
        initialize  propertyArea
        
        call  "M$ALLOC"  using k-ll-propertyArea      | in
                               lk-instancePtr         | out
                               
        move  lk-instancePtr to  currentInstancePTR                       
     goback returning 1
     . |__________________________________________________________ endParagraph     
 
         
     entry  "co_test.dispose"  using  lk-instancePtr. | inout
        call "M$FREE" using lk-instancePtr
        if  lk-instancePtr  = currentInstancePTR
            move null    to currentInstancePTR        
        end-if        
        move null        to lk-instancePtr
     goback returning 1                          
     . |__________________________________________________________ endEntry     
     
     entry  "co_test.setStringA"  using  lk-instancePtr  | in  
                                         lk-string.      | in
        perform  p-getCurrentInstance
        
        call  "c$paramsize"  using  2  giving par-size
        move  lk-string (1:par-size)  to  pa-stringA        
        
     goback returning 1                          
     . |__________________________________________________________ endEntry
     
     entry  "co_test.getStringA"  using  lk-instancePtr  | in  
                                         lk-string.      | out
        perform  p-getCurrentInstance
        
        call  "c$paramsize"  using  2  giving par-size
        move  pa-stringA  to  lk-string (1:par-size)          
        
     goback returning 1                          
     . |__________________________________________________________ endEntry                        
 
 p-saveCurrentInstance.
     if currentInstancePTR not = null     
        call "M$PUT"   using currentInstancePTR   | dataddress  
                             propertyArea         | data
                             k-ll-propertyArea    | data size
                             1                    | data-offset
     end-if                          
     . |__________________________________________________________ endParagraph
     
 p-getCurrentInstance.
     if  lk-instancePtr = null
         stop  "null pointer exception (ahr ahr)"
         goback returning 0         
     end-if   
 
     if  lk-instancePtr not = currentInstancePTR
         perform  p-saveCurrentInstance  
         call "M$GET"   using lk-instancePtr         | dataddress
                              propertyArea           | data
                              k-ll-propertyArea      | data size
                              1                      | data-offset         
         move  lk-instancePtr to  currentInstancePTR                     
     end-if   
     . |__________________________________________________________ endParagraph