package nsqd

type inFlightPqueue []*Message

func newInFlightPqueue(capacity int) inFlightPqueue {
    return make(inFlightPqueue, 0, capacity)
}

func (pq inFlightPqueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *inFlightPqueue) Push(x *Message) {
    n := len(*pq)
    c := cap(*pq)
    if n+1 > c {
        npq := make(inFlightPqueue, n, c*2)
        copy(npq, *pq)
        *pq = npq
    }
    *pq = (*pq)[0 : n+1]
    x.index = n
    (*pq)[n] = x
    pq.up(n)
}

func (pq *inFlightPqueue) Pop() *Message {
    n := len(*pq)
    c := cap(*pq)
    pq.Swap(0, n-1)
    pq.down(0, n-1)
    if n < (c/2) && c > 25 {
        npq := make(inFlightPqueue, n, c/2)
        copy(npq, *pq)
        *pq = npq
    }
    x := (*pq)[n-1]
    x.index = -1
    *pq = (*pq)[0 : n-1]
    return x
}

func (pq *inFlightPqueue) Remove(i int) *Message {
    n := len(*pq)
    if n-1 != i {
        pq.Swap(i, n-1)
        pq.down(i, n-1)
        pq.up(i)
    }
    x := (*pq)[n-1]
    x.index = -1
    *pq = (*pq)[0 : n-1]
    return x
}

func (pq *inFlightPqueue) PeekAndShift(max int64) (*Message, int64) {
    if len(*pq) == 0 {
        return nil, 0
    }

    x := (*pq)[0]
    if x.pri > max {
        return nil, x.pri - max
    }
    pq.Pop()

    return x, 0
}

func (pq *inFlightPqueue) up(j int) {
    for {
        i := (j - 1) / 2 // parent
        if i == j || (*pq)[j].pri >= (*pq)[i].pri {
            break
        }
        pq.Swap(i, j)
        j = i
    }
}

func (pq *inFlightPqueue) down(i, n int) {
    for {
        j1 := 2*i + 1
        if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
            break
        }
        j := j1 // left child
        if j2 := j1 + 1; j2 < n && (*pq)[j1].pri >= (*pq)[j2].pri {
            j = j2 // = 2*i + 2  // right child
        }
        if (*pq)[j].pri >= (*pq)[i].pri {
            break
        }
        pq.Swap(i, j)
        i = j
    }
}

in_flight_pqueue.go的更多相关文章

  1. nsq源码阅读笔记之nsqd(四)——Channel

    与Channel相关的代码主要位于nsqd/channel.go, nsqd/nsqd.go中. Channel与Topic的关系 Channel是消费者订阅特定Topic的一种抽象.对于发往Topi ...

随机推荐

  1. ethtool确定网卡对应的物理网口

    在配置有多个网络接口的设备时我们会犯难,eth0.eth1.--到底是那个接口? 我使用的机器是CentOS系统,打开终端,输入ethtool –help 显示帮助信息,下面我就简要介绍一下最常用的两 ...

  2. day08_Servlet学习笔记

     ============================================================ 一.什么是Servlet?(非常非常重要) servlet 是运行在 Web ...

  3. JVM学习--(一)基本原理

    前言 JVM一直是java知识里面进阶阶段的重要部分,如果希望在java领域研究的更深入,则JVM则是如论如何也避开不了的话题,本系列试图通过简洁易读的方式,讲解JVM必要的知识点. 运行流程 我们都 ...

  4. 关于MySQL 5.6.24 解压缩版重启电脑后,无法启动的问题

    最近的项目需要用到mysql,想起以前安装过,就得应该没啥问题.也不知道是软件更新换代的问题,还是版权问题,网上找的msi版本的mysql都很难安装,一开始要安装.NET,我忍了,然后又要安装Visu ...

  5. python---生成器、迭代器

    # -*- coding:utf-8 -*- # LC # 列表生成式 def func(x): print(x) return 2*x print([ func(i) for i in range( ...

  6. Ubuntu 18.04 启动root账号并授权远程登录

    Ubuntu 18.04 刚刚上市2个月,下载安装,尝尝鲜~ 安装界面看上去舒服许多, 安装的速度也较之前17.04 和16.04 都快了许多.抱歉,未截图. Ubuntu 安装完成后默认不启动roo ...

  7. Node笔记三

    global --类似与客户端javascript运行环境中的window process --用于获取当前node进程信息,一般用于获取环境变量之类的信息 console --node中内置的con ...

  8. Html5的表单元素

    表单是HTML中获取用户输入的手段,,对于web应用系统及其重要,文字是不能说明问题的: 直接上代码把: <!DOCTYPE html><html lang="en&quo ...

  9. 初入thinkphp

    花3天时间入门了php和thinkphp框架,紧接着就做了一个小后台,简单使用了thinkphp框架封装的一些类和函数. 现在来总结一下:             //登陆函数 public func ...

  10. Oracle数据库逻辑迁移之数据泵的注意事项

    环境:数据迁移,版本 11.2.0.4 -> 12.2.0.1 思考: 对于DBA而言,常用物理方式的迁移,物理迁移的优势不必多说,使用这种方式不必担心对象前后不一致的情况,而这往往也解决了不懂 ...