CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
Going Deeper

Everything above is enough to build systems. This page is the expert track: the machinery underneath, and the parts of CMSDK that are valuable even outside Psyclone. Each section links into the reference groups generated from the source, where the full details live.

Shared memory: the backbone — and its ABI rule

A Psyclone node's inter-process state lives in named shared-memory segments owned by the cmlabs::MemoryManager singleton (Shared-Memory Subsystem): a master segment plus segments for the temporal message store (cmlabs::TemporalMemory), the process/queue tables (cmlabs::ProcessMemory), the component registry with parameters and stats (cmlabs::ComponentMemory) and the name↔id maps (cmlabs::DataMapsMemory). On Windows these are named file mappings; on POSIX they are shm_open/mmap regions. Processes attach by name, which is what makes crash isolation and re-attach possible.

Warning
The ABI rule. The structs in these headers are mapped simultaneously into multiple processes: their size, field order and alignment are a de-facto ABI. If you change any shared struct — or update the library — you must rebuild every binary that maps the segments (make clean && make). Mixing binaries built from different layouts silently corrupts shared memory across processes; there is no compiler diagnostic. This is also why make clean matters when switching debug/release.

Messages themselves are cmlabs::DataMessage objects (Messaging): one flat allocation, copied verbatim into shared memory or onto a socket, with typed user entries, arrays and maps, and no serialisation step anywhere.

Threading model

cmlabs::ThreadManager (Threading) is the process-wide registry of every native thread the SDK spawns, with per-thread CPU statistics. The scheduling policy above it maps crank work onto threads two ways: a continuous crank owns a dedicated thread for its lifetime, while a one-shot crank borrows a pool thread each time its trigger fires — which is why the same crank function can run concurrently on several threads and must guard shared state (see Writing a Module (Crank)). Synchronisation primitives (utils::Mutex, events, wait queues) and portable thread wrappers live in Utility functions and objects. Prefer cooperative shutdown (loop on cmlabs::PsyAPI::shouldContinue(), Runnable::stop()) — asynchronously killed threads do not unwind.

The request fabric

For distributed request/response workloads (as opposed to pub/sub), CMSDK ships a three-role fabric (Requests, Networking):

  • cmlabs::RequestClient — wraps each outgoing cmlabs::DataMessage in a RequestReply "future"; block on waitForResult() or register a callback.
  • cmlabs::RequestGateway — the router/load balancer. Accepts requests from many clients over binary, HTTP(S) or WebSocket on the same ports via protocol auto-detection, queues them, picks an executor and routes replies back. Clients and executors dial in; a gateway does not dial out to clients or executors (though gateways can link to other gateways via addGateway), which simplifies firewalling. Includes a call log and an embedded web server.
  • cmlabs::RequestExecutor — the worker. Connects out to gateways, announces itself with heartbeats (used for liveness and load balancing), and separates short (interactive) from long (expensive) request queues so long jobs cannot starve short ones.

This fabric is independent of Psyclone systems — you can use it as a stand-alone RPC/work-distribution layer in any C++ program.

The built-in HTTP server (and PsyProbe)

cmlabs::NetworkManager (Networking) turns any port into a full HTTP(S)/WebSocket server via createListener() with PROTOCOL_HTTP_SERVER — this is exactly how the PsyProbe monitoring UI is served. It also provides an HTTP(S) client (makeHTTPRequest(), including multipart POST), protocol auto-detection per listener, and typed dispatch of parsed protocol objects (HTTPRequest, DataMessage, WebsocketData) either to callbacks or to blocking waitFor*() calls. HTML generation helpers live in HTML.h, REST helpers in RESTAPI.h.

Microsecond time

All timestamps in the system are 64-bit integer microsecond times (Functions dealing with time): GetTimeNow(), GetTimeAge(), conversion and pretty-printing helpers, plus cross-node time synchronisation state in the master shared segment. Message creation/posting times are captured at microsecond resolution — the ping-pong example measures per-message latency this way.

SSL

Build with the SSL targets (see Compiling and linking with the CMSDK library) to enable TLS in the networking stack — server and client side — via the OpenSSL-backed wrappers in PsySSL.h. The SSL library variants carry SSL in their file names.

Utilities and the rest

Utility functions and objects is the everything-drawer that makes the rest portable: strings and formatting (utils::StringFormat), files and directories, processes and dynamic libraries, sockets, shared-memory primitives, timers, compression, Base64 (Base64.h), bitmaps (Bitmap.h), maths and statistics (MathClasses.h, Stats.h, MovingAverage.h, Observations.h), and a unit-test framework (Unit Test Framework, UnitTestFramework.h) used by the SDK's own test suite (Examples/psytest.xml, Examples/src/PsyTest.cpp).

Reference groups

Group Contents
Messaging DataMessage, binary containers, message protocol
Shared-Memory Subsystem Shared-memory segments, maps, queues, allocators
Threading ThreadManager, thread stats and lifecycle
Networking NetworkManager, HTTP/WebSocket server and client
Requests RequestClient / RequestGateway / RequestExecutor
Functions dealing with time Microsecond time functions
Unit Test Framework Unit-test framework
Utility functions and objects Utility functions and objects