// File: /workspace/github_cpp_makefile_star2_O1/cybozu[P]yrmcds/cybozu/tcp.cpp
// Function: cybozu::tcp_socket::_send(int, char const*, unsigned long, std::unique_lock<std::mutex>&)
bool tcp_socket::_send(int fd, const char* p, std::size_t len, lock_guard& g) {
    while( ! can_send(len) ) {
        on_buffer_full();
        m_cond_write.wait(g);
    }
    if( m_shutdown ) return false;

    if( m_pending.empty() ) {
        while( len > 0 ) {
            ssize_t n = ::send(fd, p, len, 0);
            if( n == -1 ) {
                if( errno == EAGAIN || errno == EWOULDBLOCK ) break;
                if( errno == EINTR ) continue;
                auto ecnd = std::system_category().default_error_condition(errno);
                if( ecnd.value() != EPIPE )
                    logger::error() << "<tcp_socket::_send>: ("
                                    << ecnd.value() << ") "
                                    << ecnd.message();
                return false;
            }
            p += n;
            len -= n;
        }
        if( len == 0 ) return true;
    }

    // put data in the pending request queue.
    if( capacity() < len ) {
        // here, m_pending.empty() and m_tmpbuf.empty() holds true.
        logger::debug() << "<tcp_socket::_send> buffering "
                        << len << " bytes data.";
        m_tmpbuf.resize(len);
        std::memcpy(m_tmpbuf.data(), p, len);
        return true;
    }

    if( ! m_pending.empty() ) {
        auto& t = m_pending.back();
        char* t_p;
        std::size_t t_len;
        std::tie(t_p, t_len, std::ignore) = t;
        std::size_t room = SENDBUF_SIZE - t_len;
        if( room > 0 ) {
            std::size_t to_write = std::min(room, len);
            std::memcpy(t_p + t_len, p, to_write);
            p += to_write;
            len -= to_write;
            std::get<1>(t) = t_len + to_write;
            if( len == 0 ) return true;
        }
    }

    while( len > 0 ) {
        char* t_p = m_free_buffers.back();
        m_free_buffers.pop_back();
        std::size_t to_write = std::min(len, SENDBUF_SIZE);
        std::memcpy(t_p, p, to_write);
        p += to_write;
        len -= to_write;
        m_pending.emplace_back(t_p, to_write, 0);
    }
    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %r8, %r12
movq %rcx, %rbx
movq %rdx, %r14
movl %esi, %ebp
movq %rdi, %r15
movq %rcx, %rsi
callq 0x21d46
testb %al, %al
jne 0x20872
leaq 0xd0(%r15), %r13
movq (%r15), %rax
movq %r15, %rdi
callq *0x38(%rax)
movq %r13, %rdi
movq %r12, %rsi
callq 0x7100
movq %r15, %rdi
movq %rbx, %rsi
callq 0x21d46
testb %al, %al
je 0x2084f
cmpb $0x0, 0xa0(%r15)
je 0x20883
xorl %eax, %eax
jmp 0x20ba3
movq 0x70(%r15), %rax
cmpq 0x78(%r15), %rax
jne 0x20a13
testq %rbx, %rbx
je 0x20a0a
movl $0x4, %eax
movl %eax, %eax
movq %rax, 0x50(%rsp)
leaq 0x15dd3(%rip), %r13     # 0x36680
movl $0x1, %eax
movl %eax, %eax
movq %rax, 0x40(%rsp)
movl %ebp, %edi
movq %r14, %rsi
movq %rbx, %rdx
xorl %ecx, %ecx
callq 0x7240
cmpq $-0x1, %rax
je 0x208ec
addq %rax, %r14
subq %rax, %rbx
xorl %eax, %eax
movl %eax, %eax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
testq %rbx, %rbx
jne 0x208b9
jmp 0x20a0a
callq 0x7040
movl (%rax), %r12d
cmpl $0xb, %r12d
je 0x2090f
cmpl $0x4, %r12d
jne 0x20916
movq 0x50(%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movl $0x5, %eax
jmp 0x208d6
callq 0x72e0
movq (%rax), %rcx
movq %rax, %rdi
movl %r12d, %esi
callq *0x28(%rcx)
movl %eax, %r12d
movl $0x1, %eax
cmpl $0x20, %r12d
je 0x208d6
movq %rdx, 0x48(%rsp)
leaq 0x26157(%rip), %rax     # 0x46a98
movl (%rax), %esi
notl %esi
shrl $0x1f, %esi
leaq 0x8(%rsp), %rdi
leaq 0x13872(%rip), %rdx     # 0x341c6
callq 0x9718
cmpb $0x1, 0x8(%rsp)
jne 0x20976
movq 0x10(%rsp), %rdi
movl $0x16, %edx
leaq 0x15e34(%rip), %rsi     # 0x367a5
callq 0x7580
cmpb $0x1, 0x8(%rsp)
jne 0x2098a
movq 0x10(%rsp), %rdi
movl %r12d, %esi
callq 0x7990
cmpb $0x1, 0x8(%rsp)
jne 0x209a7
movq 0x10(%rsp), %rdi
movl $0x2, %edx
leaq 0x13730(%rip), %rsi     # 0x340d2
callq 0x7580
movq 0x48(%rsp), %rsi
movq (%rsi), %rax
leaq 0x18(%rsp), %rdi
movl %r12d, %edx
callq *0x20(%rax)
cmpb $0x1, 0x8(%rsp)
jne 0x209d5
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rdx
callq 0x7580
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x209f1
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x7510
leaq 0x8(%rsp), %rdi
callq 0x8f94
movq 0x40(%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
testq %rbx, %rbx
je 0x20ba1
movq 0x60(%r15), %rcx
subq 0x58(%r15), %rcx
movq 0x70(%r15), %rax
shlq $0x11, %rcx
movq 0x78(%r15), %rdx
cmpq %rdx, %rax
je 0x20a37
subq -0x10(%rdx), %rcx
addq $0x100000, %rcx         # imm = 0x100000
cmpq %rbx, %rcx
jae 0x20ae4
leaq 0x26051(%rip), %rax     # 0x46a98
movl (%rax), %eax
xorl %esi, %esi
cmpl $0x3, %eax
setge %sil
leaq 0x137ee(%rip), %rdx     # 0x34247
leaq 0x18(%rsp), %r12
movq %r12, %rdi
callq 0x9718
cmpb $0x1, (%r12)
jne 0x20a83
movq 0x20(%rsp), %rdi
leaq 0x15d43(%rip), %rsi     # 0x367bc
movl $0x1e, %edx
callq 0x7580
cmpb $0x1, 0x18(%rsp)
jne 0x20a97
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x7330
cmpb $0x1, 0x18(%rsp)
jne 0x20ab4
movq 0x20(%rsp), %rdi
leaq 0x15d31(%rip), %rsi     # 0x367db
movl $0xc, %edx
callq 0x7580
leaq 0x18(%rsp), %rdi
callq 0x8f94
leaq 0x88(%r15), %rdi
movq %rbx, %rsi
callq 0x21d94
movq 0x88(%r15), %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x7410
jmp 0x20ba1
movq 0x78(%r15), %r13
cmpq %r13, %rax
je 0x20b34
movq -0x10(%r13), %rbp
cmpq $0x100000, %rbp         # imm = 0x100000
jne 0x20afe
xorl %eax, %eax
jmp 0x20b30
movl $0x100000, %r12d        # imm = 0x100000
subq %rbp, %r12
cmpq %r12, %rbx
cmovbq %rbx, %r12
movq -0x8(%r13), %rdi
addq %rbp, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x7410
addq %r12, %r14
addq %r12, %rbp
subq %r12, %rbx
movq %rbp, -0x10(%r13)
sete %al
testb %al, %al
jne 0x20ba3
movb $0x1, %al
testq %rbx, %rbx
je 0x20ba3
leaq 0x70(%r15), %r12
leaq 0x3c(%rsp), %r13
movq 0x60(%r15), %rax
movq -0x8(%rax), %rdi
addq $-0x8, %rax
movq %rdi, 0x18(%rsp)
movq %rax, 0x60(%r15)
movl $0x100000, %eax         # imm = 0x100000
cmpq %rax, %rbx
movl $0x100000, %edx         # imm = 0x100000
cmovbq %rbx, %rdx
movq %rdx, 0x8(%rsp)
movq %r14, %rsi
callq 0x7410
movq 0x8(%rsp), %rbp
addq %rbp, %r14
movl $0x0, 0x3c(%rsp)
movq %r12, %rdi
leaq 0x18(%rsp), %rsi
leaq 0x8(%rsp), %rdx
movq %r13, %rcx
callq 0x21dc0
subq %rbp, %rbx
jne 0x20b44
movb $0x1, %al
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x20bda
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x7510
jmp 0x20bda
jmp 0x20bd7
jmp 0x20bd7
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
jmp 0x20be9
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x8f94
movq %rbx, %rdi
callq 0x79b0