// File: waket[P]ThreadPool/ThreadPoolTask.cpp
// Function: ThreadPoolTask::startWorker()
void ThreadPoolTask::startWorker() {
    pthread_t id = pthread_self();
    cout << "\tStart the worker: " << id << endl;

    startWorkersMutex.lock();
    workersSet.insert(id);
    // Check if all the workers have started then unblock startWorkersCond
    if (workersSet.size() == workerCount) {
        cout << "\t" << id << " All workers started wakeup startWorkersCond" << endl;
        startWorkersCond.signal();
    }
    startWorkersMutex.unlock();

    while (true) {
        cout << "\t" << id << " waiting for the release of the lock" << endl;
        tasksMutex.lock();
        cout << "\t" << id << " is locked " <<tasksDeque.size() << " " << isStarted << " " << isStopWorker << endl;
        // Wait if no task to do and the thread pool is not stopped 
        while (tasksDeque.empty() && isStarted && !isStopWorker) {
            // The wait will be released due to availability of a new task 
            // (signal() from doTask()) or due to the stooping of the
            // pool (broadcast() from stop())
            // The Wait will release the unlock of the mutex tasksMutex and lock it
            // back as soon as it is signaled
            cout << "\t" << id << " is waiting" << endl;
            tasksCond.wait(tasksMutex.mutexPtr());
            cout << "\t" << id << " is signaled " << isStarted << " " << isStopWorker << endl;
        }

        // Check if the thread pool is still on
        if (!isStarted) {
            cout << "\t" << id << " exit (thread pool is stopped) " << workersSet.size() << endl;
            tasksMutex.unlock();
            pthread_exit(NULL);
        }

        // Check for dynamic count worker
        if (isStopWorker) {
            assert(workersSet.size() != workerCount);
            workersSet.erase(id);
            tasksCond.signal();
            if (workersSet.size() == workerCount) {
                isStopWorker = false;
                cout << "\t" << id << " is the last exiting worker " << workersSet.size() << " " << isStopWorker << endl;
                // Unblock setWorkerCount()
                stopWorkersCond.signal();
            }
            cout << "\t" << id << " exit (reduce the worker count) " << workersSet.size() << endl;
            tasksMutex.unlock();
            pthread_exit(NULL);
        }

        assert(!tasksDeque.empty());

        // pick a task
        TaskItem task = tasksDeque.front();
        tasksDeque.pop_front();
        cout << "\t" << id << " pop. Size of the task queue is: " << tasksDeque.size() << endl;
        tasksMutex.unlock();
        // do the task
        (task) ();
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x58(%rbp)
callq 0x2140
movq %rax, -0x10(%rbp)
movq 0x9401(%rip), %rdi      # 0xdfd8
leaq 0x46ba(%rip), %rsi      # 0x9298
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
movq 0x93cf(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
addq $0x158, %rdi            # imm = 0x158
callq 0x5b00
movq -0x58(%rbp), %rdi
addq $0x60, %rdi
leaq -0x10(%rbp), %rsi
callq 0x5b70
movq -0x58(%rbp), %rdi
movq %rax, -0x20(%rbp)
movb %dl, -0x18(%rbp)
addq $0x60, %rdi
callq 0x5bc0
movq -0x58(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jne 0x4c8a
movq 0x9394(%rip), %rdi      # 0xdfd8
leaq 0x4661(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x4648(%rip), %rsi      # 0x92ae
callq 0x2180
movq %rax, %rdi
movq 0x9353(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
addq $0x188, %rdi            # imm = 0x188
callq 0x5be0
movq -0x58(%rbp), %rdi
addq $0x158, %rdi            # imm = 0x158
callq 0x3d90
movq 0x9337(%rip), %rdi      # 0xdfd8
leaq 0x4604(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x4618(%rip), %rsi      # 0x92db
callq 0x2180
movq %rax, %rdi
movq 0x92f6(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
addq $0x90, %rdi
callq 0x5b00
movq 0x92ea(%rip), %rdi      # 0xdfd8
leaq 0x45b7(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x45f0(%rip), %rsi      # 0x9300
callq 0x2180
movq -0x58(%rbp), %rdi
movq %rax, -0x60(%rbp)
addq $0x10, %rdi
callq 0x5c00
movq -0x60(%rbp), %rdi
movq %rax, %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x4608(%rip), %rsi      # 0x9344
callq 0x2180
movq %rax, %rdi
movq -0x58(%rbp), %rax
movb 0x150(%rax), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x22e0
movq %rax, %rdi
leaq 0x45e2(%rip), %rsi      # 0x9344
callq 0x2180
movq %rax, %rdi
movq -0x58(%rbp), %rax
movb 0x152(%rax), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x22e0
movq %rax, %rdi
movq 0x9240(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
addq $0x10, %rdi
callq 0x5c30
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x61(%rbp)
jne 0x4da8
jmp 0x4dc9
movq -0x58(%rbp), %rcx
xorl %eax, %eax
testb $0x1, 0x150(%rcx)
movb %al, -0x61(%rbp)
je 0x4dc9
movq -0x58(%rbp), %rax
movb 0x152(%rax), %al
xorb $-0x1, %al
movb %al, -0x61(%rbp)
movb -0x61(%rbp), %al
testb $0x1, %al
jne 0x4dd5
jmp 0x4eba
movq 0x91fc(%rip), %rdi      # 0xdfd8
leaq 0x44c9(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x450e(%rip), %rsi      # 0x930c
callq 0x2180
movq %rax, %rdi
movq 0x91bb(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
movq %rdi, %rax
addq $0xc0, %rax
movq %rax, -0x70(%rbp)
addq $0x90, %rdi
callq 0x5b60
movq -0x70(%rbp), %rdi
movq %rax, %rsi
callq 0x5b30
movq 0x9196(%rip), %rdi      # 0xdfd8
leaq 0x4463(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x44b4(%rip), %rsi      # 0x9318
callq 0x2180
movq %rax, %rdi
movq -0x58(%rbp), %rax
movb 0x150(%rax), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x22e0
movq %rax, %rdi
leaq 0x44ba(%rip), %rsi      # 0x9344
callq 0x2180
movq %rax, %rdi
movq -0x58(%rbp), %rax
movb 0x152(%rax), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x22e0
movq %rax, %rdi
movq 0x9118(%rip), %rsi      # 0xdfc8
callq 0x21c0
jmp 0x4d8d
movq -0x58(%rbp), %rax
testb $0x1, 0x150(%rax)
jne 0x4f3a
movq 0x910a(%rip), %rdi      # 0xdfd8
leaq 0x43d7(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x4436(%rip), %rsi      # 0x9326
callq 0x2180
movq -0x58(%rbp), %rdi
movq %rax, -0x78(%rbp)
addq $0x60, %rdi
callq 0x5bc0
movq -0x78(%rbp), %rdi
movq %rax, %rsi
callq 0x2050
movq %rax, %rdi
movq 0x90ac(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
addq $0x90, %rdi
callq 0x3d90
xorl %eax, %eax
movl %eax, %edi
callq 0x22d0
movq -0x58(%rbp), %rax
testb $0x1, 0x152(%rax)
je 0x50d3
movq -0x58(%rbp), %rdi
addq $0x60, %rdi
callq 0x5bc0
movq -0x58(%rbp), %rcx
cmpq 0x8(%rcx), %rax
je 0x4f64
jmp 0x4f83
leaq 0x43db(%rip), %rdi      # 0x9346
leaq 0x43f5(%rip), %rsi      # 0x9367
movl $0x58, %edx
leaq 0x43fc(%rip), %rcx      # 0x937a
callq 0x20e0
movq -0x58(%rbp), %rdi
addq $0x60, %rdi
leaq -0x10(%rbp), %rsi
callq 0x5c60
movq -0x58(%rbp), %rdi
addq $0xc0, %rdi
callq 0x5be0
movq -0x58(%rbp), %rdi
addq $0x60, %rdi
callq 0x5bc0
movq -0x58(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jne 0x505a
movq -0x58(%rbp), %rax
movb $0x0, 0x152(%rax)
movq 0x9007(%rip), %rdi      # 0xdfd8
leaq 0x42d4(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x43aa(%rip), %rsi      # 0x939d
callq 0x2180
movq -0x58(%rbp), %rdi
movq %rax, -0x80(%rbp)
addq $0x60, %rdi
callq 0x5bc0
movq -0x80(%rbp), %rdi
movq %rax, %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x4325(%rip), %rsi      # 0x9344
callq 0x2180
movq %rax, %rdi
movq -0x58(%rbp), %rax
movb 0x152(%rax), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x22e0
movq %rax, %rdi
movq 0x8f83(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
addq $0x1e8, %rdi            # imm = 0x1E8
callq 0x5be0
movq 0x8f77(%rip), %rdi      # 0xdfd8
leaq 0x4244(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, %rdi
leaq 0x4337(%rip), %rsi      # 0x93ba
callq 0x2180
movq -0x58(%rbp), %rdi
movq %rax, -0x88(%rbp)
addq $0x60, %rdi
callq 0x5bc0
movq -0x88(%rbp), %rdi
movq %rax, %rsi
callq 0x2050
movq %rax, %rdi
movq 0x8f13(%rip), %rsi      # 0xdfc8
callq 0x21c0
movq -0x58(%rbp), %rdi
addq $0x90, %rdi
callq 0x3d90
xorl %eax, %eax
movl %eax, %edi
callq 0x22d0
movq -0x58(%rbp), %rdi
addq $0x10, %rdi
callq 0x5c30
xorb $-0x1, %al
testb $0x1, %al
jne 0x50e8
jmp 0x50ea
jmp 0x5109
leaq 0x42ea(%rip), %rdi      # 0x93db
leaq 0x426f(%rip), %rsi      # 0x9367
movl $0x66, %edx
leaq 0x4276(%rip), %rcx      # 0x937a
callq 0x20e0
movq -0x58(%rbp), %rdi
addq $0x10, %rdi
movq %rdi, -0x98(%rbp)
callq 0x5c90
movq %rax, %rsi
leaq -0x40(%rbp), %rdi
callq 0x5cc0
movq -0x98(%rbp), %rdi
callq 0x5cf0
movq 0x8e9c(%rip), %rdi      # 0xdfd8
leaq 0x4169(%rip), %rsi      # 0x92ac
callq 0x2180
movq %rax, -0x90(%rbp)
jmp 0x5151
movq -0x90(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x2050
movq %rax, -0xa0(%rbp)
jmp 0x516a
movq -0xa0(%rbp), %rdi
leaq 0x4277(%rip), %rsi      # 0x93ef
callq 0x2180
movq %rax, -0xa8(%rbp)
jmp 0x5186
movq -0x58(%rbp), %rdi
addq $0x10, %rdi
callq 0x5c00
movq -0xa8(%rbp), %rdi
movq %rax, %rsi
callq 0x2050
movq %rax, -0xb0(%rbp)
jmp 0x51ab
movq -0xb0(%rbp), %rdi
movq 0x8e0f(%rip), %rsi      # 0xdfc8
callq 0x21c0
jmp 0x51c0
movq -0x58(%rbp), %rdi
addq $0x90, %rdi
callq 0x3d90
jmp 0x51d2
leaq -0x40(%rbp), %rdi
callq 0x5d60
jmp 0x51dd
leaq -0x40(%rbp), %rdi
callq 0x3180
jmp 0x4c9a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x3180
movq -0x48(%rbp), %rdi
callq 0x22c0
nopl (%rax)