// File: iamlouk[P]asbi/src/events/loop.cc
// Function: asbi::evts::Loop::getEvent()
evts::Event* evts::Loop::getEvent() {
	// check if done:
	// TODO: extract in other function to return early and avoid unnecessary locking
	{
		std::unique_lock<std::mutex> lock1(eventsMtx);
		std::unique_lock<std::mutex> lock2(tasksMtx);
		if (events.empty() && tasksRunning == 0 && tasks.empty() && timers.empty())
			return nullptr;
	}

	// check for timers
	evts::Timer timer;
	if (getNextTimer(timer)) {
		auto evt = new evts::Event();
		evt->taskDone = true;
		evt->callback = timer.callback;
		evt->callback->gc_manage = true;
		evt->doCall = true;
		return evt;
	}


	// wait for event from task or timer
	if (timers.empty()) {
		eventsSem.acquire();
	} else {
		std::chrono::duration<double, std::milli> tts = timers.first().dueAt - evts::timestamp();
		auto timedout = !eventsSem.acquireFor(tts);
		if (timedout)
			return getEvent(); // so that we can check on timers again
	}


	// take event from queue
	evts::Event* evt;
	{
		std::unique_lock<std::mutex> lock(eventsMtx);
		assert(!events.empty());
		evt = events.front();
		events.pop_front();

		if (evt->taskDone)
			evt->callback->gc_manage = true;
	}

	if (evt->doCall) {
		return evt;
	} else {
		delete evt;
		return getEvent();
	}
}

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0xb8(%rsp)
movq 0xb8(%rsp), %rsi
movq %rsi, 0x20(%rsp)
addq $0xe8, %rsi
leaq 0xa8(%rsp), %rdi
callq 0x2ecf0
movq 0x20(%rsp), %rsi
addq $0x10, %rsi
leaq 0x98(%rsp), %rdi
callq 0x2ecf0
jmp 0x2ff88
movq 0x20(%rsp), %rdi
addq $0x170, %rdi            # imm = 0x170
callq 0x30ec0
testb $0x1, %al
jne 0x2ffa2
jmp 0x30041
movq 0x20(%rsp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x30041
movq 0x20(%rsp), %rdi
addq $0x98, %rdi
callq 0x30ee0
testb $0x1, %al
jne 0x2ffc8
jmp 0x30041
movq 0x20(%rsp), %rdi
addq $0x1c0, %rdi            # imm = 0x1C0
callq 0x30f00
movb %al, 0x1f(%rsp)
jmp 0x2ffdf
movb 0x1f(%rsp), %al
testb $0x1, %al
jne 0x2ffe9
jmp 0x30041
movq $0x0, 0xc0(%rsp)
movl $0x1, 0x88(%rsp)
jmp 0x3004c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
jmp 0x3010b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x2ed30
jmp 0x3010b
movl $0x0, 0x88(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x2ed30
leaq 0xa8(%rsp), %rdi
callq 0x2ed30
movl 0x88(%rsp), %eax
testl %eax, %eax
je 0x30078
jmp 0x30073
jmp 0x302cb
leaq 0x78(%rsp), %rdi
callq 0x317c0
movq 0x20(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x306a0
testb $0x1, %al
jne 0x3009a
jmp 0x3011d
movl $0x28, %edi
callq 0x6460
movq %rax, %rdi
movq %rdi, 0x10(%rsp)
xorl %esi, %esi
movl $0x28, %edx
callq 0x6250
movq 0x10(%rsp), %rdi
callq 0x31490
movq 0x10(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rax
movb $0x1, 0x20(%rax)
movq 0x78(%rsp), %rcx
movq 0x70(%rsp), %rax
movq %rcx, 0x18(%rax)
movq 0x70(%rsp), %rax
movq 0x18(%rax), %rax
movb $0x1, 0x11(%rax)
movq 0x70(%rsp), %rax
movb $0x1, 0x21(%rax)
movq 0x70(%rsp), %rax
movq %rax, 0xc0(%rsp)
jmp 0x302cb
leaq 0xa8(%rsp), %rdi
callq 0x2ed30
jmp 0x302db
movq 0x20(%rsp), %rdi
addq $0x1c0, %rdi            # imm = 0x1C0
callq 0x30f00
testb $0x1, %al
jne 0x30134
jmp 0x3014a
movq 0x20(%rsp), %rdi
addq $0x110, %rdi            # imm = 0x110
callq 0x2e860
jmp 0x301dd
movq 0x20(%rsp), %rdi
addq $0x1c0, %rdi            # imm = 0x1C0
callq 0x31840
movq %rax, 0x58(%rsp)
movsd %xmm0, 0x60(%rsp)
leaq 0x58(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x8(%rsp)
callq 0x2eb00
movq 0x8(%rsp), %rdi
movsd %xmm0, 0x50(%rsp)
leaq 0x50(%rsp), %rsi
callq 0x317d0
movq 0x20(%rsp), %rdi
movsd %xmm0, 0x68(%rsp)
addq $0x110, %rdi            # imm = 0x110
movq 0x68(%rsp), %rax
movq %rax, 0x40(%rsp)
movsd 0x40(%rsp), %xmm0
callq 0x2e9b0
xorb $-0x1, %al
andb $0x1, %al
movb %al, 0x4f(%rsp)
testb $0x1, 0x4f(%rsp)
je 0x301db
movq 0x20(%rsp), %rdi
callq 0x2ff40
movq %rax, 0xc0(%rsp)
jmp 0x302cb
jmp 0x301dd
movq 0x20(%rsp), %rsi
addq $0xe8, %rsi
leaq 0x28(%rsp), %rdi
callq 0x2ecf0
movq 0x20(%rsp), %rdi
addq $0x170, %rdi            # imm = 0x170
callq 0x30ec0
xorb $-0x1, %al
testb $0x1, %al
jne 0x3020c
jmp 0x3020e
jmp 0x3022d
leaq 0x9484(%rip), %rdi      # 0x39699
leaq 0x9454(%rip), %rsi      # 0x39670
movl $0x91, %edx
leaq 0x9481(%rip), %rcx      # 0x396a9
callq 0x62b0
movq 0x20(%rsp), %rdi
addq $0x170, %rdi            # imm = 0x170
callq 0x318a0
movq 0x20(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0x38(%rsp)
addq $0x170, %rdi            # imm = 0x170
callq 0x318d0
movq 0x38(%rsp), %rax
testb $0x1, 0x20(%rax)
je 0x3026f
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rax
movb $0x1, 0x11(%rax)
leaq 0x28(%rsp), %rdi
callq 0x2ed30
movq 0x38(%rsp), %rax
testb $0x1, 0x21(%rax)
je 0x30293
movq 0x38(%rsp), %rax
movq %rax, 0xc0(%rsp)
jmp 0x302cb
movq 0x38(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x302b9
movq (%rsp), %rdi
callq 0x31290
movq (%rsp), %rdi
movl $0x28, %esi
callq 0x6470
movq 0x20(%rsp), %rdi
callq 0x2ff40
movq %rax, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
addq $0xc8, %rsp
retq
movq 0x90(%rsp), %rdi
callq 0x67a0
nopl (%rax,%rax)