-
Notifications
You must be signed in to change notification settings - Fork 0
/
memoria.go
103 lines (82 loc) · 2.63 KB
/
memoria.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package memoria
import (
"sync"
"time"
)
// Almacén representa un conjunto de objetos con un tiempo de vida común.
type Almacén struct {
mu sync.Mutex
tdvm time.Duration // Tiempo de vida máximo de los objetos almacenados.
tdvsu time.Duration // Tiempo de vida de los objetos almacenados desde la última vez que fueron adquiridos.
elementos map[string]*elemento
}
type elemento struct {
tdvm *time.Timer
tdvsu *time.Timer
objeto interface{}
}
// NuevoAlmacén crea un nuevo Almacén donde se almacenarán los objetos.
// Los objetos almacenados se eliminarán después de transcurrir tiempoDeVidaSinUso desde el uso más reciente,
// o, al transcurrir tiempoDeVidaMáximo desde el momento en que se almacenó, lo primero que ocurra.
func NuevoAlmacén(tiempoDeVidaMáximo time.Duration, tiempoDeVidaSinUso time.Duration) *Almacén {
return &Almacén{
tdvm: tiempoDeVidaMáximo,
tdvsu: tiempoDeVidaSinUso,
elementos: map[string]*elemento{},
}
}
// Almacenar almacena un objeto asignándole un identificador único.
// Si ya existe un objeto con el mismo identificador, se sobrescribirá.
func (O *Almacén) Almacenar(identificador string, objeto interface{}) {
O.mu.Lock()
var elementoExistente, existe = O.elementos[identificador]
if existe {
reiniciarTemporizador(elementoExistente.tdvm, O.tdvm)
reiniciarTemporizador(elementoExistente.tdvsu, O.tdvsu)
elementoExistente.objeto = objeto
O.elementos[identificador] = elementoExistente
O.mu.Unlock()
return
}
var elementoNuevo = &elemento{
tdvm: time.NewTimer(O.tdvm),
tdvsu: time.NewTimer(O.tdvsu),
objeto: objeto,
}
go func() {
<-elementoNuevo.tdvm.C
O.removerElemento(identificador, elementoNuevo.tdvsu)
}()
go func() {
<-elementoNuevo.tdvsu.C
O.removerElemento(identificador, elementoNuevo.tdvm)
}()
O.elementos[identificador] = elementoNuevo
O.mu.Unlock()
}
// Adquirir obtiene un objeto dado su identificador.
// El valor lógico retornado indica si existe o no.
func (O *Almacén) Adquirir(identificador string) (interface{}, bool) {
O.mu.Lock()
defer O.mu.Unlock()
var elemento, existe = O.elementos[identificador]
if !existe {
return nil, false
}
reiniciarTemporizador(elemento.tdvsu, O.tdvsu)
return elemento.objeto, true
}
func (O *Almacén) removerElemento(identificador string, temporizadorADetener *time.Timer) {
O.mu.Lock()
if !temporizadorADetener.Stop() {
<-temporizadorADetener.C
}
delete(O.elementos, identificador)
O.mu.Unlock()
}
func reiniciarTemporizador(temporizador *time.Timer, duración time.Duration) {
if !temporizador.Stop() {
<-temporizador.C
}
temporizador.Reset(duración)
}