Regarding the (im)possibility of "practical realization of promise pipelining in non-GC'd languages"

29 views
Skip to first unread message

David Nicol

unread,
May 27, 2026, 6:31:42 PM (8 days ago) May 27
to cap-...@googlegroups.com

What's a non-garbage-collected language? I gather that one means a language (such as FORTH) where there is only a stack, implying only one thread, that uses that stack.

Promise pipelining, as I understand it, is syntactic sugar for backgrounding a procedure that will error out and stop if any of the instructions within the procedure fail. Promise pipelining is great as it is vastly simpler to write such things using it than it was when one had to bury the code for what one wanted to do within some kind of thread launcher with explicit exception handling pillowing every line of code.

Of course they aren't compatible. To have threads, the inter-thread communications need to live somewhere that isn't going to get recycled because the stack unwinds.

On the other hand, you could do it by requiring all promise pipelines to complete before exiting the stack frame from which they are launched, at the cost of allocating sufficient space in said frame as working memory for the backgrounded thread(s).

But at that point we might be back in "garbage collected language" again, with the GC policy being "recycle all stack frames when done with them."

... a little research into what is meant by "non-GC'd languages" indicates that the term refers to not only languages in which the developers are responsible for the memory management but also languages where the compiler takes care of the details in a way that doesn't involve a background thread occasionally declaring a maintenance window so it can mark and sweep.

One can certainly do reference counting across multiple threads without needing maintenance windows, compiler-provided scaffolding or no. Just good mutexes around the reference counters.

What is meant by "non-GC'd languages" in the quote, and why does promise pipelining (please correct me if my understanding of it is flawed) require a mark-and-sweep process?

In my own project (which I'm now calling "op256" but might change again) designs, I've selected deletable backreferences and copy-on-write rather than marking and sweeping, which might make op256 a "non-GC'd" system. op256 is designed to handle robust concurrency, with storage resources freed when the last backreference goes away. This requires discipline regarding adding a reference to the resource before doing anything with the resource. And storage of lots and lots of ephemeral backreferences.

dln

--
"Plot complication appearing on sensors now"

Matt Rice

unread,
May 27, 2026, 6:38:31 PM (8 days ago) May 27
to cap-...@googlegroups.com
On Wed, May 27, 2026 at 3:31 PM David Nicol <david...@gmail.com> wrote:
>
>
> What's a non-garbage-collected language? I gather that one means a language (such as FORTH) where there is only a stack, implying only one thread, that uses that stack.
>

I think what is typically meant by non-gc languages are the various
means of manual memory management, particularly c, c++, zig, rust, and
other substructural type systems which all have heap and stack
allocation, and vary in their unsafety.
> --
> You received this message because you are subscribed to the Google Groups "cap-talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to cap-talk+u...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/cap-talk/CAFwScO8jwYm9E1khrJF9ewfY72sEqo4fFBvs3EP-601FqYQyVA%40mail.gmail.com.

Chip Morningstar

unread,
May 27, 2026, 6:49:55 PM (8 days ago) May 27
to cap-...@googlegroups.com
I’m not sure I follow.

IIRC, the very first implementation of promise pipelining was in C++ and it worked fine.

The first major implementation I participated in (at Electric Communities) was written in Java. Java *is* GC’d but the issues you outline have to do with threading and this implementation was not really threaded — some threading was required to isolate the Java I/O libraries which at the time didn’t offer a non-blocking option, which necessitated a small, fixed set of threads (7 of them, IIRC) -- but the realization of message handling with promise pipelining was a single-threaded event loop. GC was certainly a convenience but in no way central.

In the same vein, the main contemporary embodiments of these ideas are in JavaScript, which also has GC but is aggressively non-threaded.

— Chip

Matt Rice

unread,
May 27, 2026, 7:31:25 PM (8 days ago) May 27
to cap-...@googlegroups.com
Mark also noted in the other thread that cap-n-proto primarily targets c++,
I'll note that there is also a rust implementation, it is from scratch
in rust though
I don't believe it's just a FFI wrapper.

I totally understand the questions in the other thread about denial of
heap, in particular
none of these languages do a good job of resource accounting, allowing
some promised thing
to be freed whenever the owner damn well pleases.

But I wonder if what shap is referring to about non-gc'd languages can
be explained by noting
that cap-n-proto does come with a runtime library, so I assume the
concern might be within that?
Definitely not familiar with the dynamic allocations within promise
pipelining, or who pays the cost for those.
When it comes to promising revocable resources.
> To view this discussion visit https://groups.google.com/d/msgid/cap-talk/2D9454F2-3D16-4562-968F-6063E9A3378B%40fudco.com.

Matt Rice

unread,
May 27, 2026, 8:20:46 PM (8 days ago) May 27
to cap-...@googlegroups.com
On Wed, May 27, 2026 at 4:31 PM Matt Rice <rat...@gmail.com> wrote:
>
> Mark also noted in the other thread that cap-n-proto primarily targets c++,
> I'll note that there is also a rust implementation, it is from scratch
> in rust though
> I don't believe it's just a FFI wrapper.
>
> I totally understand the questions in the other thread about denial of
> heap, in particular
> none of these languages do a good job of resource accounting, allowing
> some promised thing
> to be freed whenever the owner damn well pleases.
>
> But I wonder if what shap is referring to about non-gc'd languages can
> be explained by noting
> that cap-n-proto does come with a runtime library, so I assume the
> concern might be within that?
> Definitely not familiar with the dynamic allocations within promise
> pipelining, or who pays the cost for those.
> When it comes to promising revocable resources.


Sorry, I kind of lost my train of thought....
Anyhow my other point was that neither rust (memory leaks, panics, are
both considered totally safe)
and failure to allocate memory is considered impossible (panic), and
c/c++ both have laissez faire memory management
which doesn't distinguish between or provide any guarantees across
sharing boundaries.
So I don't think any of these languages are really doing anything for
the other mentioned problem (denial of service)

Raoul Duke

unread,
May 27, 2026, 8:36:34 PM (7 days ago) May 27
to cap-...@googlegroups.com
Note that just because JavaScript is "single threaded" doesn't mean it lacks many fun fun fun concurrency gotchyas as soon as you use async/await and the micro-task queue.

Rob Meijer

unread,
May 28, 2026, 4:26:49 AM (7 days ago) May 28
to cap-...@googlegroups.com
In my project, where I'm currently designing the memory management for a second runtime (while still implementing the first), I'm taking a single owner plus dependencies approach. And because it's an async closures based language, dependencies live down in the scheduling tree as descendents. 

At layer zero I'm using mmap to allocate 8k chunks of memory to schedualables. At layer 1 I'm assigning muttables and immuttables to these pages. 

No reference counting on individual scalars, frames,  dag nodes or tensors, only on pages. Each page is marked as private or closure level. 

When a schedualable finishes and the scheduler handles that event, the private pages get deallocated. If at that point in time no more child schedualables are alive, the closure pages are deallocated too, the child count of the parent is decremented, and if it hits zero and the parent was already marked as completed, the same algorithm repeats for the parent. 

I'm not sure if this would qualify as a garbage collected runtime. Because there really is no garbage collector, just a scheduler cleaning up completed schedualables. But the cleanup does happen seperate from the runners, so I'm not sure if it is garbage collection. 

So far it's just been experiments, my non-compiled  v0. 3 runtime has priority, but so far the experiments look like it's going to work like this. Minimum overhead coarse granularity memory management tied to schedualable lifetimes. 



dln

--
"Plot complication appearing on sensors now"

--
Reply all
Reply to author
Forward
0 new messages