(* TEST
include runtime_events
*)
open Runtime_events

let majors = Atomic.make 0
let minors = Atomic.make 0

let got_start = ref false

let lost_events_count = ref 0

let lost_events domain_id num_events =
    lost_events_count := !lost_events_count + num_events

let lifecycle domain_id ts lifecycle_event data =
    match lifecycle_event with
    | EV_RING_START ->
        begin
            assert(match data with
            | Some(pid) -> true
            | None -> false);
            got_start := true
        end
    | _ -> ()

type phase_record = { mutable major: int; mutable minor: int }

let domain_tbl : (int, phase_record) Hashtbl.t = Hashtbl.create 5

let runtime_begin domain_id ts phase =
    let phase_count = Hashtbl.find_opt domain_tbl domain_id
        |> Option.value ~default:{ major = 0; minor = 0 } in
    match phase with
    | EV_MAJOR ->
        begin
            assert(phase_count.major >= 0);
            phase_count.major <- phase_count.major + 1
        end
    | EV_MINOR ->
        begin
            assert(phase_count.minor == 0);
            phase_count.minor <- 1
        end
    | _ -> ();
    Hashtbl.add domain_tbl domain_id phase_count

let runtime_end domain_id ts phase =
    let phase_count = Hashtbl.find_opt domain_tbl domain_id
        |> Option.value ~default:{ major = 0; minor = 0 } in
    match phase with
    | EV_MAJOR ->
        begin
            assert(phase_count.major >= 1);
            phase_count.major <- phase_count.major - 1;
            Atomic.incr majors
        end
    | EV_MINOR ->
        begin
            assert(phase_count.minor == 1);
            phase_count.minor <- 0;
            Atomic.incr minors
        end
    | _ -> ();
    Hashtbl.add domain_tbl domain_id phase_count

let num_domains = 3
let num_minors = 30

let () =
    start ();
    let cursor = create_cursor None in
    let gc_churn_f () =
        let list_ref = ref [] in
        for j = 0 to num_minors do
            list_ref := [];
            for a = 0 to 100 do
                list_ref := (Sys.opaque_identity(ref 42)) :: !list_ref
            done;
            Gc.minor ();
        done
    in
    let domains_list = List.init num_domains (fun _ -> Domain.spawn gc_churn_f) in
    let _ = List.iter Domain.join domains_list in
    let callbacks = Callbacks.create ~runtime_begin ~runtime_end ~lifecycle
                                        ~lost_events () in
    ignore(read_poll cursor callbacks None);
    assert(!got_start);
    (* this is num_full_majors rather than num_full_majors*num_domains
        because in the worst case it can be that low. *)
    assert(Atomic.get minors >= num_minors);
    assert(!lost_events_count == 0)
