// File: cybozu[P]yrmcds/cybozu/tcp.cpp
// Function: cybozu::tcp_socket::write_pending_data(int)
bool tcp_socket::write_pending_data(int fd) {
    lock_guard g(m_lock);

    while( ! m_tmpbuf.empty() ) {
        ssize_t n = ::send(fd, m_tmpbuf.data(), m_tmpbuf.size(), 0);
        if( n == -1 ) {
            if( errno == EINTR ) continue;
            if( errno == EAGAIN || errno == EWOULDBLOCK ) return true;
            auto ecnd = std::system_category().default_error_condition(errno);
            if( ecnd.value() != EPIPE )
                logger::error() << "<tcp_socket::write_pending_data>: ("
                                << ecnd.value() << ") "
                                << ecnd.message();
            return false;
        }
        m_tmpbuf.erase(m_tmpbuf.begin(), m_tmpbuf.begin() + n);
    }
    m_tmpbuf.shrink_to_fit();

    while( ! m_pending.empty() ) {
        auto& t = m_pending.front();
        char* p;
        std::size_t len;
        std::size_t sent;
        std::tie(p, len, sent) = t;

        while( len != sent ) {
            ssize_t n = ::send(fd, p+sent, len-sent, 0);
            if( n == -1 ) {
                if( errno == EINTR ) continue;
                if( errno == EAGAIN || errno == EWOULDBLOCK ) break;
                auto ecnd = std::system_category().default_error_condition(errno);
                logger::error() << "<tcp_socket::write_pending_data>: ("
                                << ecnd.value() << ") "
                                << ecnd.message();
                return false;
            }
            sent += n;
        }
        if( len == sent ) {
            m_pending.erase(m_pending.begin());
            m_free_buffers.push_back(p);
        } else {
            std::get<2>(t) = sent;
            g.unlock();
            // notify other threads of the new free space
            m_cond_write.notify_all();
            return true;
        }
    }

    // all data have been sent.
    _flush(fd);

    if( ! m_shutdown ) {
        g.unlock();
        m_cond_write.notify_all();
        return true;
    }

    // invalidate and close this socket when m_shutdown==true.
    return false;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x200, %rsp            # imm = 0x200
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rsi
movq %rsi, -0x160(%rbp)
addq $0xa8, %rsi
leaq -0x28(%rbp), %rdi
callq 0x3cc10
movq -0x160(%rbp), %rdi
addq $0x88, %rdi
callq 0x3cdd0
xorb $-0x1, %al
testb $0x1, %al
jne 0x56a9b
jmp 0x56d12
movq -0x160(%rbp), %rdi
movl -0x14(%rbp), %eax
movl %eax, -0x174(%rbp)
addq $0x88, %rdi
movq %rdi, -0x180(%rbp)
callq 0x34be0
movq -0x180(%rbp), %rdi
movq %rax, -0x170(%rbp)
callq 0x34c00
movl -0x174(%rbp), %edi
movq -0x170(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x8310
movq %rax, -0x168(%rbp)
jmp 0x56af1
movq -0x168(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpq $-0x1, -0x30(%rbp)
jne 0x56c6b
callq 0x8050
cmpl $0x4, (%rax)
jne 0x56b27
jmp 0x56a7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x570af
callq 0x8050
cmpl $0xb, (%rax)
je 0x56b3b
callq 0x8050
cmpl $0xb, (%rax)
jne 0x56b4b
movb $0x1, -0x1(%rbp)
movl $0x1, -0x40(%rbp)
jmp 0x57098
callq 0x83a0
movq %rax, -0x188(%rbp)
callq 0x8050
movq -0x188(%rbp), %rdi
movl (%rax), %esi
movq (%rdi), %rax
callq *0x28(%rax)
movl %eax, -0x50(%rbp)
movq %rdx, -0x48(%rbp)
leaq -0x50(%rbp), %rdi
callq 0xe060
cmpl $0x20, %eax
je 0x56c5b
leaq -0x60(%rbp), %rdi
callq 0xa600
jmp 0x56b8f
leaq 0x25ff5(%rip), %rsi     # 0x7cb8b
leaq -0x60(%rbp), %rdi
callq 0x58200
movq %rax, -0x190(%rbp)
jmp 0x56ba8
leaq -0x50(%rbp), %rdi
callq 0xe060
movq -0x190(%rbp), %rdi
movl %eax, -0x64(%rbp)
leaq -0x64(%rbp), %rsi
callq 0xdff0
movq %rax, -0x198(%rbp)
jmp 0x56bcd
movq -0x198(%rbp), %rdi
leaq 0x23517(%rip), %rsi     # 0x7a0f2
callq 0xa6e0
movq %rax, -0x1a0(%rbp)
jmp 0x56be9
leaq -0x88(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0xdfa0
jmp 0x56bfb
movq -0x1a0(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0xa690
jmp 0x56c10
leaq -0x88(%rbp), %rdi
callq 0x83f0
leaq -0x60(%rbp), %rdi
callq 0xa770
jmp 0x56c5b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x56c4d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x83f0
leaq -0x60(%rbp), %rdi
callq 0xa770
jmp 0x570af
movb $0x0, -0x1(%rbp)
movl $0x1, -0x40(%rbp)
jmp 0x57098
movq -0x160(%rbp), %rdi
addq $0x88, %rdi
movq %rdi, -0x1b0(%rbp)
callq 0x582d0
movq %rax, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x58300
movq -0x1b0(%rbp), %rdi
callq 0x582d0
movq %rax, -0xb0(%rbp)
movq -0x30(%rbp), %rsi
leaq -0xb0(%rbp), %rdi
callq 0x58340
movq %rax, -0xa8(%rbp)
leaq -0xa0(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x58300
movq -0x1b0(%rbp), %rdi
movq -0x90(%rbp), %rsi
movq -0xa0(%rbp), %rdx
callq 0x58240
movq %rax, -0x1a8(%rbp)
jmp 0x56cff
movq -0x1a8(%rbp), %rax
movq %rax, -0xb8(%rbp)
jmp 0x56a7d
movq -0x160(%rbp), %rdi
addq $0x88, %rdi
callq 0x57d80
jmp 0x56d27
jmp 0x56d29
movq -0x160(%rbp), %rdi
addq $0x70, %rdi
callq 0x3cd90
xorb $-0x1, %al
testb $0x1, %al
jne 0x56d44
jmp 0x57041
movq -0x160(%rbp), %rdi
addq $0x70, %rdi
callq 0x58380
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
movq %rax, -0x1b8(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
leaq -0xd0(%rbp), %rdx
leaq -0xd8(%rbp), %rcx
callq 0x583b0
movq -0x1b8(%rbp), %rsi
leaq -0xf0(%rbp), %rdi
callq 0x583f0
movq -0xd0(%rbp), %rax
cmpq -0xd8(%rbp), %rax
je 0x56f67
movl -0x14(%rbp), %edi
movq -0xc8(%rbp), %rsi
movq -0xd8(%rbp), %rax
addq %rax, %rsi
movq -0xd0(%rbp), %rdx
subq %rax, %rdx
xorl %ecx, %ecx
callq 0x8310
movq %rax, -0x1c0(%rbp)
jmp 0x56ddf
movq -0x1c0(%rbp), %rax
movq %rax, -0xf8(%rbp)
cmpq $-0x1, -0xf8(%rbp)
jne 0x56f4d
callq 0x8050
cmpl $0x4, (%rax)
jne 0x56e07
jmp 0x56d9d
callq 0x8050
cmpl $0xb, (%rax)
je 0x56e1b
callq 0x8050
cmpl $0xb, (%rax)
jne 0x56e20
jmp 0x56f67
callq 0x83a0
movq %rax, -0x1c8(%rbp)
callq 0x8050
movq -0x1c8(%rbp), %rdi
movl (%rax), %esi
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
movl %eax, -0x108(%rbp)
movq %rdx, -0x100(%rbp)
leaq -0x118(%rbp), %rdi
callq 0xa600
jmp 0x56e5e
leaq 0x25d26(%rip), %rsi     # 0x7cb8b
leaq -0x118(%rbp), %rdi
callq 0x58200
movq %rax, -0x1d0(%rbp)
jmp 0x56e7a
leaq -0x108(%rbp), %rdi
callq 0xe060
movq -0x1d0(%rbp), %rdi
movl %eax, -0x11c(%rbp)
leaq -0x11c(%rbp), %rsi
callq 0xdff0
movq %rax, -0x1d8(%rbp)
jmp 0x56ea8
movq -0x1d8(%rbp), %rdi
leaq 0x2323c(%rip), %rsi     # 0x7a0f2
callq 0xa6e0
movq %rax, -0x1e0(%rbp)
jmp 0x56ec4
leaq -0x140(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0xdfa0
jmp 0x56ed9
movq -0x1e0(%rbp), %rdi
leaq -0x140(%rbp), %rsi
callq 0xa690
jmp 0x56eee
leaq -0x140(%rbp), %rdi
callq 0x83f0
leaq -0x118(%rbp), %rdi
callq 0xa770
movb $0x0, -0x1(%rbp)
movl $0x1, -0x40(%rbp)
jmp 0x57098
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x56f3c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x83f0
leaq -0x118(%rbp), %rdi
callq 0xa770
jmp 0x570af
movq -0xf8(%rbp), %rax
addq -0xd8(%rbp), %rax
movq %rax, -0xd8(%rbp)
jmp 0x56d9d
movq -0xd0(%rbp), %rax
cmpq -0xd8(%rbp), %rax
jne 0x56fed
movq -0x160(%rbp), %rdi
addq $0x70, %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x57bf0
movq %rax, -0x150(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0x584a0
movq -0x1f0(%rbp), %rdi
movq -0x148(%rbp), %rsi
callq 0x58430
movq %rax, -0x1e8(%rbp)
jmp 0x56fc4
movq -0x160(%rbp), %rdi
movq -0x1e8(%rbp), %rax
movq %rax, -0x158(%rbp)
addq $0x58, %rdi
leaq -0xc8(%rbp), %rsi
callq 0x57b80
jmp 0x56feb
jmp 0x5703c
movq -0xd8(%rbp), %rax
movq %rax, -0x1f8(%rbp)
movq -0xc0(%rbp), %rdi
callq 0x584e0
movq -0x1f8(%rbp), %rcx
movq %rcx, (%rax)
leaq -0x28(%rbp), %rdi
callq 0x3cfb0
jmp 0x5701c
movq -0x160(%rbp), %rdi
addq $0xd0, %rdi
callq 0x8b50
movb $0x1, -0x1(%rbp)
movl $0x1, -0x40(%rbp)
jmp 0x57098
jmp 0x56d29
movq -0x160(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x3cca0
jmp 0x57052
movq -0x160(%rbp), %rax
testb $0x1, 0xa0(%rax)
jne 0x5708d
leaq -0x28(%rbp), %rdi
callq 0x3cfb0
jmp 0x5706d
movq -0x160(%rbp), %rdi
addq $0xd0, %rdi
callq 0x8b50
movb $0x1, -0x1(%rbp)
movl $0x1, -0x40(%rbp)
jmp 0x57098
movb $0x0, -0x1(%rbp)
movl $0x1, -0x40(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x3ccf0
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x200, %rsp            # imm = 0x200
popq %rbp
retq
leaq -0x28(%rbp), %rdi
callq 0x3ccf0
movq -0x38(%rbp), %rdi
callq 0x8bc0
nopw %cs:(%rax,%rax)