Commit a2cd9dc3bd

Isaac Yonemoto <isaac.yonemoto@gmail.com>
2020-12-03 21:49:35
Gpa mutex configurable (#7234)
* makes the mutex for the gpa configurable * fixed logic, added test * updates docstring; pushes logic to one place, better duck-type
1 parent 5317f00
Changed files (1)
lib/std/heap/general_purpose_allocator.zig
@@ -148,6 +148,16 @@ pub const Config = struct {
     /// Whether the allocator may be used simultaneously from multiple threads.
     thread_safe: bool = !std.builtin.single_threaded,
 
+    /// What type of mutex you'd like to use, for thread safety.
+    /// when specfied, the mutex type must have the same shape as `std.Mutex` and
+    /// `std.mutex.Dummy`, and have no required fields. Specifying this field causes
+    /// the `thread_safe` field to be ignored.
+    ///
+    /// when null (default):
+    /// * the mutex type defaults to `std.Mutex` when thread_safe is enabled.
+    /// * the mutex type defaults to `std.mutex.Dummy` otherwise.
+    MutexType: ?type = null,
+
     /// This is a temporary debugging trick you can use to turn segfaults into more helpful
     /// logged error messages with stack trace details. The downside is that every allocation
     /// will be leaked!
@@ -174,7 +184,8 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
         const total_requested_bytes_init = if (config.enable_memory_limit) @as(usize, 0) else {};
         const requested_memory_limit_init = if (config.enable_memory_limit) @as(usize, math.maxInt(usize)) else {};
 
-        const mutex_init = if (config.thread_safe) std.Mutex{} else std.mutex.Dummy{};
+        const mutex_init = if (config.MutexType) |T| T{} else
+          if (config.thread_safe) std.Mutex{} else std.mutex.Dummy{};
 
         const stack_n = config.stack_trace_frames;
         const one_trace_size = @sizeOf(usize) * stack_n;
@@ -849,6 +860,18 @@ test "realloc large object to small object" {
     std.testing.expect(slice[16] == 0x34);
 }
 
+test "overrideable mutexes" {
+    var gpa = GeneralPurposeAllocator(.{.MutexType = std.Mutex}){
+        .backing_allocator = std.testing.allocator,
+        .mutex = std.Mutex{}
+    };
+    defer std.testing.expect(!gpa.deinit());
+    const allocator = &gpa.allocator;
+
+    const ptr = try allocator.create(i32);
+    defer allocator.destroy(ptr);
+}
+
 test "non-page-allocator backing allocator" {
     var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = std.testing.allocator };
     defer std.testing.expect(!gpa.deinit());