so true. This is one ecosystem where you could actually just include another persons code as if it was yours, and get a great understanding of how to use it from a header.
Being able to drop in to low-level C for real-time applications (audio, in my case) was a great aspect of ObjC. Though there were plenty of times I wished I could program in ObjC in the real-time threads. There were many debates on the Core Audio forums about whether ObjC was safe in real-time threads. Most of Core Audio was developed by C++ programmers, and their default was to avoid ObjC out of a fear that a surprise lock or memory allocation would glitch out the audio. There was, however, at least one NeXT veteran on the forums who felt this was nonsense, and recalled writing device drivers in ObjC.
So did I.
https://www.nextop.de/NeXTstep_3.3_Developer_Documentation/O...
It was quite lovely, and I later heard from Apple kernel devs that moving to C++ from Objective-C was one of their biggest regrets.
You cannot use any GC-based language if you want to guarantee an upper bound on latency. You cannot use any language that uses global or even large-scope locks if you want to guarantee an upper bound on latency.
It has nothing to do with "writing device drivers" - there are plenty of device drivers for which latency is not anything like the issue that it is for audio.
ObjC wasn't then and isn't now an GC-based language.
My copy of Jones and Lins "Garbage Collection" textbook includes Reference Counting as its first item its "classical algorithms" chapter.
It's usually non-tracing, but variants that can cycle collect will even do some limited tracing to resolve cycles.
And the original comment about latency still stands, even for RC. A single de-reference can lead to a whole series of collections, taking an unknown amount of time, and thrashing cache in the process. A deep tree of objects deleted at the top creates a cascade of de-references. And modern high level languages tend to encourage deep object trees.
When doing realtime programming, I avoid anything with GC. Out of experience. Yes it is possible to tune GC for realtime performance -- but it's fiddly, and never perfect. There are systems tuned for incremental realtime collection -- but there is a cost to this.
As software engineers our job is to pick the right tool for the job. I had many years usually almost exclusively garbage collected languages (including Objective C) before ending up where I am now (I work mainly in C++ lower down the stack)
Manual memory management still exists for a reason.
But there is a cognitive overhead cost to working with Rust. Or even just following consistent RAII patterns in C++. It doesn't come for free.
Trade-offs.
Malloc heuristics also mean that it is not true that everything is 100% deterministic at runtime. It's easy to forget that malloc is simply an abstraction like any other. When do free memory blocks get reshuffled between threads in a thread-caching malloc? When does unused memory get returned to the OS? These are all things that cannot be predicted. Even retain and release are not 100% deterministic, as they can and will be optimized away by the compiler.
[1]: https://www.memorymanagement.org/glossary/g.html#term-garbag...
a reference counting gc is a form of garbage collection.
not sure what applies here, as am not versed in objc, but, the terms are distinct - in theory one can have an object system that refcounts objects so that they are not mis-deleted if some reference still exists and the object is accidentally deleted by some code, but still allow for mostly-manual memory management.
Ruby also never had much if any cooperate backing. MRI / CRuby is still by and large improved by people in their free time. It wasn't until the past 2 may be 3 years did Github and Shopify had some interest in the Ruby Runtime.
1: https://www.wired.com/1996/02/jobs-2/