<?php
class Que {
//队列最大值
protected $m = 10;
//头指针
protected $h = 0;
//尾脂针
protected $t = 0;
//是否安全
protected $isSave = false;
function __construct($isSave = false)
{
$this->isSave = $isSave;
$this->arr = array_fill(0, $this->m, null);
}
/**
* $n >= -100
* 满返回-999
* 不满返回入队列后队列元素的数目
*
*/
function in($n){
if($this->isSave){
static::lock('in');
}
if($n < -100){
throw new \Exception("数据异常", 1);
}
if( !$this->canIn() ){
return -999;
}
$this->t = $this->newInOffset();
$this->arr[$this->t] = $n;
return $this->getLength();
}
/**
* 空返回-999
* 非空返回出队列的值
*/
function out(){
if($this->isSave){
static::lock('out');
}
if(!$this->canOut()){
return -999;
}
$n = $this->arr[$this->h];
unset($this->arr[$this->h]);
$this->arr[$this->h] = null;
$this->h = $this->newOutOffest();
return $n;
}
/**
*获取数组长度
*/
function getLength(){
if($this->isEmpty()) return 0;
if($this->t < $this->h){
$l = $this->m - $this->h + $this->t;
}else{
$l = $this->t - $this->h;
}
return $l + 1;
}
/**
* 判断数组是否为空数组
*/
function isEmpty(){
return $this->h == $this->t && is_null($this->arr[$this->h]);
}
/**
*获取入队后的尾指诊偏移量
*/
function newInOffset(){
if( $this->isEmpty() ){//是否是空队列
return $this->t;
}
return ($this->t + 1) % $this->m;
}
/**
*判断出队后头指诊的偏移量
*/
function newOutOffest(){
if(!$this->isEmpty() && $this->h == $this->t){
return $this->h;
}
return ($this->h + 1) % $this->m;
}
/**
*能否入队
*/
function canIn(){
return is_null($this->arr[$this->newInOffset()]);
}
/**
*能否出队
*/
function canOut(){
return !is_null($this->arr[$this->h]);
}
/**
*获取队列内容
*/
function getQueList(){
return $this->arr;
}
/**
*加锁
*/
public static function lock($name, $ex = 60)
{
if ($res = Redis::setnx($name, '1', 'NX')) {
Redis::expire($name, $ex);
register_shutdown_function(function () use ($name) {
Que::unlock($name);
});
} else {
throw new \Exception('执行中,请稍等');
}
}
/**
* 解锁
*/
public static function unlock($name)
{
Redis::del($name);
}
}
/**
$q = new Que;
for($i = 0; $i < 20; $i++){
$r = $q->in($i);
var_dump($r);
if($i % 3 == 0){
var_dump("out : ".$q->out());
}
}
for($i = 0; $i < 20; $i++){
var_dump("out : ".$q->out());
}
**/