// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: blockingPopGenericCommand
void blockingPopGenericCommand(redisClient *c, int where) {
    robj *o;
    mstime_t timeout;
    int j;

    // 取出 timeout 参数
    if (getTimeoutFromObjectOrReply(c,c->argv[c->argc-1],&timeout,UNIT_SECONDS)
        != REDIS_OK) return;

    // 遍历所有列表键
    for (j = 1; j < c->argc-1; j++) {

        // 取出列表键
        o = lookupKeyWrite(c->db,c->argv[j]);

        // 有非空列表？
        if (o != NULL) {
            if (o->type != REDIS_LIST) {
                addReply(c,shared.wrongtypeerr);
                return;
            } else {
                // 非空列表
                if (listTypeLength(o) != 0) {
                    /* Non empty list, this is like a non normal [LR]POP. */
                    char *event = (where == REDIS_HEAD) ? "lpop" : "rpop";

                    // 弹出值
                    robj *value = listTypePop(o,where);

                    redisAssert(value != NULL);

                    // 回复客户端
                    addReplyMultiBulkLen(c,2);
                    // 回复弹出元素的列表
                    addReplyBulk(c,c->argv[j]);
                    // 回复弹出值
                    addReplyBulk(c,value);

                    decrRefCount(value);

                    notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,
                                        c->argv[j],c->db->id);

                    // 删除空列表
                    if (listTypeLength(o) == 0) {
                        dbDelete(c->db,c->argv[j]);
                        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",
                                            c->argv[j],c->db->id);
                    }

                    signalModifiedKey(c->db,c->argv[j]);

                    server.dirty++;

                    /* Replicate it as an [LR]POP instead of B[LR]POP. */
                    // 传播一个 [LR]POP 而不是 B[LR]POP
                    rewriteClientCommandVector(c,2,
                        (where == REDIS_HEAD) ? shared.lpop : shared.rpop,
                        c->argv[j]);
                    return;
                }
            }
        }
    }

    /* If we are inside a MULTI/EXEC and the list is empty the only thing
     * we can do is treating it as a timeout (even with timeout 0). */
    // 如果命令在一个事务中执行，那么为了不产生死等待
    // 服务器只能向客户端发送一个空回复
    if (c->flags & REDIS_MULTI) {
        addReply(c,shared.nullmultibulk);
        return;
    }

    /* If the list is empty or the key does not exists we must block */
    // 所有输入列表键都不存在，只能阻塞了
    blockForKeys(c, c->argv + 1, c->argc - 2, timeout, NULL);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movq -0x8(%rbp), %rcx
movl 0x30(%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rsi
leaq -0x20(%rbp), %rdx
xorl %ecx, %ecx
callq 0x81d90
cmpl $0x0, %eax
je 0x4a8d1
jmp 0x4ab63
movl $0x1, -0x24(%rbp)
movl -0x24(%rbp), %eax
movq -0x8(%rbp), %rcx
movl 0x30(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x4ab13
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x3c090
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x4ab03
movq -0x18(%rbp), %rax
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x1, %eax
je 0x4a940
movq -0x8(%rbp), %rdi
leaq 0xc981e(%rip), %rax     # 0x114150
movq 0x70(%rax), %rsi
callq 0x35a70
jmp 0x4ab63
movq -0x18(%rbp), %rdi
callq 0x480f0
cmpq $0x0, %rax
je 0x4aaff
movl -0xc(%rbp), %edx
leaq 0x939e5(%rip), %rax     # 0xde342
leaq 0x939f6(%rip), %rcx     # 0xde35a
cmpl $0x0, %edx
cmoveq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x47fa0
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x4a988
jmp 0x4a9aa
leaq 0x987d4(%rip), %rdi     # 0xe3163
leaq 0x9869b(%rip), %rsi     # 0xe3031
movl $0x5f8, %edx            # imm = 0x5F8
callq 0x63ca0
movl $0x1, %edi
callq 0x1f3b0
movq -0x8(%rbp), %rdi
movl $0x2, %esi
callq 0x364f0
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x36620
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x36620
movq -0x38(%rbp), %rdi
callq 0x3aaa0
movq -0x30(%rbp), %rsi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x30(%rax), %ecx
movl $0x10, %edi
callq 0x814a0
movq -0x18(%rbp), %rdi
callq 0x480f0
cmpq $0x0, %rax
jne 0x4aa68
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x3c4f0
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x30(%rax), %ecx
movl $0x4, %edi
leaq 0x93aa2(%rip), %rsi     # 0xde505
callq 0x814a0
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x3c3d0
leaq 0xc8e6c(%rip), %rax     # 0x1138f8
movq 0x560(%rax), %rcx
addq $0x1, %rcx
leaq 0xc8e5a(%rip), %rax     # 0x1138f8
movq %rcx, 0x560(%rax)
movq -0x8(%rbp), %rax
movq %rax, -0x40(%rbp)
cmpl $0x0, -0xc(%rbp)
jne 0x4aac7
leaq 0xc9696(%rip), %rax     # 0x114150
movq 0x138(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0x4aad9
leaq 0xc9682(%rip), %rax     # 0x114150
movq 0x130(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rdi
movq -0x48(%rbp), %rdx
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rcx
movl $0x2, %esi
movb $0x0, %al
callq 0x38860
jmp 0x4ab63
jmp 0x4ab01
jmp 0x4ab03
jmp 0x4ab05
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x4a8d8
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x4ab3b
movq -0x8(%rbp), %rdi
leaq 0xc9620(%rip), %rax     # 0x114150
movq 0x58(%rax), %rsi
callq 0x35a70
jmp 0x4ab63
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rsi
addq $0x8, %rsi
movq -0x8(%rbp), %rax
movl 0x30(%rax), %edx
subl $0x2, %edx
movq -0x20(%rbp), %rcx
xorl %eax, %eax
movl %eax, %r8d
callq 0x4a130
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax)