Skip to content

Instantly share code, notes, and snippets.

@ravlio
Last active August 15, 2019 14:37
Show Gist options
  • Select an option

  • Save ravlio/296032849c6881ec757c9d3670128a68 to your computer and use it in GitHub Desktop.

Select an option

Save ravlio/296032849c6881ec757c9d3670128a68 to your computer and use it in GitHub Desktop.

Revisions

  1. ravlio revised this gist Aug 15, 2019. 2 changed files with 23 additions and 7 deletions.
    26 changes: 19 additions & 7 deletions rr_item_test.go
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,19 @@
    package rr_item_test

    /*
    Example of round robin with elements of arbitrary types based of interface method `Value() interface{}` and also with Stringer.
    */

    import (
    "github.com/stretchr/testify/require"
    "strconv"
    "sync"
    "testing"
    )

    type Item interface {
    Value() interface{}
    String() string
    }

    type Int int
    @@ -19,12 +22,20 @@ func (i Int) Value() interface{} {
    return i
    }

    func (i Int) String() string {
    return strconv.Itoa(int(i))
    }

    type String string

    func (i String) Value() interface{} {
    return i
    }

    func (i String) String() string {
    return string(i)
    }

    type Roundrobin struct {
    cur int // current elem position
    obj []Item // elements slice
    @@ -67,10 +78,11 @@ func TestRR(t *testing.T) {

    rr.Add(Int(4), Int(5), String("6"))

    require.Equal(t, Int(2), rr.Next())
    require.Equal(t, String("3"), rr.Next())
    require.Equal(t, Int(4), rr.Next())
    require.Equal(t, Int(5), rr.Next())
    require.Equal(t, String("6"), rr.Next())
    require.Equal(t, Int(1), rr.Next())
    require.Equal(t, "2", rr.Next().String())
    require.Equal(t, "3", rr.Next().String())
    require.Equal(t, "4", rr.Next().String())
    require.Equal(t, "5", rr.Next().String())
    require.Equal(t, "6", rr.Next().String())
    require.Equal(t, "1", rr.Next().String())
    }

    4 changes: 4 additions & 0 deletions rr_test.go
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,9 @@
    package rr_test

    /*
    Пример раунд робина с элементами конкретного типа int
    */

    import (
    "github.com/stretchr/testify/require"
    "math/rand"
  2. ravlio revised this gist Aug 15, 2019. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion rr_item_test.go
    Original file line number Diff line number Diff line change
    @@ -1,12 +1,14 @@
    package rr_item_test

    /*
    */
    import (
    "github.com/stretchr/testify/require"
    "sync"
    "testing"
    )

    /*
    type Item interface {
    Value() interface{}
    }
  3. ravlio revised this gist Aug 15, 2019. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion rr_item_test.go
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,12 @@
    package main
    package rr_item_test

    import (
    "github.com/stretchr/testify/require"
    "sync"
    "testing"
    )

    /*
    type Item interface {
    Value() interface{}
    }
  4. ravlio revised this gist Aug 15, 2019. 1 changed file with 73 additions and 0 deletions.
    73 changes: 73 additions & 0 deletions rr_item_test.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    package main

    import (
    "github.com/stretchr/testify/require"
    "sync"
    "testing"
    )

    type Item interface {
    Value() interface{}
    }

    type Int int

    func (i Int) Value() interface{} {
    return i
    }

    type String string

    func (i String) Value() interface{} {
    return i
    }

    type Roundrobin struct {
    cur int // current elem position
    obj []Item // elements slice
    mx sync.RWMutex // sync mutex
    }

    // constructor
    func New(i ...Item) *Roundrobin {
    ret := &Roundrobin{}
    ret.Add(i...)

    return ret
    }

    func (r *Roundrobin) Add(i ...Item) {
    r.mx.Lock()
    // defer could affect performance, so we could move unlock at the end of function in production
    defer r.mx.Unlock()

    r.obj = append(r.obj, i...)
    }

    func (r *Roundrobin) Next() Item {
    r.mx.RLock()
    defer r.mx.RUnlock()

    ret := r.obj[r.cur]
    r.cur = (r.cur + 1) % len(r.obj) // Calculates next element id

    return ret
    }

    func TestRR(t *testing.T) {
    rr := New(Int(1), Int(2), String("3"))

    require.Equal(t, Int(1), rr.Next())
    require.Equal(t, Int(2), rr.Next())
    require.Equal(t, String("3"), rr.Next())
    require.Equal(t, Int(1), rr.Next())

    rr.Add(Int(4), Int(5), String("6"))

    require.Equal(t, Int(2), rr.Next())
    require.Equal(t, String("3"), rr.Next())
    require.Equal(t, Int(4), rr.Next())
    require.Equal(t, Int(5), rr.Next())
    require.Equal(t, String("6"), rr.Next())
    require.Equal(t, Int(1), rr.Next())
    }
  5. ravlio created this gist Aug 15, 2019.
    72 changes: 72 additions & 0 deletions rr_test.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,72 @@
    package rr_test

    import (
    "github.com/stretchr/testify/require"
    "math/rand"
    "sync"
    "testing"
    )

    type Roundrobin struct {
    cur int // current elem position
    obj []int // elements slice
    mx sync.RWMutex // sync mutex
    }

    // constructor
    func New(i ...int) *Roundrobin {
    ret := &Roundrobin{}
    ret.Add(i...)

    return ret
    }

    func (r *Roundrobin) Add(i ...int) {
    r.mx.Lock()
    // defer could affect performance, so we could move unlock at the end of function in production
    defer r.mx.Unlock()

    r.obj = append(r.obj, i...)
    }

    func (r *Roundrobin) Next() int {
    r.mx.RLock()
    defer r.mx.RUnlock()

    ret := r.obj[r.cur]
    r.cur = (r.cur + 1) % len(r.obj) // Calculates next element id

    return ret
    }

    func TestRR(t *testing.T) {
    rr := New(1, 2, 3)

    require.Equal(t, 1, rr.Next())
    require.Equal(t, 2, rr.Next())
    require.Equal(t, 3, rr.Next())
    require.Equal(t, 1, rr.Next())

    rr.Add(4, 5, 6)

    require.Equal(t, 2, rr.Next())
    require.Equal(t, 3, rr.Next())
    require.Equal(t, 4, rr.Next())
    require.Equal(t, 5, rr.Next())
    require.Equal(t, 6, rr.Next())
    require.Equal(t, 1, rr.Next())
    }

    func BenchmarkRR(b *testing.B) {
    rr := New(1, 2, 3)
    b.RunParallel(func(pb *testing.PB) {
    for pb.Next() {

    // Randomly adding elements
    if rand.Intn(10) == 1 {
    rr.Add(rand.Intn(1000))
    }
    rr.Next()
    }
    })
    }