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 }