Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Preserve upstream document bytes and original whitespace on every platform.
upstream/** -text -whitespace
90 changes: 90 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
mcpp:
name: mcpp (${{ matrix.os }}, ${{ matrix.toolchain }})
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-24.04, toolchain: 'gcc@16.1.0' }
- { os: ubuntu-24.04, toolchain: 'llvm@23.1.3' }
- { os: macos-15, toolchain: 'llvm@23.1.3' }
- { os: windows-2025, toolchain: 'llvm@23.1.3' }
runs-on: ${{ matrix.os }}
timeout-minutes: 60
defaults:
run:
shell: bash
env:
XLINGS_NON_INTERACTIVE: 1
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Mwrap identity and bilingual README contract
run: python3 tools/check_mwrap_release.py

- name: Install Xlings (Linux/macOS)
if: runner.os != 'Windows'
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/refs/heads/main/tools/other/quick_install.sh | bash
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"

- name: Install Xlings (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
irm https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.ps1 | iex
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Install project tools (.xlings.json)
run: |
for attempt in 1 2 3; do
xlings update > /dev/null 2>&1 || true
if xlings install; then break; fi
[ "$attempt" = 3 ] && exit 1
sleep 30
done
mcpp --version

- name: Select the toolchain
run: |
name="${{ matrix.toolchain }}"
mcpp toolchain install "${name%@*}" "${name#*@}"
mcpp toolchain default "$name"

- name: Build the modules (and with the c-api feature)
run: |
mcpp build
mcpp build --features c-api

- name: Tests (the queues through the module from many threads, the constants, header mixing)
run: mcpp test

- name: Tests with the c-api and no-thread-local features (the C API; gtest beside the queue)
working-directory: tests/c_api
run: mcpp test

- name: Export audit (every declaration of moodycamel, every helper of details, the C API, every macro)
run: python3 tools/check_exports.py

- name: Upstream's tests/unittests built against the module
run: python3 tools/run_conformance.py
49 changes: 49 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Release
on:
push:
tags: ["mwrap-*"]
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
actions: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Check tag, upstream version and bilingual entry pages
run: python3 tools/check_mwrap_release.py --tag "$GITHUB_REF_NAME"
- name: Require successful source CI at this exact commit
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail
result=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow ci.yml --commit "$GITHUB_SHA" --limit 1 --json status,conclusion --jq '.[0] | .status == "completed" and .conclusion == "success"')
test "$result" = true || { echo 'No successful source CI at the tag commit'; exit 1; }
- name: Build immutable source asset and publish
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail
version="${GITHUB_REF_NAME#mwrap-}"
repo="${GITHUB_REPOSITORY#*/}"
asset="${repo}-${version}.tar.gz"
git archive --format=tar.gz --prefix="${repo}-${version}/" "$GITHUB_SHA" > "$RUNNER_TEMP/$asset"
(cd "$RUNNER_TEMP" && sha256sum "$asset" > "$asset.sha256")
if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
echo 'Release already exists; refusing to change immutable assets'; exit 1
fi
extra=()
if [[ "$version" == *-rc* ]]; then extra+=(--prerelease); fi
gh release create "$GITHUB_REF_NAME" "$RUNNER_TEMP/$asset" "$RUNNER_TEMP/$asset.sha256" \
--repo "$GITHUB_REPOSITORY" --verify-tag --title "$repo $version" \
--notes "Module wrapper for upstream $version. New mwrap package identities become installable after mcpp-index publication; see the bilingual README for the tested support scope." "${extra[@]}"
28 changes: 28 additions & 0 deletions .github/workflows/templates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Actual project templates
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: templates-${{ github.ref }}
cancel-in-progress: true
env:
MCPP_VERSION: "2026.10.26.1"
jobs:
templates:
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- name: Install the pinned mcpp
shell: bash
run: |
archive="mcpp-${MCPP_VERSION}-linux-x86_64.tar.gz"
curl -L -fsS -o "$archive" "https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/$archive"
tar -xzf "$archive"
echo "$PWD/mcpp-${MCPP_VERSION}-linux-x86_64/bin" >> "$GITHUB_PATH"
- name: Actual scaffold, strict build and run of the default template
run: python3 tools/test_template.py --toolchain gcc@16.1.0
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
target
compile_commands.json
mcpp.lock
.mcpp/
.xlings/
doctor.log
__pycache__/
5 changes: 5 additions & 0 deletions .xlings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"workspace": {
"xim:mcpp": "2026.10.26.1"
}
}
16 changes: 16 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
concurrentqueue-m: C++ module wrapper
Copyright (c) 2026 mcpp-community contributors

The wrapper contributions are licensed under the Apache License, Version 2.0.
Upstream code, copied interfaces and dependencies retain their original
licenses and copyright notices. moodycamel::ConcurrentQueue is distributed
under the Simplified BSD license or, at your option, the Boost Software
License 1.0; its lightweight semaphore embeds Jeff Preshing's semaphore under
the zlib license:

Copyright (c) 2013-2016, Cameron Desrochers.
Copyright (c) 2015 Jeff Preshing.

Its original README and license are retained in upstream/concurrentqueue/.
The headers themselves are provided by compat.concurrentqueue from the same
release. Provenance and checksums are recorded in upstream/documents.json.
95 changes: 94 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,94 @@
# concurrentqueue-m — moodycamel::ConcurrentQueue as C++23 modules (mcpplibs.mwrap.concurrentqueue)
# concurrentqueue

> moodycamel::ConcurrentQueue, the lock-free multi-producer multi-consumer queue, through C++23 modules.

**English** · [简体中文](README.zh.md) · [Upstream](https://github.com/cameron314/concurrentqueue) · [Releases](https://github.com/mcpplibs/concurrentqueue-m/releases) · [mcpp](https://github.com/mcpp-community/mcpp) · [Index](https://github.com/mcpplibs/mcpp-index)

[![C++23](https://img.shields.io/badge/C%2B%2B-23-blue.svg)](https://en.cppreference.com/w/cpp/23)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
[![mcpp-community](https://img.shields.io/badge/mcpp--community-mwrap-blue)](https://github.com/mcpp-community)
[![CI](https://github.com/mcpplibs/concurrentqueue-m/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/mcpplibs/concurrentqueue-m/actions/workflows/ci.yml)

The upstream API is unchanged: `moodycamel::ConcurrentQueue`,
`BlockingConcurrentQueue`, `ProducerToken`, `ConsumerToken` and
`LightweightSemaphore` are the upstream entities of the three headers,
templates over your element and `Traits` types. The headers are
`compat.concurrentqueue` 1.0.5. The value macros are constants. Upstream's
own `tests/unittests` (all 45 tests) pass on every CI run, built against the
module instead of the headers.

## Modules

- `import mcpplibs.mwrap.concurrentqueue;`: the queues, tokens, traits, semaphore and `swap` in `moodycamel`, re-exporting the one below
- `import mcpplibs.mwrap.concurrentqueue.macros;`: `MOODYCAMEL_EXCEPTIONS_ENABLED`, `MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED` … in `mcpplibs::mwrap::concurrentqueue::macros`
- `import mcpplibs.mwrap.concurrentqueue.c_api;`: the C API (`moodycamel_cq_*`, `moodycamel_bcq_*`), with the `c-api` feature

> More Modules API -> [Usage and API](docs/usage.md)

## Getting started

```sh
mcpp new pipeline --template mcpplibs.mwrap.concurrentqueue@1.0.5
cd pipeline
mcpp run
```

The default template runs a producer-consumer pipeline. Producer threads
enqueue numbers in bulk through their tokens. Consumers wait on a blocking
queue with a timeout and count primes.

```toml
[dependencies]
"mcpplibs.mwrap.concurrentqueue" = "1.0.5"
```

```cpp
import std;
import mcpplibs.mwrap.concurrentqueue;

int main() {
moodycamel::ConcurrentQueue<std::function<void()>> tasks;
std::jthread worker([&] { tasks.enqueue([] { std::println("ran on the main thread"); }); });
worker.join();
std::function<void()> task;
while (tasks.try_dequeue(task)) task();
}
```

| Feature | Effect |
|---|---|
| `c-api` | upstream's C API: compat.concurrentqueue's sources and the `c_api` module |
| `no-thread-local` | `MOODYCAMEL_NO_THREAD_LOCAL`: no `thread_local`, implicit producers not recycled at thread exit |

## Configuration and macros

Configuration macros must be set before the module is built. The module
uses upstream's defaults, with `MOODYCAMEL_NOEXCEPT_CTOR` / `_ASSIGN` spelled
as the equivalent type traits so that GCC accepts the interface
([config.hpp](include/mwrap/concurrentqueue/config.hpp)). Per-queue settings
(block size, index sizes, allocation) are the `Traits` argument, as upstream
documents. The syntax macros (`MOODYCAMEL_NOEXCEPT`,
`MOODYCAMEL_DELETE_FUNCTION`, `MOODYCAMEL_TRY` …) stay in
`<mwrap/concurrentqueue/macros.hpp>`, included before the imports. With GCC,
a unit that includes `<cxxabi.h>` (gtest does) cannot use the queue's
thread-exit path: use `no-thread-local` there. Details:
[docs/usage.md](docs/usage.md).

## Build and testing

Linux, macOS and Windows CI build the modules and run the tests:
multi-producer multi-consumer traffic, tokens, bulk operations, timed waits,
user types and traits, the semaphore, the C API and header mixing. CI also
runs the export audit ([tools/check_exports.py](tools/check_exports.py): every
declaration exported or listed with its reason, every macro mapped or kept)
and upstream's `tests/unittests` against the module
([tools/run_conformance.py](tools/run_conformance.py)). A separate job
scaffolds the default template as an installed package and runs it.

## License

[Apache-2.0](LICENSE) for the wrapper, by mcpp-community ([NOTICE](NOTICE)).
concurrentqueue remains under the Simplified BSD license or the Boost Software
License, and its semaphore under zlib
([upstream/concurrentqueue/LICENSE.md](upstream/concurrentqueue/LICENSE.md),
[README](upstream/concurrentqueue/README.md)).
86 changes: 86 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# concurrentqueue

> 通过 C++23 模块使用 moodycamel::ConcurrentQueue(无锁的多生产者多消费者队列)。

[English](README.md) · **简体中文** · [上游](https://github.com/cameron314/concurrentqueue) · [发布](https://github.com/mcpplibs/concurrentqueue-m/releases) · [mcpp](https://github.com/mcpp-community/mcpp) · [索引](https://github.com/mcpplibs/mcpp-index)

[![C++23](https://img.shields.io/badge/C%2B%2B-23-blue.svg)](https://en.cppreference.com/w/cpp/23)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
[![mcpp-community](https://img.shields.io/badge/mcpp--community-mwrap-blue)](https://github.com/mcpp-community)
[![CI](https://github.com/mcpplibs/concurrentqueue-m/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/mcpplibs/concurrentqueue-m/actions/workflows/ci.yml)

上游 API 保持不变:`moodycamel::ConcurrentQueue`、`BlockingConcurrentQueue`、
`ProducerToken`、`ConsumerToken`、`LightweightSemaphore` 就是三个头文件里的上游
实体,是以你的元素类型和 `Traits` 类型为参数的模板。头文件由
`compat.concurrentqueue` 1.0.5 提供,表示值的宏映射为常量。每次 CI 都会把上游自带的
`tests/unittests`(共 45 个测试)改为基于本模块构建(而不是头文件),并且全部通过。

## 模块

- `import mcpplibs.mwrap.concurrentqueue;`:`moodycamel` 中的队列、令牌、traits、信号量和 `swap`,并重新导出下面这个模块
- `import mcpplibs.mwrap.concurrentqueue.macros;`:`MOODYCAMEL_EXCEPTIONS_ENABLED`、`MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED` 等,位于 `mcpplibs::mwrap::concurrentqueue::macros`
- `import mcpplibs.mwrap.concurrentqueue.c_api;`:C API(`moodycamel_cq_*`、`moodycamel_bcq_*`),需要 `c-api` 特性

> 更多模块 API -> [用法和 API](docs/usage.md)

## 快速开始

```sh
mcpp new pipeline --template mcpplibs.mwrap.concurrentqueue@1.0.5
cd pipeline
mcpp run
```

默认模板运行一条生产者-消费者流水线:生产者线程通过各自的令牌批量入队数字,
消费者在阻塞队列上带超时地等待,并统计其中的素数。

```toml
[dependencies]
"mcpplibs.mwrap.concurrentqueue" = "1.0.5"
```

```cpp
import std;
import mcpplibs.mwrap.concurrentqueue;

int main() {
moodycamel::ConcurrentQueue<std::function<void()>> tasks;
std::jthread worker([&] { tasks.enqueue([] { std::println("ran on the main thread"); }); });
worker.join();
std::function<void()> task;
while (tasks.try_dequeue(task)) task();
}
```

| 特性 | 作用 |
|---|---|
| `c-api` | 上游的 C API:compat.concurrentqueue 中的源文件和 `c_api` 模块 |
| `no-thread-local` | `MOODYCAMEL_NO_THREAD_LOCAL`:不使用 `thread_local`,线程退出时不回收隐式生产者 |

## 配置与宏

配置宏必须在模块构建之前设定。模块使用上游默认配置,只是把
`MOODYCAMEL_NOEXCEPT_CTOR` / `_ASSIGN` 写成等价的类型特征,这样 GCC 才能接受这个
接口([config.hpp](include/mwrap/concurrentqueue/config.hpp))。单个队列的设置
(块大小、索引大小、内存分配)按上游文档通过 `Traits` 参数传入。语法类的宏
(`MOODYCAMEL_NOEXCEPT`、`MOODYCAMEL_DELETE_FUNCTION`、`MOODYCAMEL_TRY` 等)保留在
`<mwrap/concurrentqueue/macros.hpp>` 中,需要在 import 之前包含。使用 GCC 时,包含了
`<cxxabi.h>` 的翻译单元(gtest 会包含它)不能使用队列在线程退出时的回收路径,
这时请启用 `no-thread-local`。详见 [docs/usage.md](docs/usage.md)。

## 构建与测试

Linux、macOS 和 Windows 的 CI 会构建模块并运行测试,覆盖:多生产者多消费者流量、
令牌、批量操作、带超时的等待、用户类型与 traits、信号量、C API,以及头文件与模块
混用。CI 还会运行导出审计([tools/check_exports.py](tools/check_exports.py):每个
声明都已导出或注明原因,每个宏都已映射或保留为宏),并基于本模块运行上游的
`tests/unittests`([tools/run_conformance.py](tools/run_conformance.py))。另一个任务
把默认模板当作已安装的包生成出来并运行。

## 许可证

封装部分采用 [Apache-2.0](LICENSE),作者为 mcpp-community([NOTICE](NOTICE))。
concurrentqueue 仍采用 Simplified BSD 许可证或 Boost Software License,其中的
信号量部分采用 zlib 许可证
([upstream/concurrentqueue/LICENSE.md](upstream/concurrentqueue/LICENSE.md)、
[README](upstream/concurrentqueue/README.md))。
Loading
Loading