Electronic Joint Business

Solution for E-Business

编程语言

将 GCC 工具链迁移到 Moxie 处理器上 (一)— Moxie 处理器架构

Moxie 是一种通用的、采用混合编码(Bi-Endian,也成为大小端) 和加载/存储架构的处理器。所谓加载/存储架构也称为寄存器到寄存器架构。在该架构中,所有算术运算都要从可寻址寄存器中获得操作数,并将生成的结果送往可寻址寄存器。存储器和寄存器间的通信需要通过独立的”加载”和”存储”操作。加载/存储概念是 RISC 体系结构背后的基本理念之一。

Moxie 处理器有 16 个 32 位通用寄存器和完整的指令集体系架构(ISA — Instruction Set Architecture) ,它最早的设计目的是为 GNU 工具链提供一个假想目标(target),后来演化出许多监管级别指令(supervisor level)以满足运行诸如 RTEMS 这类实时操作系统(RTOS)的需要。1

大多数 moxie 指令长度是 16 位,再加上额外的 16 位或 32 位立即数,最终生成了 32 位或 48 位指令。之所以在固定宽度的 RISC 实现中混入了可变宽度指令架构,是为了优化指令内存带宽,这是影响许多 FPGA 应用性能的关键制约因素。

一、Moxie 寄存器
Moxie 定义了以下 16个 32位寄存器:

  • $fp 帧指针
  • $sp 栈指针
  • $r0 – $r13 一共 14 个通用寄存器

此外,Moxie 处理器还定义了一系列特殊寄存器(保留数目 256),这些寄存器的值只能通过 gsr (Get Special Register) 和 ssr (Set Special Registers) 等指令来访问, 下面列出一些特殊寄存器的用途:

>>> 阅读全文

 

,

利用 ANSI 转义码打造个人风格的命令行

大家都习惯了程序将输出打印到终端时,屏幕随着文本而滚动,其实你能做不仅限于此:你可以给文本上色,可以上、下、左、右移动光标,可以清除部分屏幕然后重新输出。这一切使得 Git 可以实现动态进度指示条、Vim 或 Bash 实现能够修改屏幕上的文本的编辑器而无需滚动终端。1

诸如 readline、jline 或 python Prompt Toolkit 等类库可让你用各种编程语言来实现类似操作, 但你可以自己动手。本文用一些 Python 示例展示了如何从命令行程序来如何控制终端的基础知识, 并讨论了你自己的代码要如何直接利用终端提供的这些特殊功能。.

大多数程序与 UNIX 终端交互的方式是通过 ANSI 转义码。这是一些特殊代码,你的程序将之输出以便向终端提供指令。不同的终端支持这些代码的不同子集, 很难找到一个“权威” 列表来说明每个代码的作用。维基百科给了一个不错的列表, 你还可以找到其他网站。

利用 ANSI 转移码,编写的程序可以工作在常见的 UNIX 系统上, 比如 Ubuntu 或 OS-X 。(对于 Windows ,建议你使用 Windows 10 TH2 以后版本,并如下修改注册表以支持 ANSI VT100 终端显示:找到“HKCU\Console” 创建一个 DWORD 类型的键,名称为“VirtualTerminalLevel”,值为 0x1 2)。本文将先探讨 ANSI 转义代码的基础知识, 并演示如何使用它们从零开始编写自己的交互式命令行程序。

富文本
最基本的 ANSI 转义码是那些参与文本渲染的编码。利用它们可以为打印文本添加”颜色”、”背景色”等修饰。打印的文本仍将最终显示在终端的底部, 并仍会使得终端滚动只不过是彩色文本, 而不是终端的默认黑白配色方案。

>>> 阅读全文

 

, ,

用 Python LARK 开发 DSL 语言

第一次接触 Logo 语言时,你会觉得它像魔法。只需一小段简单命令,就可以在屏幕上画出漂亮又复杂的图形。本文将向你展示如何用 70 行代码来解析并解释一种类 Logo 语言,你可以以此为基础来设计并实现你自己的语言。在这里,我们会用到解析类库 Lark 以及 Python 的 turtle 模块。 1

什么是 DSL?
在编写软件项目时, 有时候你所选择的语言不太适合表达你的信息 — 包括数据、配置、命令列表等。可能缺少某种抽象、语言可能会过于冗长, 或者代码由于缺少适当的验证而容易出错。这时候,创建自己的语言就能以简洁的方式描述信息。这种语言被称为“领域特定语言” 或 DSL。

DSL 往往短小简洁。既有优点, 也有缺点。

DSL 优点:

  • 表达自由 (在其应用范围内)
  • 代码简洁, 更易于阅读、编写和调试
  • 按设计进行验证
  • 动态 — 可在运行时执行动态代码 (evaluated)
  • 可重用 — DSL 可以在不同的语言和平台之间共享,比如正则表达式

DSL 缺点:

>>> 阅读全文

 

, ,

Binutils 移植指南 (一)

本文是对 Binutils 现有文档的补充,旨在帮助那些第一次将 Binutils 工具移植到新的硬件架构的软件工程师。本文是根据作者的实际经验编写的。难免会有疏漏,欢迎读者提出任何改善建议。1

一、 为什么写这篇文章?
虽然 Binutils 项目中包含了 100 多页的内部指南, 但本文主要针对那些初次进行 Binutils 开发/移植的人。Binutils 内部指南存在一些缺陷:

  • 它更倾向于对每个函数进行详细描述,而不是跟出宏观视图。
  • 文档尚不完整,许多有用章节尚待编写。(例如有关 relocation详细信息) 。

因此,当工程师初次尝试将 Binutils 移植到新的架构上时,他总要不断阅读源代码来弄明白 Binutils 如何工作,进而了解如何移植到其他体系架构。

本文将讨论如何将紧凑 RISC (又称 CR16) 体系结构植入 Binutils , 希望这些学习经验可以帮助到其他人, 特别是那些正在寻找将 Binutils工具移植到新架构的工程师。有关 CR16 的代码可以在最新的 Binutils 中获得。

二、Binutils 文件的组织结构
Binutils 源代码被按目录组织,其中一些组件是类库,仅供内部或其他项目使用。比如 GNU GDB 调试器会用到 BFD 类库。这些类库大多有自己的顶层目录。主要的目录列举如下:

这些目录包含如下组件:

>>> 阅读全文

 

利用 Python 工具和库实现语法解析

想用 Python 来解析编程语言或者文档,一般有三种做法:1

  • 利用现成的库来支持语言的解析,如 XML 类库:对于那些使用广泛的语言如 XML 和 HTML,这是无疑是最好的选择。好的类库通常还会包括创建或修改语言的可编程 API,这要比基础解析器的功能多得多。不过只有最常见的语言才有这种类库。
  • 从头构造一个解析器:有时候你可能要自己构造解析器。比如语言无法用传统的解析器生成器来解析,或者生成器的功能无法满足性能需求或者无法和其他组件深度集成。
  • 利用工具或者库来帮助生成解析器,例如 ANTLR 可以为任何语言生成解析器。

在前两种选项之外的场合,生成器应该是默认的选择,因为它既灵活又可以大大缩短开发时间。这就是为什么本文重点关注此种类库和工具的原因。

用工具创建解析器
在后续的章节中我们会看到:

  • 利用工具来生成 Python 可用(或其他语言可用)的解析器
  • 用来创建解析器的 Python 类库

生成解析器代码的工具称一般为解析器生成器(parser generators)或者编译器的编译器(compiler compiler)。生成解析器的类库则称为解析器组合器(parser combinator)。

不管是生成器还是组合器都不是易上手的工具,你需要花时间学习它们的使用方法。请注意并不是所有生成器都适用于所有的语言。在这里, 我们列出了一些最常见的生成器并对它们逐一进行简单介绍。并且我们的目标语言定为 Python。这意味一般来说这些工具和库自身也是用 Python 编写的。

>>> 阅读全文

 

, , , , , ,

Linux 内核网络之邻接子系统

当两台或者多台设备通过物理链路连接在一起时候,就构成了网络。多个网络之间还可为了信息交换和服务的目的连接在一起,构成网间网。通信网络中的两台主机要进行通信时,发送方一般都需要知道接收方是哪一个站,以确保每一帧都能正确地送到目的站。接受方也应当知道发送方是哪一个站,以便对消息做出应答。为了确认通信主体,参与通信各方一般都用“地址”来进行标识,地址的本质是一种标识符,用来表示系统中的某一个对象。而同一个系统中不允许有 2 个地址相同的通信主体存在,这就是地址的唯一性。所有的网络都要求某种形式的寻址机制,以识别设备。寻址还可以确定网络本身,或者网络的一个网段(例如子网)。

在计算机通信中,每一层协议的编址方式都不同。1。网络、子网和设备可以由 OSI 参考模型的二、三层协议来确定。硬件寻址在数据链路层(第 2 层)来确定设备。例如以太网是以烧录在网络设备中的唯一识别码作为硬件地址,当网络设备从共享的线路侦听到数据帧时,它负责检出数据帧中的目的地址,并与自己的物理地址进行比较,如二者相符,则接收;否则丢弃。而诸如 IP、IPX 协议则工作在 OSI 协议层的网络层(第 3 层)以确定网络和子网。 网络地址是为了方便寻址人为划分的地址格式,也被称为逻辑地址,也被称为3层地址。

以太网址是一种不包含位置信息的简单标识,它只是对网络设备简单加以区分。这种无位置信息的地址对局域网来说就已经足够。但对于广域网这种复杂无规则,采用点到点连线构成的总体结构,有着庞大的主机数目,使用这种无位置的标识符作为地址就面临着巨大的挑战,无论是采用局域网的广播方式,还是逐一试探,无疑都是开销巨大、笨拙不堪的做法。所以广域网必须采用有结构的地址标识符,不但标识主机,还要指出主机的位置。

之所以存在两种寻址方式,这正是 OSI 参考模型的设计初衷之一:每一层的变化都不会影响到其他层。网络层协议也不用关心物理地址的差异,无论其下一层的物理地址是什么类型,都可以被统一到一致的 IP 地址形式上。而当存在一个附加层的地址寻址时,设备更易于移动。例如以太网交换机可以无需了解具体的网络层协议,无论网络采用 IP 协议还是 IPX 协议,都无需更换一台交换机。

为了标识数据链路层的众多设备,IEEE 为 802 协议族定义了如下的寻址方式:网络设备制造商在生产网络设备时,会为每个硬件分配一个全球唯一码,称为 MAC 地址,并被固化到硬件内部,因此也叫物理地址或硬件地址。当网络设备收到数据帧时,它负责检出数据帧中的目的地址,并与自己的物理地址进行比较,如二者相符,则接收;否则丢弃。

>>> 阅读全文

 

, , ,

PyDAAL 简介 (1)数据结构

Intel DAAL 是在针对英特尔架构优化过构建模块上编写的, 为所有数据分析阶段提供了支持。通过 DAAL, 数据驱动决策获得了包括数据获取、预处理、转换、数据挖掘、建模和验证等等基础支撑。Python 用户可以通过称为 PyDAAL 的 Python API 获取这些基础支撑。 利用 Python 进行机器学习时,你可以通过一个简单的脚本 API 来访问 PyDAAL。此外, PyDAAL 提供了独特功能, 可以轻松地将 Python 脚本化的批处理分析扩展到在线 (流) 数据获取和/或分布式数学处理。

在本系列文章中, 我们将从最基础的部分开始,逐一介绍 PyDAAL 的基础知识。第一部分将介绍 Intel DAAL 的自定义数据结构、数值表和数据管理在 PyDAAL 世界里的表示。1

一、PyDAAL 数据管理
Intel DAAL 支持以下几种数据处理方式:

  • 批处理
  • 在线处理
  • 分布式处理
  • 复合处理(结合在线处理和分布式处理)

本文重点关注批处理方式。在线和分布式处理将在后面的文章中进行讨论。

Python 编程方面的一些思考
强类型:Python 脚本大量使用了动态类型 (鸭子类型) , 借助于 Python 解释器在运行时来进行类型推断。但对于内存占用敏感或进行混合代码部署的情况, 这种做法可能会导致问题。PyDAAL API 调用了用 C++ 和汇编语言编写的库, 这迫使用户使用混合代码环境。因此, PyDAAL 需要一致的类型, 其支持 numpy 类型 “np.float32”, “np.float64”, 和 “np.intc” 。静态/强类型不仅允许显式声明数据类型以实现最佳内存管理, 还可以在编译过程中强制进行类型检查, 大大缩短了运行时间。

>>> 阅读全文

 

, , , ,

将 Win32 枚举型 APIs 转换为 STL 迭代器

原文1 2

操作系统用于访问实体集合的 API 十分普遍,如 Unix 的 opendir()/readdir() 函数。Win32 API 也提供了函数来枚举集合内的元素,通常采用的模型无外乎下面几种:回调函数 (如 EnumChildWindows), get-first/get-next (取第一个/再取下一个 比如FindFirst/NextFile), 或 get-nth (按 n 访问 如 RegEnumValue) — 其语义和前二者完全不同。

当前 C++ 社区正在逐步朝着符合 STL 的通用编码格式迈进,如使用容器 (序列容器和关联容器)、迭代器、泛函数 (仿函数或函数对象)、算法和适配器等等。这种做法的好处是可以使用通用的方法操纵不同的实体, 大大减少开发者的工作量, 同时提高健壮性、可维护性且有利于重用。

STL 技术未能被广泛运用的原因之一是除了标准库提供的类和函数 (list, vector, for_each 等) 之外, 缺少可用的 STL 兼容库, 特别对于广泛使用的操作系统 API。因为这涉及到编程模型之间迁移转换的复杂性, 特别是对于集合和序列。本文将创建两个封装了 Win32 API 的轻量级序列类, 并提供了按 STL 标准算法来操纵枚举实体的迭代器,由此将两种 Win32 枚举模型实际转换成 STL 序列,

本文所演示的类是 WinSTL 库的一部分,WinSTL 则是 STLSoft 的子项目。STLSoft 是个开源组织,一直致力于将 STL 概念运用到多种技术和操作系统中去。

>>> 阅读全文

 

, , , ,

C++ 设计模式之一 建造型模式

设计模式既不是某种静态解决方案,也不是某种算法。设计模式通过其名称(大多数是对目标的简单描述)来介绍或引入一些常见设计问题的重复解决方案或方法,或者说是解决一般性问题的常用方法。因此作为对具体实现的一种抽象,设计模式在设计阶段就十分有用。有了这个概念,在做设计选择时作为标准技术进行沟通,可以让团队成员更容易分享其设计理念。

根据所解决的设计问题,设计模式主要分为以下几大类:

  • 创建型模式 (Creational Patterns)
  • 结构型模式 (Structural Patterns)
  • 行为型模式 (Behavioral Patterns)

模式在 C++ 或 Java 这类面向对象的编程语言中十分常见。它可被视为模板,用来说明如何解决某个在不同场景或应用中反复出现的问题。设计模式不是代码重用,因为它通常没有具体代码,但通过设计模式轻松创建代码。面向对象的设计模式通常显示的是类或对象之间的关系和互动,而无需涉及应用最终呈现的类或对象。

每个设计模式由以下几个部分组成:

  • 问题或需求(Problem/Requirement):它阐述了所要解决的问题的需求。通常是在多个应用中都会遇到的常见问题。
  • 制约条件(Forces): 它描述了技术限制,用来帮助指导创建解决方案.
  • 解决方案(Solution): 它描述了介绍如何编码来解决上述问题。这是设计模式的设计部分。它可能包含类图
    时序图等等。

设计模式可以视为一个标准,是广泛认可的用来解决某个特定设计问题的最佳实践。在应用程序内采用良好的设计模式,可以大大加速你的设计工作,并有助于和其他程序员进行沟通,从而避免解决方案陷入繁琐晦涩的境地。

>>> 阅读全文

 

,

用 PostgreSQL Schemas 创建多租户 Rails 应用

许多 Rails 应用有多租户的需求。为此可以采取多种不同的策略,而每种策略都各有利弊。Guy Naor 曾对每一策略的利弊都进行了详细论述,具体可以参考他的 2009 Acts As Conference talk(必看)。1

这些多租户策略之一运用了 Postgresql 特有的称为 “Schemas” 的特性。不过 Guy 只是在技术层面泛泛带过,并未深入到实现细节。要如何运用这一策略来实际完成多租户应用,你可以从网上搜到几篇博客、StackOverflow 的讨论以及一些半成品,但诸多细节还要自己推敲,这里我将之记录下来,以飨读者。

为什么使用 PostgreSQL Schemas
Guy 列举了多租户 Rails 应用的三种基本策略:2

  • 每个租户使用独立数据库
  • 单一数据库,用记录维护着租户关系的范围
  • 单一数据库,每个租户使用不同的 Schemas (只适用 PostgreSQL)

选择哪一种策略需要诸多考量,这里不一一列举,我想说的是,对于第 3 种策略,应用应有以下特征:

  • 租户的数据是私有的,不能泄露给其他租户
  • 几乎不进行跨租户数据聚合的查询
  • 租户数量很多,无法承担过高管理开销

由于应用间存在千差万别,所以个人建议你最好认真看完该演讲,然后自己阿里做决定。如果你最终还是选择了 PostgreSQL Schema ,你再回来继续读完这篇文章。

>>> 阅读全文

 

, , ,

无锁双向链表

基于锁的同步机制总是受到象优先级反转(priority inversion )和死锁的困扰,即使这样,无锁同步还未引起重视。原因是要编写正确且高效的无锁代码实在困难1。本文演示了一个无锁双向链表的实现,实用且易于理解。第一个无锁双向链表是由 H°akan Sundell 实现的,本文中的方案利用了单字 (single-word) 的比较并转换(CAS — compare-and-swap)原子原语。在附录中提供了本方案与 H°akan Sundell 实现的链表的比较结果。 2

背景: 原子操作与 CAS
原子操作是指一系列必须整体完成的操作步骤,如果任何一步操作没有完成,那么所有完成的步骤都必须回滚,这样就可以保证要么所有操作步骤都未完成,要么所有操作步骤都被完成。在单核系统里,单个的机器指令可以看成是原子操作(如果有编译器优化、乱序执行等情况除外);在多核系统中,单个的机器指令就不是原子操作,因为多核系统里是多指令流并行运行的,一个核在执行一个指令时,其他核同时执行的指令有可能操作同一块内存区域,从而出现数据竞争现象。多核系统中的原子操作通常使用内存栅障(memory barrier)来实现,即一个 CPU 核在执行原子操作时,其他 CPU 核必须停止对内存操作或者不对指定的内存进行操作,这样才能避免数据竞争问题。3

因此在 X86 平台上,Intel 提供了在指令执行期间对总线加锁的手段。CPU 芯片上有一条引线 #HLOCKpin,如果汇编程序中的某条指令带了前缀 “LOCK”,CPU 执行到这条指令时就会 #HLOCKpin 的电位拉低直到该指令结束,从而将总线锁住,这样同一总线上其它 CPU 就暂时不能通过总线访问内存了,这样保证了指令在多处理器环境中的原子性。

所谓比较并交换 (CAS) 是在多线程中可用来获得同步的原子指令。CAS 操作包含三个操作数 —— 目标值(V)、原值(A)和新值(B)。CAS 指令会先将目标值 V 与原值 A 进行比较,如果二者相同,那么就可以新值 B 赋予目标值。

在 Windows 和 .NET 平台,由于历史原因,CAS 被写做 Interlocked API。原子操作在 Intel 架构 CPU 对应的汇编指令有 XCHG、CMPXCHG、INC 等,当然还得加上 LOCK 作为前缀。

>>> 阅读全文

 

, , ,

在 .NET 4.5 中使用 Websocket

作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas、本地存储、多媒体编程接口、WebSocket 等等。这其中有“Web 的 TCP ”之称的 WebSocket 格外吸引开发人员的注意。WebSocket 的出现使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道。Web 开发人员可以非常方便地使用 WebSocket 构建实时 web 应用,

IETF 的 RFC 6455 对 WebSocket 协议进行了标准化, 在 Wikipedia 和 W3C 站点上提供了更多的介绍和详细资料。

WebSocket 连接是通过在客户端和服务器之间的 HTTP 握手来建立的(前缀是 “ws://” 或者 “wss://”) 。拿 Wikepedia 上例子来说明,客户端会这样发出请求:

GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

之后服务器发出响应来接受连接:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

这里的 “Sec-WebSocket-Key” 和 “Sec-WebSocket-Accept” 用于通过密钥验证算法来确认客户端和服务器之间的连接。

>>> 阅读全文

 

, , , ,

Ada 语言编程 (二)

由于 Ada 出生年月略迟了一点,加上现在的操作系统基本上由 C 或 C++ 写成,导致 Ada 在“平民层”的推广比较糟糕,至今还不是很流行,Why Ada isn’t Popular 一文对此有比较详细的解释。而 Ada 爱好者们为了显示 Ada 的优越性(这种心情相当能理解),将 Ada 与 C、C++ 做了一系列比较,其结果反正综和指数都是 Ada 高,这方面文章有不少,如 Comparing Development Costs of C and Ada,Contrasts: Ada 95 & C++ 等等。在这里,我们只初略地了解一下 Ada 的优势即可,在读者朋友接下去的学习中,应该是能从心里感受到 Ada 的优点。1

  • 更高的安全性、可靠性。Ada 中对于访问内存、数值计算等很多方面有一些严格的规定,而没有 C 和 C++ 那么自由;程序的错误绝大部份能在编译和运行时检测到,另外,语言也包含异常特性,能方便地处理错误。
  • 更高的移植性。 Ada 最初的语言环境中就有了异常(约等于 Unix 下的 Signal)、任务(线程)、分布式计算、随机数产生、宽字符集等众多特性,而在其他语言中,这些特性往往随系统而异。即使 Ada95 里缺少一些功能,也可以通过额外标准和函数库来弥补:比如 GDI 库方面,可以使用 GtkAda;
  • 语法明确,基本上没有令人混淆的地方。Ada 程序的源代码远远比 C 或 C++ 的代码易懂。

总之,C 和 C++ 能做的 Ada 肯定能做,但 Ada 要省时方便得多。在学习 Ada之后,无需多说也就明白了。

第一个程序
大部份书籍一般都是用 “hello world” 程序来开始,我们就来看一下在屏幕上输出 “Hello World!”的简单例子。

— filename:hello.adb;
 with Ada.Text_IO;
 procedure Hello is
 begin
    Ada.Text_IO.Put ("Hello World!");
    Ada.Text_IO.New_Line;
 end Hello;

现在让我们分析上述的简单程序:

[000]标示该程序文件名为 hello.adb,在程序中并不需要;– 是注释符,表示从其所在位置至行尾都是注释,对程序没有什么影响,与 C 的 /* */类似。

>>> 阅读全文

 

用 libclang 实现代码生成器

文章评价:
代码生成器对大型 C++ 项目而言是非常有用的工具。由于语言层面上缺乏自省(introspection)机制,要实现反射、脚本绑定(script binding)及序列化都需要编写代码样板(boilerplate) 以保留相关信息,否则在编译时这些数据会全部被丢弃。大部分解决方案要嘛是侵入式的(严重依赖于宏 — Macro,结果难以调试且要求怪异的语法声明)要嘛非常脆弱(fragile)(要根据实际代码不断更新样板,常常没有任何警告就中止运行)。提高鲁棒性的方法之一是自动生成这类样板。要实现这一目标,需要用某种方式解析代码,换句话说,需要了解什么信息该被保留。然而,解析 C++ 本身就是极其复杂的工作,要考虑各种怪异情况,如果真想这样做,消费的时间可能相当漫长。 1

即使只针对 C++ 某个“差堪可用”的子集进行解析,这类尝试要嘛失败了要嘛对编码规则有严格要求。也就是说,要求避免使用解析器无法理解的语法 — 一旦有人不按规矩提交代码解析器就会中止工作。要解决这个问题,我发现 LLVM 项目中有一个很好的工具:libclang2。由于 CLANG C++ 前端 和 libclang 调用的代码是相同的,所以它了解 C++ 的一切。该类库的最新发布可以支持 C++1x(如不出意外将是 C++14)的功能。唯一略有欠缺的是文档方面:其官方文档不过是 Doxygen 生成的参考,虽然有用,但不足以介绍如何使用该类库;加上问题本身的复杂性,学习曲线将十分陡峭。

本文要讲述的是如何用 libclang 及其 Python 绑定来实现一个实用的 C++ 代码生成器。在某种意义上,“实用” 意味着这不是一个通用的解决方案。这里所演示的不是某种具体的实现,而是一种解决问题的思路、一个详细的范例。借助这些想法,你可以自己创建通用的反射方案。本文的另一设计原则是尽力减少代码侵入以便能按自然 C++ 语法编写代码。同时我也鼓励读者自己动手,从头开始尝试实现自己的代码生成器。

我必须感谢 Eli Bendersky 的有关帖子3,它是我收集的资料中最好的参考之一。

准备工作
要读懂本文,读者可能需要具备以下知识点:

>>> 阅读全文

 

, , , , ,

C++ 11 中的多线程

文章评价:

第一个 C++ 标准发布至今已经过去十三年了,随着新的 C++11(或称 C++0X)标准的推出,C++ 标准委员会所做出的显著改变之一就是支持多线程编程。这是首次在 C++ 语言中为并行编程提供支持,而且与平台无关。

在 C++11 标准之前,编写多线程应用需要依赖于特定的平台扩展,如 Intel TBB、OpenMP、Pthreads 等等。现在有了 C++11 的标准线程库就方便了应用移植(例如 Windows 上的 C++11 多线程应用将很容易移植到 Linux 平台),另外对于熟知 Boost 线程库的用户来说,由于 C++11 标准库中许多命名与结构都和 Boost 相同,上手非常容易。1

C++11 标准库中的类可用于线程操作与同步、公用保护数据及低层次的原子操作。

C++11 标准中涉及多线程编程的主要有四个头文件,分别是:<atomic> ,<thread>,<mutex>,<condition_variable>和<future>:

>>> 阅读全文

 

, , ,

Previous Posts