// File: lyqscmy[P]array_lock_free_queue/test.cpp
// Function: test_in_multithreads()
void test_in_multithreads() {
  ArrayLockFreeQueue<int, 31> q;

  constexpr int size = 200;
  std::atomic<int> pushsum(0);
  std::thread writer1([&]() {
    for (int i = 0; i < size; i += 2) {
      bool succed = false;
      while (succed != true) {
        succed = q.push(i);
      }
      std::atomic_fetch_add(&pushsum, i);
    }
  });

  std::thread writer2([&]() {
    for (int i = 1; i < size; i += 2) {
      bool succed = false;
      while (succed != true) {
        succed = q.push(i);
      }
      std::atomic_fetch_add(&pushsum, i);
    }
  });

  std::atomic<int> popsum(0);
  std::thread reader1([&]() {
    for (int i = 0; i < size / 2; i++) {
      int item = -1;
      bool succed = false;
      while (succed != true) {
        succed = q.pop(item);
      }
      std::atomic_fetch_add(&popsum, item);
      /* std::cout << item << "\n"; */
    }
  });

  std::thread reader2([&]() {
    for (int i = 0; i < size / 2; i++) {
      int item = -1;
      bool succed = false;
      while (succed != true) {
        succed = q.pop(item);
      }
      std::atomic_fetch_add(&popsum, item);
      /* std::cout << item << "\n"; */
    }
  });

  writer1.join();
  writer2.join();
  reader1.join();
  reader2.join();
  assert(pushsum.load() == (size - 1) * size / 2);
  assert(popsum.load() == (size - 1) * size / 2);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
leaq -0xd0(%rbp), %rdi
movq %rdi, -0x158(%rbp)
callq 0x2dd0
movq -0x158(%rbp), %rax
movl $0xc8, -0xd4(%rbp)
movl $0x0, -0xd8(%rbp)
movq %rax, -0xf0(%rbp)
leaq -0xd8(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x19e0
jmp 0x16c3
leaq -0xd0(%rbp), %rax
movq %rax, -0x118(%rbp)
leaq -0xd8(%rbp), %rax
movq %rax, -0x110(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0x1aa0
jmp 0x16f4
movl $0x0, -0x11c(%rbp)
leaq -0xd0(%rbp), %rax
movq %rax, -0x138(%rbp)
leaq -0x11c(%rbp), %rax
movq %rax, -0x130(%rbp)
leaq -0x128(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x1b60
jmp 0x172f
leaq -0xd0(%rbp), %rax
movq %rax, -0x150(%rbp)
leaq -0x11c(%rbp), %rax
movq %rax, -0x148(%rbp)
leaq -0x140(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0x1c20
jmp 0x1760
leaq -0xe0(%rbp), %rdi
callq 0x10d0
jmp 0x176e
leaq -0x108(%rbp), %rdi
callq 0x10d0
jmp 0x177c
leaq -0x128(%rbp), %rdi
callq 0x10d0
jmp 0x178a
leaq -0x140(%rbp), %rdi
callq 0x10d0
jmp 0x1798
leaq -0xd8(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x5, -0xc(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x168(%rbp)
movl -0xc(%rbp), %edi
movl $0xffff, %esi           # imm = 0xFFFF
callq 0x2fa0
movl %eax, -0x10(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x15c(%rbp)
decl %eax
subl $0x2, %eax
jb 0x17f2
jmp 0x17d7
movl -0x15c(%rbp), %eax
subl $0x5, %eax
je 0x1800
jmp 0x17e4
movq -0x168(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x14(%rbp)
jmp 0x180c
movq -0x168(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x14(%rbp)
jmp 0x180c
movq -0x168(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x14(%rbp)
cmpl $0x4dbc, -0x14(%rbp)    # imm = 0x4DBC
jne 0x181a
jmp 0x18b8
leaq 0x291c(%rip), %rdi      # 0x413d
leaq 0x2816(%rip), %rsi      # 0x403e
movl $0x6a, %edx
leaq 0x2931(%rip), %rcx      # 0x4165
callq 0x1060
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x19bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x19b3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x19a7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
jmp 0x199b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x2e30
jmp 0x199b
leaq -0x11c(%rbp), %rax
movq %rax, -0x20(%rbp)
movl $0x5, -0x24(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x178(%rbp)
movl -0x24(%rbp), %edi
movl $0xffff, %esi           # imm = 0xFFFF
callq 0x2fa0
movl %eax, -0x28(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x16c(%rbp)
decl %eax
subl $0x2, %eax
jb 0x1912
jmp 0x18f7
movl -0x16c(%rbp), %eax
subl $0x5, %eax
je 0x1920
jmp 0x1904
movq -0x178(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
jmp 0x192c
movq -0x178(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
jmp 0x192c
movq -0x178(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
cmpl $0x4dbc, -0x2c(%rbp)    # imm = 0x4DBC
jne 0x1937
jmp 0x1956
leaq 0x2843(%rip), %rdi      # 0x4181
leaq 0x26f9(%rip), %rsi      # 0x403e
movl $0x6b, %edx
leaq 0x2814(%rip), %rcx      # 0x4165
callq 0x1060
leaq -0x140(%rbp), %rdi
callq 0x2e30
leaq -0x128(%rbp), %rdi
callq 0x2e30
leaq -0x108(%rbp), %rdi
callq 0x2e30
leaq -0xe0(%rbp), %rdi
callq 0x2e30
leaq -0xd0(%rbp), %rdi
callq 0x2e60
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
leaq -0x128(%rbp), %rdi
callq 0x2e30
leaq -0x108(%rbp), %rdi
callq 0x2e30
leaq -0xe0(%rbp), %rdi
callq 0x2e30
leaq -0xd0(%rbp), %rdi
callq 0x2e60
movq -0xf8(%rbp), %rdi
callq 0x10e0
nopw (%rax,%rax)