// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: blockForKeys
void blockForKeys(redisClient *c, robj **keys, int numkeys, mstime_t timeout, robj *target) {
    dictEntry *de;
    list *l;
    int j;

    // 设置阻塞状态的超时和目标选项
    c->bpop.timeout = timeout;

    // target 在执行 RPOPLPUSH 命令时使用
    c->bpop.target = target;

    if (target != NULL) incrRefCount(target);

    // 关联阻塞客户端和键的相关信息
    for (j = 0; j < numkeys; j++) {

        /* If the key already exists in the dict ignore it. */
        // c->bpop.keys 是一个集合（值为 NULL 的字典）
        // 它记录所有造成客户端阻塞的键
        // 以下语句在键不存在于集合的时候，将它添加到集合
        if (dictAdd(c->bpop.keys,keys[j],NULL) != DICT_OK) continue;

        incrRefCount(keys[j]);

        /* And in the other "side", to map keys -> clients */
        // c->db->blocking_keys 字典的键为造成客户端阻塞的键
        // 而值则是一个链表，链表中包含了所有被阻塞的客户端
        // 以下程序将阻塞键和被阻塞客户端关联起来
        de = dictFind(c->db->blocking_keys,keys[j]);
        if (de == NULL) {
            // 链表不存在，新创建一个，并将它关联到字典中
            int retval;

            /* For every key we take a list of clients blocked for it */
            l = listCreate();
            retval = dictAdd(c->db->blocking_keys,keys[j],l);
            incrRefCount(keys[j]);
            redisAssertWithInfo(c,keys[j],retval == DICT_OK);
        } else {
            l = dictGetVal(de);
        }
        // 将客户端填接到被阻塞客户端的链表中
        listAddNodeTail(l,c);
    }
    blockClient(c,REDIS_BLOCKED_LIST);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x20(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x120(%rax)
movq -0x28(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x130(%rax)
cmpq $0x0, -0x28(%rbp)
je 0x4a179
movq -0x28(%rbp), %rdi
callq 0x3a3f0
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x4a291
movq -0x8(%rbp), %rax
movq 0x128(%rax), %rdi
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x236d0
cmpl $0x0, %eax
je 0x4a1b6
jmp 0x4a283
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x3a3f0
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x10(%rax), %rdi
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x23aa0
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x4a26a
callq 0x1fdb0
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x10(%rax), %rdi
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movq -0x38(%rbp), %rdx
callq 0x236d0
movl %eax, -0x40(%rbp)
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x3a3f0
cmpl $0x0, -0x40(%rbp)
jne 0x4a235
jmp 0x4a268
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x986d6(%rip), %rdx     # 0xe2922
leaq 0x98dde(%rip), %rcx     # 0xe3031
movl $0x498, %r8d            # imm = 0x498
callq 0x648b0
movl $0x1, %edi
callq 0x1f3b0
jmp 0x4a276
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
movq -0x8(%rbp), %rsi
callq 0x1ff90
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x4a180
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0x81e30
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)