-
Notifications
You must be signed in to change notification settings - Fork 0
/
locked_shrinker.hh
80 lines (67 loc) · 2.07 KB
/
locked_shrinker.hh
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
#ifndef _LOCKED_SHRINKER_HH
#define _LOCKED_SHRINKER_HH
#include <sys/cdefs.h>
#include <sys/types.h>
#include <osv/types.h>
#include <osv/mempool.hh>
#include <functional>
namespace osv_apps {
/**
* @class locked_shrinker
*
* This class is meant to protect the memory consumption and memory shrinking
* critical sections.
*
* It implements the memory::shrinker interface to get triggers for memory
* freeing.
*
* It implements lock()/unlock() methods to have a semanticist of standard mutex
* and to work with WITH_LOCK() macros.
*
* It prevents the dead-lock situation in the shrinking flow (when shrinking is
* caused by the allocation of a new memory for the cache) by using a try_lock()
* in the shrinking flow. If there is a lock contention during the shrinking
* then it sets the shrinking to the next time the lock() method is called.
*/
class locked_shrinker : public memory::shrinker {
public:
locked_shrinker(std::function<size_t (size_t)> func) :
memory::shrinker("osv-memcached-locked-shrinker"),
_shrink_cache_locked_func(func) {}
/**
* Take a lock and call a shrinking if it's pending.
*/
void lock()
{
_lock.lock();
if (_bytes_to_release) {
_shrink_cache_locked_func(_bytes_to_release);
_bytes_to_release = 0;
}
}
void unlock() { _lock.unlock(); }
size_t request_memory(size_t n, bool hard)
{
//
// Don't block here to prevent a dead-lock:
//
// allocation in a critical section may trigger a shrinker and will
// block until it ends - deadlock.
//
if (_lock.try_lock()) {
size_t released_amount = _shrink_cache_locked_func(n);
_bytes_to_release = 0;
_lock.unlock();
return released_amount;
} else {
_bytes_to_release = n;
return 0;
}
}
private:
lockfree::mutex _lock;
std::function<size_t (size_t)> _shrink_cache_locked_func;
size_t _bytes_to_release = 0;
};
} // namespace osv_apps
#endif //_LOCKED_SHRINKER_HH