Back to Asynchronous Flush

Interprocess Communication (IPC) · Asynchronous Flush · Practice Question

Demonstrate Asynchronous Flush

Sign in to track your progress

Question

What is meant by an "asynchronous flush", and how would you demonstrate it?

Solution

On the server, open a connection to the client and send an async message asking the client to set a variable a to the client's local time when the message is received:

q)h:hopen 5002
q)f:{[] show .z.p; neg[h]"a:.z.p"; show .z.H; show .z.W; system"sleep 10"}
q)f[]
2026.05.10D10:40:32.006242147
`s#,5i
5| 20

Checking a on the client shows it was set roughly 10 seconds after the server sent the message:

q)a
2026.05.10D10:40:42.009351379

Adding an async flush — neg[h](::) — right after the async send fixes this:

q)f:{[] show .z.p; neg[h]"a:.z.p"; neg[h](::); show .z.H; show .z.W; system"sleep 10"}
q)f[]
2026.05.10D10:41:34.656795681
`s#,5i
5| 0

Now a on the client is set almost immediately, not 10 seconds later:

q)a
2026.05.10D10:41:34.657160954

Explanation

neg[h] "..." queues a message on h's outgoing buffer and returns immediately — it doesn't guarantee the bytes hit the socket right away. .z.W confirms this: handle 5 still shows 20 bytes queued right after the send. (.z.H lists the process's open socket handles.) In the second version, the flush runs before .z.W is shown, so the queue is already empty (5| 0).

q only flushes outgoing queues when it returns to its event loop. Since f moves straight into system"sleep 10", the process stays inside that function — and out of the event loop — for the full 10 seconds, so the message isn't sent until f finishes. That's why a is set on the client roughly 10 seconds late.

neg[h](::) (or neg[h][]) is the async flush — it forces the queue to be serviced immediately, instead of waiting for the next return to the event loop. Calling it before the sleep sends the message right away, and the client updates a almost instantly.

An async flush only confirms the sender pushed the bytes out — not that the remote side processed them. For that, follow with a synchronous chaser like h"": since messages on one handle are processed in order, its response confirms every earlier async message has already run.