// File: walaj[P]pthread-lite/example.cpp
// Function: main
int main() {	

  // create the work item queue and consumer threads    	   	
  WorkQueue<MyWorkItem*>  queue; // queue of work items to be processed by threads
  std::vector<ConsumerThread<MyWorkItem, MyThreadItem>* > threadqueue;

  // add 1000 work jobs to the WorkQueue
  for (int i = 0; i < 5000; ++i) {

    // establish some chunk of data...
    const size_t len = 5000;
    char * data = (char*)malloc(len + 1); 
    for (size_t j = 0; j < len; ++j)
      data[j] = 'a';
    data[len] = '\0';

    // add to work item and then to queue for processing
    // must be on heap, since dealloc is done inside ConsumerThread
    MyWorkItem * wu = new MyWorkItem(data, len);
    queue.add(wu);    
  } 

  // establish and start the threads
  size_t num_cores = 2;
  for (int i = 0; i < num_cores; ++i) {
    MyThreadItem * tu  = new MyThreadItem(i);  // create the thread-specific data, must be on heap.
    ConsumerThread<MyWorkItem, MyThreadItem>* threadr =        // establish new thread to draw from queue
      new ConsumerThread<MyWorkItem, MyThreadItem>(queue, tu); // always takes WorkQueue and some thread item
    threadr->start(); 
    threadqueue.push_back(threadr); // add thread to the threadqueue
  }

  // wait for the threads to finish
  for (int i = 0; i < num_cores; ++i) 
    threadqueue[i]->join();

  // display the results
  for (int i = 0; i < num_cores; ++i) {
    const MyThreadItem * td = threadqueue[i]->GetThreadData();
    std::cerr << "thread " << td->id << " results " << td->hit_counts << std::endl;
  }
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x140, %rsp            # imm = 0x140
movl $0x0, -0x4(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x2730
leaq -0x90(%rbp), %rdi
callq 0x2780
movl $0x0, -0x94(%rbp)
cmpl $0x1388, -0x94(%rbp)    # imm = 0x1388
jge 0x247b
movq $0x1388, -0xa0(%rbp) # imm = 0x1388
movl $0x1389, %edi           # imm = 0x1389
callq 0x2150
movq %rax, -0xa8(%rbp)
movq $0x0, -0xb0(%rbp)
cmpq $0x1388, -0xb0(%rbp) # imm = 0x1388
jae 0x23cb
movq -0xa8(%rbp), %rax
movq -0xb0(%rbp), %rcx
movb $0x61, (%rax,%rcx)
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb0(%rbp)
jmp 0x2398
movq -0xa8(%rbp), %rax
movb $0x0, 0x1388(%rax)
movl $0x10, %edi
callq 0x20f0
movq %rax, -0x100(%rbp)
jmp 0x23ec
movq -0x100(%rbp), %rdi
movq -0xa8(%rbp), %rsi
movl $0x1388, %edx           # imm = 0x1388
callq 0x27a0
jmp 0x2406
movq -0x100(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rsi
leaq -0x78(%rbp), %rdi
callq 0x27d0
jmp 0x2426
jmp 0x2428
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x2361
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0x2701
movq -0x100(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
movl $0x10, %esi
callq 0x2100
jmp 0x2701
movq $0x2, -0xd0(%rbp)
movl $0x0, -0xd4(%rbp)
movslq -0xd4(%rbp), %rax
cmpq -0xd0(%rbp), %rax
jae 0x259d
movl $0x10, %edi
callq 0x20f0
movq %rax, -0x108(%rbp)
jmp 0x24b7
movq -0x108(%rbp), %rdi
movslq -0xd4(%rbp), %rsi
callq 0x2820
jmp 0x24cc
movq -0x108(%rbp), %rax
movq %rax, -0xe0(%rbp)
movl $0x28, %edi
callq 0x20f0
movq %rax, -0x110(%rbp)
jmp 0x24ed
movq -0x110(%rbp), %rdi
movq -0xe0(%rbp), %rdx
leaq -0x78(%rbp), %rsi
callq 0x2850
jmp 0x2506
movq -0x110(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rdi
callq 0x28a0
jmp 0x2522
leaq -0x90(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x28f0
jmp 0x2537
jmp 0x2539
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x2490
movq -0x108(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
movl $0x10, %esi
callq 0x2100
jmp 0x2701
movq -0x110(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
movl $0x28, %esi
callq 0x2100
jmp 0x2701
movl $0x0, -0xec(%rbp)
movslq -0xec(%rbp), %rax
cmpq -0xd0(%rbp), %rax
jae 0x25e7
movslq -0xec(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x2960
movq (%rax), %rdi
callq 0x2980
jmp 0x25d4
jmp 0x25d6
movl -0xec(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xec(%rbp)
jmp 0x25a7
movl $0x0, -0xf0(%rbp)
movslq -0xf0(%rbp), %rax
cmpq -0xd0(%rbp), %rax
jae 0x26d9
movslq -0xf0(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x2960
movq (%rax), %rdi
callq 0x29e0
movq %rax, -0x118(%rbp)
jmp 0x2629
movq -0x118(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq 0x49b2(%rip), %rdi      # 0x6ff0
leaq 0x19bf(%rip), %rsi      # 0x4004
callq 0x20e0
movq %rax, -0x120(%rbp)
jmp 0x2653
movq -0x120(%rbp), %rdi
movq -0xf8(%rbp), %rax
movq (%rax), %rsi
callq 0x2050
movq %rax, -0x128(%rbp)
jmp 0x2672
movq -0x128(%rbp), %rdi
leaq 0x198c(%rip), %rsi      # 0x400c
callq 0x20e0
movq %rax, -0x130(%rbp)
jmp 0x268e
movq -0x130(%rbp), %rdi
movq -0xf8(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x2050
movq %rax, -0x138(%rbp)
jmp 0x26ae
movq -0x138(%rbp), %rdi
movq 0x490c(%rip), %rsi      # 0x6fc8
callq 0x2110
jmp 0x26c3
jmp 0x26c5
movl -0xf0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf0(%rbp)
jmp 0x25f1
movl $0x0, -0x4(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x2a00
leaq -0x78(%rbp), %rdi
callq 0x2a60
movl -0x4(%rbp), %eax
addq $0x140, %rsp            # imm = 0x140
popq %rbp
retq
leaq -0x90(%rbp), %rdi
callq 0x2a00
leaq -0x78(%rbp), %rdi
callq 0x2a60
movq -0xc0(%rbp), %rdi
callq 0x21c0
nopw %cs:(%rax,%rax)
nopl (%rax)