Overview
The Base module provides small, reusable building blocks that higher-level components can inherit or depend on. Its primary purpose is to standardize common infrastructure concerns (most notably logging) without imposing additional runtime or architectural constraints.
The module is intentionally lightweight:
- It relies on compile-time patterns where possible (e.g., CRTP).
- It keeps ownership semantics explicit via
std::shared_ptr.
- It avoids coupling to external frameworks in its public API documentation.
Key types
The module currently centers around:
- GBase : A CRTP base class that equips derived objects with a ready-to-use logger.
- GLogger : The logging facility used by GBase .
- GOptions : The options/configuration mechanism used to initialize GLogger .
GBase responsibilities
GBase is designed to solve a recurring pattern in component implementations: ensuring that each component can emit consistent log messages with minimal boilerplate.
It provides two common construction modes:
- Dedicated logger per object:
- Construct GBase with a
std::shared_ptr<GOptions>.
- GBase creates a GLogger configured from the provided options.
- Shared logger across objects:
- Construct GBase with an existing
std::shared_ptr<GLogger>.
- Multiple objects can reuse the same logger to reduce initialization cost and keep log routing consistent.
It also standardizes lifecycle logging:
- On construction, GBase emits a constructor message through its logger.
- On destruction, GBase emits a destructor message when a logger is available.
Verbosity and debugging
Many components in GEMC rely on the logging conventions exposed by GLogger and used by GBase. In typical usage:
info(0, ...) is for essential, user-facing messages (minimal, high signal).
info(1, ...) is for additional operational context (useful progress/detail).
info(2, ...) is for very verbose informational output (diagnostics, repeated status).
debug(...) is for developer-focused traces (function-level flow, state snapshots, and messages intended primarily for debugging).
Exact routing/enablement is controlled by the logger configuration (via options).
Typical usage
The common usage pattern is CRTP inheritance:
class MyComponent :
public GBase<MyComponent> {
public:
explicit MyComponent(const std::shared_ptr<GOptions>& gopt)
:
GBase(gopt,
"my_logger_channel") {}
log->info(0, "running");
}
};
CRTP base class that provides logging facilities to the derived class.
Notes:
- The derived class accesses the logger via the protected member
log.
- The derived class does not need to implement any logging bootstrapping logic.
- Passing an empty logger channel name typically selects default behavior in the configured logging backend.
Examples
The examples below are included in the repository as reference implementations and are intentionally small. They are meant to be read alongside the header documentation.
Example: examples/test_gbase.cc
Demonstrates:
- Constructing a derived type that creates its own logger from options.
- Constructing a derived type that reuses a shared logger instance.
- Emitting
info, warning, and debug messages from derived code.
Non-goals
The Base module does not attempt to:
- Provide a full application framework.
- Hide ownership or lifetime rules behind implicit global state.
- Wrap or re-document third-party libraries in its public documentation.
Files in this module
gbase.h : Defines GBase and the type-name demangling helper used for readable diagnostics.
gbaseDoxy.h : This documentation entry point and module landing page.
examples/test_gbase.cc : A small usage example demonstrating both logger construction modes.
Where to look next
- Start with GBase to understand the base class contract and expected inheritance pattern.
- Review GLogger for logging configuration and routing behavior.
- Consult the examples to see typical construction patterns.