Skip to content

Commit 6c5ee83

Browse files
S.KulishS.Kulish
authored andcommitted
list
1 parent 27351a3 commit 6c5ee83

6 files changed

Lines changed: 300 additions & 87 deletions

File tree

hw04_lru_cache/.sync

Whitespace-only changes.

hw04_lru_cache/cache.go

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package hw04lrucache
22

3+
import (
4+
"sync"
5+
)
6+
37
type Key string
48

59
type Cache interface {
@@ -9,8 +13,7 @@ type Cache interface {
913
}
1014

1115
type lruCache struct {
12-
Cache // Remove me after realization.
13-
16+
mu sync.Mutex
1417
capacity int
1518
queue List
1619
items map[Key]*ListItem
@@ -28,3 +31,57 @@ func NewCache(capacity int) Cache {
2831
items: make(map[Key]*ListItem, capacity),
2932
}
3033
}
34+
35+
func (cache lruCache) Set(key Key, value2 interface{}) bool {
36+
cache.mu.Lock()
37+
defer cache.mu.Unlock()
38+
39+
existedListItem, ok := cache.items[key]
40+
41+
if ok {
42+
cache.queue.Remove(existedListItem)
43+
} else {
44+
len := cache.queue.Len()
45+
46+
if len == cache.capacity {
47+
//remove the last item from the map and queue
48+
lastItem := cache.queue.Back()
49+
itemKey := lastItem.Value.(cacheItem).key
50+
delete(cache.items, itemKey)
51+
cache.queue.Remove(lastItem)
52+
}
53+
}
54+
55+
newListItem := cacheItem{key, value2}
56+
//add item to the front
57+
cache.queue.PushFront(newListItem)
58+
cache.items[key] = cache.queue.Front()
59+
60+
return ok
61+
}
62+
63+
func (cache lruCache) Get(key Key) (interface{}, bool) {
64+
cache.mu.Lock()
65+
defer cache.mu.Unlock()
66+
67+
var result interface{}
68+
69+
value, ok := cache.items[key]
70+
71+
if ok {
72+
cache.queue.PushFront(cache.items[key])
73+
result = value.Value.(cacheItem).value
74+
} else {
75+
result = nil
76+
}
77+
78+
return result, ok
79+
}
80+
81+
func (cache *lruCache) Clear() {
82+
cache.mu.Lock()
83+
defer cache.mu.Unlock()
84+
85+
cache.queue = NewList()
86+
cache.items = make(map[Key]*ListItem, cache.capacity)
87+
}

hw04_lru_cache/cache_test.go

Lines changed: 142 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,158 @@
11
package hw04lrucache
22

33
import (
4-
"math/rand"
5-
"strconv"
6-
"sync"
7-
"testing"
4+
"math/rand"
5+
"strconv"
6+
"sync"
7+
"testing"
88

9-
"github.com/stretchr/testify/require"
9+
"github.com/stretchr/testify/require"
1010
)
1111

1212
func TestCache(t *testing.T) {
13-
t.Run("empty cache", func(t *testing.T) {
14-
c := NewCache(10)
13+
t.Run("empty cache", func(t *testing.T) {
14+
c := NewCache(10)
1515

16-
_, ok := c.Get("aaa")
17-
require.False(t, ok)
16+
_, ok := c.Get("aaa")
17+
require.False(t, ok)
1818

19-
_, ok = c.Get("bbb")
20-
require.False(t, ok)
21-
})
19+
_, ok = c.Get("bbb")
20+
require.False(t, ok)
21+
})
2222

23-
t.Run("simple", func(t *testing.T) {
24-
c := NewCache(5)
23+
t.Run("simple", func(t *testing.T) {
24+
c := NewCache(5)
2525

26-
wasInCache := c.Set("aaa", 100)
27-
require.False(t, wasInCache)
26+
wasInCache := c.Set("aaa", 100)
27+
require.False(t, wasInCache)
28+
29+
wasInCache = c.Set("bbb", 200)
30+
require.False(t, wasInCache)
2831

29-
wasInCache = c.Set("bbb", 200)
30-
require.False(t, wasInCache)
31-
32-
val, ok := c.Get("aaa")
33-
require.True(t, ok)
34-
require.Equal(t, 100, val)
35-
36-
val, ok = c.Get("bbb")
37-
require.True(t, ok)
38-
require.Equal(t, 200, val)
39-
40-
wasInCache = c.Set("aaa", 300)
41-
require.True(t, wasInCache)
42-
43-
val, ok = c.Get("aaa")
44-
require.True(t, ok)
45-
require.Equal(t, 300, val)
46-
47-
val, ok = c.Get("ccc")
48-
require.False(t, ok)
49-
require.Nil(t, val)
50-
})
51-
52-
t.Run("purge logic", func(t *testing.T) {
53-
// Write me
54-
})
32+
val, ok := c.Get("aaa")
33+
require.True(t, ok)
34+
require.Equal(t, 100, val)
35+
36+
val, ok = c.Get("bbb")
37+
require.True(t, ok)
38+
require.Equal(t, 200, val)
39+
40+
wasInCache = c.Set("aaa", 300)
41+
require.True(t, wasInCache)
42+
43+
val, ok = c.Get("aaa")
44+
require.True(t, ok)
45+
require.Equal(t, 300, val)
46+
47+
val, ok = c.Get("ccc")
48+
require.False(t, ok)
49+
require.Nil(t, val)
50+
})
51+
52+
t.Run("more elements then in cache", func(t *testing.T) {
53+
c := NewCache(3)
54+
55+
c.Set("aaa", 100)
56+
c.Set("bbb", 200)
57+
c.Set("ccc", 300)
58+
c.Set("ddd", 400)
59+
60+
val, ok = c.Get("aaa")
61+
require.False(t, ok)
62+
require.Nil(t, val)
63+
64+
val, ok = c.Get("bbb")
65+
require.True(t, ok)
66+
require.Equal(t, 200, val)
67+
68+
val, ok = c.Get("ccc")
69+
require.True(t, ok)
70+
require.Equal(t, 300, val)
71+
72+
val, ok = c.Get("ddd")
73+
require.True(t, ok)
74+
require.Equal(t, 400, val)
75+
})
76+
77+
t.Run("more elements then in cache with get", func(t *testing.T) {
78+
c := NewCache(3)
79+
80+
c.Set("aaa", 100)
81+
c.Set("bbb", 200)
82+
c.Set("ccc", 300)
83+
84+
c.Get("ccc")
85+
c.Get("bbb")
86+
c.Get("aaa")
87+
c.Set("ddd", 400)
88+
89+
val, ok = c.Get("aaa")
90+
require.True(t, ok)
91+
require.Equal(t, 100, val)
92+
93+
val, ok = c.Get("bbb")
94+
require.True(t, ok)
95+
require.Equal(t, 200, val)
96+
97+
val, ok = c.Get("ccc")
98+
require.False(t, ok)
99+
require.Nil(t, val)
100+
101+
val, ok = c.Get("ddd")
102+
require.True(t, ok)
103+
require.Equal(t, 400, val)
104+
})
105+
106+
t.Run("more elements then in cache with set", func(t *testing.T) {
107+
c := NewCache(3)
108+
109+
c.Set("aaa", 100)
110+
c.Set("bbb", 200)
111+
c.Set("ccc", 300)
112+
113+
c.Set("ccc", 300)
114+
c.Set("bbb", 200)
115+
c.Set("aaa", 100)
116+
c.Set("ddd", 400)
117+
118+
val, ok = c.Get("aaa")
119+
require.True(t, ok)
120+
require.Equal(t, 100, val)
121+
122+
val, ok = c.Get("bbb")
123+
require.True(t, ok)
124+
require.Equal(t, 200, val)
125+
126+
val, ok = c.Get("ccc")
127+
require.False(t, ok)
128+
require.Nil(t, val)
129+
130+
val, ok = c.Get("ddd")
131+
require.True(t, ok)
132+
require.Equal(t, 400, val)
133+
})
55134
}
56135

57136
func TestCacheMultithreading(t *testing.T) {
58-
t.Skip() // Remove me if task with asterisk completed.
59-
60-
c := NewCache(10)
61-
wg := &sync.WaitGroup{}
62-
wg.Add(2)
63-
64-
go func() {
65-
defer wg.Done()
66-
for i := 0; i < 1_000_000; i++ {
67-
c.Set(Key(strconv.Itoa(i)), i)
68-
}
69-
}()
70-
71-
go func() {
72-
defer wg.Done()
73-
for i := 0; i < 1_000_000; i++ {
74-
c.Get(Key(strconv.Itoa(rand.Intn(1_000_000))))
75-
}
76-
}()
77-
78-
wg.Wait()
137+
t.Skip() // Remove me if task with asterisk completed.
138+
139+
c := NewCache(10)
140+
wg := &sync.WaitGroup{}
141+
wg.Add(2)
142+
143+
go func() {
144+
defer wg.Done()
145+
for i := 0; i < 1_000_000; i++ {
146+
c.Set(Key(strconv.Itoa(i)), i)
147+
}
148+
}()
149+
150+
go func() {
151+
defer wg.Done()
152+
for i := 0; i < 1_000_000; i++ {
153+
c.Get(Key(strconv.Itoa(rand.Intn(1_000_000))))
154+
}
155+
}()
156+
157+
wg.Wait()
79158
}

hw04_lru_cache/go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
module github.com/fixme_my_friend/hw04_lru_cache
1+
module hw04_lru_cache
22

33
go 1.16
44

55
require (
66
github.com/davecgh/go-spew v1.1.1 // indirect
77
github.com/stretchr/testify v1.7.0
8-
gopkg.in/yaml.v2 v2.4.0 // indirect
98
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
109
)

hw04_lru_cache/go.sum

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
1-
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
21
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
32
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
43
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
54
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
65
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
76
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
8-
github.com/stretchr/testify v1.5.0 h1:DMOzIV76tmoDNE9pX6RSN0aDtCYeCg5VueieJaAo1uw=
9-
github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
107
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
118
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
129
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1310
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
14-
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
15-
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
16-
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
17-
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
1811
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
1912
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
2013
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)