Several aRFC with WAIT, how to synchronize access to variable in callback?
Asked Answered
M

1

5

I am using asynchronous RFC calls for doing some parallel work in SAP. Here you can see my pseudo code.

* class variable
data: gv_counter type i .

....

method start_tasks .

    do 10 times .

        call function 'my_remote_function'
            starting new task task_identifier
            calling task_finish on end of task .

    enddo .

    wait for asynchronous tasks until gv_counter eq 10 .    

endmethod .

.....

method task_finish .

    gv_counter = gv_counter + 1 .

endmethod .

As you can see I start 10 processes and I wait until they are all finished.

My question is about the method task_finish and the access to the global class variable gv_counter. How can I ensure that the access to the variable gv_counter is synchronized?

E.g. in Java I would do something like that:

synchronized {
    gv_counter += 1 ;
}
Mckinleymckinney answered 4/5, 2019 at 9:6 Comment(1)
There is no such thing as "synchronized" in ABAP as there are no threads in ABAP. Are you experiencing any race conditions in your code?Franky
F
6

Here is a quotation from the SAP documentation on the topic.

Addition 2

... {CALLING meth}|{PERFORMING subr} ON END OF TASK

...

If multiple callback routines are registered during a program section, they are executed in an undefined order when the work process changes in a roll-in.

For me it means that they will be executed one after another (in order) which is however undefined. This would mean that your variable would always reach the value of 10.

You can actually debug it, to see how it is processed sequentially when you put a breakpoint in the task_finish method. Here is my example.

REPORT ZZZ.

CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    CLASS-METHODS:
      main,
      task_finish
        IMPORTING
          p_task TYPE clike.
  PRIVATE SECTION.
    CLASS-DATA:
      gv_counter TYPE i.
    CLASS-METHODS:
      start_tasks.
ENDCLASS.

CLASS lcl_main IMPLEMENTATION.
  METHOD main.
    start_tasks( ).
  ENDMETHOD.

  METHOD start_tasks.
    DATA: l_task TYPE string.
    DO 10 TIMES.
      l_task = sy-index.
      CALL FUNCTION 'Z_ARFC_ECHO'
        STARTING NEW TASK l_task
        CALLING task_finish ON END OF TASK
        EXPORTING
          i_value       = sy-index.

    ENDDO.

    WAIT FOR ASYNCHRONOUS TASKS UNTIL gv_counter = 10.
  ENDMETHOD.

  METHOD task_finish.
    DATA: l_value TYPE sy-index.
    RECEIVE RESULTS FROM FUNCTION 'Z_ARFC_ECHO'
      IMPORTING
        e_echo = l_value.

    WRITE: /, p_task, l_value.

    gv_counter = gv_counter + 1.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  lcl_main=>main( ).

My RFC looks as follows

FUNCTION Z_ARFC_ECHO.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*"  IMPORTING
*"     VALUE(I_VALUE) TYPE  SY-INDEX
*"  EXPORTING
*"     VALUE(E_ECHO) TYPE  SY-INDEX
*"----------------------------------------------------------------------

e_echo = i_value.

ENDFUNCTION.

What is also interesting (and also mentioned in the documentation) the list output statements like WRITE are not processed in such a handler, so that's why you do not see anything getting printed at the end of the execution of the abovementioned report.

Franky answered 4/5, 2019 at 11:1 Comment(3)
To clarify the "they will be executed", you mean the "callback routines", not the "RFC tasks".Italia
Exactly, so after all the processes for the asynchronous RFC calls are finished.Franky
Sorry, nitpicking again, but it's NOT "after all the processes are finished", it's on the fly as soon as each task finishes, but never two in parallel, always in sequence.Italia

© 2022 - 2024 — McMap. All rights reserved.