#threads, slices and `BoundedArray`s

1 messages · Page 1 of 1 (latest)

hollow glacier
#

I am trying to implement dynamic resize for a termbox2 application and simple pattern works flawlessly. But things get very chaotic when I am trying to implement advanced patterns. My original approach used gpallocator and it worked as expected, but I could not figure out the way to free array allocations due segfaults (single updateWidthSec works but not both). So I started reading lib src and found BoundedArray. But with this approach, width/height arrays are corrupted. For weeks tried to refactor and merge these functions into one, move around the calls, increased delays—nothing works, and errors do not output anything useful (bus error, segfaults and just empty errors (all runtime)).

patch:
https://github.com/charlesrocket/xtxf/commit/ab8d39fc15acf44d33b768c62f4025c7ad4d5407

also this only works on release builds for some reason, not debug

feels like allocator issues are due scoping conditionals, but bounded array issues are without any useful error outputs so not sure why this is happening (bug or i need to be more gentle with the stack, cannot tell 🫠)

#
fn updateWidthSec(self: *@This(), adv_w: u32) !void {
        self.mutex.lock();
        defer self.mutex.unlock();

        var array_w: std.BoundedArrayAligned(u32, 4, 2000) = undefined;

        array_w = try std.BoundedArrayAligned(u32, 4, 2000).init(0);
        var w_val = adv_w;

        while (w_val <= @as(u32, @intCast(self.width))) {
            try array_w.append(w_val);
            w_val += adv_w;
        }

        try array_w.resize(array_w.len);
        self.width_g_arr = array_w.slice();
    }

    fn updateHeightSec(self: *@This(), adv_h: u32) !void {
        self.mutex.lock();
        defer self.mutex.unlock();

        var array_h: std.BoundedArrayAligned(u32, 4, 1000) = undefined;
        array_h = try std.BoundedArrayAligned(u32, 4, 1000).init(0);

        var h_val = adv_h;

        while (h_val <= @as(u32, @intCast(self.height))) {
            try array_h.append(h_val);
            h_val += adv_h;
        }

        try array_h.resize(array_h.len);
        self.height_g_arr = array_h.slice();
    }
#
if (self.style != Style.default) {
            if (self.style == Style.crypto) {
                try core.updateWidthSec(5);
                try core.updateHeightSec(3);
            } else if (self.style == Style.columns) {
                try core.updateWidthSec(4);
            }
        }

candid salmon
#
    fn updateWidthSec(self: *@This(), adv_w: u32) !void {
         self.mutex.lock();
         defer self.mutex.unlock();

         var array_w: std.BoundedArrayAligned(u32, 4, 2000) = undefined;

         array_w = try std.BoundedArrayAligned(u32, 4, 2000).init(0);
         var w_val = adv_w;

         while (w_val <= @as(u32, @intCast(self.width))) {
             try array_w.append(w_val);
             w_val += adv_w;
         }

         try array_w.resize(array_w.len);
         self.width_g_arr = array_w.slice();
     }

This code has some rather evident errors... it's quite a challenge to discuss them without sounding a bit puzzled.

hollow glacier
#

@candid salmon this is a rough draft, there is no need to explicitly init the array, its a leftover from a merged try. not sure tho where the answer since i only introduced Bounded array, and resize making it work for basic pattern

candid salmon
#

What you mentioned is not the critical issue. The real key problem is that memory cannot appear out of nowhere. Where does the memory for your so-called new matrix come from? The answer to this question is the key to the issue you're encountering.

hollow glacier
#

then how come everything works with columns but not with another pattern? i assumed bounded array init function takes care of the memory, and i just dont utilize it properly, or need to really isolate both calls

#

i can get everything to work with old allocator but cant properly defer the free() due conditional scopes so other thread leaks, respectfully

#

when bounded array introduced, it works flawlessly if i only do one bounded array (width), no compiler/ext tooling errors. but when i start touching height arrays go corrupt. it still works with no errors, but width values are complete mess

candid salmon
#

The phenomenon you mentioned is indeed very interesting, but I personally believe it is definitely an unrelated illusion. This phenomenon may not be truly related to the problem you are encountering. I tried to fork the repository and provided a very simple but temporary solution. However, I have not verified its runtime environment. If it works, you can directly use it.

hollow glacier
#

@candid salmon thank you! this is interesting, going to test asap

#

oh, completely forgot to mention that current patch only works for release but not debug

#

thats why i thought theres a bug or some overlap

smoky dawn
hollow glacier
#

@smoky dawn ooo i see

#

now it makes sense

smoky dawn
#

you could use an allocator to dupe it one you leave the function? or just store a bounded array directly if you have a sane limit

hollow glacier
#

@smoky dawn could not figure out proper scoping to defer the free() but storing arrays directly would probably work

#

i dont expect them to be massive, tho they could grow big depending on the patter and the size of the terminal. but thats probably would be an issue decades later))

smoky dawn
#

you could store ArrayLists instead and have them have the same lifetime as whatever @This() is

hollow glacier
#

@smoky dawn thanks! need to look into this

smoky dawn
#

np, lemme know if you need help with the scoping

hollow glacier
#

@smoky dawn this is my original approach that failing with segfault:

    fn updateHeightSec(self: *@This(), adv: u32) !void {
        self.mutex.lock();
        defer self.mutex.unlock();

        const array = try getNthValues(self.height, adv, self.allocator);
        defer self.allocator.free(array);

        self.height_g_arr = array;
    }
fn getNthValues(number: i32, adv: u32, allocator: std.mem.Allocator) ![]u32 {
    var array = std.ArrayList(u32).init(allocator);
    var val = adv;

    while (val <= @as(u32, @intCast(number))) {
        try array.append(val);
        val += adv;
    }

    return array.toOwnedSlice();
}
#

tried merging Sec functions and moving around allocated variables but nothing

#

this is with GPA initiated in the Core struct withing main()

smoky dawn
#

in updateHeightSec youre freeing the array right after you assign it, its a pointer so self.height_g_arr and array are pointing to the same memory. a simpler solution would be to make height_g_arr an ArrayList and in getNthValues take a pointer to an arraylist to append to, and clear it at the beginning of updateHeightSec