-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from guojun1992/main
add xslice
- Loading branch information
Showing
2 changed files
with
286 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
package xslice | ||
|
||
import ( | ||
"errors" | ||
"math" | ||
"sync" | ||
|
||
"github.com/heiyeluren/xds" | ||
) | ||
|
||
var InvalidType = errors.New("type Error") // 类型错误 | ||
|
||
type _gap []byte | ||
const _blockSize int = 8 | ||
|
||
type Xslice struct{ | ||
s [][_blockSize]_gap //[]*uintptr 改为[]数组。数组内存放基本类型结构体和指针。string的话,存放指针。 | ||
|
||
//s []uintptr uintptr地址指向一个连续内存(数组)的头。 | ||
// s 的创建和扩容,通过xmm的alloc(元素个数*8)。迁移完后销毁。 | ||
// s 中的元素创建:通过xmm的alloc(元素个数*元素单位长度)。append到s中。 | ||
// 基本类型存放:int、uint、直接放入到s的元素中。 | ||
// 非基本类型存放:string、[]byte,先拷贝内存到xmm中,然后,将指针append到s的元素中。 | ||
|
||
lock *sync.RWMutex | ||
|
||
sizeCtl int64 // -1 正在扩容 | ||
|
||
//游标位置 | ||
curRPos int //读光标 | ||
curWGapPos int //写gap光标 | ||
curWSlotPos int //写slot光标 | ||
|
||
_sizeof int //每个元素大小 | ||
_stype xds.Kind //类型 | ||
_len int //元素个数计数 | ||
|
||
_scap int //容量 | ||
} | ||
|
||
//func NewXslice(mm xmm.XMemory,_type Kind,_cap int) * Xslice { | ||
func NewXslice(_type xds.Kind,_cap int) *Xslice { | ||
|
||
//计算分配slot数量,有余数会多分配一个 | ||
slotCap := float64(_cap % _blockSize) | ||
var slotNum int64 = int64(math.Ceil(slotCap)) | ||
|
||
if slotNum <= 0{ | ||
slotNum = 1 | ||
} | ||
|
||
slot := make([][8]_gap,slotNum,slotNum) | ||
return &Xslice{ | ||
s: slot, | ||
lock: new(sync.RWMutex), | ||
_scap: _cap, | ||
_stype: _type, | ||
} | ||
} | ||
|
||
func(xs *Xslice) Append(v interface{}) (*Xslice,error) { | ||
xs.lock.Lock() | ||
defer xs.lock.Unlock() | ||
|
||
|
||
//判断类型:基本copy进去。 | ||
// s中将要存放的uintptr拿到,uintptr为一个起始地址,加上一个index偏移量为写入地址。 | ||
|
||
|
||
var gapPos int64 = 0 | ||
|
||
slotCap := float64(xs.curWGapPos % _blockSize) | ||
|
||
gapPos = int64(slotCap) | ||
// 没有空位,扩容 | ||
if slotCap == 0 && xs.curWGapPos >= _blockSize{ | ||
newSlot := [_blockSize]_gap{} | ||
xs.s = append(xs.s,newSlot) | ||
xs.curWSlotPos += 1 | ||
} | ||
|
||
b,err := xds.Marshal(xs._stype,v) | ||
if err != nil{ | ||
return xs,err | ||
} | ||
|
||
xs.s[xs.curWSlotPos][gapPos] = b | ||
|
||
xs.curWGapPos += 1 | ||
xs._len += 1 | ||
|
||
return xs,nil | ||
} | ||
|
||
func (xs *Xslice) Set(n int,v interface{}) error { | ||
xs.lock.Lock() | ||
defer xs.lock.Unlock() | ||
|
||
var gapPos int64 = 0 | ||
slotCap := float64(n % _blockSize) | ||
gapPos = int64(slotCap) | ||
|
||
// 没有空位,扩容 | ||
if slotCap == 0 && xs.curWGapPos >= _blockSize{ | ||
newSlot := [_blockSize]_gap{} | ||
xs.s = append(xs.s,newSlot) | ||
xs.curWSlotPos += 1 | ||
} | ||
|
||
b,err := xds.Marshal(xs._stype,v) | ||
if err != nil{ | ||
return err | ||
} | ||
|
||
xs.s[xs.curWSlotPos][gapPos] = b | ||
xs.curWGapPos += 1 | ||
xs._len += 1 | ||
|
||
return nil | ||
} | ||
|
||
func (xs *Xslice) Get(n int) (interface{}, error) { | ||
xs.lock.Lock() | ||
defer xs.lock.Unlock() | ||
|
||
var gapPos int64 = 0 | ||
slotCap := float64(n % _blockSize) | ||
gapPos = int64(slotCap) | ||
|
||
b := xs.s[xs.curWSlotPos][gapPos] | ||
v,err := xds.UnMarshal(xs._stype,b) | ||
if err != nil{ | ||
return nil,err | ||
} | ||
|
||
return v,nil | ||
} | ||
|
||
func (xs *Xslice) Free () { | ||
xs.lock.Lock() | ||
xs.curWGapPos = 0 | ||
xs.curRPos = 0 | ||
xs._scap = 0 | ||
xs._sizeof = 0 | ||
xs._len = 0 | ||
xs.curWSlotPos = 0 | ||
xs.s = nil | ||
xs.lock.Unlock() | ||
} | ||
|
||
func(xs *Xslice) ForEach(f func(i int, v []byte) error) error{ | ||
xs.lock.Lock() | ||
defer xs.lock.Unlock() | ||
|
||
var c int = 0 | ||
for i,gaps := range xs.s { | ||
for _, b := range gaps { | ||
//判断坐标是否到头 | ||
if xs.curWSlotPos == i && xs.curWGapPos == c{ | ||
return nil | ||
} | ||
c = c + 1 | ||
if err := f(c,b);err != nil{ | ||
return err | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
//返回xslice长度 | ||
func (xs *Xslice) Len() int { | ||
xs.lock.Lock() | ||
defer xs.lock.Unlock() | ||
return xs._len | ||
} | ||
|
||
//@todo 把扩容逻辑封装起来 | ||
func (xs *Xslice) increase() *Xslice { | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package xslice | ||
|
||
import ( | ||
"log" | ||
"testing" | ||
|
||
"github.com/heiyeluren/xds" | ||
|
||
) | ||
|
||
func TestNewXslice(t *testing.T) { | ||
xs := NewXslice(xds.String,10) | ||
log.Println(xs.s) | ||
} | ||
|
||
func TestXslice_Append(t *testing.T) { | ||
xs2 := NewXslice(xds.Int,1) | ||
log.Println(xs2.s) | ||
|
||
for i:=0;i<=30;i++ { | ||
xs2.Append(i) | ||
} | ||
|
||
log.Println(xs2.s) | ||
} | ||
|
||
func TestXslice_Set(t *testing.T) { | ||
xs3 := NewXslice(xds.Int,1) | ||
log.Println(xs3.s) | ||
|
||
err := xs3.Set(1,123) | ||
if err != nil{ | ||
panic(err) | ||
} | ||
|
||
log.Println(xs3.s) | ||
|
||
} | ||
|
||
func TestXslice_Get(t *testing.T) { | ||
xs4 := NewXslice(xds.Int,1) | ||
err := xs4.Set(1,123) | ||
if err != nil{ | ||
panic(err) | ||
} | ||
|
||
v,err := xs4.Get(1) | ||
|
||
if err !=nil{ | ||
panic(err) | ||
} | ||
|
||
log.Println(v) | ||
} | ||
|
||
func TestXslice_Free(t *testing.T) { | ||
xs5 := NewXslice(xds.Int,1) | ||
err := xs5.Set(1,123) | ||
if err != nil{ | ||
panic(err) | ||
} | ||
|
||
log.Println(xs5) | ||
|
||
xs5.Free() | ||
|
||
log.Println(xs5) | ||
} | ||
|
||
func TestXslice_ForEach(t *testing.T) { | ||
xs6 := NewXslice(xds.String,1) | ||
xs6.Append("aaaa") | ||
xs6.Append("bbb") | ||
xs6.Append("cccc") | ||
xs6.Append("cccc") | ||
xs6.Append("cccc") | ||
xs6.Append("cccc") | ||
xs6.Append("cccc") | ||
xs6.Append("cccc") | ||
xs6.Append("cccc") | ||
xs6.Append("eee") | ||
|
||
|
||
xs6.ForEach(func(i int, v []byte) error { | ||
log.Println("i: ",i, "v: ", string(v)) | ||
return nil | ||
}) | ||
} | ||
|
||
func TestXslice_Len(t *testing.T) { | ||
xs8 := NewXslice(xds.Int,1) | ||
log.Println(xs8.s) | ||
|
||
err := xs8.Set(1,123) | ||
if err != nil{ | ||
panic(err) | ||
} | ||
|
||
log.Println(xs8.s) | ||
xs8.Set(2,123) | ||
xs8.Set(3,123) | ||
|
||
log.Println("len: ",xs8.Len()) | ||
} |