diff options
author | Christian Pointner <equinox@anytun.org> | 2017-09-19 22:07:17 +0200 |
---|---|---|
committer | Christian Pointner <equinox@anytun.org> | 2017-09-19 22:07:17 +0200 |
commit | a798752efe899180ffa0958507101cc9c07e22ac (patch) | |
tree | 820a83a7d839fc17fc70c696dc0358ebdeb146cc /satp | |
parent | sequence window partially implemented (diff) |
properly intialize sequence window with top value
Diffstat (limited to 'satp')
-rw-r--r-- | satp/sequence-window.go | 37 | ||||
-rw-r--r-- | satp/sequence-window_test.go | 52 |
2 files changed, 54 insertions, 35 deletions
diff --git a/satp/sequence-window.go b/satp/sequence-window.go index 94a7b0b..4c53ee5 100644 --- a/satp/sequence-window.go +++ b/satp/sequence-window.go @@ -33,14 +33,13 @@ package satp import ( "errors" "sync" - "sync/atomic" ) type SequenceWindow struct { - size int - head uint64 - body []uint32 - mutex *sync.RWMutex + size int + head uint64 + body []uint32 + mtx *sync.RWMutex } func (w *SequenceWindow) Size() int { @@ -48,18 +47,18 @@ func (w *SequenceWindow) Size() int { } func (w *SequenceWindow) Top() uint32 { - if w.size > 0 { - w.mutex.RLock() - defer w.mutex.RUnlock() - } - v := atomic.LoadUint64(&w.head) - return uint32(v >> 32) + w.mtx.RLock() + defer w.mtx.RUnlock() + // return uint32(atomic.LoadUint64(&w.head) >> 32) + return uint32(w.head >> 32) } func (w *SequenceWindow) Check(sequenceNumber uint32) (bool, error) { if w.size <= 0 { return false, nil } + w.mtx.RLock() + defer w.mtx.RUnlock() // TODO: implement this return false, nil } @@ -68,25 +67,31 @@ func (w *SequenceWindow) CheckAndSet(sequenceNumber uint32) (bool, error) { if w.size <= 0 { return false, nil } + w.mtx.Lock() + defer w.mtx.Unlock() // TODO: implement this return false, nil } -func NewSequenceWindow(size int) (w *SequenceWindow, err error) { +func NewSequenceWindow(size int, top uint32) (w *SequenceWindow, err error) { if size < 0 { return nil, errors.New("invalid sequence window size") } - w = &SequenceWindow{size: size, head: 0} + w = &SequenceWindow{size: size, head: uint64(top) << 32, mtx: &sync.RWMutex{}} if w.size > 0 { - bodyLen := (w.size / 32) + bodyLen := w.size / 32 if (w.size % 32) != 0 { bodyLen++ } w.body = make([]uint32, bodyLen, bodyLen) + + remain := uint(top % 32) + for i := uint(0); i < remain; i++ { + w.head |= 1 << i + } for i := range w.body { - w.body[i] = 0 + w.body[i] = 0xFFFFFFFF } - w.mutex = &sync.RWMutex{} } return } diff --git a/satp/sequence-window_test.go b/satp/sequence-window_test.go index 4fc244a..2f38a23 100644 --- a/satp/sequence-window_test.go +++ b/satp/sequence-window_test.go @@ -37,23 +37,37 @@ import ( func TestSequenceWindowNew(t *testing.T) { testvectors := []struct { size int + top uint32 + head uint64 bodyLen int valid bool }{ - {-1, 0, false}, - {0, 0, true}, - {1, 1, true}, - {10, 1, true}, - {32, 1, true}, - {33, 2, true}, - {63, 2, true}, - {64, 2, true}, - {65, 3, true}, - {100, 4, true}, + {-1, 0, 0, 0, false}, + {0, 0, 0, 0, true}, + {1, 0, 0, 1, true}, + {10, 0, 0, 1, true}, + {10, 0x4, 0x40000000F, 1, true}, + {10, 0x12, 0x120003FFFF, 1, true}, + {32, 0, 0, 1, true}, + {32, 0x1F, 0x1F7FFFFFFF, 1, true}, + {32, 0x20, 0x2000000000, 1, true}, + {33, 0, 0, 2, true}, + {33, 1, 0x100000001, 2, true}, + {63, 0, 0, 2, true}, + {64, 0, 0, 2, true}, + {65, 0, 0, 3, true}, + {100, 0, 0, 4, true}, + {100, 0xFFFF0000, 0xFFFF000000000000, 4, true}, + {100, 0xFFFF0001, 0xFFFF000100000001, 4, true}, + {100, 0xFFFF0002, 0xFFFF000200000003, 4, true}, + {100, 0xFFFF0003, 0xFFFF000300000007, 4, true}, + {100, 0xFFFF0004, 0xFFFF00040000000F, 4, true}, + {100, 0xFFFF0005, 0xFFFF00050000001F, 4, true}, + {100, 0xAAAA5555, 0xAAAA5555001FFFFF, 4, true}, } for _, vector := range testvectors { - w, err := NewSequenceWindow(vector.size) + w, err := NewSequenceWindow(vector.size, vector.top) if vector.valid { if err != nil { t.Fatal("unexpected error:", err) @@ -61,28 +75,28 @@ func TestSequenceWindowNew(t *testing.T) { if w.Size() != vector.size { t.Fatalf("sequence-window has wrong size, is: %d, should be %d", w.Size(), vector.size) } - if w.Top() != 0 { - t.Fatalf("sequence-window(%d) top value not 0: 0x%08X", vector.size, w.Top()) + if w.Top() != vector.top { + t.Fatalf("sequence-window(%d/%d) top value invalid, is: 0x%08X, should be 0x%08X", vector.size, vector.top, w.Top(), vector.top) } - if w.head != 0 { - t.Fatalf("sequence-window(%d) head not 0: 0x%16X", vector.size, w.head) + if w.head != vector.head { + t.Fatalf("sequence-window(%d/%d) head invalid, is: 0x%016X, should be 0x%016X", vector.size, vector.top, w.head, vector.head) } bodyLen := len(w.body) if bodyLen != vector.bodyLen { - t.Fatalf("sequence-window(%d) body length has invalid length, is: %d, should be %d", vector.size, bodyLen, vector.bodyLen) + t.Fatalf("sequence-window(%d/%d) body length has invalid length, is: %d, should be %d", vector.size, vector.top, bodyLen, vector.bodyLen) } isEmpty := true for _, v := range w.body { - if v != 0 { + if v != 0xFFFFFFFF { isEmpty = false } } if !isEmpty { - t.Fatalf("sequence-window(%d) body not empty, is: %v", vector.size, w.body) + t.Fatalf("sequence-window(%d/%d) body not full, is: %v", vector.size, vector.top, w.body) } } else { if err == nil { - t.Fatalf("creating sequence-window(%d) should give an error", vector.size) + t.Fatalf("creating sequence-window(%d/%d) should give an error", vector.size, vector.top) } } } |