1 #pragma once
2 // IWYU pragma: private, include "rlbox.hpp"
3 // IWYU pragma: friend "rlbox_.*\.hpp"
4 
5 #include <map>
6 #ifndef RLBOX_USE_CUSTOM_SHARED_LOCK
7 #  include <shared_mutex>
8 #endif
9 #include <type_traits>
10 
11 #include "rlbox_helpers.hpp"
12 #include "rlbox_type_traits.hpp"
13 #include "rlbox_types.hpp"
14 
15 namespace rlbox {
16 
17 template<typename T_PointerType>
18 class app_pointer_map
19 {
20 
21 private:
22   using T_PointerTypeUnsigned = detail::unsigned_int_of_size_t<T_PointerType>;
23 
24   std::map<T_PointerTypeUnsigned, void*> pointer_map;
25   T_PointerTypeUnsigned counter = 1;
26   RLBOX_SHARED_LOCK(map_mutex);
27 
get_unused_index()28   T_PointerType get_unused_index()
29   {
30     constexpr auto max_val = std::numeric_limits<T_PointerTypeUnsigned>::max();
31     constexpr auto min_val = std::numeric_limits<T_PointerTypeUnsigned>::min();
32     for (T_PointerTypeUnsigned i = counter; i < max_val; i++) {
33       if (pointer_map.find(i) == pointer_map.end()) {
34         counter = i + 1;
35         return reinterpret_cast<T_PointerType>(i);
36       }
37     }
38     for (T_PointerTypeUnsigned i = min_val; i < counter; i++) {
39       if (pointer_map.find(i) == pointer_map.end()) {
40         counter = i + 1;
41         return reinterpret_cast<T_PointerType>(i);
42       }
43     }
44     detail::dynamic_check(false, "Could not find free app pointer slot");
45     return 0;
46   }
47 
48 public:
app_pointer_map()49   app_pointer_map()
50   {
51     // ensure we can't use app pointer 0 as this is sometimes confused as null
52     // by the sandbox
53     pointer_map[0] = nullptr;
54   }
55 
get_app_pointer_idx(void * ptr)56   T_PointerType get_app_pointer_idx(void* ptr)
57   {
58     RLBOX_ACQUIRE_UNIQUE_GUARD(lock, map_mutex);
59     T_PointerType idx = get_unused_index();
60     T_PointerTypeUnsigned idx_int =
61       reinterpret_cast<T_PointerTypeUnsigned>(idx);
62     pointer_map[idx_int] = ptr;
63     return idx;
64   }
65 
remove_app_ptr(T_PointerType idx)66   void remove_app_ptr(T_PointerType idx)
67   {
68     RLBOX_ACQUIRE_UNIQUE_GUARD(lock, map_mutex);
69     T_PointerTypeUnsigned idx_int =
70       reinterpret_cast<T_PointerTypeUnsigned>(idx);
71     auto it = pointer_map.find(idx_int);
72     detail::dynamic_check(it != pointer_map.end(),
73                           "Error: removing a non-existing app pointer");
74     pointer_map.erase(it);
75   }
76 
lookup_index(T_PointerType idx)77   void* lookup_index(T_PointerType idx)
78   {
79     RLBOX_ACQUIRE_SHARED_GUARD(lock, map_mutex);
80     T_PointerTypeUnsigned idx_int =
81       reinterpret_cast<T_PointerTypeUnsigned>(idx);
82     auto it = pointer_map.find(idx_int);
83     detail::dynamic_check(it != pointer_map.end(),
84                           "Error: looking up a non-existing app pointer");
85     return it->second;
86   }
87 };
88 
89 }