[ABAP] Eine bestimmte Zeit (Sekundenbruchteile) warten

* WAIT UP TO ... SECONDS funktioniert nicht in allen Releases gleich zuverlässig
* Siehe auch BAPI_TRANSACTION_COMMIT mit Parameter WAIT = 'X'
* https://blogs.sap.com/2019/08/13/code-snippet-series-wait-a-fraction-of-a-second/
CLASS lcl_wait DEFINITION.
  PUBLIC SECTION.

    TYPES : BEGIN OF ty_s_tmstmp,
              start     TYPE timestampl, " Startzeit
              now       TYPE timestampl, " akt. Zeit
              elapsed   TYPE tzntstmpl,  " verstrichene Zeit in Sekunden
              limit     TYPE tzntstmpl,  " Limit in Sekunden
              condition TYPE abap_bool,  " Abbruch durch Bedingung oder Limit?
            END OF ty_s_tmstmp.

    CLASS-METHODS: wait
      IMPORTING
                i_time         TYPE tzntstmpl
      RETURNING VALUE(rv_info) TYPE ty_s_tmstmp.

  PRIVATE SECTION.
    CLASS-METHODS: condition_code
      RETURNING VALUE(rv_ok) TYPE abap_bool.
ENDCLASS.

CLASS lcl_wait IMPLEMENTATION.

  METHOD wait.
    rv_info = VALUE ty_s_tmstmp( elapsed = 0 limit = i_time condition = abap_false ).

    GET TIME STAMP FIELD rv_info-start.

* 1. Prüfung: Zeitlimit
    WHILE rv_info-elapsed < rv_info-limit.
* 2. Prüfung: Erfüllung der Abbruchbedingung
      IF abap_true = condition_code( ).
        rv_info-condition = abap_true.
        EXIT.
      ENDIF.

      GET TIME STAMP FIELD rv_info-now.
      rv_info-elapsed = cl_abap_tstmp=>subtract( tstmp1 = rv_info-now tstmp2 = rv_info-start ).
    ENDWHILE.

  ENDMETHOD.

  METHOD condition_code.
* Code mit Prüfbedingung hier (z.B. ENQUEUE_READ)
* Beispielcode testet, wann zufällig die Zahl 10 aus einer Seed von 0-100000 erzeugt wird
    DATA(lv_i) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) min = 0 max = 100000 )->get_next( ).

    IF lv_i = 10.
      rv_ok = abap_true.
    ELSE.
      rv_ok = abap_false.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA(lv_ts) = VALUE timestampl( ).

  GET TIME STAMP FIELD lv_ts.
  WRITE: / |Start: { lv_ts TIMESTAMP = ISO }|.

* max. Wartezeit in Sekunden (auch Sekundenbruchteile möglich)
  DATA(lv_info) = lcl_wait=>wait( '1.5' ).
  WRITE: / |Elapsed: { lv_info-elapsed TIMESTAMP = ISO }|.
  WRITE: / |Abbruchbedingung erfüllt: { lv_info-condition }|.

  GET TIME STAMP FIELD lv_ts.
  WRITE: / |Ende: { lv_ts TIMESTAMP = ISO }|.