// File: rachit31[P]CubeSatADCS/threadManager.cpp
// Function: ThreadManager::wait()
const char* ThreadManager::wait()
{
  std::stringstream message;

  // Join with terminated threads
  while (!m_threadMap.empty())
  {
    std::string error;

    // Lock the thread Mutex (TLPI pg 636)
    error = m_mutex.lock();
    if (!error.empty())
    {
      return error.c_str();
    }

    // Set the Conditional Variable to wait for a thread to die
    if (m_numUnjoined == 0)
    {
      error = m_mutex.wait();
      if (!error.empty())
      {
        return error.c_str();
      }
    }

    // Loop through the threads to find the dead ones
    std::vector<unsigned int> eraseVec;
    std::map<unsigned int, Thread*>::iterator it;
    for (it = m_threadMap.begin(); it != m_threadMap.end(); ++it)
    {
      if (!it->second->isAlive())
      {
        void* pthreadRetVal;

        // Join with terminated thread (TLPI pg 625)
        int retVal = pthread_join(it->second->getThread(), &pthreadRetVal);
        if (retVal != 0)
        {
          message << "pthread_join(): " << std::strerror(retVal);
          return message.str().c_str();
        }

        if (pthreadRetVal == PTHREAD_CANCELED)
        {
          message << "thread " << it->first << " was canceled" << std::endl;
        }
        else
        {
          message << "thread " << it->first << " joined successfully" << std::endl;
        }

        // Release the dynamically allocated memory
        delete it->second;

        // Add the map key to the delete vector
        eraseVec.push_back(it->first);

        // Decrement the number of unjoined threads
        m_numUnjoined--;
      }
    }

    std::vector<unsigned int>::iterator iter;
    for (iter = eraseVec.begin(); iter != eraseVec.end(); ++iter)
    {
      if (!m_threadMap.erase(*iter))
      {
        error = "could not remove thread from threadManager threadMap";
        return error.c_str();
      }
    }

    // Lock the thread Mutex (TLPI pg 636)
    error = m_mutex.unlock();
    if (!error.empty())
    {
      return error.c_str();
    }
  }

  return message.str().c_str();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2f0, %rsp            # imm = 0x2F0
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x268(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x3190
movq -0x268(%rbp), %rdi
addq $0x8, %rdi
callq 0x6f60
xorb $-0x1, %al
testb $0x1, %al
jne 0x63e1
jmp 0x6940
leaq -0x1b8(%rbp), %rdi
callq 0x3340
movq -0x268(%rbp), %rdi
addq $0x38, %rdi
callq 0x49e0
movq %rax, -0x270(%rbp)
jmp 0x6406
movq -0x270(%rbp), %rsi
leaq -0x1b8(%rbp), %rdi
callq 0x3330
jmp 0x641b
leaq -0x1b8(%rbp), %rdi
callq 0x33e0
testb $0x1, %al
jne 0x6461
leaq -0x1b8(%rbp), %rdi
callq 0x3100
movq %rax, -0x8(%rbp)
movl $0x1, -0x1c8(%rbp)
jmp 0x6915
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1c0(%rbp)
movl %eax, -0x1c4(%rbp)
jmp 0x6932
movq -0x268(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x64cc
movq -0x268(%rbp), %rdi
addq $0x38, %rdi
callq 0x4c80
movq %rax, -0x278(%rbp)
jmp 0x6486
movq -0x278(%rbp), %rsi
leaq -0x1b8(%rbp), %rdi
callq 0x3330
jmp 0x649b
leaq -0x1b8(%rbp), %rdi
callq 0x33e0
testb $0x1, %al
jne 0x64ca
leaq -0x1b8(%rbp), %rdi
callq 0x3100
movq %rax, -0x8(%rbp)
movl $0x1, -0x1c8(%rbp)
jmp 0x6915
jmp 0x64cc
leaq -0x1e0(%rbp), %rdi
callq 0x6f80
leaq -0x1e8(%rbp), %rdi
callq 0x6fa0
movq -0x268(%rbp), %rdi
addq $0x8, %rdi
callq 0x6c90
movq %rax, -0x1f0(%rbp)
movq -0x1f0(%rbp), %rax
movq %rax, -0x1e8(%rbp)
movq -0x268(%rbp), %rdi
addq $0x8, %rdi
callq 0x6cf0
movq %rax, -0x1f8(%rbp)
leaq -0x1e8(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x6cc0
testb $0x1, %al
jne 0x653c
jmp 0x67c2
leaq -0x1e8(%rbp), %rdi
callq 0x6d20
movq 0x8(%rax), %rdi
callq 0x9970
movb %al, -0x279(%rbp)
jmp 0x6559
movb -0x279(%rbp), %al
testb $0x1, %al
jne 0x67af
jmp 0x6569
leaq -0x1e8(%rbp), %rdi
callq 0x6d20
movq 0x8(%rax), %rdi
callq 0x9990
movq %rax, -0x288(%rbp)
jmp 0x6587
movq -0x288(%rbp), %rdi
leaq -0x200(%rbp), %rsi
callq 0x3240
movl %eax, -0x28c(%rbp)
jmp 0x65a2
movl -0x28c(%rbp), %eax
movl %eax, -0x204(%rbp)
cmpl $0x0, -0x204(%rbp)
je 0x6656
leaq -0x188(%rbp), %rdi
leaq 0x6d35(%rip), %rsi      # 0xd2fe
callq 0x3270
movq %rax, -0x298(%rbp)
jmp 0x65d7
movl -0x204(%rbp), %edi
callq 0x30d0
movq -0x298(%rbp), %rdi
movq %rax, %rsi
callq 0x3270
jmp 0x65f3
leaq -0x228(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0x3260
jmp 0x6608
leaq -0x228(%rbp), %rdi
callq 0x3100
movq %rax, -0x8(%rbp)
leaq -0x228(%rbp), %rdi
callq 0x3160
movl $0x1, -0x1c8(%rbp)
jmp 0x6909
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1c0(%rbp)
movl %eax, -0x1c4(%rbp)
leaq -0x1e0(%rbp), %rdi
callq 0x7160
jmp 0x6932
movq $-0x1, %rax
cmpq %rax, -0x200(%rbp)
jne 0x66d8
leaq -0x188(%rbp), %rdi
leaq 0x6c67(%rip), %rsi      # 0xd2db
callq 0x3270
movq %rax, -0x2a0(%rbp)
jmp 0x6682
leaq -0x1e8(%rbp), %rdi
callq 0x6d20
movq -0x2a0(%rbp), %rdi
movl (%rax), %esi
callq 0x3320
movq %rax, -0x2a8(%rbp)
jmp 0x66a5
movq -0x2a8(%rbp), %rdi
leaq 0x6c5c(%rip), %rsi      # 0xd30f
callq 0x3270
movq %rax, -0x2b0(%rbp)
jmp 0x66c1
movq -0x2b0(%rbp), %rdi
movq 0xb8f1(%rip), %rsi      # 0x11fc0
callq 0x32b0
jmp 0x66d6
jmp 0x674a
leaq -0x188(%rbp), %rdi
leaq 0x6bf5(%rip), %rsi      # 0xd2db
callq 0x3270
movq %rax, -0x2b8(%rbp)
jmp 0x66f4
leaq -0x1e8(%rbp), %rdi
callq 0x6d20
movq -0x2b8(%rbp), %rdi
movl (%rax), %esi
callq 0x3320
movq %rax, -0x2c0(%rbp)
jmp 0x6717
movq -0x2c0(%rbp), %rdi
leaq 0x6bf8(%rip), %rsi      # 0xd31d
callq 0x3270
movq %rax, -0x2c8(%rbp)
jmp 0x6733
movq -0x2c8(%rbp), %rdi
movq 0xb87f(%rip), %rsi      # 0x11fc0
callq 0x32b0
jmp 0x6748
jmp 0x674a
leaq -0x1e8(%rbp), %rdi
callq 0x6d20
movq 0x8(%rax), %rax
movq %rax, -0x2d0(%rbp)
cmpq $0x0, %rax
je 0x6784
movq -0x2d0(%rbp), %rdi
callq 0x9960
movq -0x2d0(%rbp), %rdi
movl $0x20, %esi
callq 0x3290
leaq -0x1e8(%rbp), %rdi
callq 0x6d20
movq %rax, %rsi
leaq -0x1e0(%rbp), %rdi
callq 0x6fc0
jmp 0x67a1
movq -0x268(%rbp), %rax
movl (%rax), %ecx
addl $-0x1, %ecx
movl %ecx, (%rax)
jmp 0x67b1
leaq -0x1e8(%rbp), %rdi
callq 0x6d40
jmp 0x6509
leaq -0x230(%rbp), %rdi
callq 0x7030
leaq -0x1e0(%rbp), %rdi
callq 0x7050
movq %rax, -0x238(%rbp)
movq -0x238(%rbp), %rax
movq %rax, -0x230(%rbp)
leaq -0x1e0(%rbp), %rdi
callq 0x70c0
movq %rax, -0x240(%rbp)
leaq -0x230(%rbp), %rdi
leaq -0x240(%rbp), %rsi
callq 0x7080
testb $0x1, %al
jne 0x681e
jmp 0x68a5
movq -0x268(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x2e0(%rbp)
leaq -0x230(%rbp), %rdi
callq 0x7120
movq -0x2e0(%rbp), %rdi
movq %rax, %rsi
callq 0x70f0
movq %rax, -0x2d8(%rbp)
jmp 0x6854
movq -0x2d8(%rbp), %rax
cmpq $0x0, %rax
jne 0x6892
leaq 0x6aca(%rip), %rsi      # 0xd332
leaq -0x1b8(%rbp), %rdi
callq 0x3330
jmp 0x6876
leaq -0x1b8(%rbp), %rdi
callq 0x3100
movq %rax, -0x8(%rbp)
movl $0x1, -0x1c8(%rbp)
jmp 0x6909
jmp 0x6894
leaq -0x230(%rbp), %rdi
callq 0x7140
jmp 0x67ef
movq -0x268(%rbp), %rdi
addq $0x38, %rdi
callq 0x4b30
movq %rax, -0x2e8(%rbp)
jmp 0x68be
movq -0x2e8(%rbp), %rsi
leaq -0x1b8(%rbp), %rdi
callq 0x3330
jmp 0x68d3
leaq -0x1b8(%rbp), %rdi
callq 0x33e0
testb $0x1, %al
jne 0x68ff
leaq -0x1b8(%rbp), %rdi
callq 0x3100
movq %rax, -0x8(%rbp)
movl $0x1, -0x1c8(%rbp)
jmp 0x6909
movl $0x0, -0x1c8(%rbp)
leaq -0x1e0(%rbp), %rdi
callq 0x7160
leaq -0x1b8(%rbp), %rdi
callq 0x3160
movl -0x1c8(%rbp), %eax
testl %eax, %eax
jne 0x6991
jmp 0x692d
jmp 0x63c6
leaq -0x1b8(%rbp), %rdi
callq 0x3160
jmp 0x69aa
leaq -0x260(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0x3260
jmp 0x6955
leaq -0x260(%rbp), %rdi
callq 0x3100
movq %rax, -0x8(%rbp)
leaq -0x260(%rbp), %rdi
callq 0x3160
movl $0x1, -0x1c8(%rbp)
jmp 0x6991
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1c0(%rbp)
movl %eax, -0x1c4(%rbp)
jmp 0x69aa
leaq -0x198(%rbp), %rdi
callq 0x31d0
movq -0x8(%rbp), %rax
addq $0x2f0, %rsp            # imm = 0x2F0
popq %rbp
retq
leaq -0x198(%rbp), %rdi
callq 0x31d0
movq -0x1c0(%rbp), %rdi
callq 0x3420
nopw %cs:(%rax,%rax)