Tanoda
MemoryManager.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using AOT;
10using System;
11using System.Collections.Concurrent;
12using System.Collections.Generic;
13using System.Runtime.InteropServices;
14
15namespace LeapInternal {
16
17 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
18 public delegate IntPtr Allocate(UInt32 size, eLeapAllocatorType typeHint, IntPtr state);
19
20 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
21 public delegate void Deallocate(IntPtr buffer, IntPtr state);
22
23 public static class MemoryManager {
24
35 public static bool EnablePooling = true;
36
44 public static uint MinPoolSize = 64;
45
46 private static ConcurrentDictionary<IntPtr, ActiveMemoryInfo> _activeMemory =
47 new ConcurrentDictionary<IntPtr, ActiveMemoryInfo>();
48 private static ConcurrentDictionary<PoolKey, Queue<object>> _pooledMemory =
49 new ConcurrentDictionary<PoolKey, Queue<object>>();
50
51 [MonoPInvokeCallback(typeof(Allocate))]
52 public static IntPtr Pin(UInt32 size, eLeapAllocatorType typeHint, IntPtr state) {
53 try {
54 //Construct a key to identify the desired allocation
55 PoolKey key = new PoolKey() {
56 type = typeHint,
57 size = size
58 };
59
60 //Attempt to find the pool that holds this type of allocation
61 Queue<object> pool;
62 if (!_pooledMemory.TryGetValue(key, out pool)) {
63 //Construct a new pool if none exists yet
64 pool = new Queue<object>();
65 _pooledMemory[key] = pool;
66 }
67
68 //Attempt to get an object from the pool
69 object memory;
70 if (EnablePooling && pool.Count > MinPoolSize) {
71 memory = pool.Dequeue();
72 } else {
73 //If the pool is empty, we need to construct a new object
74 switch (typeHint) {
75 default:
76 case eLeapAllocatorType.eLeapAllocatorType_Uint8:
77 memory = new byte[size];
78 break;
79 case eLeapAllocatorType.eLeapAllocatorType_Float:
80 memory = new float[(size + sizeof(float) - 1) / sizeof(float)];
81 break;
82 }
83 }
84
85 //Pin the object so its address will not change
86 GCHandle handle = GCHandle.Alloc(memory, GCHandleType.Pinned);
87 IntPtr ptr = handle.AddrOfPinnedObject();
88
89 //Put the information about the newly pinned allocation into the
90 //active memory map so it can be retrieved and freed layer.
91 _activeMemory.TryAdd(ptr, new ActiveMemoryInfo() {
92 handle = handle,
93 key = key
94 });
95
96 return ptr;
97 } catch (Exception e) {
98 UnityEngine.Debug.LogException(e);
99 }
100
101 return IntPtr.Zero;
102 }
103
104 [MonoPInvokeCallback(typeof(Deallocate))]
105 public static void Unpin(IntPtr ptr, IntPtr state) {
106 try {
107 //Grab the info for the given pointer
108 ActiveMemoryInfo info = _activeMemory[ptr];
109
110 //First we return the object back to its pool
111 if (EnablePooling) {
112 _pooledMemory[info.key].Enqueue(info.handle.Target);
113 }
114
115 //Then we remove the pointer from the active memory map
116 ActiveMemoryInfo value;
117
118 _activeMemory.TryRemove(ptr, out value);
119
120 //Finally we unpin the memory
121 info.handle.Free();
122 } catch (Exception e) {
123 UnityEngine.Debug.LogException(e);
124 }
125 }
126
127 public static object GetPinnedObject(IntPtr ptr) {
128 try {
129 return _activeMemory[ptr].handle.Target;
130 } catch (Exception) { }
131 return null;
132 }
133
134 private struct PoolKey : IEquatable<PoolKey> {
135 public eLeapAllocatorType type;
136 public UInt32 size;
137
138 public override int GetHashCode() {
139 return (int)type | (int)size << 4;
140 }
141
142 public bool Equals(PoolKey other) {
143 return type == other.type &&
144 size == other.size;
145 }
146
147 public override bool Equals(object obj) {
148 if (obj is PoolKey) {
149 return Equals((PoolKey)obj);
150 } else {
151 return false;
152 }
153 }
154 }
155
156 private struct ActiveMemoryInfo {
157 public GCHandle handle;
158 public PoolKey key;
159 }
160 }
161}
eLeapAllocatorType
Definition: LeapC.cs:233
delegate void Deallocate(IntPtr buffer, IntPtr state)
delegate IntPtr Allocate(UInt32 size, eLeapAllocatorType typeHint, IntPtr state)