| ... | ... | @@ -148,6 +148,16 @@ pub const Config = struct { |
| 148 | 148 | /// Whether the allocator may be used simultaneously from multiple threads. |
| 149 | 149 | thread_safe: bool = !std.builtin.single_threaded, |
| 150 | 150 | |
| 151 | /// What type of mutex you'd like to use, for thread safety. |
| 152 | /// when specfied, the mutex type must have the same shape as `std.Mutex` and |
| 153 | /// `std.mutex.Dummy`, and have no required fields. Specifying this field causes |
| 154 | /// the `thread_safe` field to be ignored. |
| 155 | /// |
| 156 | /// when null (default): |
| 157 | /// * the mutex type defaults to `std.Mutex` when thread_safe is enabled. |
| 158 | /// * the mutex type defaults to `std.mutex.Dummy` otherwise. |
| 159 | MutexType: ?type = null, |
| 160 | |
| 151 | 161 | /// This is a temporary debugging trick you can use to turn segfaults into more helpful |
| 152 | 162 | /// logged error messages with stack trace details. The downside is that every allocation |
| 153 | 163 | /// will be leaked! |
| ... | ... | @@ -174,7 +184,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { |
| 174 | 184 | const total_requested_bytes_init = if (config.enable_memory_limit) @as(usize, 0) else {}; |
| 175 | 185 | const requested_memory_limit_init = if (config.enable_memory_limit) @as(usize, math.maxInt(usize)) else {}; |
| 176 | 186 | |
| 177 | | const mutex_init = if (config.thread_safe) std.Mutex{} else std.mutex.Dummy{}; |
| 187 | const mutex_init = if (config.MutexType) |T| T{} else |
| 188 | if (config.thread_safe) std.Mutex{} else std.mutex.Dummy{}; |
| 178 | 189 | |
| 179 | 190 | const stack_n = config.stack_trace_frames; |
| 180 | 191 | const one_trace_size = @sizeOf(usize) * stack_n; |
| ... | ... | @@ -849,6 +860,18 @@ test "realloc large object to small object" { |
| 849 | 860 | std.testing.expect(slice[16] == 0x34); |
| 850 | 861 | } |
| 851 | 862 | |
| 863 | test "overrideable mutexes" { |
| 864 | var gpa = GeneralPurposeAllocator(.{.MutexType = std.Mutex}){ |
| 865 | .backing_allocator = std.testing.allocator, |
| 866 | .mutex = std.Mutex{} |
| 867 | }; |
| 868 | defer std.testing.expect(!gpa.deinit()); |
| 869 | const allocator = &gpa.allocator; |
| 870 | |
| 871 | const ptr = try allocator.create(i32); |
| 872 | defer allocator.destroy(ptr); |
| 873 | } |
| 874 | |
| 852 | 875 | test "non-page-allocator backing allocator" { |
| 853 | 876 | var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = std.testing.allocator }; |
| 854 | 877 | defer std.testing.expect(!gpa.deinit()); |