HW4 is completed
This commit is contained in:
parent
89a2446cef
commit
11d4b35774
@ -1,4 +1,5 @@
|
|||||||
package hw04_lru_cache //nolint:golint,stylecheck
|
package hw04_lru_cache //nolint:golint,stylecheck
|
||||||
|
import "sync"
|
||||||
|
|
||||||
type Key string
|
type Key string
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ type lruCache struct {
|
|||||||
capacity int
|
capacity int
|
||||||
queue *List
|
queue *List
|
||||||
items map[Key]*ListItem
|
items map[Key]*ListItem
|
||||||
|
mx sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
@ -23,25 +25,33 @@ func NewCache(capacity int) Cache {
|
|||||||
return &lruCache{
|
return &lruCache{
|
||||||
capacity: capacity,
|
capacity: capacity,
|
||||||
queue: NewList(),
|
queue: NewList(),
|
||||||
items: map[Key]*ListItem{},
|
items: make(map[Key]*ListItem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lruCache) Set(key Key, value interface{}) bool {
|
func (l *lruCache) Set(key Key, value interface{}) bool {
|
||||||
if _, exists := l.Get(key); exists {
|
if _, exists := l.items[key]; exists {
|
||||||
l.items[key].Value = value
|
l.mx.RLock()
|
||||||
|
l.items[key].Value = Item{Value: value, Key: key}
|
||||||
|
l.queue.MoveToFront(l.items[key])
|
||||||
|
l.mx.RUnlock()
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
if l.queue.Len() >= l.capacity {
|
if l.queue.Len() == l.capacity {
|
||||||
// TODO: нужно как-то удалить элемент из мапа
|
l.mx.RLock()
|
||||||
//delete(l.items,l.queue.Back().(*Item).Key)
|
delete(l.items, l.queue.Back().Value.(Item).Key)
|
||||||
l.queue.Remove(l.queue.Back())
|
l.queue.Remove(l.queue.Back())
|
||||||
|
l.mx.RUnlock()
|
||||||
}
|
}
|
||||||
l.items[key] = l.queue.PushFront(value)
|
l.mx.RLock()
|
||||||
|
l.items[key] = l.queue.PushFront(Item{Value: value, Key: key})
|
||||||
|
l.mx.RUnlock()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lruCache) Get(key Key) (interface{}, bool) {
|
func (l *lruCache) Get(key Key) (interface{}, bool) {
|
||||||
|
l.mx.Lock()
|
||||||
|
defer l.mx.Unlock()
|
||||||
if l.items[key] == nil {
|
if l.items[key] == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
@ -50,7 +60,9 @@ func (l *lruCache) Get(key Key) (interface{}, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *lruCache) Clear() {
|
func (l *lruCache) Clear() {
|
||||||
|
l.mx.Lock()
|
||||||
l.items = nil
|
l.items = nil
|
||||||
l.queue.len = 0
|
l.queue.len = 0
|
||||||
l.queue.Info = ListItem{}
|
l.queue.Info = ListItem{}
|
||||||
|
l.mx.Unlock()
|
||||||
}
|
}
|
||||||
|
@ -31,18 +31,18 @@ func TestCache(t *testing.T) {
|
|||||||
|
|
||||||
val, ok := c.Get("aaa")
|
val, ok := c.Get("aaa")
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, 100, val)
|
require.Equal(t, 100, val.(Item).Value)
|
||||||
|
|
||||||
val, ok = c.Get("bbb")
|
val, ok = c.Get("bbb")
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, 200, val)
|
require.Equal(t, 200, val.(Item).Value)
|
||||||
|
|
||||||
wasInCache = c.Set("aaa", 300)
|
wasInCache = c.Set("aaa", 300)
|
||||||
require.True(t, wasInCache)
|
require.True(t, wasInCache)
|
||||||
|
|
||||||
val, ok = c.Get("aaa")
|
val, ok = c.Get("aaa")
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, 300, val)
|
require.Equal(t, 300, val.(Item).Value)
|
||||||
|
|
||||||
val, ok = c.Get("ccc")
|
val, ok = c.Get("ccc")
|
||||||
require.False(t, ok)
|
require.False(t, ok)
|
||||||
@ -79,7 +79,6 @@ func TestCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCacheMultithreading(t *testing.T) {
|
func TestCacheMultithreading(t *testing.T) {
|
||||||
t.Skip() // Remove if task with asterisk completed
|
|
||||||
|
|
||||||
c := NewCache(10)
|
c := NewCache(10)
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user