I guess I'll have to have a separate pair of queues for each client, and have the server non-deterministically choose which one it receives from. That's closer to reality, too.
The nice thing about that is that each queue has its own bound, so checking for 2 empty slots makes sense.
The problem with that is that each queue has its own bound, so state space goes to the mooooon!
And like, yes I can make only allow it to send that first message if there are 2 free slots in the send queue.
But how does that generalize to multiple clients?
IRL each would have a separate TCP connection to the server, but currently I model them all as a single pair of queues, one from clients to server, one from server to clients.
So if one client checks that there are 2 slots in a queue, sends first msg, then another client sends a different one, I'm still stuck.
So yesterday TLA+ made me realize that the property of my protocol that I'm trying to verify makes no sense (the incorrect behaviour is indistinguishable from a client's PoV from a correct behaviour).
So I was thinking how I could make it distinguishable in a way that will work not only in TLA+ but also in real life, and it turns out I could really use pings in the protocol.
Then I looked into my WIP testsuite for this protocol from 2 years ago, and guess what I found?
Of course the problem with pings with nonces in TLA+ is that the set of possible nonces must be larger than the worst-case-scenario number of in-flight pings.
So if you simulate a TCP connection with 2 queues, one in each direction, up to 5 messages in each
then you need 11 different nonces (ok maybe 10 would suffice), which means you get extra 11!-ish states from all the ways your queues can be stuffed with various pings and pongs...
So, last time I figured out I need pings in my protocol to check that a certain other message isn't still sitting in a queue / as a kind of synchronization fence.
So I added pings to the model, and now I'm making the client send a ping immediately after that other message, and...
ofc it doesn't compile because sending 2 messages means modifying the queue twice, which, in Pluscal, can't be done in a single label.
Well ok, let's add a label inbetween the messages then.
If I post a tech rant / a description of a problem I have, and you don't understand it, feel free to ask questions.
Like, I'd prefer if people were like "you used the word $W which i don't know, what does that even mean" instead of being like "I don't know what he's talking about so I'll stay silent"
I just read through https://learntla.com (all of Core and some of the Topics) in two days and...
It was quite enjoyable.
It's been a long time since I've read a tutorial or a manual start-to-finish and I forgot how much nicer it is, compared to learning only the pieces you immediately need, and never knowing what else is possible.
I think the desire to get immediate answers to your current problem, as opposed to developing a broader understanding of the tools you're working with, is part of what led to the LLM chatbot brainrot we're seeing these days.
And I think practicing the skill of actually reading the manual start-to-finish removes some of that temptation, makes you less prone to being misled by some LLM, and is a tiny step towards making those AI companies have less power over people.
@kspalaiologos and so far I encountered three cathegories of code that turned out completely inscrutable to me:
Scala, React, and whatever Pipewire is written in (not sure if it's just GObject, or a special evolution of GObject found in gstreamer, or some different beast).