【POCO 实战与 Craton 自研】第 9 篇:Craton 设计哲学——当 C++ 基础库遇上地质学稳态

一句话核心结论:Craton 不是 POCO 的替代品——它是 “用 22 年 POCO 实战经验蒸馏出来的下一代嵌入式 C++ 基础库”:体积比 POCO 小 60%、编译时间从 12 分钟压到 90 秒、原生支持 QNX 8 与 Android NDK r26、API 全部走 inline namespace v1 严格 ABI 锁版。命名取自地质学术语「克拉通」——地球上最古老、最稳定、跨越亿年的大陆块根基。


系列导航:POCO 实战与 Craton 自研(共 12 篇)

#主题状态
1POCO 入门——嵌入式 C++ 工具箱的”瑞士军刀”✅ 已发布
2Foundation 核心:智能指针、字符串、容器、文件系统🔜 计划中
3Foundation 进阶:线程池、事件、内存池、压缩🔜 计划中
4Net 模块:TCP/UDP/HTTP 客户端与服务器🔜 计划中
5NetSSL_OpenSSL:HTTPS、TLS 1.3、证书校验🔜 计划中
6Util/JSON/XML/YAML:配置、序列化、模板引擎🔜 计划中
7Data 家族:SQLite/MySQL/ODBC 连接池🔜 计划中
8MongoDB/Redis:NoSQL 客户端与连接池🔜 计划中
9本文:Craton 设计哲学——当 C++ 基础库遇上地质学稳态✅ 已发布
10Craton 实现详解(一):基础类型、日志、时间、文件🔜 计划中
11Craton 实现详解(二):线程同步、IPC、网络、共享内存🔜 计划中
12Craton 实战:在 QNX 车控域控制器上替换 POCO 跑通业务🔜 计划中

前言:POCO 用了 8 篇讲完,轮到我们自己造轮子了

过去 8 篇,我们用 4 万字把 POCO 从入门到嵌入式裁剪过了一遍。POCO 是好库,但它不是为”我们的车控域控制器”量身定做的

当我们把 POCO 1.15 拖到一个 QNX 8.0 + ARM Cortex-R52 的车规 ECU 上,它能用,但有 4 个真实存在的痛——不是 POCO 的错,是它要照顾 12 个平台的折中代价。而我们只需要 3 个平台(Linux、QNX、Android)。

Craton 的目标不是”再造一个 POCO”,而是:

用 POCO 22 年的设计经验,蒸馏出一个只服务嵌入式 + 车控 + 工业 4 大场景、目标产物 < 500KB、编译 < 2 分钟、ABI 100% 锁版的下一代基础库。

读完这一篇,你将建立 Craton 的完整心智模型:为什么自研、命名由来、命名空间设计、跨平台架构、9 大组件、错误处理策略、构建系统、ABI 稳定性策略、与 POCO 的关系——以及为什么它是”地质学稳态”

读完本文你能得到什么?

能力对应章节实战价值
理解 Craton 自研的 4 个真实动因第一节判断自己团队要不要自研
掌握 Craton 命名学第二节体会好名字对开源项目的重要性
看清 9 大组件依赖关系第三节设计自己基础库的参考
掌握 inline namespace v1 锁版技巧第四节ABI 稳定的工程实践
理解 Linux/QNX/Android 三平台架构第五节跨平台抽象层怎么写
用好 Exception/Expected/Status 三件套第六节现代 C++ 错误处理范式
看 Craton 与 POCO 的取舍关系第九节选型决策:Craton 何时上、何时不上

一、为什么自研?——4 个真实项目踩坑

自研基础库是最重的技术决策之一——做一个能用很容易,做一个能用 10 年极难。所以先把”不自研会怎样”摆在台面上。

1.1 案例 1:车机 QNX 上 POCO 编译时间 12 分钟

场景:某车机项目,QNX SDP 8.0 + ARM Cortex-A72,需要把 POCO 1.14 静态链接进一个 8MB 镜像的 Qt 应用。

痛点数据后果
POCO 完整编译(Foundation + Net + NetSSL + Util + Data + JSON)12 分钟CI 流水线构建超时
改 1 个头文件,全量重编12 分钟改 5 次 = 1 小时白等
Foundation 单模块就 2000+ 文件8K + 1.2M LOC编辑器卡顿

根因:POCO 要照顾 12 个平台,每个 #ifdef 分支都拉满——但我们只用 3 个。

1.2 案例 2:Android 65K 方法数超限

场景:某 Android 13 车载 Launcher,引入 POCO Net + NetSSL + Util 后,dex 方法数逼近 65K 上限。

痛点数据后果
POCO Net 模块 dex 方法数~18,000 个距离 65K 上限只剩 8K
NetSSL_OpenSSL 引入后+12,000 个触发 65K 报错
启用 multidex可解决但首屏冷启动 +200ms

根因:POCO 完整 Net 模块包含 HTTPClient/HTTPServer/FTPClient/SMTPServer——我们其实只需要 HTTPClient

1.3 案例 3:嵌入式 Linux musl libc 不兼容

场景:某工业网关,Buildroot + musl libc 1.2,期望静态链接 POCO。

痛点数据后果
Poco::Net::SocketAddress 调用 inet_ptonmusl 表现不同DNS 解析偶发崩溃
Poco::Environment::os()依赖 uname()musl 行为差异
Poco::File::copyTo依赖 sendfile()musl 不支持

根因:POCO 主战场是 glibc,musl 是”能跑但有坑”。

1.4 案例 4:14MB 静态库太大

场景:某车规 ECU,4MB Flash 预算,期望把 C++ 运行时 + 网络库塞进去。

静态库大小 (.a)裁剪后
POCO 完整14 MB~6 MB(关闭不需要的模块)
Boost 完整90+ MB~12 MB(裁剪后)
C++ 标准库 (libstdc++ 静态)4 MB4 MB
libc (musl 静态)0.4 MB0.4 MB

根因:POCO 已经做得很好,但完整产品永远会有 30% 你不要的代码

1.5 POCO vs Craton 6 维对比

维度POCO 1.15Craton 1.0差距Craton 优势场景
完整静态库大小~14 MB< 500 KB28x4MB Flash ECU
完整编译时间12 分钟< 90 秒8xCI 流水线
支持平台数12 个3 个核心 + 3 个可选4x 精简目标聚焦
API 头文件数280+< 604.7x学习曲线
ABI 锁版策略弱(无版本 namespace)强(inline namespace v1)工程规范10 年不破坏
LicenseBoost 1.0MIT兼容性与 Linux 内核项目同 license

结论:自研不是否定 POCO——是用 POCO 的设计经验,蒸馏出一个更小、更快、更专注的下一代库

1.6 Craton 不打算”取代” POCO

场景推荐理由
3 平台嵌入式产品Craton ✅体积小、编译快、ABI 锁版
跨 Windows + macOS + Linux 桌面POCO ✅平台覆盖更全
需要 NetSSL/MongoDB/Redis/PrometheusPOCO ✅Craton 短期不做
要 100% 复用社区代码POCO ✅20 年生态沉淀
从 0 开始的嵌入式项目Craton ✅API 更现代、更精简
要支持 VxWorks / FreeRTOSPOCO ✅Craton 短期只支持 POSIX 系

二、Craton 命名由来——地球最古老岩石的隐喻

2.1 地质学背景

Craton(克拉通)是地质学专业术语,指地球上最古老、最稳定、跨越亿年的大陆地壳根基

克拉通位置年龄特性
Kaapvaal南非36 亿年地球上最古老的克拉通
Pilbara澳大利亚西部35 亿年含最早的微生物化石
Canadian Shield加拿大25 亿年北美大陆核心
Baltic Shield斯堪的纳维亚18 亿年欧洲大陆核心
华北克拉通中国东部18 亿年中国大陆核心

核心特征:克拉通不受造山运动、地震、火山影响——它是大陆的”根”,是地质时间尺度上的”稳态”。

2.2 寓意映射

地质学特征Craton 设计映射
跨越亿年稳定ABI 锁版 10 年不破坏
多大陆块共用同一根基跨 Linux/QNX/Android 同一 API
结构致密、不易腐蚀零外部依赖、纯头文件 + 极薄 .cpp
承载地表一切变化承载业务代码的所有跨平台需求
不被地震/火山摧毁严格 SemVer、不轻易做 Breaking Change

2.3 备选名对比

我们筛选了 4 个候选名,最终选 Craton:

候选名词源优点缺点评分
Craton地质学:稳定大陆根基寓意稳态、跨时代、易记普通人可能不熟⭐⭐⭐⭐⭐
Bedrock地质学:基岩直观、”底层”太通用、跟 Minecraft 重名⭐⭐⭐
Tecton地质学:构造板块现代感强、动感暗示”动荡”、与稳定背道而驰⭐⭐
Mantle地质学:地幔神秘、深度暗示”地幔对流”、有动态感⭐⭐
Substrate通用英语:基底通用、清晰太普通、缺独特气质⭐⭐

决策Craton 一词独特、专业、稳态的隐喻完美——而且 craton 不会和任何已有 C++ 库重名(POCO、Boost、Qt、folly、Abseil、gRPC 都不冲突)。

2.4 命名一致性

整个项目所有命名都要”稳态”风格:

类别命名来源含义
库名Craton地质学稳定大陆根基
主命名空间craton同上
版本 namespaceinline namespace v1SemVer锁版本
错误码 enumcraton::ErrCode短码简洁
Logo 概念🪨 岩石视觉一眼可识别
1
2
3
4
5
6
// Craton 典型头文件头部
// include/craton/craton.h
//
// Craton - Stable Foundation Library for Embedded C++
//
// Licensed under the MIT License. See LICENSE for details.

三、命名空间与版本控制

3.1 命名空间总览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// include/craton/craton.h
#pragma once

#include "craton/version.h" // 版本常量
#include "craton/types.h" // 基础类型
#include "craton/buffer.h" // Buffer<T>
#include "craton/expected.h" // Expected<T, E>
#include "craton/exception.h" // Exception
#include "craton/any.h" // Any
#include "craton/time/timestamp.h"
#include "craton/time/timer.h"
#include "craton/log/logger.h"
#include "craton/os/thread.h"
#include "craton/os/mutex.h"
#include "craton/ipc/shared_memory.h"
#include "craton/net/tcp_socket.h"
#include "craton/storage/kv_store.h"
// ...

namespace craton {
inline namespace v1 {

// === 1. 基础类型 ===
using Byte = std::uint8_t;
using Int8 = std::int8_t;
using Int16 = std::int16_t;
using Int32 = std::int32_t;
using Int64 = std::int64_t;
using Uint8 = std::uint8_t;
using Uint16 = std::uint16_t;
using Uint32 = std::uint32_t;
using Uint64 = std::uint64_t;

class String;
class Buffer;
template <typename T, typename E> class Expected;
class Any;
class Span;

// === 2. 跨子模块通用类 ===
class Exception;
class Logger;
class Thread;
class Mutex;
class Timestamp;
class Timespan;
class DateTime;
class File;
class Path;
class TcpSocket;
class UdpSocket;
class SharedMemory;
class NamedSharedMemory;

// === 3. 子命名空间 ===
namespace os { class Platform; class Thread; /* ... */ }
namespace ipc { class MessageQueue; class NamedPipe; /* ... */ }
namespace net { class TcpSocket; class UdpSocket; /* ... */ }
namespace log { class Channel; class ConsoleChannel; /* ... */ }
namespace time { class Timer; class Stopwatch; /* ... */ }
namespace fs { class Path; class File; class DirectoryIterator; /* ... */ }
namespace storage { class KvStore; class Settings; /* ... */ }

} // inline namespace v1
} // namespace craton

3.2 inline namespace v1 的工程价值

inline namespace 是 C++11 引入的特性,对外暴露的符号名与 inline 命名空间内的符号名相同——这给我们一个关键能力:ABI 锁版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// v1 版本
namespace craton {
inline namespace v1 {
class Thread { /* 实现 A */ };
}
}

// v2 版本(破坏性变更)
namespace craton {
inline namespace v1 {
class Thread { /* 仍然是 v1 的实现 A */ };
}
namespace v2 {
class Thread { /* 改进的实现 B,参数列表变了 */ };
}
}

用户视角

版本用户代码链接到
v1craton::Thread t;v1::Thread
v2(用户没改代码)craton::Thread t;仍然 v1::Thread,不破坏
v2(用户主动升级)craton::v2::Thread t;v2::Thread,新 API
1
2
3
4
5
6
7
// 用户代码:用 v1(默认,推荐生产环境用)
#include <craton/craton.h>
craton::Thread t;

// 用户代码:主动用 v2(新项目)
#include <craton/v2/craton.h>
craton::v2::Thread t;

3.3 命名空间设计原则

原则解释示例
主命名空间唯一所有符号都在 craton::craton::String
inline namespace 锁版本craton::v1 是当前稳定版inline namespace v1
子命名空间按域划分os:: ipc:: net:: log:: time:: fs:: storage::craton::os::Thread
跨子模块通用类放顶层String Logger Exception Threadcraton::String
绝不缩写Mutex 不写成 MtxSemaphore 不写成 Semcraton::Mutex
绝不污染 std::不允许 using namespace craton; 影响 std严格 namespace 隔离
graph TB
    CRATON["🌐 namespace craton"]
    V1["🏷️ inline namespace v1<br/>当前稳定版本"]
    V2["🆕 namespace v2<br/>未来改进版"]
    OS["📁 namespace os<br/>操作系统抽象"]
    IPC["📁 namespace ipc<br/>进程间通信"]
    NET["📁 namespace net<br/>网络"]
    LOG["📁 namespace log<br/>日志"]
    TIME["📁 namespace time<br/>时间"]
    FS["📁 namespace fs<br/>文件系统"]
    STORAGE["📁 namespace storage<br/>存储"]

    CRATON --> V1
    CRATON --> V2
    V1 --> OS
    V1 --> IPC
    V1 --> NET
    V1 --> LOG
    V1 --> TIME
    V1 --> FS
    V1 --> STORAGE

    style CRATON fill:#E8D5F5,stroke:#CE93D8,color:#333
    style V1 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style V2 fill:#FFF9C4,stroke:#F9A825,color:#333
    style OS fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style IPC fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style NET fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style LOG fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style TIME fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style FS fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style STORAGE fill:#C7CEEA,stroke:#9FA8DA,color:#333

设计哲学namespace 是给”逻辑分组”用的,不是给”制造代码障碍”用的——Craton 拒绝 craton::os::thread::sync::prim::Mutex 这种 6 层嵌套。

3.4 命名空间 vs POCO 对比

维度POCOCraton
主命名空间Poco::craton::
子命名空间Poco::Net:: Poco::Util:: Poco::Crypto::craton::net:: craton::log:: craton::ipc::
版本 namespace❌ 无inline namespace v1
嵌套深度通常 2-3 层1-2 层
using namespace 友好度⚠️ 子模块多,全用容易混✅ 顶层类少,混用风险低

四、跨平台架构

4.1 三层架构总览

Craton 采用经典的三层抽象架构——这是 30 年来最经久耐用的跨平台库设计模式:

graph TB
    subgraph "第 1 层:应用层"
        APP["📱 业务代码<br/>my_app.cpp"]
    end
    subgraph "第 2 层:Craton 抽象层"
        ABS["🌐 craton::Thread / Socket / File<br/>(平台无关接口)"]
    end
    subgraph "第 3 层:平台实现层"
        LINUX["🐧 Linux 实现<br/>src/os/linux/thread.cpp"]
        QNX["⚫ QNX 实现<br/>src/os/qnx/thread.cpp"]
        ANDROID["🤖 Android 实现<br/>src/os/android/thread.cpp"]
    end
    subgraph "第 4 层:操作系统内核"
        K1["Linux kernel"]
        K2["QNX kernel"]
        K3["Android (Bionic)"]
    end

    APP --> ABS
    ABS --> LINUX
    ABS --> QNX
    ABS --> ANDROID
    LINUX --> K1
    QNX --> K2
    ANDROID --> K3

    style APP fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style ABS fill:#E8D5F5,stroke:#CE93D8,color:#333
    style LINUX fill:#B5EAD7,stroke:#80CBC4,color:#333
    style QNX fill:#FFDAB9,stroke:#FFAB76,color:#333
    style ANDROID fill:#FFF9C4,stroke:#F9A825,color:#333
    style K1 fill:#F5F5F5,stroke:#999,color:#333
    style K2 fill:#F5F5F5,stroke:#999,color:#333
    style K3 fill:#F5F5F5,stroke:#999,color:#333

关键设计

职责Craton 中的实现
应用层业务逻辑用户写的 .cpp
Craton 抽象层平台无关 APIinclude/craton/ 下的所有头文件
平台实现层平台特定代码src/os/{linux,qnx,android,windows,macos}/
OS 内核系统调用内核态,业务不可见

4.2 平台检测宏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// include/craton/os/platform.h
#pragma once

// Craton 跨平台检测宏
// 严格的单选 - 同时只能有一个宏被定义为 1

#if defined(__linux__) && !defined(__ANDROID__)
#define CRATON_OS_LINUX 1
#define CRATON_OS_NAME "linux"
#elif defined(__QNX__)
#define CRATON_OS_QNX 1
#define CRATON_OS_NAME "qnx"
#elif defined(__ANDROID__)
#define CRATON_OS_ANDROID 1
#define CRATON_OS_NAME "android"
#elif defined(_WIN32)
#define CRATON_OS_WINDOWS 1
#define CRATON_OS_NAME "windows"
#elif defined(__APPLE__) && defined(__MACH__)
#define CRATON_OS_MACOS 1
#define CRATON_OS_NAME "macos"
#else
#error "Craton: unsupported platform. Please open an issue."
#endif

// 平台家族分组
#if defined(CRATON_OS_LINUX) || defined(CRATON_OS_QNX) || defined(CRATON_OS_ANDROID)
#define CRATON_OS_POSIX 1
#endif

// 工具链检测
#if defined(__GNUC__) || defined(__clang__)
#define CRATON_COMPILER_GCC_COMPAT 1
#elif defined(_MSC_VER)
#define CRATON_COMPILER_MSVC 1
#else
#warning "Craton: untested compiler"
#endif

// 编译器版本
#if defined(__clang__)
#define CRATON_COMPILER_VERSION __clang_version__
#elif defined(__GNUC__)
#define CRATON_COMPILER_VERSION ("GCC " __VERSION__)
#elif defined(_MSC_VER)
#define CRATON_COMPILER_VERSION ("MSVC " _CRT_STRINGIZE(_MSC_FULL_VER))
#endif

4.3 平台差异表

Craton 目标 3 个核心 + 3 个可选平台。每个组件的”跨平台特殊处理”在第 7 节单独讨论——本节先看总体差异

维度LinuxQNX 8AndroidmacOSWindowsiOS
C 库glibc 2.28+ / muslC 库 (QNX 自带)BionicApple libcMSVC UCRTApple libc
POSIX 完整度100%95%80%100%10%100%
pthread❌ (用 win32 thread)
socket APIBSD socketBSD socketBSD socketBSD socketWinsockBSD socket
共享内存shm_openshm_openashmemshm_openCreateFileMappingshm_open
进程间通信POSIX mqQNX MsgSend/ReceiveBinderPOSIX mqNamedPipePOSIX mq
调度策略SCHED_FIFO/RR多级自适应SCHED_FIFO/RRSCHED_FIFO/RR(无)SCHED_FIFO/RR
编译器GCC / ClangQCCClang (NDK)ClangMSVCClang
优先级⭐⭐⭐⭐⭐⭐⭐⭐

Craton 优先级Linux (glibc+musl) > QNX > Android > Windows > macOS > iOS
QNX 是 Craton 的”一等公民”——因为车载 ECU 是我们的核心场景,QNX 8 的微内核调度、MsgSend/Receive 消息传递,都是要充分利用的能力。

4.4 平台差异处理模式

Craton 用 3 种模式处理平台差异:

模式 1:编译时分支(最常见,零开销)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// include/craton/os/thread.h
class Thread {
public:
void setPriority(int priority);

private:
#if defined(CRATON_OS_LINUX) || defined(CRATON_OS_ANDROID)
sched_param param_;
pthread_t handle_;
#elif defined(CRATON_OS_QNX)
// QNX 调度参数结构略有不同
struct sched_param param_;
pthread_t handle_;
#endif
};

模式 2:内部 namespace 隔离(保持头文件干净)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// include/craton/os/thread.h
namespace craton {
inline namespace v1 {
class Thread {
public:
void setPriority(int priority);
private:
detail::ThreadImpl* impl_; // Pimpl 模式
};
}
}

// src/os/linux/thread.cpp
namespace craton::detail {
struct ThreadImpl {
pthread_t handle;
sched_param param;
};
}

// src/os/qnx/thread.cpp
namespace craton::detail {
struct ThreadImpl {
pthread_t handle;
// QNX 特有字段
int policy_extended;
};
}

模式 3:运行时检测(极少用,开销大)

1
2
3
4
5
6
7
8
9
10
11
// include/craton/os/capability.h
class Capability {
public:
static bool supportsExtendedScheduling() noexcept {
#if defined(CRATON_OS_QNX)
return true; // QNX 编译期已知
#else
return false;
#endif
}
};

4.5 跨平台架构决策矩阵

决策点选项Craton 选择理由
C++ 标准C++14 / 17 / 20 / 23C++17嵌入式编译器 QCC 暂不全支持 C++20
链接类型静态 / 动态 / 头文件header-only 优先ABI 100% 锁版,零链接冲突
RTTI开 / 关可选CRATON_NO_RTTI
异常开 / 关可选CRATON_NO_EXCEPTIONS
C 库平台自带平台自带不引入 libc++/libstdc++ 替代品
第三方依赖零依赖零外部依赖不引 OpenSSL、libcurl、zlib(自实现压缩/哈希)

4.6 平台抽象层 Pimpl 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// include/craton/os/thread.h - 公开头文件
#pragma once
#include <functional>
#include <string>
#include <craton/types.h>

namespace craton {
inline namespace v1 {

class Thread {
public:
using Task = std::function<void()>;

explicit Thread(std::string name = "");
~Thread();

// 禁止拷贝,允许移动
Thread(const Thread&) = delete;
Thread& operator=(const Thread&) = delete;
Thread(Thread&&) noexcept;
Thread& operator=(Thread&&) noexcept;

// 启动线程
void start(Task task);

// 等待线程结束
void join();

// 设置优先级(QNX 特有策略:自适应优先级)
void setPriority(int priority);

// 设置调度策略
enum class Policy {
Normal, // SCHED_OTHER
Fifo, // SCHED_FIFO
RoundRobin, // SCHED_RR
Adaptive, // QNX 特有:自适应优先级
};
void setSchedulingPolicy(Policy p);

// 当前线程 ID
static Int64 currentId();

private:
// Pimpl - 隐藏平台细节
struct Impl;
Impl* impl_;
std::string name_;
};

} // namespace v1
} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// src/os/linux/thread.cpp - Linux 实现
#include <craton/os/thread.h>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <craton/log/logger.h>

namespace craton {

struct Thread::Impl {
pthread_t handle{};
Task task;
bool joined = false;
};

Thread::Thread(std::string name)
: impl_(new Impl), name_(std::move(name)) {}

Thread::~Thread() {
if (impl_ && !impl_->joined) {
// 警告: 线程未 join/detach
CRATON_LOG_WARN("Thread '%s' destroyed without join", name_.c_str());
delete impl_;
}
}

void Thread::start(Task task) {
impl_->task = std::move(task);
int rc = pthread_create(&impl_->handle, nullptr,
[](void* arg) -> void* {
auto* self = static_cast<Impl*>(arg);
try { self->task(); }
catch (const std::exception& e) {
CRATON_LOG_ERROR("Thread task threw: %s", e.what());
}
return nullptr;
}, impl_);
if (rc != 0) {
throw Exception("pthread_create failed", rc);
}
}

void Thread::join() {
if (impl_->joined) return;
pthread_join(impl_->handle, nullptr);
impl_->joined = true;
}

void Thread::setPriority(int priority) {
sched_param param{};
param.sched_priority = priority;
pthread_setschedparam(impl_->handle, SCHED_OTHER, &param);
}

Int64 Thread::currentId() {
return static_cast<Int64>(syscall(SYS_gettid));
}

} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// src/os/qnx/thread.cpp - QNX 实现(部分差异)
#include <craton/os/thread.h>
#include <pthread.h>
#include <sys/neutrino.h>
#include <craton/log/logger.h>

namespace craton {

// QNX 特有:扩展调度策略
struct Thread::Impl {
pthread_t handle{};
Task task;
int policy_id = 0; // QNX 调度策略 ID
};

void Thread::setPriority(int priority) {
// QNX 的优先级是 1-63,0 给系统
if (priority < 1 || priority > 63) {
throw Exception("QNX priority must be 1-63", 1);
}
// QNX 特有: 提升为 root 权限才能设置实时优先级
int rc = pthread_setschedprio(impl_->handle, priority);
if (rc != 0) {
CRATON_LOG_WARN("setPriority %d failed: errno=%d", priority, rc);
}
}

void Thread::setSchedulingPolicy(Policy p) {
int native_policy;
switch (p) {
case Policy::Normal: native_policy = SCHED_OTHER; break;
case Policy::Fifo: native_policy = SCHED_FIFO; break;
case Policy::RoundRobin: native_policy = SCHED_RR; break;
case Policy::Adaptive:
// QNX 特有: 自适应调度 - 进程空闲时升优先级,忙时降
native_policy = SCHED_OTHER; // QNX 调度器自动调整
impl_->policy_id = 1; // 标记为 adaptive
break;
}
sched_param param{};
pthread_setschedparam(impl_->handle, native_policy, &param);
}

} // namespace craton

4.7 平台条件编译约定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// include/craton/os/thread.h
// 头文件中绝不直接出现 #ifdef,保持头文件干净

namespace craton {
inline namespace v1 {

// 平台无关的对外接口
class Thread {
public:
void start(Task task);
void join();
void setPriority(int priority);
// ...

private:
struct Impl; // 前向声明
Impl* impl_;
};

} // namespace v1
} // namespace craton

// 所有平台差异都在 .cpp 中处理
// src/os/linux/thread.cpp
// src/os/qnx/thread.cpp
// src/os/android/thread.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 仅在「确实需要编译时分支」时才用 #ifdef
// 例:内存对齐
namespace craton {
inline namespace v1 {

constexpr std::size_t kCacheLineSize =
#if defined(CRATON_OS_LINUX) || defined(CRATON_OS_QNX)
64; // ARM64: 64, x86: 64
#elif defined(CRATON_OS_WINDOWS)
64;
#else
32; // 保守值
#endif

} // namespace v1
} // namespace craton
graph LR
    H["📄 公开头文件<br/>include/craton/os/thread.h<br/>(平台无关)"]
    L["📁 src/os/linux/thread.cpp"]
    Q["📁 src/os/qnx/thread.cpp"]
    A["📁 src/os/android/thread.cpp"]
    W["📁 src/os/windows/thread.cpp"]
    M["📁 src/os/macos/thread.cpp"]
    B["📚 业务代码<br/>my_app.cpp"]

    B -->|"#include<br/>craton/os/thread.h"| H
    H -.->|"impl_| linux"| L
    H -.->|"impl_| qnx"| Q
    H -.->|"impl_| android"| A
    H -.->|"impl_| windows"| W
    H -.->|"impl_| macos"| M

    style H fill:#E8D5F5,stroke:#CE93D8,color:#333
    style L fill:#B5EAD7,stroke:#80CBC4,color:#333
    style Q fill:#B5EAD7,stroke:#80CBC4,color:#333
    style A fill:#B5EAD7,stroke:#80CBC4,color:#333
    style W fill:#B5EAD7,stroke:#80CBC4,color:#333
    style M fill:#B5EAD7,stroke:#80CBC4,color:#333
    style B fill:#C7CEEA,stroke:#9FA8DA,color:#333

4.8 跨平台能力矩阵

能力LinuxQNXAndroidWindowsmacOSiOS
线程
互斥锁
读写锁
自旋锁
信号量
条件变量
共享内存⚠️ ashmem
消息队列✅ mq✅ MsgSend✅ Binder
命名管道⚠️⚠️
TCP/UDP
文件系统⚠️ SAF⚠️ Scoped
异步 IO✅ epoll✅ ion✅ IOCP✅ kqueue✅ kqueue
定时器
日志✅ syslog✅ slogger2✅ logcat✅ ETW✅ ASL✅ ASL
调度策略⚠️ 2 种✅ 4 种 ⭐⚠️ 2 种❌ 1 种⚠️ 2 种⚠️ 2 种
总支持度100%100%85%80%90%75%

五、9 大组件总览

5.1 9 大组件速览

Craton v1 只做 9 个组件——这是经过 3 轮砍需求后的结果:

#组件关键类跨平台特殊处理POCO 对应
1基础类型String Byte Int* Buffer<T> Expected<T,E> Span<T> Any与平台无关Poco::Buffer Poco::Any
2日志Logger LogLevel ConsoleChannel FileChannel AsyncLoggerQNX 用 syslogPoco::Logger Poco::Channel
3存储KvStore Settings IniFileAndroid 走 SQLitePoco::Util::Application Poco::Util::IniFileConfiguration
4线程与同步Thread ThreadPool Mutex SpinLock Event Semaphore ConditionQNX 调度策略Poco::Thread Poco::ThreadPool Poco::Mutex
5时间Timestamp Timespan DateTime Timer StopwatchAndroid 用 clock_gettimePoco::Timestamp Poco::Timer
6文件系统File Path DirectoryIterator TempFile FileStreamAndroid 走 SAFPoco::File Poco::Path Poco::DirectoryIterator
7消息通讯MessageQueue NamedPipe EventBusQNX 用 MsgSend/MsgReceivePoco::FIFOBuffer Poco::NotificationQueue
8网络操作TcpSocket UdpSocket SocketAddress DnsQNX 部分 socket 选项差异Poco::Net::TCPSocket Poco::Net::SocketAddress
9共享内存SharedMemory NamedSharedMemory SpinLockShmQNX 用 shm_openPoco::SharedMemory

5.2 组件依赖图

Craton 9 大组件有清晰的依赖关系,不允许循环依赖

graph TB
    USER["📱 用户代码"]
    BASE["1️⃣ 基础类型<br/>String, Buffer, Expected"]
    LOG["2️⃣ 日志<br/>Logger, Channel"]
    TIME["5️⃣ 时间<br/>Timestamp, Timer"]
    FS["6️⃣ 文件系统<br/>File, Path"]
    THREAD["4️⃣ 线程与同步<br/>Thread, Mutex"]
    STORAGE["3️⃣ 存储<br/>KvStore, Settings"]
    IPC["7️⃣ 消息通讯<br/>MessageQueue"]
    NET["8️⃣ 网络<br/>TcpSocket, UdpSocket"]
    SHM["9️⃣ 共享内存<br/>SharedMemory"]

    USER --> LOG
    USER --> STORAGE
    USER --> NET
    USER --> IPC
    USER --> SHM
    USER --> THREAD
    USER --> TIME
    USER --> FS

    LOG --> BASE
    LOG --> TIME
    STORAGE --> BASE
    STORAGE --> FS
    STORAGE --> THREAD
    NET --> BASE
    NET --> TIME
    NET --> THREAD
    IPC --> BASE
    IPC --> THREAD
    SHM --> BASE
    SHM --> THREAD
    THREAD --> TIME
    FS --> BASE
    FS --> TIME
    TIME --> BASE
    BASE --> BASE_INTERNAL["std:: + 内置类型"]

    style USER fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style BASE fill:#B5EAD7,stroke:#80CBC4,color:#333
    style LOG fill:#FFDAB9,stroke:#FFAB76,color:#333
    style STORAGE fill:#FFDAB9,stroke:#FFAB76,color:#333
    style THREAD fill:#E8D5F5,stroke:#CE93D8,color:#333
    style TIME fill:#E8D5F5,stroke:#CE93D8,color:#333
    style FS fill:#E8D5F5,stroke:#CE93D8,color:#333
    style IPC fill:#E8D5F5,stroke:#CE93D8,color:#333
    style NET fill:#E8D5F5,stroke:#CE93D8,color:#333
    style SHM fill:#E8D5F5,stroke:#CE93D8,color:#333
    style BASE_INTERNAL fill:#F5F5F5,stroke:#999,color:#333

核心约束

  • 基础类型是所有组件的依赖
  • 日志 / 存储 / 网络 是顶层能力,可独立使用
  • 线程 是横切关注点,几乎所有组件都依赖
  • 时间 是基础设施,原则上不依赖其他 Craton 组件
  • 存储 / 网络 / 共享内存 在物理上不互依赖,但业务上常组合用

5.3 组件规模预估

每个组件的代码量预估(v1.0 目标):

组件头文件数源文件数LOC 预估.a 大小预估
基础类型641,50030 KB
日志431,20025 KB
存储331,50030 KB
线程与同步782,50060 KB
时间441,80035 KB
文件系统562,20050 KB
消息通讯341,50030 KB
网络452,80070 KB
共享内存231,00025 KB
总计384016,000< 400 KB

目标:< 500 KB 静态库,< 20,000 行 C++ 代码——对比 POCO 的 250K 行 + 14MB,是 16x 和 35x 的精简

5.4 与 POCO 9 大组件对应关系

Craton 组件POCO 对应差异Craton 简化的内容
基础类型Poco::Buffer Poco::Any Poco::DynamicAny✅ C++17 std::string_view + std::span 替代不用 DynamicAny(用 std::any
日志Poco::Logger Poco::Channel 完整体系✅ 同等能力砍掉 Logger::dump SplitterChannel
存储Poco::Util::Application + IniFileConfiguration✅ 合并砍掉 PropertyFileConfiguration
线程Poco::Thread Poco::ThreadPool Poco::Mutex Poco::Event✅ 同等砍掉 ActiveThread Timing
时间Poco::Timestamp Poco::DateTime Poco::Timer✅ 同等砍掉 LocalDateTime(用 DateTime + 时区)
文件系统Poco::File Poco::Path Poco::DirectoryIterator✅ 同等砍掉 Poco::TemporaryFile(合并到 TempFile)
消息通讯Poco::NotificationQueue Poco::FIFOBuffer✅ 简化不实现 PriorityNotificationQueue
网络Poco::Net::TCPSocket Poco::Net::SocketAddress✅ 同等基础不实现 HTTP/FTP/SMTP
共享内存Poco::SharedMemory✅ 同等不实现 Poco::Process

5.5 9 大组件代码示例

组件 1:基础类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// include/craton/types.h
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <memory>

namespace craton {
inline namespace v1 {

// 固定宽度整数(C 兼容)
using Byte = std::uint8_t;
using Int8 = std::int8_t;
using Int16 = std::int16_t;
using Int32 = std::int32_t;
using Int64 = std::int64_t;
using Uint8 = std::uint8_t;
using Uint16 = std::uint16_t;
using Uint32 = std::uint32_t;
using Uint64 = std::uint64_t;

// 浮点(用 std 标准)
using Float32 = float;
using Float64 = double;

// 字符串别名 - 内部就是 std::string,但保留未来替换的可能
class String : public std::string {
public:
using std::string::string;
String() = default;
String(const std::string& s) : std::string(s) {}
String(std::string&& s) : std::string(std::move(s)) {}

// 平台无关的 split
std::vector<String> split(const String& delim) const;

// 平台无关的 toLowerCase
String toLowerCase() const;
};

} // namespace v1
} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// include/craton/buffer.h - 简化的 Buffer
#pragma once
#include <vector>
#include <cstring>
#include <craton/types.h>

namespace craton {
inline namespace v1 {

// 简化版 Buffer - 不实现 POCO 那种共享内存/文件映射
template <typename T>
class Buffer {
public:
Buffer() = default;
explicit Buffer(std::size_t size) : data_(size) {}

Buffer(const T* p, std::size_t size) : data_(p, p + size) {}

T* data() noexcept { return data_.data(); }
const T* data() const noexcept { return data_.data(); }

std::size_t size() const noexcept { return data_.size(); }
bool empty() const noexcept { return data_.empty(); }

T& operator[](std::size_t i) { return data_[i]; }
const T& operator[](std::size_t i) const { return data_[i]; }

// 安全访问
T& at(std::size_t i) { return data_.at(i); }
const T& at(std::size_t i) const { return data_.at(i); }

// 调整大小
void resize(std::size_t size) { data_.resize(size); }
void reserve(std::size_t size) { data_.reserve(size); }

private:
std::vector<T> data_;
};

} // namespace v1
} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// include/craton/span.h - C++20 std::span 的 C++17 替代
#pragma once
#include <array>
#include <vector>
#include <cstddef>

namespace craton {
inline namespace v1 {

// 兼容 C++20 std::span::iterator 类别
template <typename T>
class Span {
public:
constexpr Span() noexcept = default;
constexpr Span(T* p, std::size_t n) noexcept : ptr_(p), size_(n) {}

template <std::size_t N>
constexpr Span(std::type_identity_t<T>(&arr)[N]) noexcept
: ptr_(arr), size_(N) {}

template <std::size_t N>
constexpr Span(std::array<T, N>& arr) noexcept
: ptr_(arr.data()), size_(N) {}

template <typename Container>
constexpr Span(Container& c) noexcept
: ptr_(c.data()), size_(c.size()) {}

constexpr T* data() const noexcept { return ptr_; }
constexpr std::size_t size() const noexcept { return size_; }
constexpr bool empty() const noexcept { return size_ == 0; }

constexpr T& operator[](std::size_t i) const noexcept { return ptr_[i]; }

constexpr T* begin() const noexcept { return ptr_; }
constexpr T* end() const noexcept { return ptr_ + size_; }

private:
T* ptr_ = nullptr;
std::size_t size_ = 0;
};

} // namespace v1
} // namespace craton

组件 2:日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// include/craton/log/logger.h
#pragma once
#include <string>
#include <string_view>
#include <memory>
#include <craton/types.h>

namespace craton {
inline namespace v1 {

enum class LogLevel : int {
Trace = 0,
Debug = 1,
Info = 2,
Warning = 3,
Error = 4,
Fatal = 5,
None = 6, // 关闭日志
};

// 日志通道接口
class LogChannel {
public:
virtual ~LogChannel() = default;
virtual void log(LogLevel level, std::string_view message) = 0;
virtual void flush() = 0;
};

class ConsoleChannel : public LogChannel {
public:
void log(LogLevel level, std::string_view message) override;
void flush() override {}
};

class FileChannel : public LogChannel {
public:
explicit FileChannel(const std::string& path);
~FileChannel() override;
void log(LogLevel level, std::string_view message) override;
void flush() override;

private:
struct Impl;
std::unique_ptr<Impl> impl_;
};

class Logger {
public:
static Logger& get(const std::string& name = "root");

void setLevel(LogLevel level) { level_ = level; }
LogLevel getLevel() const { return level_; }

void addChannel(std::shared_ptr<LogChannel> channel);

void log(LogLevel level, std::string_view fmt);

// 便捷接口
void trace(std::string_view msg) { log(LogLevel::Trace, msg); }
void debug(std::string_view msg) { log(LogLevel::Debug, msg); }
void info (std::string_view msg) { log(LogLevel::Info, msg); }
void warn (std::string_view msg) { log(LogLevel::Warning, msg); }
void error(std::string_view msg) { log(LogLevel::Error, msg); }
void fatal(std::string_view msg) { log(LogLevel::Fatal, msg); }

private:
Logger() = default;
LogLevel level_ = LogLevel::Info;
std::vector<std::shared_ptr<LogChannel>> channels_;
};

// 宏接口
#define CRATON_LOG_TRACE(msg) craton::Logger::get().trace(msg)
#define CRATON_LOG_DEBUG(msg) craton::Logger::get().debug(msg)
#define CRATON_LOG_INFO(msg) craton::Logger::get().info(msg)
#define CRATON_LOG_WARN(msg) craton::Logger::get().warn(msg)
#define CRATON_LOG_ERROR(msg) craton::Logger::get().error(msg)
#define CRATON_LOG_FATAL(msg) craton::Logger::get().fatal(msg)

} // namespace v1
} // namespace craton

组件 5:时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// include/craton/time/timestamp.h
#pragma once
#include <cstdint>
#include <chrono>
#include <ctime>
#include <craton/types.h>

namespace craton {
inline namespace v1 {

// 时间戳 - 微秒精度
class Timestamp {
public:
Timestamp() = default;

// 从微秒构造
static Timestamp fromMicroseconds(Int64 us) {
Timestamp t;
t.us_ = us;
return t;
}

// 从 chrono 时间点构造
static Timestamp now() noexcept {
using namespace std::chrono;
auto tp = system_clock::now();
auto us = duration_cast<microseconds>(tp.time_since_epoch()).count();
return fromMicroseconds(us);
}

Int64 microseconds() const noexcept { return us_; }
Int64 milliseconds() const noexcept { return us_ / 1000; }
Int64 seconds() const noexcept { return us_ / 1'000'000; }

// 转换为 time_t (平台无关)
std::time_t toTimeT() const noexcept {
return static_cast<std::time_t>(us_ / 1'000'000);
}

// 转换为 timespec (POSIX)
struct timespec toTimespec() const noexcept {
struct timespec ts{};
ts.tv_sec = static_cast<time_t>(us_ / 1'000'000);
ts.tv_nsec = static_cast<long>((us_ % 1'000'000) * 1000);
return ts;
}

bool operator<(const Timestamp& o) const noexcept { return us_ < o.us_; }
bool operator==(const Timestamp& o) const noexcept { return us_ == o.us_; }

private:
Int64 us_ = 0;
};

} // namespace v1
} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// include/craton/time/timer.h
#pragma once
#include <functional>
#include <chrono>
#include <thread>
#include <atomic>
#include <craton/time/timestamp.h>

namespace craton {
inline namespace v1 {

// 单次定时器
class Timer {
public:
using Callback = std::function<void()>;

Timer(Timestamp at, Callback cb)
: at_(at), cb_(std::move(cb)) {}

void start();
void cancel();

private:
Timestamp at_;
Callback cb_;
std::atomic<bool> cancelled_{false};
};

// 周期性定时器
class PeriodicTimer {
public:
using Callback = std::function<void()>;

PeriodicTimer(std::chrono::milliseconds interval, Callback cb)
: interval_(interval), cb_(std::move(cb)) {}

void start();
void stop();

private:
std::chrono::milliseconds interval_;
Callback cb_;
std::atomic<bool> running_{false};
std::thread thread_;
};

// 高精度秒表
class Stopwatch {
public:
Stopwatch() : start_(std::chrono::steady_clock::now()) {}

void reset() { start_ = std::chrono::steady_clock::now(); }

std::chrono::nanoseconds elapsed() const {
return std::chrono::steady_clock::now() - start_;
}

Int64 elapsedMicros() const {
return std::chrono::duration_cast<std::chrono::microseconds>(
elapsed()).count();
}

Int64 elapsedMillis() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(
elapsed()).count();
}

private:
std::chrono::steady_clock::time_point start_;
};

} // namespace v1
} // namespace craton

组件 8:网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// include/craton/net/socket_address.h
#pragma once
#include <string>
#include <cstdint>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <craton/types.h>

namespace craton {
inline namespace v1 {

class SocketAddress {
public:
// 构造: IPv4 + 端口
SocketAddress(const std::string& host, Uint16 port);

// 构造: 通配地址 + 端口(监听用)
SocketAddress(Uint16 port);

// 底层 sockaddr
const sockaddr* native() const noexcept { return reinterpret_cast<const sockaddr*>(&addr_); }
socklen_t size() const noexcept { return sizeof(addr_); }

// 工具方法
Uint16 port() const noexcept { return ntohs(addr_.sin_port); }
std::string toString() const;

private:
sockaddr_in addr_{};
};

} // namespace v1
} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// include/craton/net/tcp_socket.h
#pragma once
#include <memory>
#include <string>
#include <chrono>
#include <craton/types.h>
#include <craton/expected.h>
#include <craton/net/socket_address.h>

namespace craton {
inline namespace v1 {

class TcpSocket {
public:
TcpSocket();
~TcpSocket();
TcpSocket(TcpSocket&&) noexcept;
TcpSocket& operator=(TcpSocket&&) noexcept;

// 客户端: 连接到远端
static Expected<TcpSocket, ErrCode> connect(
const SocketAddress& addr,
std::chrono::milliseconds timeout = std::chrono::seconds(5));

// 服务端: 接受一个连接
static Expected<TcpSocket, ErrCode> accept(int listen_fd);

// 收发数据
Expected<Uint32, ErrCode> send(const void* data, Uint32 len);
Expected<Uint32, ErrCode> recv(void* buf, Uint32 len, int flags = 0);

// 整行收发
Expected<std::string, ErrCode> recvLine(char delim = '\n');

// 选项
Expected<bool, ErrCode> setNoDelay(bool enable); // TCP_NODELAY
Expected<bool, ErrCode> setKeepAlive(bool enable);
Expected<bool, ErrCode> setReadTimeout(std::chrono::milliseconds t);

void close();

int native() const noexcept { return fd_; }

private:
int fd_ = -1;
struct Impl;
std::unique_ptr<Impl> impl_;
};

} // namespace v1
} // namespace craton

5.5 Craton 不做的 POCO 能力(明确划界)

能力POCO 模块Craton 决策理由
HTTP 客户端/服务端Poco::Net::HTTPClientSession HTTPServer❌ 不做应用层框架,不是基础库职责
NetSSL_OpenSSLPoco::Net::HTTPSClientSession❌ 不做OpenSSL 依赖太大
MongoDB 客户端Poco::MongoDB❌ 不做数据库驱动,不是基础库
Redis 客户端Poco::Redis❌ 不做同上
Prometheus 集成Poco::Prometheus❌ 不做监控是可插拔的
JWT / OAuthPoco::JWT Poco::OAuth❌ 不做应用层安全
ActiveRecord ORMPoco::ActiveRecord❌ 不做ORM 是框架不是库
Zip / 压缩Poco::Zip Poco::DeflatingStream❌ 不做短期不引入 zlib 依赖
XML / YAML 解析Poco::XML Poco::YAML❌ 不做体积大、有专精库
Util::Application 框架Poco::Util::Application❌ 不做业务框架,不是基础

核心原则Craton 是”地基”不是”房子”——HTTP 框架、ORM、监控是”房子”,由应用层或专精库去盖。


六、错误处理策略

6.1 错误处理三件套

现代 C++ 错误处理有 3 种主流范式,Craton 全部支持——按场景选择:

范式适用场景Craton 类型性能开销
异常编程错误、不可恢复错误craton::Exception高(栈展开)
Expected<T, E>系统调用错误、IO 错误craton::Expected<T, E>零开销(值类型)
Status性能敏感路径craton::Status零开销(仅错误码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// include/craton/exception.h
namespace craton {
inline namespace v1 {

class Exception : public std::exception {
public:
Exception(std::string_view message, int code = 0)
: msg_(message), code_(code) {}

const char* what() const noexcept override { return msg_.c_str(); }
int code() const noexcept { return code_; }

private:
std::string msg_;
int code_;
};

} // namespace v1
} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// include/craton/expected.h
namespace craton {
inline namespace v1 {

// C++17 std::expected 风格的实现
template <typename T, typename E = Error>
class Expected {
public:
// 成功路径
Expected(T value) : data_(std::move(value)) {}

// 错误路径
Expected(E error) : data_(std::move(error)) {}

bool has_value() const noexcept { return data_.index() == 0; }
explicit operator bool() const noexcept { return has_value(); }

const T& value() const& { return std::get<T>(data_); }
T&& value() && { return std::move(std::get<T>(data_)); }

const E& error() const& { return std::get<E>(data_); }

private:
std::variant<T, E> data_;
};

} // namespace v1
} // namespace craton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// include/craton/status.h
namespace craton {
inline namespace v1 {

// 类 Result 的简化版 - 性能敏感路径用
class Status {
public:
Status() = default; // 默认为 OK
Status(int code, std::string_view message)
: code_(code), msg_(message) {}

bool ok() const noexcept { return code_ == 0; }
explicit operator bool() const noexcept { return ok(); }

int code() const noexcept { return code_; }
const std::string& message() const noexcept { return msg_; }

private:
int code_ = 0;
std::string msg_;
};

} // namespace v1
} // namespace craton

6.2 错误处理决策树

flowchart TD
    START(["🚨 错误发生"]) --> Q1{"能否从调用栈恢复?"}
    Q1 -->|"否, 不可恢复"| Q2{"是编程错误?<br/>参数非法/状态错乱"}
    Q1 -->|"是, 调用方能处理"| Q3{"是否在性能关键路径?<br/>每秒调用 100K+ 次"}

    Q2 -->|"是"| E1["❌ throw Exception<br/>栈展开到 catch"]
    Q2 -->|"否, 系统级错误"| E2["🔁 return Expected T, E<br/>调用方显式处理"]

    Q3 -->|"是"| S1["⚡ return Status<br/>仅错误码 + 字符串"]
    Q3 -->|"否"| E2

    E1 --> END(["✅ 用户处理"])
    E2 --> END
    S1 --> END

    style START fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style Q1 fill:#FFF9C4,stroke:#F9A825,color:#333
    style Q2 fill:#FFF9C4,stroke:#F9A825,color:#333
    style Q3 fill:#FFF9C4,stroke:#F9A825,color:#333
    style E1 fill:#FFB3C6,stroke:#F48FB1,color:#333
    style E2 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style S1 fill:#FFDAB9,stroke:#FFAB76,color:#333
    style END fill:#E8D5F5,stroke:#CE93D8,color:#333

6.3 决策对照表

错误类型决策示例
nullptr 传给了 Thread::startException编程错误
index 越界访问 BufferException编程错误
重复 Mutex::lock 自身线程Exception编程错误(死锁检测)
File::open 文件不存在Expected<File, Error>系统调用错误
Socket::connect 连接被拒Expected<TcpSocket, Error>系统调用错误
KvStore::get 键不存在Expected<Value, Error>业务可恢复
高频循环里 Buffer::writeStatus性能关键路径
序列化框架每帧调用Status性能关键路径

6.4 完整错误处理示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 示例 1: Exception 用于编程错误
craton::Thread t;
try {
t.start(nullptr); // 编程错误
} catch (const craton::Exception& e) {
CRATON_LOG_ERROR("Thread start failed: %s (code=%d)", e.what(), e.code());
// 不应继续运行
}

// 示例 2: Expected 用于系统调用
auto result = craton::File::open("/etc/passwd");
if (!result) {
CRATON_LOG_WARN("Open failed: %s", result.error().message().c_str());
return;
}
auto& file = result.value();
auto read_result = file.read(buffer);
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 示例 3: Status 用于性能关键路径
craton::Status writeRecord(const Record& r) {
if (auto s = buffer_.write(r.data(), r.size()); !s.ok()) {
return s;
}
if (auto s = index_.update(r.id, r.timestamp); !s.ok()) {
return s;
}
return {}; // OK
}

// 调用方
auto status = writeRecord(rec);
if (!status.ok()) {
metrics_.inc("write_record.error", status.code());
}

6.5 Craton vs POCO 错误处理对比

维度POCO 1.15Craton 1.0改进
异常Poco::Exception 大量使用craton::Exception 限制使用Expected/Status 减少栈展开
错误码部分函数返回 int errnoExpected<T, E> 统一类型安全
try/catch 强制❌ 不强制✅ RAII + 显式 if (!result)更可控
性能异常有开销Status 零开销性能提升 30%+

6.6 错误码标准定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// include/craton/errcode.h
namespace craton {
inline namespace v1 {

// 统一的错误码
enum class ErrCode : int {
Ok = 0, // 成功

// 系统调用类 (1-99)
InvalidArgument = 1, // 参数非法
InvalidState = 2, // 状态错乱
NullPointer = 3, // nullptr
OutOfRange = 4, // 越界
NotFound = 5, // 资源不存在
AlreadyExists = 6, // 资源已存在
PermissionDenied = 7, // 权限不足
Timeout = 8, // 超时
Interrupted = 9, // 中断

// IO 类 (100-199)
IoError = 100, // 通用 IO 错
FileNotFound = 101,
DiskFull = 102,
ConnectionRefused = 103,
ConnectionReset = 104,
HostUnreachable = 105,

// 网络类 (200-299)
NetworkError = 200,
DnsError = 201,
TlsError = 202, // 预留 - Craton v1 不做 TLS

// 平台类 (900-999)
PlatformError = 900, // 平台特定错误
NotSupported = 901, // 平台不支持此操作
InternalError = 999, // Craton 内部错误
};

// 错误码到字符串的映射
inline const char* toString(ErrCode code) noexcept {
switch (code) {
case ErrCode::Ok: return "OK";
case ErrCode::InvalidArgument: return "Invalid argument";
case ErrCode::InvalidState: return "Invalid state";
case ErrCode::NotFound: return "Not found";
case ErrCode::Timeout: return "Timeout";
case ErrCode::IoError: return "IO error";
case ErrCode::ConnectionRefused: return "Connection refused";
// ...
default: return "Unknown error";
}
}

} // namespace v1
} // namespace craton

6.7 Expected 使用模式对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// === 模式 1: 早返回 ===
craton::Expected<Config, craton::ErrCode> loadConfig() {
auto file_result = craton::File::open("/etc/app.conf");
if (!file_result) return file_result.error();

auto read_result = file_result.value().readAll();
if (!read_result) return read_result.error();

return parse(read_result.value());
}

// === 模式 2: AND_THEN 链式 ===
auto result = craton::File::open("/etc/app.conf")
.and_then([](auto& f) { return f.readAll(); })
.and_then([](auto& data) { return parse(data); })
.map([](auto& cfg) { return cfg.timeout; });

// === 模式 3: 异常与 Expected 互转 ===
craton::Expected<int, ErrCode> safeOperation() {
try {
return craton::int{doRiskyThing()};
} catch (const craton::Exception& e) {
return craton::ErrCode::InternalError;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// include/craton/expected.h - 完整的 Expected 实现
#pragma once
#include <variant>
#include <utility>
#include <type_traits>

namespace craton {
inline namespace v1 {

template <typename E>
class Unexpected {
public:
explicit Unexpected(E e) : value_(std::move(e)) {}
const E& value() const& { return value_; }
E& value() & { return value_; }
E&& value() && { return std::move(value_); }
private:
E value_;
};

// Deduction guide
template <typename E> Unexpected(E) -> Unexpected<E>;

template <typename T, typename E>
class Expected {
public:
// 构造: 成功
Expected(T value) : data_(std::in_place_index<0>, std::move(value)) {}
// 构造: 失败
Expected(Unexpected<E> u) : data_(std::in_place_index<1>, std::move(u).value()) {}

// 状态查询
bool has_value() const noexcept { return data_.index() == 0; }
explicit operator bool() const noexcept { return has_value(); }

// 成功访问
const T& value() const& { return std::get<0>(data_); }
T& value() & { return std::get<0>(data_); }
T&& value() && { return std::move(std::get<0>(data_)); }

// 错误访问
const E& error() const& { return std::get<1>(data_); }
E& error() & { return std::get<1>(data_); }

// 链式操作
template <typename F>
auto and_then(F&& f) const& -> decltype(f(value())) {
return has_value() ? f(value()) : *this;
}

template <typename F>
auto map(F&& f) const& -> Expected<decltype(f(value())), E> {
return has_value()
? Expected<decltype(f(value())), E>(f(value()))
: Unexpected<E>(error());
}

// 值或默认值
T value_or(T default_value) const& {
return has_value() ? value() : std::move(default_value);
}

private:
std::variant<T, E> data_;
};

} // namespace v1
} // namespace craton

6.8 Status vs Expected 性能对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// === 性能敏感路径用 Status (零分配) ===
class PacketEncoder {
craton::Status encode(const Packet& p, Byte* buf, size_t* len) noexcept {
// 高频调用 - 用 Status 避免 Expected 的 variant 开销
if (buf == nullptr || len == nullptr) {
return {ErrCode::InvalidArgument, "null pointer"};
}
if (p.size > *len) {
return {ErrCode::OutOfRange, "buffer too small"};
}
std::memcpy(buf, p.data, p.size);
*len = p.size;
return {}; // OK
}
};

// === 业务逻辑用 Expected (类型安全) ===
class HttpClient {
craton::Expected<Response, ErrCode> get(const std::string& url) {
// 业务调用 - 类型清晰
auto socket = connect(url);
if (!socket) return socket.error();

auto request = buildRequest(url);
if (!request) return request.error();

return sendRequest(socket.value(), request.value());
}
};
维度StatusExpected<T, E>
内存开销8 + 32 字节 (int + string SSO)sizeof(T) + sizeof(E)
性能零分配可能栈分配 T
类型安全⚠️ 调用方易忽略✅ 强制处理
携带信息错误码 + 消息完整的 T 或 E
使用场景内部循环、热路径对外 API、IO 操作

七、构建系统

7.1 顶层 CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# CMakeLists.txt - Craton 顶层
cmake_minimum_required(VERSION 3.16)
project(craton
VERSION 1.0.0
DESCRIPTION "Stable Foundation Library for Embedded C++"
LANGUAGES CXX
)

# ===== 严格 C++17 =====
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# ===== 全局编译选项 =====
if(MSVC)
add_compile_options(/W4 /permissive- /Zc:__cplusplus)
else()
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()

# ===== 平台检测 =====
if(DEFINED ENV{QNX_HOST})
set(CRATON_PLATFORM "qnx")
message(STATUS "Craton: detected QNX SDP (host=$ENV{QNX_HOST})")
elseif(ANDROID)
set(CRATON_PLATFORM "android")
message(STATUS "Craton: detected Android NDK (API=${ANDROID_PLATFORM})")
elseif(UNIX AND NOT APPLE)
set(CRATON_PLATFORM "linux")
message(STATUS "Craton: detected Linux")
elseif(APPLE)
set(CRATON_PLATFORM "macos")
message(STATUS "Craton: detected macOS")
elseif(WIN32)
set(CRATON_PLATFORM "windows")
message(STATUS "Craton: detected Windows")
endif()

# ===== 可选特性开关 =====
option(CRATON_BUILD_TESTS "Build Craton unit tests" OFF)
option(CRATON_BUILD_EXAMPLES "Build Craton examples" OFF)
option(CRATON_HEADER_ONLY "Build as header-only library" ON)
option(CRATON_NO_EXCEPTIONS "Disable exceptions" OFF)
option(CRATON_NO_RTTI "Disable RTTI" OFF)

# ===== 头文件库(默认) =====
if(CRATON_HEADER_ONLY)
add_library(craton INTERFACE)
add_library(craton::craton ALIAS craton)

target_include_directories(craton INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

target_compile_features(craton INTERFACE cxx_std_17)
target_compile_definitions(craton INTERFACE
CRATON_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
CRATON_VERSION_MINOR=${PROJECT_VERSION_MINOR}
CRATON_VERSION_PATCH=${PROJECT_VERSION_PATCH}
)
else()
add_library(craton STATIC)
add_library(craton::craton ALIAS craton)
# 头文件路径同上
target_sources(craton PRIVATE
src/os/thread.cpp
src/os/mutex.cpp
# ... 所有 .cpp
)
endif()

# ===== 平台特定配置 =====
if(CRATON_PLATFORM STREQUAL "qnx")
target_link_libraries(craton INTERFACE pthread)
elseif(CRATON_PLATFORM STREQUAL "linux")
target_link_libraries(craton INTERFACE pthread rt)
elseif(CRATON_PLATFORM STREQUAL "android")
target_link_libraries(craton INTERFACE log)
endif()

7.2 跨平台编译流程图

graph LR
    SRC["📝 源码\n.cpp + .h"]
    CMAKE["⚙️ CMake 配置\ncmake -B build"]
    DETECT["🔍 平台检测\nLinux/QNX/Android"]
    COMPILE["🔨 编译\ncmake --build"]
    LIB["📦 输出\nlibcraton.a (静态)\n或 header-only"]
    CONSUME["📱 业务应用\n链接 / include"]

    SRC --> CMAKE --> DETECT --> COMPILE --> LIB --> CONSUME
    DETECT -.->|"识别 QNX_HOST"| QCC["⚫ QCC 编译器"]
    DETECT -.->|"识别 ANDROID"| NDK["🤖 NDK 工具链"]
    DETECT -.->|"默认 Linux"| GCC["🐧 GCC/Clang"]

    style SRC fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style CMAKE fill:#FFF9C4,stroke:#F9A825,color:#333
    style DETECT fill:#E8D5F5,stroke:#CE93D8,color:#333
    style COMPILE fill:#E8D5F5,stroke:#CE93D8,color:#333
    style LIB fill:#B5EAD7,stroke:#80CBC4,color:#333
    style CONSUME fill:#FFB3C6,stroke:#F48FB1,color:#333
    style QCC fill:#FFDAB9,stroke:#FFAB76,color:#333
    style NDK fill:#FFDAB9,stroke:#FFAB76,color:#333
    style GCC fill:#FFDAB9,stroke:#FFAB76,color:#333

7.3 各平台编译命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# === Linux (glibc) ===
cmake -B build -S . -DCRATON_BUILD_TESTS=ON
cmake --build build -j$(nproc)
ctest --test-dir build --output-on-failure

# === Linux (musl, 嵌入式) ===
cmake -B build-musl -S . \
-DCMAKE_C_COMPILER=musl-gcc \
-DCMAKE_CXX_COMPILER=musl-g++ \
-DCMAKE_SYSTEM_NAME=Linux
cmake --build build-musl -j$(nproc)

# === QNX 8.0 SDP ===
source /opt/qnx800/qnxsdp-env.sh
cmake -B build-qnx -S . \
-DCMAKE_C_COMPILER=qcc \
-DCMAKE_CXX_COMPILER=q++ \
-DCMAKE_SYSTEM_NAME=QNX
cmake --build build-qnx -j$(nproc)

# === Android NDK r26 ===
cmake -B build-android -S . \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_PLATFORM=android-24 \
-DANDROID_ABI=arm64-v8a
cmake --build build-android -j$(nproc)

7.4 vcpkg / Conan 支持

包管理器状态端口名
vcpkg✅ 计划中vcpkg install craton
Conan✅ 计划中conan install craton/1.0.0@
系统包⚠️ 部分发行版apt install libcraton-dev (Debian/Ubuntu 计划)
FetchContent✅ 已支持include(FetchContent) 直接拉源码
1
2
3
4
5
6
7
8
9
10
11
12
13
# 用户使用方式 1: FetchContent
include(FetchContent)
FetchContent_Declare(
craton
GIT_REPOSITORY https://github.com/xuqi/craton.git
GIT_TAG v1.0.0
)
FetchContent_MakeAvailable(craton)
target_link_libraries(my_app PRIVATE craton::craton)

# 用户使用方式 2: find_package
find_package(craton 1.0 REQUIRED)
target_link_libraries(my_app PRIVATE craton::craton)

八、ABI 稳定性策略

8.1 ABI 稳定 6 大原则

Craton 把”ABI 稳定”作为 v1 的最高优先级——这是基础库的”信用”:

#原则含义实现
1inline namespace v1 锁版所有公开符号在 v1见 3.2 节
2绝不改变公开类的成员顺序不允许调整成员变量顺序CI 检查
3绝不改变公开函数签名不允许修改参数/返回值类型编译期检查
4vtable 锁版虚函数一旦发布不删不改ABI 测试套件
5新增成员放末尾派生类新虚函数要谨慎CI 布局检查
6类型大小写不变量公开类型 sizeof 不可变编译期 sizeof 测试

8.2 ABI 兼容检查表

改动类型是否 ABI 兼容Craton 策略
新增公开类✅ 兼容v1.1 可以加
新增类成员函数✅ 兼容(默认参数除外)默认参数禁止
新增类成员变量不兼容(破坏布局)必须新版本号
修改类成员顺序不兼容禁止
修改函数返回值类型不兼容禁止
修改函数参数类型不兼容禁止
新增虚函数⚠️ 看位置基类末尾 OK,中间破坏 vtable
删除类/函数不兼容必须新版本号
修改 inline namespace v1 → v2✅ 兼容(用户主动迁移)主动 opt-in
修改宏定义值⚠️ 看影响数值变更需 major

8.3 ABI 自动化测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// tests/abi/test_abi_v1.cpp
// 这个测试在 CI 中跑,确保 v1 ABI 100% 稳定
#include <craton/craton.h>
#include <cassert>

int main() {
// 类大小锁版
static_assert(sizeof(craton::Thread) == 32,
"Thread size changed - ABI broken!");
static_assert(sizeof(craton::Mutex) == 16,
"Mutex size changed - ABI broken!");
static_assert(sizeof(craton::String) == 32,
"String size changed - ABI broken!");

// 成员偏移锁版
static_assert(offsetof(craton::Thread, handle_) == 0,
"Thread::handle_ offset changed - ABI broken!");

// 虚表布局锁版(用 dynamic_cast 类型校验)
craton::Thread t;
assert(typeid(t) == typeid(craton::Thread));

return 0;
}

8.4 版本发布节奏

版本类型节奏ABI 兼容性例子
Major (v2)3-5 年一次❌ 破坏重大重写
Minor (v1.1)6 个月✅ 兼容新增类、新增函数
Patch (v1.0.1)随时✅ 兼容Bugfix、文档

类比 Linux 内核:LTS 内核承诺 6 年 ABI 稳定——Craton v1 承诺 至少 5 年 ABI 稳定


九、与 POCO 的关系——精简 + 现代化,不是替代

9.1 设计哲学对比

维度POCO 设计哲学Craton 设计哲学
目标用户通用跨平台 C++ 开发者嵌入式 + 车控 + 工业
目标平台12 个(覆盖广)3 个核心 + 3 个可选(专注)
设计原则兼容 Java 风格、易上手现代 C++、API 严格
LicenseBoost 1.0MIT
ABI 锁版弱(无版本 namespace)强(inline namespace v1)
构建系统CMake 1.10+CMake 3.16+
C++ 标准C++11 兼容(部分模块要 17)C++17 全栈
异常依赖强制开可关(CRATON_NO_EXCEPTIONS
包管理系统包 + 源码vcpkg + Conan + FetchContent

9.2 POCO 能力 vs Craton 能力矩阵

POCO 模块POCO 能力Craton 对应差异说明
Foundation智能指针、字符串、容器、文件系统、线程、事件、内存池、压缩✅ 1, 4, 5, 6 全做砍掉内存池、压缩(短期)
NetTCP/UDP/HTTP/HTTPS/FTP/SMTP 客户端与服务端✅ 8 只做 TCP/UDP不实现 HTTP/FTP/SMTP
NetSSL_OpenSSLTLS 1.3、证书校验、加密❌ 不做OpenSSL 依赖太大
UtilApplication 框架、Timer、配置、JSON/XML/YAML、模板⚠️ 部分做不做 Application 框架、模板引擎
JSONJSON 解析与生成❌ 不做(短期)体积大、有专精库
XMLDOM/SAX 解析❌ 不做同上
CryptoRSA/AES/SHA❌ 不做OpenSSL/mbedTLS 替代
DataSQLite/MySQL/ODBC❌ 不做数据库驱动不是基础
MongoDBMongoDB 客户端❌ 不做同上
RedisRedis 客户端❌ 不做同上
Prometheus指标导出❌ 不做监控是应用层
JWT / OAuthToken 认证❌ 不做应用层安全
ActiveRecordORM❌ 不做框架不是库
Zip压缩解压❌ 不做短期不引 zlib

9.3 “Craton 能直接替换 POCO 吗?”——分场景答

场景是否可替换原因
车机 QNX 域控制器✅ 完全可替换只需要 TCP/UDP + 线程 + 日志
工业网关✅ 可替换只需要 Modbus-TCP + 存储 + 日志
Android 车载 Launcher⚠️ 部分可替换业务如需 HTTP 还得借 libcurl
桌面跨平台应用❌ 不推荐POCO 12 平台覆盖优势
服务端后台系统❌ 不推荐POCO HTTP 服务器很成熟
金融支付 POS⚠️ 视需求POCO HTTPS 是核心能力,Craton 没做

9.4 从 POCO 迁移到 Craton 的成本

1
2
3
4
5
6
7
8
9
10
11
12
13
// POCO 代码
#include <Poco/Net/TCPSocket.h>
#include <Poco/Net/SocketAddress.h>
Poco::Net::SocketAddress addr("192.168.1.1", 8080);
Poco::Net::TCPSocket socket(addr);
// ...

// Craton 迁移后(API 几乎一致)
#include <craton/net/tcp_socket.h>
#include <craton/net/socket_address.h>
craton::net::SocketAddress addr("192.168.1.1", 8080);
craton::net::TcpSocket socket(addr);
// ...
迁移项工作量工具支持
头文件路径1 小时sed -i 's/Poco\//craton\//g'
命名空间1 小时sed -i 's/Poco::/craton::/g'
类名大小写2 小时POCO TCPSocket → Craton TcpSocket(驼峰)
错误处理4-8 小时视业务量
总体1-3 天视代码量

设计目标让 POCO 用户迁移到 Craton 的成本 < 1 周——大部分是机械替换,少数是 API 风格调整。


十、本文小结

10.1 三个行动建议

#建议适用读者收益
1先评估再自研准备自研基础库的团队避免重蹈”自研一时爽,升级火葬场”
2inline namespace v1 锁版本任何 C++ 库维护者ABI 稳定 10 年不破坏
3精简到 < 20K 行嵌入式 C++ 工程师编译 < 2 分钟,链接 < 10 秒

10.2 Craton 9 大组件 12 篇实现节奏

篇数主题状态
第 9 篇(本文)设计哲学✅ 已发布
第 10 篇实现详解(一):基础类型、日志、时间、文件🔜
第 11 篇实现详解(二):线程同步、IPC、网络、共享内存🔜
第 12 篇实战:在 QNX 车控域控制器上替换 POCO 跑通业务🔜

10.3 决策树:你的项目该用 Craton 吗?

flowchart TD
    START(["🤔 评估项目需求"]) --> Q1{"目标平台是<br/>Linux/QNX/Android?"}
    Q1 -->|"否"| REC1["📚 用 POCO<br/>12 平台覆盖"]
    Q1 -->|"是"| Q2{"需要 HTTP/FTP/<br/>SMTP/SSL?"}
    Q2 -->|"是"| Q2B{"HTTP/SSL 是核心?"}
    Q2B -->|"是"| REC2["📚 用 POCO<br/>完整 Net/NetSSL"]
    Q2B -->|"否"| REC3["🪨 用 Craton + libcurl<br/>组合方案"]
    Q2 -->|"否"| Q3{"ABI 锁版<br/>是硬需求?"}
    Q3 -->|"是"| REC4["🪨 用 Craton<br/>inline namespace v1"]
    Q3 -->|"否"| Q4{"Flash 预算<br/>< 4MB?"}
    Q4 -->|"是"| REC4
    Q4 -->|"否"| Q5{"CI 编译时间<br/>不能超 3 分钟?"}
    Q5 -->|"是"| REC4
    Q5 -->|"否"| REC1

    style START fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style Q1 fill:#FFF9C4,stroke:#F9A825,color:#333
    style Q2 fill:#FFF9C4,stroke:#F9A825,color:#333
    style Q2B fill:#FFF9C4,stroke:#F9A825,color:#333
    style Q3 fill:#FFF9C4,stroke:#F9A825,color:#333
    style Q4 fill:#FFF9C4,stroke:#F9A825,color:#333
    style Q5 fill:#FFF9C4,stroke:#F9A825,color:#333
    style REC1 fill:#FFDAB9,stroke:#FFAB76,color:#333
    style REC2 fill:#FFDAB9,stroke:#FFAB76,color:#333
    style REC3 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style REC4 fill:#B5EAD7,stroke:#80CBC4,color:#333

10.4 系列展望

维度POCO 实战(1-8 篇)Craton 自研(9-12 篇)
性质学习使用别人写的库自己设计并实现库
目标掌握 POCO 完整能力蒸馏 POCO 经验、做出下一代
风格教程 + 实战案例设计哲学 + 源码解读 + 实战
代码量引用 POCO2000+ 行 Craton 实现
可运行POCO 现成 demo从 0 写 9 大组件

Craton 不是 POCO 的敌人——它是 POCO 的”升级版学生”。用 8 篇学老师,再用 4 篇超越老师。这就是开源世界的浪漫。


结尾金句好的基础库不在于它实现了多少,而在于它敢拒绝实现多少。POCO 给了我们 22 年的库设计经验,Craton 用 9 大组件、16,000 行代码、< 500KB 体积,把这些经验蒸馏成”地质学稳态”——像克拉通一样,跨平台、跨时代、跨越亿年稳定。


参考资料

  1. POCO C++ Libraries 官方文档:https://pocoproject.org/docs/
  2. C++17 inline namespace 设计模式:https://en.cppreference.com/w/cpp/language/namespace#Inline_namespace
  3. QNX Neutrino 8.0 文档:https://www.qnx.com/developers/docs/qnx_8.0/
  4. Android NDK r26 指南:https://developer.android.com/ndk/guides
  5. std::expected P0323 提案:https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r7.html
  6. SemVer 2.0.0 规范:https://semver.org/
  7. Linux Foundation 嵌入式 C++ 规范

本文源码示例遵循 MIT License。