π§© Observer Library (MISRA-C / Safety-Oriented Ready)¶
A deterministic, zero-dynamic-memory, and MISRA-C:2012 compliant implementation of the Observer Pattern in pure C β designed for embedded, real-time, and safety-oriented applications.
β οΈ Note: This library is not certified for ISO 26262, DO-178C, or any other formal safety standard. It provides a deterministic, statically-allocated foundation and demonstrates best practices for safety-oriented software design. Formal certification requires additional safety analysis, risk assessment, and documentation.
π Online Documentation¶
Looking for a better browsing experience?
π Explore the full documentation at:
π https://niwciu.github.io/OBSERVER
Includes Doxygen docs, examples, coverage and analysis reports.
Additional reports and analysis:
- π GCOVR Report (Code Coverage)
- π Code Complexity Report
π‘ Recommended: The web version provides full navigation, diagrams, and integration examples with better readability.
π Key Features¶
This library provides a deterministic, static-memory foundation for the Observer pattern, suitable for safety-oriented embedded systems. Its key characteristics include:
- β MISRA-C:2012 compliant β verified via Cppcheck and PC-lint
- β Zero dynamic memory allocation β all subscription tables are statically allocated
- β Deterministic execution β all operations bounded by compile-time table sizes
- β Externally synchronized thread-safety β safe if caller manages access via mutex or critical section
- β Designed for safety-oriented projects β demonstrates best practices in modularity, static memory, and defensive programming
- β Defensive argument validation β all public API functions validate input parameters
- β Full unit test coverage β 100% statement coverage verified with Unity and gcovr
- β Support for static analysis and complexity checks β integrates with Cppcheck, Lizard, clang-format, and Doxygen for maintainability
β οΈ Note: While this library demonstrates safety-oriented design practices, it is not formally certified. Formal certification requires additional safety analysis, documentation, and risk assessment.
π§ Observer Design Pattern β Concept Overview¶
The Observer Pattern defines a one-to-many dependency between objects so that when one object (the Publisher) changes state, all its dependent objects (the Observers) are notified automatically.
In embedded and safety-oriented systems, this pattern enables deterministic event propagation without dynamic allocation or runtime discovery.
π§© Conceptual Flow¶
flowchart TD
A[Publisher / Event Source]
B[Observer #1]
C[Observer #2]
D[Observer #3]
%% Subscriptions
B -->|subscribe| A
C -->|subscribe| A
D -->|subscribe| A
%% Notifications
A -->|notify| B
A -->|notify| C
A -->|notify| D
style A fill:#444444,stroke:#ffffff,stroke-width:2px,color:#ffffff
style B fill:#666666,stroke:#ffffff,stroke-width:1px,color:#ffffff
style C fill:#666666,stroke:#ffffff,stroke-width:1px,color:#ffffff
style D fill:#666666,stroke:#ffffff,stroke-width:1px,color:#ffffff
π‘ How it works: Observers register their callbacks in a static subscription table owned by the Publisher.
When an event occurs, the Publisher callsnotify()deterministically.
No dynamic memory or recursion is used β all behavior is bounded at compile time.
π§© Integration & Observer Library Examples¶
The library provides ready-to-run integration examples in the examples directory.
These demonstrate:
- How to integrate the Observer library into an application.
- Realistic usage patterns with mocked embedded hardware modules (e.g., pushbuttons, LEDs, sensors).
- Deterministic behavior using statically allocated observer tables and MISRA-C:2012 compliant design.
π‘ Each example includes block diagrams and commented code explaining module interactions, subscription flow, and event notifications.
π Available Examples¶
| Example | Description | Folder |
|---|---|---|
| Basic Observer | Simple callback example using pushbutton, LED and LCD mocks | π Open basic_observer |
| State Observer | Observer with event_state_e argument demonstrating ENTER/EXIT states |
π Open state_observer |
| Sensor Observer | Observer with uint8_t argument demonstrating periodic sensor updates |
π Open observer_u8 |
π‘ Each example includes block diagrams and commented code explaining module interactions, subscription flow, and event notifications.
β οΈ All examples demonstrate deterministic behavior using statically allocated tables and are not certified for safety-critical use.
βΉοΈ Seeexamples/README.mdfor detailed explanations and flow diagrams.
π Directory Layout¶
/observer_lib/
βββ .github/
β βββ workflows/ # Github Actions workflows
βββ docs/ # Files required for deploy library webpage & publish documentation
βββ examples/
β βββ basic_observer/ # Basic no-arg callback
β βββ state_observer/ # Uses event_state_e argument callback
β βββ observer_u8/ # Uses uint8_t argument callback
β βββ README.md # Examples description file
β
βββ hw/ # Specific hardware configurations
βββ lib/
β βββ observer/
β βββ observer.c # Core implementation
β βββ observer.h # Public API
β βββ observer_public_types.h # Enums & callback typedefs
βββ test/
β βββ config_scripts/
β β βββ run_targets
β β β βββ CI.py # CI python script to run on local machine
β β β βββ config.yaml # CI config file for setup and customize CI workflow
β β βββ venv_setup
β β βββ requirements.txt # Python tools required by scripts in project
β β βββ venv_setup.py # Python script for setting up venv and install dependencies
β βββ observer/ # Unit tests (Unity)
β βββ template/ # Module unit tests template
β βββ unity/ # Test framework
βββ .clang-format # clang-format rules
βββ LICENSE
βββ mkdocs.yml # MkDocs deploy settings
βββ README.md
β οΈ Note: All examples are deterministic, statically allocated, and intended for demonstration purposes; they are not certified for safety-critical use.
π§ Core Concepts¶
| Role | Responsibility |
|---|---|
| Publisher | Maintains a static table of observer callbacks and notifies them upon events. |
| Observer | Registers a callback function to receive event notifications. |
| Event | A deterministic trigger (button press, state change, sensor update). |
βοΈ Why This Implementation Is Different¶
Unlike typical dynamic implementations, this library is:
- Zero-dynamic-memory β all subscription tables are statically allocated.
- MISRA-C:2012 compliant β validated through Cppcheck and PC-lint.
- Deterministic β every operation bounded at compile time.
- Safety-oriented β promotes traceability and modular isolation of side effects.
π‘ This implementation bridges the conceptual simplicity of the Observer Pattern with the rigorous requirements of safety-critical embedded software.
For detailed integration examples, see π§© Observer Library Examples.
βοΈ Public API Reference¶
1οΈβ£ Callbacks Without Arguments¶
subscribe()¶
subscr_status_e subscribe(observer_cb_t *subscription_table,
observer_cb_t cb_2_register,
uint8_t subscription_table_size);
Registers a callback function. Returns one of:
OBSERVER_OKβ callback registered or already presentOBSERVER_INVALID_ARGUMENT_ERRORβ invalid pointer or zero sizeOBSERVER_TABLE_FULL_ERRORβ no free slot available
unsubscribe()¶
subscr_status_e unsubscribe(observer_cb_t *subscription_table,
observer_cb_t cb_2_register,
uint8_t subscription_table_size);
Removes a callback and compacts the table. Returns:
OBSERVER_OKOBSERVER_TABLE_EMPTY_ERROROBSERVER_INVALID_ARGUMENT_ERROR
notify()¶
subscr_status_e notify(observer_cb_t *subscription_table,
uint8_t subscription_table_size);
Invokes all registered callbacks sequentially. Returns:
OBSERVER_OKβ at least one callback executedOBSERVER_TABLE_EMPTY_ERRORβ no callbacks registeredOBSERVER_INVALID_ARGUMENT_ERROR
2οΈβ£ Callbacks with event_state_e Argument¶
subscribe_state_change()¶
subscr_status_e subscribe_state_change(observer_cb_state_t *subscription_table,
observer_cb_state_t cb_2_register,
uint8_t subscription_table_size);
unsubscribe_state_change()¶
subscr_status_e unsubscribe_state_change(observer_cb_state_t *subscription_table,
observer_cb_state_t cb_2_register,
uint8_t subscription_table_size);
notify_state_change()¶
subscr_status_e notify_state_change(observer_cb_state_t *subscription_table,
uint8_t subscription_table_size,
event_state_e state);
3οΈβ£ Callbacks with uint8_t Argument¶
subscribe_u8()¶
subscr_status_e subscribe_u8(observer_cb_u8_arg_t *subscription_table,
observer_cb_u8_arg_t cb_2_register,
uint8_t subscription_table_size);
unsubscribe_u8()¶
subscr_status_e unsubscribe_u8(observer_cb_u8_arg_t *subscription_table,
observer_cb_u8_arg_t cb_2_register,
uint8_t subscription_table_size);
notify_u8()¶
subscr_status_e notify_u8(observer_cb_u8_arg_t *subscription_table,
uint8_t subscription_table_size,
uint8_t data);
π§© Return Codes (subscr_status_e)¶
| Code | Meaning |
|---|---|
OBSERVER_OK |
Operation successful |
OBSERVER_INVALID_ARGUMENT_ERROR |
Invalid pointer or table size |
OBSERVER_TABLE_FULL_ERROR |
No free slot available |
OBSERVER_TABLE_EMPTY_ERROR |
Table contains no valid entries |
βοΈ Running Library Targets¶
π Build library¶
To build and run any of the predefined targets, follow this sequence of commands from the main project library location:
# Navigate to the observer test folder
cd test/observer
# Configure the build with CMake
# Use "Unix Makefiles" or "Ninja" generator
cmake -S ./ -B out -G "Unix Makefiles"
# cmake -S ./ -B out -G "Ninja"
# Enter the output folder
cd out
# Build the library targets
make all # or use: ninja
This sequence ensures the library and example targets are properly compiled and ready for execution.
After building the library, you can run any of the predefined targets, such as:
π Run Analysis and Reports generation¶
| Task | Command |
|---|---|
| π§ͺ Unit Tests | make run |
| π Static Analysis (Cppcheck) | make cppcheck |
| π Cyclomatic Complexity | make ccm |
| π Code Coverage | make ccc |
| π Generate Cyclomatic Complexity report | make ccmr |
| π Generate Code Coverage report | make ccr |
| β¨ Format library source | make format |
| β¨ Format test code | make format_test |
π§° Safety-Oriented Design Summary¶
This library demonstrates safety-oriented design practices suitable for embedded, real-time, and safety-critical systems.
- β Static memory only β no dynamic allocation
- β Deterministic execution β bounded by compile-time table size
- β Defensive input validation β all public APIs validate arguments
- β Externally synchronized thread safety β caller manages access if needed
- β MISRA-C:2012 compliant β verified via static analysis
- β Portable β GCC, IAR, ARMCC, GHS, etc.
β οΈ Note: This summary demonstrates safety-oriented practices. Formal certification (ISO 26262, DO-178C, or similar) requires additional safety analysis, risk assessment, and documentation.
β οΈ Safety-Critical Compliance Matrix¶
| ID | Requirement | Status |
|---|---|---|
| SC-1 | No dynamic memory | β |
| SC-2 | Deterministic control flow | β |
| SC-3 | Defensive input validation | β |
| SC-4 | MISRA-C:2012 compliance | β |
| SC-5 | Full unit test coverage (100β―% stmt) | β |
| SC-6 | Externally synchronized thread safety | β |
| SC-7 | Static analysis clean | β |
β οΈ This matrix reflects safety-oriented practices. Formal compliance requires additional safety documentation.
π§ Notes¶
- Publisher owns the static subscription table.
- Subscribers register callbacks using the publisherβs API.
- All operations are deterministic and zero-dynamic-memory.
- Designed following MISRA-C:2012 and safety-oriented software design practices.
β The clean modular separation and static memory usage make these examples ideal for real-time, embedded, and safety-oriented applications.
β οΈ Note: This demonstrates safety-oriented practices; the library is not certified.
π§© Practical Examples in /examples/¶
For more realistic use cases β including mocked hardware modules such as pushbuttons, LEDs, and sensors β check the examples/ directory.
These examples illustrate:
- Publisher/Subscriber interaction using hardware abstraction layer (HAL) mocks.
- Deterministic execution under embedded-like constraints.
- Clear modular separation, suitable for unit testing and safety certification.
π‘ Each example is fully self-contained and demonstrates real embedded-like execution flow using the same static Observer core.
π License¶
Released under the MIT License β see LICENSE.
Β© 2025 niwciu
Part of the myEmbeddedWay safety-oriented C library collection.