Lot of thanks for the attention to detail.
I really miss the reviewer.
I’ll try to explain the reasons.
Let’s start from simplest:
Sometimes I did it , sometimes don’t. I’ll probably make this a rule.
The same way I am thinking less to use type inference.
With triple CLion/ZigBrain plugin/ ZLS I have all information, but when I try to uinderstand my own code in the browser, sometimes I feel not comfortable.
Guilty. It’s example, but mindset still of ampe developer.
I’ll fix it
“Sh*t happens”. We are talking about long lived multithreaded code with non closed sockets etc. I’d like to inform caller…
If resource deallocation always succeed, we can use it with defer/errdefer. I undersand reason for Zen.
If caller won’t to get error during destroy, he/she will wrap it on own code with catch and possible additional log about failure
Ampe is “interface”:
pub const Ampe = struct {
ptr: ?*anyopaque,
vtable: *const vtables.AmpeVTable,
...............................................................
};
Is it OK to add allocator as a field ?
pub const Ampe = struct {
ptr: ?*anyopaque,
vtable: *const vtables.AmpeVTable,
allocator: std.mem.Allocator,
...............................................................
};
According to design, null is valid value for the message, all apis are dealing with this value.
null is returned when pool is empty, it is not error, it’s intent.
the same way Zig ArrayHashMap getPtr returns null for non existing value.
Error will be returned for example if allocation really failed, or system is in shutdown state.
Now let’s talk about *?*Message
var welcomeRequest: ?*Message = server.*.ampe.get(tofu.AllocationStrategy.always) catch unreachable;
defer server.*.ampe.put(&welcomeRequest);
...........................................................
...........................................................
_ = server.*.chnls.?.sendToPeer(&welcomeRequest) catch unreachable;
First of all we got welcomeRequest from the pool.
And immediatelly write defer in order to release message to the pool.
welcomeRequest may be null, but put “knows” about this possibility: If welcomeRequest != null, it returns welcomeRequest.? to the pool and sets welcomeRequest to null (remember *?).
sendToPeer also works in the same manner:
- it checks the message
- if valid,
- sends message to another thread for further processing
- set welcomeRequest to null
- otherwise returns error
For any case and any errors within function defer will return message to the pool if it was not ‘captured’
So
- ?*Message == null means message was already processed(sended or returned to the pool)
- *?*Message enables within the same function say “I captured the message” vid setting to null
Simplest ownership moving in async environment
It would be interesting to discuss this approach.