// File: Barath-Kannan[P]SignalsAndSlots/test/SignalTest_Parametrized.cpp
// Function: SignalTestParametrized_IntenseUsage_Test::TestBody()
TEST_P(SignalTestParametrized, IntenseUsage) {
    auto func = ([this](sigType x) {
        volatile sigType v = x;
        for (uint32_t i = 0; i < params.nOperations; i++) {
            v+=x;
        }
        completedFunctions++;
    });

    Signal<sigType> signal(params.threadSafe);
    cout << "Connecting " << params.nConnections << " functions" << endl;
    for (uint32_t i = 0; i < params.nConnections; i++) {
        signal.connectSlot(params.scheme, func);
    }

    FunctionTimeRegular<> printer([this]() {
        cout << "Total elements emitted: " << counter << " / " << params.nEmissions << fixed << endl;
        cout << "Emission rate: " << (double) counter / bt.getElapsedMilliseconds() << fixed << "m/ms" << endl;
        cout << "Total elements processed: " << completedFunctions << " / " << params.nEmissions * params.nConnections << fixed << endl;
        cout << "Operation rate: " << (double) completedFunctions * params.nOperations / bt2.getElapsedNanoseconds() << "m/ns" << endl;
        return (bt2.getElapsedSeconds() < 6000);
    }, std::chrono::milliseconds(500));

    FunctionTimeRegular<> checkFinished([this]() {
        return (completedFunctions != params.nEmissions * params.nConnections);
    }, std::chrono::milliseconds(1));

    cout << "Starting emission thread: " << endl;
    
    std::list<thread> emitters;
    for (uint32_t i=0; i<params.nEmitters; ++i){
        emitters.emplace_back([this, &signal, i]() {
            if (i==0){
                bt2.start();
                bt.start();
            }
            uint32_t current;
            while ((current = counter.fetch_add(1000)) < params.nEmissions-1000){
                for (uint32_t j=0; j<1000; ++j) signal.emitSignal(1);
            }
            if (current == params.nEmissions-1000){
                for (uint32_t j=0; j<1000; ++j) signal.emitSignal(1);
                bt.stop();
            }
        });
    }
    cout << "Emission thread spawned" << endl;
    cout.precision(std::numeric_limits<double>::max_digits10);
    for (auto &t : emitters){
        t.join();
    }
    cout << "Emission completed" << endl;
    checkFinished.join();
    bt2.stop();
    printer.stopAndJoin();
    cout << "Processing completed" << endl;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x390, %rsp            # imm = 0x390
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x350(%rbp)
movq %rax, -0x10(%rbp)
movzbl 0x28(%rax), %esi
andl $0x1, %esi
leaq -0x128(%rbp), %rdi
callq 0x52f30
movq 0xad570(%rip), %rdi     # 0xfafb8
leaq 0x597fc(%rip), %rsi     # 0xa724b
callq 0xd640
movq %rax, -0x348(%rbp)
jmp 0x4da5d
movq -0x348(%rbp), %rdi
movq -0x350(%rbp), %rax
movl 0x18(%rax), %esi
callq 0xd9b0
movq %rax, -0x358(%rbp)
jmp 0x4da7c
movq -0x358(%rbp), %rdi
leaq 0x597cd(%rip), %rsi     # 0xa7257
callq 0xd640
movq %rax, -0x360(%rbp)
jmp 0x4da98
movq -0x360(%rbp), %rdi
movq 0xad4ea(%rip), %rsi     # 0xfaf90
callq 0xd6e0
jmp 0x4daad
movl $0x0, -0x138(%rbp)
movq -0x350(%rbp), %rcx
movl -0x138(%rbp), %eax
cmpl 0x18(%rcx), %eax
jae 0x4db66
movq -0x350(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, -0x36c(%rbp)
leaq -0x158(%rbp), %rdi
movq %rdi, -0x368(%rbp)
leaq -0x10(%rbp), %rsi
callq 0x4df30
movl -0x36c(%rbp), %esi
movq -0x368(%rbp), %rdx
leaq -0x128(%rbp), %rdi
callq 0x52f60
jmp 0x4db0f
leaq -0x158(%rbp), %rdi
callq 0x52fe0
movl -0x138(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x138(%rbp)
jmp 0x4dab7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x130(%rbp)
movl %eax, -0x134(%rbp)
jmp 0x4df10
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x130(%rbp)
movl %eax, -0x134(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x52fe0
jmp 0x4df10
movq -0x350(%rbp), %rax
movq %rax, -0x210(%rbp)
leaq -0x208(%rbp), %rdi
leaq -0x210(%rbp), %rsi
callq 0x4dfc0
movl $0x1f4, -0x21c(%rbp)    # imm = 0x1F4
leaq -0x218(%rbp), %rdi
leaq -0x21c(%rbp), %rsi
callq 0x1d220
jmp 0x4dba6
leaq -0x1e8(%rbp), %rdi
leaq -0x208(%rbp), %rsi
leaq -0x218(%rbp), %rdx
callq 0x53000
jmp 0x4dbc2
leaq -0x208(%rbp), %rdi
callq 0x23f80
movq -0x350(%rbp), %rax
movq %rax, -0x2d8(%rbp)
leaq -0x2d0(%rbp), %rdi
leaq -0x2d8(%rbp), %rsi
callq 0x4e050
movl $0x1, -0x2e4(%rbp)
leaq -0x2e0(%rbp), %rdi
leaq -0x2e4(%rbp), %rsi
callq 0x1d220
jmp 0x4dc0e
leaq -0x2b0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
leaq -0x2e0(%rbp), %rdx
callq 0x53000
jmp 0x4dc2a
leaq -0x2d0(%rbp), %rdi
callq 0x23f80
movq 0xad37b(%rip), %rdi     # 0xfafb8
leaq 0x5961e(%rip), %rsi     # 0xa7262
callq 0xd640
movq %rax, -0x378(%rbp)
jmp 0x4dc52
movq -0x378(%rbp), %rdi
movq 0xad330(%rip), %rsi     # 0xfaf90
callq 0xd6e0
jmp 0x4dc67
leaq -0x300(%rbp), %rdi
callq 0x1d150
movl $0x0, -0x304(%rbp)
movq -0x350(%rbp), %rcx
movl -0x304(%rbp), %eax
cmpl 0x24(%rcx), %eax
jae 0x4dd63
movq -0x350(%rbp), %rax
movq %rax, -0x320(%rbp)
leaq -0x128(%rbp), %rax
movq %rax, -0x318(%rbp)
movl -0x304(%rbp), %eax
movl %eax, -0x310(%rbp)
leaq -0x300(%rbp), %rdi
leaq -0x320(%rbp), %rsi
callq 0x4e0e0
jmp 0x4dcd0
jmp 0x4dcd2
movl -0x304(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x304(%rbp)
jmp 0x4dc7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x130(%rbp)
movl %eax, -0x134(%rbp)
leaq -0x208(%rbp), %rdi
callq 0x23f80
jmp 0x4df10
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x130(%rbp)
movl %eax, -0x134(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x23f80
jmp 0x4df04
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x130(%rbp)
movl %eax, -0x134(%rbp)
jmp 0x4def8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x130(%rbp)
movl %eax, -0x134(%rbp)
leaq -0x300(%rbp), %rdi
callq 0x1d310
jmp 0x4def8
movq 0xad24e(%rip), %rdi     # 0xfafb8
leaq 0x5950c(%rip), %rsi     # 0xa727d
callq 0xd640
movq %rax, -0x380(%rbp)
jmp 0x4dd7f
movq -0x380(%rbp), %rdi
movq 0xad203(%rip), %rsi     # 0xfaf90
callq 0xd6e0
jmp 0x4dd94
movq 0xad21d(%rip), %rdi     # 0xfafb8
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
movl $0x11, %esi
callq 0x53110
jmp 0x4ddb1
leaq -0x300(%rbp), %rax
movq %rax, -0x328(%rbp)
movq -0x328(%rbp), %rdi
callq 0x1d240
movq %rax, -0x330(%rbp)
movq -0x328(%rbp), %rdi
callq 0x1d270
movq %rax, -0x338(%rbp)
leaq -0x330(%rbp), %rdi
leaq -0x338(%rbp), %rsi
callq 0x1d2a0
testb $0x1, %al
jne 0x4ddfe
jmp 0x4de2f
leaq -0x330(%rbp), %rdi
callq 0x1d2d0
movq %rax, -0x340(%rbp)
movq -0x340(%rbp), %rdi
callq 0xdc40
jmp 0x4de1f
jmp 0x4de21
leaq -0x330(%rbp), %rdi
callq 0x1d2f0
jmp 0x4dde5
movq 0xad182(%rip), %rdi     # 0xfafb8
leaq 0x59458(%rip), %rsi     # 0xa7295
callq 0xd640
movq %rax, -0x388(%rbp)
jmp 0x4de4b
movq -0x388(%rbp), %rdi
movq 0xad137(%rip), %rsi     # 0xfaf90
callq 0xd6e0
jmp 0x4de60
leaq -0x2b0(%rbp), %rdi
callq 0x53140
jmp 0x4de6e
movq -0x350(%rbp), %rdi
addq $0x48, %rdi
callq 0xfe30
jmp 0x4de80
leaq -0x1e8(%rbp), %rdi
callq 0x53160
jmp 0x4de8e
movq 0xad123(%rip), %rdi     # 0xfafb8
leaq 0x5940c(%rip), %rsi     # 0xa72a8
callq 0xd640
movq %rax, -0x390(%rbp)
jmp 0x4deaa
movq -0x390(%rbp), %rdi
movq 0xad0d8(%rip), %rsi     # 0xfaf90
callq 0xd6e0
jmp 0x4debf
leaq -0x300(%rbp), %rdi
callq 0x1d310
leaq -0x2b0(%rbp), %rdi
callq 0x53190
leaq -0x1e8(%rbp), %rdi
callq 0x53190
leaq -0x128(%rbp), %rdi
callq 0x53210
addq $0x390, %rsp            # imm = 0x390
popq %rbp
retq
leaq -0x2b0(%rbp), %rdi
callq 0x53190
leaq -0x1e8(%rbp), %rdi
callq 0x53190
leaq -0x128(%rbp), %rdi
callq 0x53210
movq -0x130(%rbp), %rdi
callq 0xdcb0
nopl (%rax,%rax)