1
1
package iris
2
2
3
3
import (
4
+ "sync"
5
+
4
6
"github.com/kataras/iris/v12/context"
5
7
)
6
8
7
- // ContextPool is a pool of T.
8
- //
9
- // See `NewContextWrapper` and `ContextPool` for more.
10
- type ContextPool [T any ] interface {
11
- Acquire (ctx Context ) T
12
- Release (T )
13
- }
9
+ type (
10
+ // ContextSetter is an interface which can be implemented by a struct
11
+ // to set the iris.Context to the struct.
12
+ // The receiver must be a pointer of the struct.
13
+ ContextSetter interface {
14
+ // SetContext sets the iris.Context to the struct.
15
+ SetContext (Context )
16
+ }
14
17
15
- // DefaultContextPool is a pool of T.
16
- // It's used to acquire and release T.
17
- // The T is acquired from the pool and released back to the pool after the handler's execution.
18
- // The T is passed to the handler as an argument.
19
- // The T is not shared between requests.
20
- type DefaultContextPool [T any ] struct {
21
- AcquireFunc func (Context ) T
22
- ReleaseFunc func (T )
23
- }
18
+ // ContextSetterPtr is a pointer of T which implements the `ContextSetter` interface.
19
+ // The T must be a struct.
20
+ ContextSetterPtr [T any ] interface {
21
+ * T
22
+ ContextSetter
23
+ }
24
+
25
+ // emptyContextSetter is an empty struct which implements the `ContextSetter` interface.
26
+ emptyContextSetter struct {}
27
+ )
28
+
29
+ // SetContext method implements `ContextSetter` interface.
30
+ func (* emptyContextSetter ) SetContext (Context ) {}
24
31
25
- // Ensure that DefaultContextPool[T] implements ContextPool[T].
26
- var _ ContextPool [any ] = (* DefaultContextPool [any ])(nil )
27
-
28
- // Acquire returns a new T from the pool's AcquireFunc.
29
- func (p * DefaultContextPool [T ]) Acquire (ctx Context ) T {
30
- acquire := p .AcquireFunc
31
- if p .AcquireFunc == nil {
32
- acquire = func (ctx Context ) T {
33
- var t T
34
- return t
35
- }
32
+ // ContextPool is a pool of T. It's used to acquire and release custom context.
33
+ // Use of custom implementation or `NewContextPool`.
34
+ //
35
+ // See `NewContextWrapper` and `NewContextPool` for more.
36
+ type (
37
+ ContextPool [T any ] interface {
38
+ // Acquire must return a new T from a pool.
39
+ Acquire (ctx Context ) T
40
+ // Release must put the T back to the pool.
41
+ Release (T )
36
42
}
37
43
38
- return acquire (ctx )
39
- }
44
+ // syncContextPool is a sync pool implementation of T.
45
+ // It's used to acquire and release T.
46
+ // The contextPtr is acquired from the sync pool and released back to the sync pool after the handler's execution.
47
+ // The contextPtr is passed to the handler as an argument.
48
+ // ThecontextPtr is not shared between requests.
49
+ // The contextPtr must implement the `ContextSetter` interface.
50
+ // The T must be a struct.
51
+ // The contextPtr must be a pointer of T.
52
+ syncContextPool [T any , contextPtr ContextSetterPtr [T ]] struct {
53
+ pool * sync.Pool
54
+ }
55
+ )
40
56
41
- // Release does nothing if the pool's ReleaseFunc is nil.
42
- func (p * DefaultContextPool [T ]) Release (t T ) {
43
- release := p .ReleaseFunc
44
- if p .ReleaseFunc == nil {
45
- release = func (t T ) {}
57
+ // Ensure that syncContextPool implements ContextPool.
58
+ var _ ContextPool [* emptyContextSetter ] = (* syncContextPool [emptyContextSetter , * emptyContextSetter ])(nil )
59
+
60
+ // NewContextPool returns a new ContextPool default implementation which
61
+ // uses sync.Pool to implement its Acquire and Release methods.
62
+ // The contextPtr is acquired from the sync pool and released back to the sync pool after the handler's execution.
63
+ // The contextPtr is passed to the handler as an argument.
64
+ // ThecontextPtr is not shared between requests.
65
+ // The contextPtr must implement the `ContextSetter` interface.
66
+ // The T must be a struct.
67
+ // The contextPtr must be a pointer of T.
68
+ //
69
+ // Example:
70
+ // w := iris.NewContextWrapper(iris.NewContextPool[myCustomContext, *myCustomContext]())
71
+ func NewContextPool [T any , contextPtr ContextSetterPtr [T ]]() ContextPool [contextPtr ] {
72
+ return & syncContextPool [T , contextPtr ]{
73
+ pool : & sync.Pool {
74
+ New : func () interface {} {
75
+ var t contextPtr = new (T )
76
+ return t
77
+ },
78
+ },
46
79
}
80
+ }
81
+
82
+ // Acquire returns a new T from the sync pool.
83
+ func (p * syncContextPool [T , contextPtr ]) Acquire (ctx Context ) contextPtr {
84
+ // var t contextPtr
85
+ // if v := p.pool.Get(); v == nil {
86
+ // t = new(T)
87
+ // } else {
88
+ // t = v.(contextPtr)
89
+ // }
90
+
91
+ t := p .pool .Get ().(contextPtr )
92
+ t .SetContext (ctx )
93
+ return t
94
+ }
47
95
48
- release (t )
96
+ // Release puts the T back to the sync pool.
97
+ func (p * syncContextPool [T , contextPtr ]) Release (t contextPtr ) {
98
+ p .pool .Put (t )
49
99
}
50
100
51
101
// ContextWrapper is a wrapper for handlers which expect a T instead of iris.Context.
@@ -60,19 +110,13 @@ type ContextWrapper[T any] struct {
60
110
// The default pool's AcquireFunc returns a zero value of T.
61
111
// The default pool's ReleaseFunc does nothing.
62
112
// The default pool is used when the pool is nil.
63
- // Use the `&iris.DefaultContextPool{...}` to pass a simple context pool.
113
+ // Use the `iris.NewContextPool[T, *T]()` to pass a simple context pool.
114
+ // Then, use the `Handler` method to wrap custom handlers to iris ones.
64
115
//
65
- // See the `Handler` method for more.
66
116
// Example: https://github.com/kataras/iris/tree/main/_examples/routing/custom-context
67
117
func NewContextWrapper [T any ](pool ContextPool [T ]) * ContextWrapper [T ] {
68
118
if pool == nil {
69
- pool = & DefaultContextPool [T ]{
70
- AcquireFunc : func (ctx Context ) T {
71
- var t T
72
- return t
73
- },
74
- ReleaseFunc : func (t T ) {},
75
- }
119
+ panic ("pool cannot be nil" )
76
120
}
77
121
78
122
return & ContextWrapper [T ]{
0 commit comments