]> git.sesse.net Git - casparcg/blob - common/page_locked_allocator.cpp
c8d0cac608cac892350a885889bdeeb0c590b01f
[casparcg] / common / page_locked_allocator.cpp
1 #include "stdafx.h"\r
2 \r
3 #include "os/windows/windows.h"\r
4 \r
5 #include <unordered_map>\r
6 #include <tbb/mutex.h>\r
7 #include <tbb/atomic.h>\r
8 \r
9 namespace caspar { namespace detail {\r
10         \r
11 tbb::mutex                                                      g_mutex;\r
12 std::unordered_map<void*, size_t>       g_map;\r
13 size_t                                                          g_free;\r
14 \r
15 void allocate_store(size_t size)\r
16 {               \r
17         SIZE_T workingSetMinSize = 0, workingSetMaxSize = 0;\r
18         if(::GetProcessWorkingSetSize(::GetCurrentProcess(), &workingSetMinSize, &workingSetMaxSize))\r
19         {                       \r
20                 workingSetMinSize += size;\r
21                 workingSetMaxSize += size;\r
22 \r
23                 if(!::SetProcessWorkingSetSize(::GetCurrentProcess(), workingSetMinSize, workingSetMaxSize))            \r
24                         throw std::bad_alloc();         \r
25 \r
26                 g_free += size;\r
27         }\r
28 }\r
29 \r
30 void* alloc_page_locked(size_t size)\r
31 {\r
32         tbb::mutex::scoped_lock lock(g_mutex);\r
33 \r
34         if(g_free < size)\r
35                 allocate_store(size);\r
36 \r
37         auto p = ::VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);\r
38         if(!p)\r
39                 throw std::bad_alloc();\r
40 \r
41         if(::VirtualLock(p, size) == 0) \r
42         {\r
43                 ::VirtualFree(p, 0, MEM_RELEASE);\r
44                 throw std::bad_alloc();\r
45         }\r
46                 \r
47         g_free   -= size;\r
48         g_map[p]        = size;\r
49         return p;\r
50 \r
51 }\r
52 \r
53 void free_page_locked(void* p)\r
54 {               \r
55         tbb::mutex::scoped_lock lock(g_mutex);\r
56 \r
57         if(g_map.find(p) == g_map.end())\r
58                 return;\r
59 \r
60         ::VirtualFree(p, 0, MEM_RELEASE);\r
61 \r
62         g_free += g_map[p];\r
63         g_map.erase(p);\r
64 }\r
65 \r
66 }}