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. ELF 文件 动态连接 - 延迟绑定(PLT)

    PLT 全称:Procedure Linkage Table ,直译:过程连接表 由于在动态连接中,程序的模块之间包含了大量的函数引用,所以在程序开始执行前,动态链接会耗费较多的时间用于模块之间函数引 ...

  2. 初步认识thymeleaf:简单表达式和标签(一)

    初步认识Thymeleaf:简单表达式和标签.(一)   本文只适用于不会Java对HTML语言有基础的程序员们,是浏览了各大博客后收集整理,重新编辑的一篇文章,希望能对大家有所帮助.最后本文如果有哪 ...

  3. 面向对象,更适合JavaScript

    面向对象程序设计是软件开发中一个很庞大很复杂的话题,它并不是仅仅学会类.继承.封装.多态这些面向对象编程语法元素就表示掌握的,这些语法元素只是实现面向对象程序的工具, 就像砖块.水泥能搭建小屋,也能造 ...

  4. Day11 数据库的基本语法(偏重于查询)

    数据库的介绍: 老师博客: MYSQL-1 - Yuan先生 - 博客园 http://www.cnblogs.com/yuanchenqi/articles/7269675.html 作业地址: h ...

  5. linux安装VLAN,系统怎么划分VLAN打标签上交换机

    前几天公司一台物理机需要连接公网,但是公网需要网卡打标签上去. 由于没有做过linux主机划分VLAN的操作,因此去查了一下,需要利用vconfig这个命令. 但是纠结的是,系统源中没有这个包.(很坑 ...

  6. Git忽略远程已存在的文件

    git设置本地忽略时远程上不存在本地忽略的文件,git将忽略.如果远程分支上存在这个文件,本地在设置ignore将不起作用.换句话说git本地忽略文件必须保证git的远程仓库分支上没有这个要忽略的文件 ...

  7. UE4笔记:利用Widget设计一个切换材质功能

    UE4引擎中的Widget蓝图是一个重要的工具,可用于场景中的页面叠加,镜头绑定,场景切换等多处地方,在这里笔者介绍一种利用控件蓝图和场景中物体进行信息交互的方法,直观的体现就是进行物体的材质切换. ...

  8. ArcCore重构-Makefile模块化

    基于官方arc-stable-9c57d86f66be,AUTOSAR版本3.1.5   基本问题 2. 编译系统中代码文件是否编译及目标文件集中定义在boards/board_common.mk,而 ...

  9. 初入thinkphp

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

  10. django自定义用户表

    django中已经给我生成默认的User表,其中的字段已经可以满足我们的日常需求. 但有时候,我们需要更多的字段,我们就可以自定义.来替换django自带的User表. #models.py from ...