Skip to content

S11.06: Sweep — POSIX adapters onto PoolAllocator #405

Description

@DavidCozens

Parent epic: #29

Context

S11.05 (#401 / #402 / #403) closed the Core sweep. This story is the first
platform-adapter sweep — POSIX. Six classes in Platform/Posix/ carry state
captured at _Create time and are file-scope singletons or storage-cast
today; all six get the canonical 3-TU split + SolidSyslogPoolAllocator
treatment.

Class Lines Vtable base Today's shape State
PosixMutex 63 Mutex Storage-cast pthread_mutex_t
PosixFile 159 File Storage-cast FILE*
PosixTcpStream 300 Stream Storage-cast socket FD, connect state
PosixDatagram 156 Datagram File-scope singleton socket FD
GetAddrInfoResolver 88 Resolver File-scope singleton none
PosixMessageQueueBuffer 97 Buffer File-scope singleton mqd_t, size + count

Out of scope per E11 epic: the five POSIX function-adapters (PosixClock,
PosixHostname, PosixProcessId, PosixSysUpTime, PosixSleep) — stateless,
no _Create.

Decisions locked in pre-raise

1. Four new public GoF nulls land in S11.06, mirroring S11.04's NullSender

  • NullSd precedent. Each is reused immediately by the next platform sweeps:
New Used by S11.06 Future consumer
SolidSyslogNullDatagram PosixDatagram S11.08 FreeRtosDatagram
SolidSyslogNullStream PosixTcpStream S11.07 WinsockTcpStream, S11.08 FreeRtosTcpStream, S11.09 TlsStream
SolidSyslogNullFile PosixFile S11.07 WindowsFile, S11.09 FatFsFile
SolidSyslogNullResolver GetAddrInfoResolver S11.08 FreeRtosStaticResolver

SolidSyslogNullMutex (existing) and SolidSyslogNullBuffer (existing) cover
the remaining two. No class-private fallbacks anywhere in S11.06.

2. NullMutex migrates from _Create/_Destroy to _Get inside S11.06.
The other GoF nulls (NullSender, NullStore, NullSd, NullSecurityPolicy,
NullBuffer, NullBlockDevice) are all on the _Get(void) shape. NullMutex
is the only odd one out. PosixMutex's fallback wiring lives in this story so
the shape-fix lands here too. Affected callers — Tests/SolidSyslogNullMutexTest.cpp,
Tests/SolidSyslogCircularBufferTest.cpp, Tests/SolidSyslogTest.cpp,
Tests/SolidSyslogBlockStoreDrainOrderingTest.cpp — get caller-site updates
in the same commit. Crc16Policy keeps its _Create/_Destroy shape; it's
not a null object and stays out of scope here.

3. PosixMessageQueueBuffer keeps its positional _Create(size_t maxMessageSize, long maxMessages) — no config struct. Pure mechanical migration. long for
maxMessages mirrors the upstream mq_attr.mq_maxmsg type and is fine under
the Pragmatic naming tier for Platform/*/Source/.

4. Pool size default 1U for every class. BDD targets and tests create one
instance per binary. Override via SOLIDSYSLOG_USER_TUNABLES_FILE per the
existing tunables mechanism.

Class Tunable Default
PosixMutex SOLIDSYSLOG_POSIX_MUTEX_POOL_SIZE 1U
PosixFile SOLIDSYSLOG_POSIX_FILE_POOL_SIZE 1U
PosixTcpStream SOLIDSYSLOG_POSIX_TCP_STREAM_POOL_SIZE 1U
PosixDatagram SOLIDSYSLOG_POSIX_DATAGRAM_POOL_SIZE 1U
GetAddrInfoResolver SOLIDSYSLOG_GETADDRINFO_RESOLVER_POOL_SIZE 1U
PosixMessageQueueBuffer SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_POOL_SIZE 1U

5. Three-TU split per class — unchanged from prior sweeps:

  • SolidSyslog<Class>.c — vtable + _Initialise/_Cleanup.
  • SolidSyslog<Class>Private.h — concrete struct + private signatures, TU-internal.
  • SolidSyslog<Class>Static.c — pool + _Create/_Destroy/IndexFromHandle
    • CleanupAtIndex + fallback assignment.

6. No new MISRA suppressions. Storage-cast deviations on the three
storage-cast classes are removed by this story (the whole point).

7. File-scope statics carry the class-prefix shape (PosixMutex_InUse,
PosixMutex_Pool, PosixMutex_Allocator) from the start, per S11.04
convention.

Sequencing on the work branch

Recommended commit shape on refactor/s11-06-posix-sweep:

  1. feat: S11.06 add SolidSyslogNullDatagram
  2. feat: S11.06 add SolidSyslogNullStream
  3. feat: S11.06 add SolidSyslogNullFile
  4. feat: S11.06 add SolidSyslogNullResolver
  5. refactor: S11.06 migrate NullMutex to _Get shape
  6. refactor: S11.06 migrate PosixMutex onto PoolAllocator
  7. refactor: S11.06 migrate PosixDatagram onto PoolAllocator
  8. refactor: S11.06 migrate GetAddrInfoResolver onto PoolAllocator
  9. refactor: S11.06 migrate PosixFile onto PoolAllocator
  10. refactor: S11.06 migrate PosixTcpStream onto PoolAllocator
  11. refactor: S11.06 migrate PosixMessageQueueBuffer onto PoolAllocator
  12. docs: update DEVLOG for S11.06

Squash-merge title: feat: S11.06 POSIX adapters onto PoolAllocator.

Per-class scope

For each of the six classes, the migration commit lands:

Storage-cast classes (PosixMutex, PosixFile, PosixTcpStream):

  1. SolidSyslog<Class>.c — vtable + _Initialise(base, ...) + _Cleanup(base).
  2. SolidSyslog<Class>Private.h — TU-internal struct + private signatures.
  3. SolidSyslog<Class>Static.c — pool + Create/Destroy/IndexFromHandle/CleanupAtIndex.
  4. Public header — delete <Class>Storage typedef and SOLIDSYSLOG_<*>_SIZE
    enum; drop the storage parameter from _Create; _Destroy(base) shape.
  5. Tunable in Core/Interface/SolidSyslogTunablesDefaults.h.
  6. Error messages in Core/Source/SolidSyslogErrorMessages.h.
  7. Platform/Posix/Source/CMakeLists.txt — add the three new TU entries.
  8. Existing test file — drop <*>Storage locals; switch to handle-based teardown.
  9. New Pool TEST_GROUP — 9 tests mirroring SolidSyslogCircularBufferPool.
  10. CLAUDE.md audience-table row updated.

File-scope singletons (PosixDatagram, GetAddrInfoResolver, PosixMessageQueueBuffer):

1–3. Same 3-TU split.
4. Public header_Destroy(void) → _Destroy(handle); no Storage deletion (none today).
5–10. Tunable / error messages / CMakeLists / test rewire / Pool TEST_GROUP / audience table.

Caller updates land in each per-class commit:

  • Bdd/Targets/Linux/main.c
  • Bdd/Targets/Common/BddTargetTlsSender_OpenSsl_PosixTcp.c
  • Tests/SolidSyslogPosix{Mutex,File,TcpStream,Datagram,MessageQueueBuffer}Test.cpp
  • Tests/SolidSyslogGetAddrInfoResolverTest.cpp
  • Tests/SolidSyslog{UdpSender,StreamSender,BlockStorePosix}Test.cpp
  • Tests/Bdd/Targets/BddTargetServiceThreadTest.cpp

Public API changes

Storage-cast classes (before → after):

/* Before */
struct SolidSyslogMutex*   SolidSyslogPosixMutex_Create(SolidSyslogPosixMutexStorage*);
struct SolidSyslogFile*    SolidSyslogPosixFile_Create(SolidSyslogPosixFileStorage*);
struct SolidSyslogStream*  SolidSyslogPosixTcpStream_Create(SolidSyslogPosixTcpStreamStorage*);

/* After */
struct SolidSyslogMutex*   SolidSyslogPosixMutex_Create(void);
struct SolidSyslogFile*    SolidSyslogPosixFile_Create(void);
struct SolidSyslogStream*  SolidSyslogPosixTcpStream_Create(void);

<Class>Storage typedefs and SOLIDSYSLOG_<*>_SIZE enums deleted from public headers.

Singletons (before → after):

/* Before */
void SolidSyslogPosixDatagram_Destroy(void);
void SolidSyslogGetAddrInfoResolver_Destroy(void);
void SolidSyslogPosixMessageQueueBuffer_Destroy(void);

/* After */
void SolidSyslogPosixDatagram_Destroy(struct SolidSyslogDatagram* base);
void SolidSyslogGetAddrInfoResolver_Destroy(struct SolidSyslogResolver* base);
void SolidSyslogPosixMessageQueueBuffer_Destroy(struct SolidSyslogBuffer* base);

NullMutex shape fix:

/* Before */
struct SolidSyslogMutex* SolidSyslogNullMutex_Create(void);
void                     SolidSyslogNullMutex_Destroy(void);

/* After */
struct SolidSyslogMutex* SolidSyslogNullMutex_Get(void);

Acceptance criteria

  1. Four new public GoF nulls (NullDatagram, NullStream, NullFile,
    NullResolver) ship with audience-table entries, 100% coverage, no new
    MISRA findings.
  2. SolidSyslogNullMutex migrated to _Get(void) shape; all callers updated.
  3. All six POSIX classes migrated onto SolidSyslogPoolAllocator. Per-class
    *Static.c lands at ≤ ~3 file-scope functions + CleanupAtIndex.
  4. Public SolidSyslogPosix{Mutex,File,TcpStream}Storage types and their
    SOLIDSYSLOG_*_SIZE enums gone from Platform/Posix/Interface/.
  5. Per-class Pool TEST_GROUP — 9 tests mirroring SolidSyslogCircularBufferPool.
  6. All previously existing tests continue to pass.
  7. All gates green: debug, clang-debug, sanitize, coverage, tidy, cppcheck,
    clang-format, iwyu.
  8. cppcheck-misra produces no new findings vs main. Per-class storage-cast
    deviations evaporate — record which in DEVLOG (feedback_cppcheck_misra_invariant).
  9. Coverage at 100% line for every new and migrated file.
  10. Validation step: per migrated class, re-run the full suite at
    SOLIDSYSLOG_<CLASS>_POOL_SIZE=3 via SOLIDSYSLOG_USER_TUNABLES_FILE.
  11. Verify in cpputest-freertos container per
    feedback_verify_in_freertos_host_image (BlockStorePosixTest runs there).
  12. DEVLOG entry on the work branch BEFORE the PR per feedback_devlog_in_pr.

Out of scope

  • POSIX function-adapters (PosixClock, PosixHostname, PosixProcessId,
    PosixSysUpTime, PosixSleep) — stateless, no _Create.
  • Crc16Policy — still uses _Create/_Destroy; not a null object; separate
    cleanup (likely S11.11).
  • SolidSyslogAddress / SolidSyslogAddressInternal — utility functions on a
    struct, no Create.
  • Windows / FreeRTOS / TLS / FatFs / AtomicCounter adapters — S11.07–S11.09.
  • SolidSyslog core retrofit — S11.10.
  • Wholesale MISRA storage-cast deviation removal — S11.11. This story removes
    only the three deviations applying to its three storage-cast classes.

Memory pointers for the next session

  • CLAUDE.md + SKILL.md.
  • MEMORY.md, especially:
    • project_e11_static_pool_design
    • project_e11_three_tu_split
    • project_pool_allocator_helper
    • project_configlock_injection
    • feedback_storage_pattern — obsoleted per class as each migrates
    • feedback_bad_setup_contract — fallback severity vocabulary
    • feedback_discuss_production_changes
    • feedback_tdd_and_review_style
    • feedback_drive_arg_values_in_same_test
    • feedback_no_premature_generalisation
    • feedback_cppcheck_misra_invariant
    • feedback_devlog_in_pr
    • feedback_pr_template
    • feedback_no_git_commit_dash_s
    • feedback_no_merge
    • feedback_verify_in_freertos_host_image
  • E11 epic body (E11: Static-Allocation Variant #29).
  • S11.04 DEVLOG entry (singleton sweep precedent).
  • S11.05 part A + part B DEVLOG entries (storage-cast sweep + composition precedent).

Open questions for the next session

  • PosixTcpStream's bounded blocking connect via SO_SNDTIMEO is captured
    in the audience-table row — confirm during migration that the timeout
    semantics survive the slot-allocated rewrite.
  • GetAddrInfoResolver has no state today — the file-scope instance is
    effectively a vtable holder. Migrating it onto PoolAllocator is honest (it
    still has a Resolver slot to vend) but it could equivalently become a
    pure null/get-style _Get(void). Default: pool-migrate for consistency
    with every other Resolver/Datagram/Stream impl that will have state.
  • PosixMessageQueueBuffer's mq_open failure mode — Create today returns
    the singleton instance unconditionally and stashes whatever mqd_t comes
    back. Pool-migration is a good moment to either keep that, or route an
    mq_open failure to the NullBuffer fallback. Default: keep current
    behaviour (mechanical migration); discuss separately if the failure-mode
    hardening fits E12 instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    storyStory issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions