// File: epfml[P]Bi-Sent2Vec/src/shmem_matrix.cc
// Function: fasttext::ShmemMatrix::load(std::istream&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, int)
std::shared_ptr<ShmemMatrix> ShmemMatrix::load(std::istream& in,
                                               const std::string& name,
                                               const int timeout_sec) {
  std::string init_name = name + ".init";

  int64_t m, n;
  in.read((char*)&m, sizeof(int64_t));
  in.read((char*)&n, sizeof(int64_t));
  size_t size = m * n * sizeof(real);

  // Create a shared memory segment to be initialized with the input matrix
  bool new_segment = true;
  int fd = shm_open(init_name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0444);
  if (fd == -1) {
    if (errno == EEXIST) {
      new_segment = false;
    } else {
      perror("ERROR ShmemMatrix::load: shm_open failed");
      exit(-1);
    }
  }

  if (new_segment) {
    // Set the size for shared memory segment
    int ret = ftruncate(fd, size);
    if (ret == -1) {
      perror("ERROR ShmemMatrix::load: ftruncate failed");
      exit(-1);
    }

    // Map the shared memory segment
    void* ptr = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
    if (ptr == (void*)-1) {
      perror("ERROR ShmemMatrix::load: mmap failed");
      exit(-1);
    }

    // Close the file descriptor
    ret = close(fd);
    if (ret == -1) {
      perror("ERROR ShmemMatrix::load: close failed");
      exit(-1);
    }

    // Populate the shared memory segment
    in.read((char*)ptr, size);

    // Unmap the shared memory segment
    ret = munmap(ptr, size);
    if (ret == -1) {
      perror("ERROR ShmemMatrix::load: munmap failed");
      exit(-1);
    }

    // Atomically link to the expected name
    std::string init_name_path = "/dev/shm/" + init_name;
    std::string name_path = "/dev/shm/" + name;
    ret = link(init_name_path.c_str(), name_path.c_str());
    if (ret == -1) {
      perror("ERROR ShmemMatrix::load: link failed");
      exit(-1);
    }
  } else {
    // Seek in the stream to skip the input matrix data
    in.seekg(size, in.cur);
  }

  return std::make_shared<ShmemMatrix>(name.c_str(), m, n, timeout_sec);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0xd8(%rbp)
movq %rdi, %rax
movq %rax, -0xd0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x18(%rbp), %rsi
leaq 0x2449f(%rip), %rdx     # 0x42f35
leaq -0x40(%rbp), %rdi
callq 0x1ed90
movq -0x10(%rbp), %rdi
leaq -0x48(%rbp), %rsi
movl $0x8, %edx
callq 0x5540
jmp 0x1eab3
movq -0x10(%rbp), %rdi
leaq -0x50(%rbp), %rsi
movl $0x8, %edx
callq 0x5540
jmp 0x1eac7
movq -0x48(%rbp), %rax
movq -0x50(%rbp), %rcx
imulq %rcx, %rax
shlq $0x2, %rax
movq %rax, -0x68(%rbp)
movb $0x1, -0x69(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x51c0
movq %rax, %rdi
movl $0xc2, %esi
movl $0x124, %edx            # imm = 0x124
callq 0x5730
movl %eax, -0xdc(%rbp)
jmp 0x1eb02
movl -0xdc(%rbp), %eax
movl %eax, -0x70(%rbp)
cmpl $-0x1, -0x70(%rbp)
jne 0x1eb4c
callq 0x5080
cmpl $0x11, (%rax)
jne 0x1eb32
movb $0x0, -0x69(%rbp)
jmp 0x1eb4a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x1ed74
leaq 0x24402(%rip), %rdi     # 0x42f3b
callq 0x53a0
jmp 0x1eb40
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x54f0
jmp 0x1eb4c
testb $0x1, -0x69(%rbp)
je 0x1ed14
movl -0x70(%rbp), %edi
movq -0x68(%rbp), %rsi
callq 0x55f0
movl %eax, -0x74(%rbp)
cmpl $-0x1, -0x74(%rbp)
jne 0x1eb83
leaq 0x243f2(%rip), %rdi     # 0x42f64
callq 0x53a0
jmp 0x1eb79
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x54f0
movq -0x68(%rbp), %rsi
movl -0x70(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x2, %edx
movl $0x1, %ecx
movq %r9, %rdi
callq 0x57c0
movq %rax, -0x80(%rbp)
movq $-0x1, %rax
cmpq %rax, -0x80(%rbp)
jne 0x1ebcb
leaq 0x243d4(%rip), %rdi     # 0x42f8e
callq 0x53a0
jmp 0x1ebc1
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x54f0
movl -0x70(%rbp), %edi
callq 0x5880
movl %eax, -0xe0(%rbp)
jmp 0x1ebdb
movl -0xe0(%rbp), %eax
movl %eax, -0x74(%rbp)
cmpl $-0x1, -0x74(%rbp)
jne 0x1ec02
leaq 0x243c2(%rip), %rdi     # 0x42fb3
callq 0x53a0
jmp 0x1ebf8
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x54f0
movq -0x10(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0x68(%rbp), %rdx
callq 0x5540
jmp 0x1ec15
movq -0x80(%rbp), %rdi
movq -0x68(%rbp), %rsi
callq 0x5270
movl %eax, -0x74(%rbp)
cmpl $-0x1, -0x74(%rbp)
jne 0x1ec43
leaq 0x243a7(%rip), %rdi     # 0x42fd9
callq 0x53a0
jmp 0x1ec39
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x54f0
leaq 0x243b6(%rip), %rsi     # 0x43000
leaq -0xa0(%rbp), %rdi
leaq -0x40(%rbp), %rdx
callq 0x1ee10
jmp 0x1ec5c
movq -0x18(%rbp), %rdx
leaq 0x24399(%rip), %rsi     # 0x43000
leaq -0xc0(%rbp), %rdi
callq 0x1ee10
jmp 0x1ec75
leaq -0xa0(%rbp), %rdi
callq 0x51c0
movq %rax, -0xe8(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x51c0
movq -0xe8(%rbp), %rdi
movq %rax, %rsi
callq 0x5160
movl %eax, -0x74(%rbp)
cmpl $-0x1, -0x74(%rbp)
jne 0x1ecec
leaq 0x24357(%rip), %rdi     # 0x4300a
callq 0x53a0
jmp 0x1ecba
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x54f0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x1ed06
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x58d8
jmp 0x1ed06
leaq -0xc0(%rbp), %rdi
callq 0x58d8
leaq -0xa0(%rbp), %rdi
callq 0x58d8
jmp 0x1ed2a
leaq -0xa0(%rbp), %rdi
callq 0x58d8
jmp 0x1ed74
movq -0x10(%rbp), %rdi
movq -0x68(%rbp), %rsi
movl $0x1, %edx
callq 0x55d0
jmp 0x1ed28
jmp 0x1ed2a
movq -0x18(%rbp), %rdi
callq 0x51c0
movq -0xd8(%rbp), %rdi
movq %rax, -0xc8(%rbp)
leaq -0xc8(%rbp), %rsi
leaq -0x48(%rbp), %rdx
leaq -0x50(%rbp), %rcx
leaq -0x1c(%rbp), %r8
callq 0x1ef20
jmp 0x1ed5b
leaq -0x40(%rbp), %rdi
callq 0x58d8
movq -0xd0(%rbp), %rax
addq $0xf0, %rsp
popq %rbp
retq
leaq -0x40(%rbp), %rdi
callq 0x58d8
movq -0x58(%rbp), %rdi
callq 0x57a0
nopw %cs:(%rax,%rax)