SafeTypes2
|
The "object" type (denoted by s2obj_t
) is the base type for all externally-exposed types except a few (e.g. s2iter_t
). It defines common interface for derived types.
Before 2025-02-17, all derived types defined by SafeTypes2 were incomplete (C language concept), as they're meant to be used from pointer handles. This is still the case - although you technically can declare a SafeTypes2 object either locally or statically, their interaction with the garbage collection, and even with regard to reference and kept counts when you're opting out of GC, are completely undefined.
The reason now they're being defined to be complete, is that the way they were defined were not compatible with C89 - a compatibility goal which @dannyniu would like to achieve to maximize the audience of the library; also, this make it easier for 3rd-party libraries and applications to create further derived types.
The internal data structures have tag names prefixed with "s2ctx_", whereas externally visible ones are defined as types and not prefixed as such.
Rules of composition:
The SafeTypes2 GC is threading-aware with the help of a reader-writer lock. In multi-threaded applications, threads obtain "reader" locks to prevent GC from operating on data structures that the threads may be using. When GC operates, the "writer" lock is locked, and all threads are stalled and prevented from operating on objects so that GC can safely traverse the graph of reachable objects, marking them and releasing unreachable objects as needed.
The "reader" lock is recursive - threads can invoke codes from 3rd-party libraries and not worry they interfere with the calling code; The "reader" lock is also "rewindable" - if while a "reader" lock is held by the calling thread, an acquire of the "writer" lock (implicitly invoked as part of s2gc_collect
) automatically clears up whilest remembering the "reader" lock.
As such, when all involved threads requests "writer" lock, the GC would eventually operate, regardless of
As long as all threads that had held any "reader" lock eventually calls s2gc_collect
.
This mechanism applies to the GC, and not the rest of the application - threads still need to prevent threading conflict using explicit synchronization.