feat add event_bus #1
@ -27,150 +27,22 @@ concurrency:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
jobs:
|
jobs:
|
||||||
linux-gcc:
|
linux-gcc-aarch64:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: cache-qemu
|
|
||||||
id: cache-qemu
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: qemu-install
|
|
||||||
key: qemu-aarch64-install-20220502-ubuntu-2004-2
|
|
||||||
- name: install-qemu-build-deps
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y autoconf automake autotools-dev ninja-build
|
|
||||||
- name: checkout-qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
mkdir qemu && cd qemu
|
|
||||||
git init
|
|
||||||
git remote add origin https://gitlab.com/qemu-project/qemu.git
|
|
||||||
git fetch --depth=1 origin f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
git checkout f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
# with:
|
|
||||||
# repository: qemu/qemu
|
|
||||||
# path: qemu
|
|
||||||
# ref: f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
- name: qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd qemu
|
|
||||||
./configure --prefix=$GITHUB_WORKSPACE/qemu-install --target-list=aarch64-linux-user --disable-system
|
|
||||||
make -j$(nproc)
|
|
||||||
make install
|
|
||||||
- name: aarch64-gnu-toolchain
|
- name: aarch64-gnu-toolchain
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y cmake make g++-aarch64-linux-gnu
|
sudo apt-get install -y cmake make g++-aarch64-linux-gnu qemu-user-binfmt
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/aarch64-linux-gnu.toolchain.cmake -DSLED_BUILD_TESTS=ON -DSLED_BUILD_BENCHMARK=ON
|
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/aarch64-linux-gnu.toolchain.cmake -DSLED_BUILD_TESTS=ON -DSLED_BUILD_BENCHMARK=ON ..
|
||||||
cmake --build . -j $(nproc)
|
|
||||||
- name: test
|
|
||||||
run: |
|
|
||||||
export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH
|
|
||||||
cd build
|
|
||||||
TESTS_EXECUTABLE_LOADER=qemu-aarch64 TESTS_EXECUTABLE_LOADER_ARGUMENTS="-L;/usr/aarch64-linux-gnu" ctest --output-on-failure -j $(nproc)
|
|
||||||
linux-gcc-arm82:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: cache-qemu
|
|
||||||
id: cache-qemu
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: qemu-install
|
|
||||||
key: qemu-aarch64-install-20220502-ubuntu-2004-2
|
|
||||||
- name: install-qemu-build-deps
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y autoconf automake autotools-dev ninja-build
|
|
||||||
- name: checkout-qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
mkdir qemu && cd qemu
|
|
||||||
git init
|
|
||||||
git remote add origin https://gitlab.com/qemu-project/qemu.git
|
|
||||||
git fetch --depth=1 origin f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
git checkout f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
# with:
|
|
||||||
# repository: qemu/qemu
|
|
||||||
# path: qemu
|
|
||||||
# ref: f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
- name: qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd qemu
|
|
||||||
./configure --prefix=$GITHUB_WORKSPACE/qemu-install --target-list=aarch64-linux-user --disable-system
|
|
||||||
make -j$(nproc)
|
|
||||||
make install
|
|
||||||
- name: aarch64-gnu-toolchain
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y cmake make g++-aarch64-linux-gnu
|
|
||||||
- name: build
|
|
||||||
run: |
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/aarch64-linux-gnu.toolchain.cmake -DSLED_BUILD_TESTS=ON -DSLED_BUILD_BENCHMARK=ON
|
|
||||||
cmake --build . -j $(nproc)
|
|
||||||
- name: test
|
|
||||||
run: |
|
|
||||||
export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH
|
|
||||||
cd build
|
|
||||||
TESTS_EXECUTABLE_LOADER=qemu-aarch64 TESTS_EXECUTABLE_LOADER_ARGUMENTS="-L;/usr/aarch64-linux-gnu" ctest --output-on-failure -j $(nproc)
|
|
||||||
linux-gcc-arm86:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: cache-qemu
|
|
||||||
id: cache-qemu
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: qemu-install
|
|
||||||
key: qemu-aarch64-install-20230717
|
|
||||||
- name: install-qemu-build-deps
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y autoconf automake autotools-dev ninja-build
|
|
||||||
- name: checkout-qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
mkdir qemu && cd qemu
|
|
||||||
git init
|
|
||||||
git remote add origin https://gitlab.com/qemu-project/qemu.git
|
|
||||||
git fetch --depth=1 origin f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
git checkout f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
# with:
|
|
||||||
# repository: qemu/qemu
|
|
||||||
# path: qemu
|
|
||||||
# ref: ed8ad9728a9c0eec34db9dff61dfa2f1dd625637
|
|
||||||
- name: qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd qemu
|
|
||||||
./configure --prefix=$GITHUB_WORKSPACE/qemu-install --target-list=aarch64-linux-user --disable-system
|
|
||||||
make -j$(nproc)
|
|
||||||
make install
|
|
||||||
- name: aarch64-gnu-toolchain
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y cmake make g++-aarch64-linux-gnu
|
|
||||||
- name: build
|
|
||||||
run: |
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/aarch64-linux-gnu.toolchain.cmake -DSLED_BUILD_TESTS=ON -DSLED_BUILD_BENCHMARK=ON
|
|
||||||
cmake --build . -j $(nproc)
|
cmake --build . -j $(nproc)
|
||||||
- name: test
|
- name: test
|
||||||
run: |-
|
run: |-
|
||||||
export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH
|
|
||||||
cd build
|
cd build
|
||||||
TESTS_EXECUTABLE_LOADER=qemu-aarch64 TESTS_EXECUTABLE_LOADER_ARGUMENTS="-L;/usr/aarch64-linux-gnu" ctest --output-on-failure -j $(nproc)
|
ln -sf /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /lib/ld-linux-aarch64.so.1
|
||||||
|
export LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib
|
||||||
|
ctest --output-on-failure -j$(nproc)
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
name: linux-arm-gcc
|
name: linux-arm-gcc
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- .gitea/workflows/linux-arm-gcc.yml
|
- .gitea/workflows/linux-arm-gcc.yml
|
||||||
- 'toolchains/arm-linux-gnueabi.toolchain.cmake'
|
- toolchains/arm-linux-gnueabi.toolchain.cmake
|
||||||
- 'toolchains/arm-linux-gnueabihf.toolchain.cmake'
|
- toolchains/arm-linux-gnueabihf.toolchain.cmake
|
||||||
- 3party/**
|
- 3party/**
|
||||||
- include/**
|
- include/**
|
||||||
- src/**
|
- src/**
|
||||||
@ -16,8 +15,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- .gitea/workflows/linux-arm-gcc.yml
|
- .gitea/workflows/linux-arm-gcc.yml
|
||||||
- 'toolchains/arm-linux-gnueabi.toolchain.cmake'
|
- toolchains/arm-linux-gnueabi.toolchain.cmake
|
||||||
- 'toolchains/arm-linux-gnueabihf.toolchain.cmake'
|
- toolchains/arm-linux-gnueabihf.toolchain.cmake
|
||||||
- 3party/**
|
- 3party/**
|
||||||
- include/**
|
- include/**
|
||||||
- src/**
|
- src/**
|
||||||
@ -27,125 +26,42 @@ on:
|
|||||||
concurrency:
|
concurrency:
|
||||||
group: linux-arm-gcc-${{ github.ref }}
|
group: linux-arm-gcc-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
linux-gcc-arm:
|
# linux-gcc-arm:
|
||||||
runs-on: ubuntu-20.04
|
# runs-on: ubuntu-20.04
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
|
# - name: arm-gnu-toolchain
|
||||||
- name: cache-qemu
|
# run: |
|
||||||
id: cache-qemu
|
# sudo apt-get update -y
|
||||||
uses: actions/cache@v4
|
# sudo apt-get install -y cmake make g++-arm-linux-gnueabi qemu-user-binfmt
|
||||||
with:
|
# - name: build
|
||||||
path: qemu-install
|
# run: |
|
||||||
key: qemu-arm-install-20220502-2
|
# mkdir build && cd build
|
||||||
- name: install-qemu-build-deps
|
# cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux-gnueabi.toolchain.cmake -DSLED_BUILD_TESTS=ON -DSLED_BUILD_TESTS=ON ..
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
# cmake --build . -j $(nproc)
|
||||||
run: |
|
# - name: test
|
||||||
sudo apt-get update -y
|
# run: |
|
||||||
sudo apt-get install -y autoconf automake autotools-dev ninja-build
|
# cd build
|
||||||
- name: checkout-qemu
|
# ln -sf /usr/arm-linux-gnueabi/lib/ld-linux.so.3
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
# export LD_LIBRARY_PATH=/usr/arm-linux-gnueabi/lib
|
||||||
run: |
|
# qemu-arm ctest --output-on-failure -j$(nproc)
|
||||||
mkdir qemu && cd qemu
|
|
||||||
git init
|
|
||||||
git remote add origin https://gitlab.com/qemu-project/qemu.git
|
|
||||||
git fetch --depth=1 origin f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
git checkout f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
# with:
|
|
||||||
# repository: qemu/qemu
|
|
||||||
# path: qemu
|
|
||||||
# ref: f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
- name: qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd qemu
|
|
||||||
./configure --prefix=$GITHUB_WORKSPACE/qemu-install --target-list=arm-linux-user --disable-system
|
|
||||||
make -j$(nproc)
|
|
||||||
make install
|
|
||||||
|
|
||||||
- name: set-qemu-cache
|
|
||||||
uses: actions/cache/save@v3
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
with:
|
|
||||||
key: qemu-arm-install-20220502-2
|
|
||||||
path: qemu-install
|
|
||||||
|
|
||||||
- name: arm-gnu-toolchain
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y cmake make g++-arm-linux-gnueabi
|
|
||||||
|
|
||||||
- name: build
|
|
||||||
run: |
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux-gnueabi.toolchain.cmake -DSLED_BUILD_TESTS=ON -DSLED_BUILD_TESTS=ON ..
|
|
||||||
cmake --build . -j $(nproc)
|
|
||||||
- name: test
|
|
||||||
run: |
|
|
||||||
export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH
|
|
||||||
cd build
|
|
||||||
TESTS_EXECUTABLE_LOADER=qemu-arm TESTS_EXECUTABLE_LOADER_ARGUMENTS="-L;/usr/arm-linux-gnueabi" ctest --output-on-failure -j $(nproc)
|
|
||||||
|
|
||||||
linux-gcc-armhf:
|
linux-gcc-armhf:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: cache-qemu
|
|
||||||
id: cache-qemu
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: qemu-install
|
|
||||||
key: qemu-arm-install-20220502-2
|
|
||||||
- name: install-qemu-build-deps
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y autoconf automake autotools-dev ninja-build
|
|
||||||
- name: checkout-qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
mkdir qemu && cd qemu
|
|
||||||
git init
|
|
||||||
git remote add origin https://gitlab.com/qemu-project/qemu.git
|
|
||||||
git fetch --depth=1 origin f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
git checkout f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
# with:
|
|
||||||
# repository: qemu/qemu
|
|
||||||
# path: qemu
|
|
||||||
# ref: f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
- name: qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd qemu
|
|
||||||
./configure --prefix=$GITHUB_WORKSPACE/qemu-install --target-list=arm-linux-user --disable-system
|
|
||||||
make -j$(nproc)
|
|
||||||
make install
|
|
||||||
|
|
||||||
- name: set-qemu-cache
|
|
||||||
uses: actions/cache/save@v3
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
with:
|
|
||||||
key: qemu-arm-install-20220502-2
|
|
||||||
path: qemu-install
|
|
||||||
|
|
||||||
- name: arm-gnu-toolchain
|
- name: arm-gnu-toolchain
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y cmake make g++-arm-linux-gnueabihf
|
sudo apt-get install -y cmake make g++-arm-linux-gnueabihf qemu-user-binfmt
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux-gnueabihf.toolchain.cmake -DSLED_BUILD_TESTS=ON ..
|
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux-gnueabihf.toolchain.cmake -DSLED_BUILD_TESTS=ON ..
|
||||||
cmake --build . -j $(nproc)
|
cmake --build . -j $(nproc)
|
||||||
- name: test
|
- name: test
|
||||||
run: |
|
run: |-
|
||||||
export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH
|
|
||||||
cd build
|
cd build
|
||||||
TESTS_EXECUTABLE_LOADER=qemu-arm TESTS_EXECUTABLE_LOADER_ARGUMENTS="-L;/usr/arm-linux-gnueabihf" ctest --output-on-failure -j $(nproc)
|
ln -sf /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 /lib/ld-linux-armhf.so.3
|
||||||
|
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib/
|
||||||
|
ctest --output-on-failure -j$(nproc)
|
||||||
|
@ -35,51 +35,19 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: cache-qemu
|
|
||||||
id: cache-qemu
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: qemu-install
|
|
||||||
key: qemu-mips64el-install-20220502-2
|
|
||||||
- name: checkout-qemu
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
mkdir qemu && cd qemu
|
|
||||||
git init
|
|
||||||
git remote add origin https://gitlab.com/qemu-project/qemu.git
|
|
||||||
git fetch --depth=1 origin f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
git checkout f5643914a9e8f79c606a76e6a9d7ea82a3fc3e65
|
|
||||||
- name: install-qemu-build-deps
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y autoconf automake autotools-dev ninja-build
|
|
||||||
- name: qemu
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/qemu
|
|
||||||
./configure --target-list=mips64el-linux-user --prefix=$GITHUB_WORKSPACE/qemu-install
|
|
||||||
make -j `nproc`
|
|
||||||
make install
|
|
||||||
- name: set-qemu-cache
|
|
||||||
uses: actions/cache/save@v3
|
|
||||||
if: steps.cache-qemu.outputs.cache-hit != 'true'
|
|
||||||
with:
|
|
||||||
key: qemu-mips64el-install-20220502-2
|
|
||||||
path: qemu-install
|
|
||||||
- name: mips64el-gnuabi64-toolchain
|
- name: mips64el-gnuabi64-toolchain
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y cmake make g++-mips64el-linux-gnuabi64
|
sudo apt-get install -y cmake make g++-mips64el-linux-gnuabi64 qemu-user-binfmt
|
||||||
- name: configure
|
- name: configure
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DSLED_BUILD_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=../toolchains/mips64el-linux-gnuabi64.toolchain.cmake -DCMAKE_CROSSCOMPILING_EMULATOR="qemu-mips64el;-L;/usr/mips64el-linux-gnuabi64"
|
cmake .. -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DSLED_BUILD_TESTS=ON -DCMAKE_TOOLCHAIN_FILE=../toolchains/mips64el-linux-gnuabi64.toolchain.cmake #-DCMAKE_CROSSCOMPILING_EMULATOR="qemu-mips64el;-L;/usr/mips64el-linux-gnuabi64"
|
||||||
- name: build
|
- name: build
|
||||||
run: cmake --build build --target all -j `nproc`
|
run: cmake --build build --target all -j `nproc`
|
||||||
- name: test
|
- name: test
|
||||||
run: |-
|
run: |-
|
||||||
export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH
|
|
||||||
cd build
|
cd build
|
||||||
|
ln -sf /usr/mips64el-linux-gnuabi64/lib64/ld.so.1 /lib64/ld.so.1
|
||||||
|
export LD_LIBRARY_PATH=/usr/mips64el-linux-gnuabi64/lib
|
||||||
ctest --output-on-failure -j`nproc`
|
ctest --output-on-failure -j`nproc`
|
||||||
|
@ -7,21 +7,21 @@
|
|||||||
# copies of the Software, and to permit persons to whom the Software is
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
# furnished to do so, subject to the following conditions:
|
# furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
# all copies or substantial portions of the Software.
|
# copies or substantial portions of the Software.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# THE SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
project(Async++ C CXX)
|
project(Async++ C CXX)
|
||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Build Async++ as a shared library" ON)
|
option(BUILD_SHARED_LIBS "Build Async++ as a shared library" OFF)
|
||||||
option(USE_CXX_EXCEPTIONS "Enable C++ exception support" ON)
|
option(USE_CXX_EXCEPTIONS "Enable C++ exception support" ON)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
option(BUILD_FRAMEWORK "Build a Mac OS X framework instead of a library" OFF)
|
option(BUILD_FRAMEWORK "Build a Mac OS X framework instead of a library" OFF)
|
||||||
@ -48,8 +48,7 @@ set(ASYNCXX_INCLUDE
|
|||||||
${PROJECT_SOURCE_DIR}/include/async++/task.h
|
${PROJECT_SOURCE_DIR}/include/async++/task.h
|
||||||
${PROJECT_SOURCE_DIR}/include/async++/task_base.h
|
${PROJECT_SOURCE_DIR}/include/async++/task_base.h
|
||||||
${PROJECT_SOURCE_DIR}/include/async++/traits.h
|
${PROJECT_SOURCE_DIR}/include/async++/traits.h
|
||||||
${PROJECT_SOURCE_DIR}/include/async++/when_all_any.h
|
${PROJECT_SOURCE_DIR}/include/async++/when_all_any.h)
|
||||||
)
|
|
||||||
set(ASYNCXX_SRC
|
set(ASYNCXX_SRC
|
||||||
${PROJECT_SOURCE_DIR}/src/internal.h
|
${PROJECT_SOURCE_DIR}/src/internal.h
|
||||||
${PROJECT_SOURCE_DIR}/src/fifo_queue.h
|
${PROJECT_SOURCE_DIR}/src/fifo_queue.h
|
||||||
@ -57,11 +56,12 @@ set(ASYNCXX_SRC
|
|||||||
${PROJECT_SOURCE_DIR}/src/singleton.h
|
${PROJECT_SOURCE_DIR}/src/singleton.h
|
||||||
${PROJECT_SOURCE_DIR}/src/task_wait_event.h
|
${PROJECT_SOURCE_DIR}/src/task_wait_event.h
|
||||||
${PROJECT_SOURCE_DIR}/src/threadpool_scheduler.cpp
|
${PROJECT_SOURCE_DIR}/src/threadpool_scheduler.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/work_steal_queue.h
|
${PROJECT_SOURCE_DIR}/src/work_steal_queue.h)
|
||||||
)
|
source_group(include FILES ${PROJECT_SOURCE_DIR}/include/async++.h
|
||||||
source_group(include FILES ${PROJECT_SOURCE_DIR}/include/async++.h ${ASYNCXX_INCLUDE})
|
${ASYNCXX_INCLUDE})
|
||||||
source_group(src FILES ${ASYNCXX_SRC})
|
source_group(src FILES ${ASYNCXX_SRC})
|
||||||
add_library(Async++ ${PROJECT_SOURCE_DIR}/include/async++.h ${ASYNCXX_INCLUDE} ${ASYNCXX_SRC})
|
add_library(Async++ ${PROJECT_SOURCE_DIR}/include/async++.h ${ASYNCXX_INCLUDE}
|
||||||
|
${ASYNCXX_SRC})
|
||||||
|
|
||||||
# Async++ only depends on the C++11 standard libraries, but some implementations
|
# Async++ only depends on the C++11 standard libraries, but some implementations
|
||||||
# require the -pthread compiler flag to enable threading functionality.
|
# require the -pthread compiler flag to enable threading functionality.
|
||||||
@ -82,7 +82,8 @@ target_include_directories(Async++ PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
|||||||
set_target_properties(Async++ PROPERTIES DEFINE_SYMBOL LIBASYNC_BUILD)
|
set_target_properties(Async++ PROPERTIES DEFINE_SYMBOL LIBASYNC_BUILD)
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
# Minimize the set of symbols exported by libraries
|
# Minimize the set of symbols exported by libraries
|
||||||
set_target_properties(Async++ PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON)
|
set_target_properties(Async++ PROPERTIES CXX_VISIBILITY_PRESET hidden
|
||||||
|
VISIBILITY_INLINES_HIDDEN ON)
|
||||||
else()
|
else()
|
||||||
target_compile_definitions(Async++ PUBLIC LIBASYNC_STATIC)
|
target_compile_definitions(Async++ PUBLIC LIBASYNC_STATIC)
|
||||||
endif()
|
endif()
|
||||||
@ -92,10 +93,10 @@ if (NOT MSVC)
|
|||||||
target_compile_options(Async++ PRIVATE -Wall -Wextra -pedantic)
|
target_compile_options(Async++ PRIVATE -Wall -Wextra -pedantic)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Async++ doesn't make use of RTTI information, so don't generate it.
|
# Async++ doesn't make use of RTTI information, so don't generate it. There are
|
||||||
# There are issues on Apple platforms with exceptions and -fno-rtti, so keep it
|
# issues on Apple platforms with exceptions and -fno-rtti, so keep it enabled
|
||||||
# enabled there.
|
# there. See
|
||||||
# See https://stackoverflow.com/questions/21737201/problems-throwing-and-catching-exceptions-on-os-x-with-fno-rtti
|
# https://stackoverflow.com/questions/21737201/problems-throwing-and-catching-exceptions-on-os-x-with-fno-rtti
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(Async++ PRIVATE /GR-)
|
target_compile_options(Async++ PRIVATE /GR-)
|
||||||
elseif(NOT APPLE)
|
elseif(NOT APPLE)
|
||||||
@ -104,7 +105,8 @@ endif()
|
|||||||
|
|
||||||
# Allow disabling exceptions, but warn the user about the consequences
|
# Allow disabling exceptions, but warn the user about the consequences
|
||||||
if(NOT USE_CXX_EXCEPTIONS)
|
if(NOT USE_CXX_EXCEPTIONS)
|
||||||
message(WARNING "Exceptions have been disabled. Any operation that would "
|
message(
|
||||||
|
WARNING "Exceptions have been disabled. Any operation that would "
|
||||||
"throw an exception will result in a call to std::abort() instead.")
|
"throw an exception will result in a call to std::abort() instead.")
|
||||||
target_compile_definitions(Async++ PUBLIC LIBASYNC_NO_EXCEPTIONS)
|
target_compile_definitions(Async++ PUBLIC LIBASYNC_NO_EXCEPTIONS)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
@ -114,52 +116,54 @@ if (NOT USE_CXX_EXCEPTIONS)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# /Zc:__cplusplus is required to make __cplusplus accurate
|
# /Zc:__cplusplus is required to make __cplusplus accurate /Zc:__cplusplus is
|
||||||
# /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7
|
# available starting with Visual Studio 2017 version 15.7 (according to
|
||||||
# (according to https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus)
|
# https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus) That
|
||||||
# That version is equivalent to _MSC_VER==1914
|
# version is equivalent to _MSC_VER==1914 (according to
|
||||||
# (according to https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019)
|
# https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019)
|
||||||
# CMake's ${MSVC_VERSION} is equivalent to _MSC_VER
|
# CMake's ${MSVC_VERSION} is equivalent to _MSC_VER (according to
|
||||||
# (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
|
# https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
|
||||||
# GREATER and EQUAL are used because GREATER_EQUAL is available starting with CMake 3.7
|
# GREATER and EQUAL are used because GREATER_EQUAL is available starting with
|
||||||
# (according to https://cmake.org/cmake/help/v3.7/release/3.7.html#commands)
|
# CMake 3.7 (according to
|
||||||
|
# https://cmake.org/cmake/help/v3.7/release/3.7.html#commands)
|
||||||
if((MSVC) AND ((MSVC_VERSION GREATER 1914) OR (MSVC_VERSION EQUAL 1914)))
|
if((MSVC) AND ((MSVC_VERSION GREATER 1914) OR (MSVC_VERSION EQUAL 1914)))
|
||||||
target_compile_options(Async++ PUBLIC /Zc:__cplusplus)
|
target_compile_options(Async++ PUBLIC /Zc:__cplusplus)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
configure_package_config_file("${CMAKE_CURRENT_LIST_DIR}/Async++Config.cmake.in"
|
configure_package_config_file(
|
||||||
"${PROJECT_BINARY_DIR}/Async++Config.cmake"
|
"${CMAKE_CURRENT_LIST_DIR}/Async++Config.cmake.in"
|
||||||
INSTALL_DESTINATION cmake
|
"${PROJECT_BINARY_DIR}/Async++Config.cmake" INSTALL_DESTINATION cmake)
|
||||||
)
|
|
||||||
|
|
||||||
install(FILES "${PROJECT_BINARY_DIR}/Async++Config.cmake"
|
install(FILES "${PROJECT_BINARY_DIR}/Async++Config.cmake" DESTINATION cmake)
|
||||||
DESTINATION cmake
|
|
||||||
)
|
|
||||||
|
|
||||||
# Install the library and produce a CMake export script
|
# Install the library and produce a CMake export script
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
install(TARGETS Async++
|
install(
|
||||||
|
TARGETS Async++
|
||||||
EXPORT Async++
|
EXPORT Async++
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
FRAMEWORK DESTINATION Frameworks
|
FRAMEWORK DESTINATION Frameworks)
|
||||||
)
|
|
||||||
export(EXPORT Async++)
|
export(EXPORT Async++)
|
||||||
install(EXPORT Async++ DESTINATION cmake)
|
install(EXPORT Async++ DESTINATION cmake)
|
||||||
if(APPLE AND BUILD_FRAMEWORK)
|
if(APPLE AND BUILD_FRAMEWORK)
|
||||||
set_target_properties(Async++ PROPERTIES OUTPUT_NAME Async++ FRAMEWORK ON)
|
set_target_properties(Async++ PROPERTIES OUTPUT_NAME Async++ FRAMEWORK ON)
|
||||||
set_source_files_properties(${ASYNCXX_INCLUDE} PROPERTIES MACOSX_PACKAGE_LOCATION Headers/async++)
|
set_source_files_properties(
|
||||||
set_source_files_properties(${PROJECT_SOURCE_DIR}/include/async++.h PROPERTIES MACOSX_PACKAGE_LOCATION Headers)
|
${ASYNCXX_INCLUDE} PROPERTIES MACOSX_PACKAGE_LOCATION Headers/async++)
|
||||||
|
set_source_files_properties(${PROJECT_SOURCE_DIR}/include/async++.h
|
||||||
|
PROPERTIES MACOSX_PACKAGE_LOCATION Headers)
|
||||||
else()
|
else()
|
||||||
set_target_properties(Async++ PROPERTIES OUTPUT_NAME async++)
|
set_target_properties(Async++ PROPERTIES OUTPUT_NAME async++)
|
||||||
target_include_directories(Async++ INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
|
target_include_directories(
|
||||||
|
Async++ INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
install(FILES ${PROJECT_SOURCE_DIR}/include/async++.h DESTINATION include)
|
install(FILES ${PROJECT_SOURCE_DIR}/include/async++.h DESTINATION include)
|
||||||
install(FILES ${ASYNCXX_INCLUDE} DESTINATION include/async++)
|
install(FILES ${ASYNCXX_INCLUDE} DESTINATION include/async++)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
SET(CPACK_GENERATOR "DEB")
|
set(CPACK_GENERATOR "DEB")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "none") #required
|
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "none") # required
|
||||||
|
|
||||||
INCLUDE(CPack)
|
include(CPack)
|
||||||
|
@ -25,7 +25,7 @@ target_include_directories(benchmark_main PUBLIC src/)
|
|||||||
add_library(sled STATIC "")
|
add_library(sled STATIC "")
|
||||||
|
|
||||||
add_subdirectory(3party/minilua EXCLUDE_FROM_ALL)
|
add_subdirectory(3party/minilua EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(3party/gperftools EXCLUDE_FROM_ALL)
|
# add_subdirectory(3party/gperftools EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(3party/asyncplusplus EXCLUDE_FROM_ALL)
|
add_subdirectory(3party/asyncplusplus EXCLUDE_FROM_ALL)
|
||||||
# add_subdirectory(3party/cppuprofile EXCLUDE_FROM_ALL)
|
# add_subdirectory(3party/cppuprofile EXCLUDE_FROM_ALL)
|
||||||
# add_subdirectory(3party/protobuf-3.21.12 EXCLUDE_FROM_ALL)
|
# add_subdirectory(3party/protobuf-3.21.12 EXCLUDE_FROM_ALL)
|
||||||
@ -111,6 +111,7 @@ if(SLED_BUILD_BENCHMARK)
|
|||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
sled_benchmark
|
sled_benchmark
|
||||||
|
src/sled/event_bus/event_bus_bench.cc
|
||||||
src/sled/random_bench.cc
|
src/sled/random_bench.cc
|
||||||
src/sled/strings/base64_bench.cc
|
src/sled/strings/base64_bench.cc
|
||||||
# src/sled/system/fiber/fiber_bench.cc
|
# src/sled/system/fiber/fiber_bench.cc
|
||||||
@ -134,8 +135,9 @@ function(sled_add_test)
|
|||||||
add_executable(${SLED_TEST_NAME} ${SLED_TEST_SRCS})
|
add_executable(${SLED_TEST_NAME} ${SLED_TEST_SRCS})
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(EXTRA_FLAGS -Wthread-safety -g -fsanitize=address
|
set(EXTRA_FLAGS # -Wthread-safety
|
||||||
-fno-omit-frame-pointer -fno-optimize-sibling-calls)
|
-g -fsanitize=address -fno-omit-frame-pointer
|
||||||
|
-fno-optimize-sibling-calls)
|
||||||
target_compile_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})
|
target_compile_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})
|
||||||
|
|
||||||
target_link_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})
|
target_link_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})
|
||||||
@ -165,7 +167,6 @@ if(SLED_BUILD_TESTS)
|
|||||||
SRCS
|
SRCS
|
||||||
src/sled/debugging/demangle_test.cc
|
src/sled/debugging/demangle_test.cc
|
||||||
src/sled/async/async_test.cc
|
src/sled/async/async_test.cc
|
||||||
src/sled/any_test.cc
|
|
||||||
src/sled/filesystem/path_test.cc
|
src/sled/filesystem/path_test.cc
|
||||||
src/sled/log/fmt_test.cc
|
src/sled/log/fmt_test.cc
|
||||||
src/sled/synchronization/sequence_checker_test.cc
|
src/sled/synchronization/sequence_checker_test.cc
|
||||||
@ -179,11 +180,20 @@ if(SLED_BUILD_TESTS)
|
|||||||
src/sled/rx_test.cc
|
src/sled/rx_test.cc
|
||||||
src/sled/uri_test.cc)
|
src/sled/uri_test.cc)
|
||||||
|
|
||||||
sled_add_test(NAME sled_symbolize_test SRCS
|
if(NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
|
||||||
src/sled/debugging/symbolize_test.cc NO_MAIN)
|
sled_add_test(NAME sled_async_test SRCS src/sled/async/async_test.cc)
|
||||||
|
sled_add_test(NAME sled_thread_pool_test SRCS
|
||||||
|
src/sled/system/thread_pool_test.cc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
sled_add_test(NAME sled_event_bus_test SRCS
|
||||||
|
src/sled/event_bus/event_bus_test.cc)
|
||||||
sled_add_test(NAME sled_lua_test SRCS tests/lua_test.cc)
|
sled_add_test(NAME sled_lua_test SRCS tests/lua_test.cc)
|
||||||
sled_add_test(NAME sled_move_on_copy_test SRCS
|
sled_add_test(NAME sled_move_on_copy_test SRCS
|
||||||
src/sled/utility/move_on_copy_test.cc)
|
src/sled/utility/move_on_copy_test.cc)
|
||||||
|
sled_add_test(NAME sled_symbolize_test SRCS
|
||||||
|
src/sled/debugging/symbolize_test.cc NO_MAIN)
|
||||||
|
sled_add_test(NAME sled_sigslot_test SRCS src/sled/sigslot_test.cc)
|
||||||
endif(SLED_BUILD_TESTS)
|
endif(SLED_BUILD_TESTS)
|
||||||
|
|
||||||
if(SLED_BUILD_FUZZ)
|
if(SLED_BUILD_FUZZ)
|
||||||
|
155
src/sled/event_bus/event_bus.h
Normal file
155
src/sled/event_bus/event_bus.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#ifndef SLED_EVENT_BUS_EVENT_BUS_H
|
||||||
|
#define SLED_EVENT_BUS_EVENT_BUS_H
|
||||||
|
|
||||||
|
#include "sled/sigslot.h"
|
||||||
|
#include "sled/synchronization/mutex.h"
|
||||||
|
#include <typeindex>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
|
||||||
|
class EventBus;
|
||||||
|
class Subscriber;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template<typename Event>
|
||||||
|
class EventRegistry {
|
||||||
|
public:
|
||||||
|
using Dispatcher = sigslot::signal1<Event>;
|
||||||
|
using SubscriberTable = std::unordered_map<EventBus *, Dispatcher>;
|
||||||
|
|
||||||
|
static EventRegistry &Instance()
|
||||||
|
{
|
||||||
|
static EventRegistry instance_;
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::function<void(EventBus *)> &GetCleanupHandler()
|
||||||
|
{
|
||||||
|
static std::function<void(EventBus *)> cleanup_handler
|
||||||
|
= std::bind(&EventRegistry::OnBusDestroyed, &Instance(), std::placeholders::_1);
|
||||||
|
return cleanup_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Post(EventBus *bus, Event event)
|
||||||
|
{
|
||||||
|
sled::SharedMutexReadLock lock(&shared_mutex_);
|
||||||
|
if (signals_.empty()) { return; }
|
||||||
|
auto iter = signals_.find(bus);
|
||||||
|
if (iter != signals_.end()) { iter->second(event); }
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
void Subscribe(EventBus *bus, C *instance, void (C::*method)(Event))
|
||||||
|
{
|
||||||
|
sled::SharedMutexWriteLock lock(&shared_mutex_);
|
||||||
|
auto iter = signals_.find(bus);
|
||||||
|
if (iter == signals_.end()) {
|
||||||
|
signals_.emplace(bus, Dispatcher());
|
||||||
|
iter = signals_.find(bus);
|
||||||
|
}
|
||||||
|
auto &dispatcher = iter->second;
|
||||||
|
dispatcher.connect(instance, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
void Unsubscribe(EventBus *bus, C *instance)
|
||||||
|
{
|
||||||
|
sled::SharedMutexWriteLock lock(&shared_mutex_);
|
||||||
|
auto iter = signals_.find(bus);
|
||||||
|
if (iter == signals_.end()) { return; }
|
||||||
|
auto &dispatcher = iter->second;
|
||||||
|
dispatcher.disconnect(instance);
|
||||||
|
if (dispatcher.is_empty()) { signals_.erase(iter); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty(EventBus *bus) const
|
||||||
|
{
|
||||||
|
sled::SharedMutexReadLock lock(&shared_mutex_);
|
||||||
|
auto iter = signals_.find(bus);
|
||||||
|
if (iter == signals_.end()) { return true; }
|
||||||
|
return iter->second.is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnBusDestroyed(EventBus *bus)
|
||||||
|
{
|
||||||
|
sled::SharedMutexWriteLock lock(&shared_mutex_);
|
||||||
|
signals_.erase(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
void OnSubscriberDestroyed(C *instance)
|
||||||
|
{
|
||||||
|
sled::SharedMutexWriteLock lock(&shared_mutex_);
|
||||||
|
for (auto &entry : signals_) {
|
||||||
|
auto &dispatcher = entry.second;
|
||||||
|
dispatcher.disconnect(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable sled::SharedMutex shared_mutex_;
|
||||||
|
|
||||||
|
SubscriberTable signals_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace
|
||||||
|
|
||||||
|
class EventBus {
|
||||||
|
public:
|
||||||
|
class Subscriber : public sigslot::has_slots<> {
|
||||||
|
public:
|
||||||
|
virtual ~Subscriber() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
EventBus() = default;
|
||||||
|
|
||||||
|
~EventBus()
|
||||||
|
{
|
||||||
|
for (const auto &handler : cleanup_handlers_) { handler.second(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBus(const EventBus &) = delete;
|
||||||
|
EventBus &operator=(const EventBus &) = delete;
|
||||||
|
|
||||||
|
template<typename Event>
|
||||||
|
void Post(const Event &event)
|
||||||
|
{
|
||||||
|
EventRegistry<Event>::Instance().Post(this, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// On<Event1> ([](const Event1 &){})
|
||||||
|
template<typename Event, typename C>
|
||||||
|
typename std::enable_if<std::is_base_of<Subscriber, C>::value>::type
|
||||||
|
Subscribe(C *instance, void (C::*method)(Event))
|
||||||
|
{
|
||||||
|
{
|
||||||
|
sled::MutexLock lock(&mutex_);
|
||||||
|
cleanup_handlers_[std::type_index(typeid(Event))] = EventRegistry<Event>::GetCleanupHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
EventRegistry<Event>::Instance().Subscribe(this, instance, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Event, typename C>
|
||||||
|
typename std::enable_if<std::is_base_of<Subscriber, C>::value>::type Unsubscribe(C *instance)
|
||||||
|
{
|
||||||
|
EventRegistry<Event>::Instance().Unsubscribe(this, instance);
|
||||||
|
{
|
||||||
|
sled::MutexLock lock(&mutex_);
|
||||||
|
if (EventRegistry<Event>::Instance().IsEmpty(this)) {
|
||||||
|
auto iter = cleanup_handlers_.find(std::type_index(typeid(Event)));
|
||||||
|
if (iter != cleanup_handlers_.end()) {
|
||||||
|
iter->second(this);
|
||||||
|
cleanup_handlers_.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
sled::Mutex mutex_;
|
||||||
|
std::unordered_map<std::type_index, std::function<void(EventBus *)>> cleanup_handlers_ GUARDED_BY(mutex_);
|
||||||
|
};
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_EVENT_BUS_EVENT_BUS_H
|
78
src/sled/event_bus/event_bus_bench.cc
Normal file
78
src/sled/event_bus/event_bus_bench.cc
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <sled/event_bus/event_bus.h>
|
||||||
|
#include <sled/log/log.h>
|
||||||
|
#include <sled/system/fiber/wait_group.h>
|
||||||
|
#include <sled/system/thread_pool.h>
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
std::shared_ptr<int> data = std::make_shared<int>(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AtomicEvent {
|
||||||
|
AtomicEvent(std::atomic<int> &v) : data(v) {}
|
||||||
|
|
||||||
|
std::atomic<int> &data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Subscriber : public sled::EventBus::Subscriber {
|
||||||
|
void OnEvent(Event event) { (*event.data)++; }
|
||||||
|
|
||||||
|
void OnAtomicnEvent(AtomicEvent event) { event.data.fetch_add(1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
BMEventBusPost_1_to_1(picobench::state &s)
|
||||||
|
{
|
||||||
|
sled::EventBus event_bus;
|
||||||
|
Subscriber subscriber;
|
||||||
|
event_bus.Subscribe(&subscriber, &Subscriber::OnEvent);
|
||||||
|
for (auto _ : s) { event_bus.Post(Event{}); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BMEventBusPost_1_to_1k(picobench::state &s)
|
||||||
|
{
|
||||||
|
sled::EventBus event_bus;
|
||||||
|
std::vector<Subscriber> subscribers(1000);
|
||||||
|
for (auto &subscriber : subscribers) { event_bus.Subscribe(&subscriber, &Subscriber::OnEvent); }
|
||||||
|
|
||||||
|
for (auto _ : s) {
|
||||||
|
Event event;
|
||||||
|
event_bus.Post(event);
|
||||||
|
SLED_ASSERT(*event.data == 1000, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BMEventBusPost_10_to_1k(picobench::state &s)
|
||||||
|
{
|
||||||
|
constexpr int kPublishCount = 10;
|
||||||
|
constexpr int kSubscriberCount = 1000;
|
||||||
|
|
||||||
|
sled::EventBus event_bus;
|
||||||
|
std::vector<Subscriber> subscribers(kSubscriberCount);
|
||||||
|
for (auto &subscriber : subscribers) { event_bus.Subscribe(&subscriber, &Subscriber::OnAtomicnEvent); }
|
||||||
|
sled::ThreadPool pool(kPublishCount);
|
||||||
|
|
||||||
|
for (auto _ : s) {
|
||||||
|
std::atomic<int> value(0);
|
||||||
|
AtomicEvent atomic_event(value);
|
||||||
|
sled::WaitGroup wg(kPublishCount);
|
||||||
|
for (int i = 0; i < kPublishCount; i++) {
|
||||||
|
pool.PostTask([atomic_event, wg, &event_bus]() {
|
||||||
|
event_bus.Post(atomic_event);
|
||||||
|
wg.Done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
wg.Wait();
|
||||||
|
SLED_ASSERT(value.load() == kPublishCount * kSubscriberCount,
|
||||||
|
"{} != {}",
|
||||||
|
value.load(),
|
||||||
|
kPublishCount * kSubscriberCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PICOBENCH_SUITE("EventBus");
|
||||||
|
|
||||||
|
PICOBENCH(BMEventBusPost_1_to_1);
|
||||||
|
PICOBENCH(BMEventBusPost_1_to_1k);
|
||||||
|
PICOBENCH(BMEventBusPost_10_to_1k);
|
120
src/sled/event_bus/event_bus_test.cc
Normal file
120
src/sled/event_bus/event_bus_test.cc
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include <sled/event_bus/event_bus.h>
|
||||||
|
#include <sled/log/log.h>
|
||||||
|
#include <sled/system/fiber/wait_group.h>
|
||||||
|
#include <sled/system/thread_pool.h>
|
||||||
|
|
||||||
|
using namespace fakeit;
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
void *
|
||||||
|
GetPtr(R (T::*p)(Args...))
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
R (T::*ptr)(Args...);
|
||||||
|
void *void_ptr;
|
||||||
|
} _;
|
||||||
|
|
||||||
|
_.ptr = p;
|
||||||
|
return _.void_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Event1 {
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Event2 {
|
||||||
|
std::string str;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Subscriber : public sled::EventBus::Subscriber {
|
||||||
|
void OnEvent1(Event1 event) { a += event.a; }
|
||||||
|
|
||||||
|
void OnEvent2(Event2 event) { str += event.str; }
|
||||||
|
|
||||||
|
int a = 0;
|
||||||
|
std::string str = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_SUITE("EventBus")
|
||||||
|
{
|
||||||
|
TEST_CASE("single thread")
|
||||||
|
{
|
||||||
|
sled::EventBus bus;
|
||||||
|
bus.Post(Event1{1});
|
||||||
|
bus.Post(Event2{"1"});
|
||||||
|
|
||||||
|
Subscriber subscriber;
|
||||||
|
bus.Subscribe<Event1>(&subscriber, &Subscriber::OnEvent1);
|
||||||
|
bus.Subscribe<Event2>(&subscriber, &Subscriber::OnEvent2);
|
||||||
|
|
||||||
|
bus.Post(Event1{1});
|
||||||
|
bus.Post(Event2{"1"});
|
||||||
|
|
||||||
|
CHECK_EQ(subscriber.a, 1);
|
||||||
|
CHECK_EQ(subscriber.str, "1");
|
||||||
|
|
||||||
|
bus.Post(Event1{1});
|
||||||
|
bus.Post(Event2{"1"});
|
||||||
|
|
||||||
|
CHECK_EQ(subscriber.a, 2);
|
||||||
|
CHECK_EQ(subscriber.str, "11");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("multi thread")
|
||||||
|
{
|
||||||
|
auto thread = sled::Thread::Create();
|
||||||
|
thread->Start();
|
||||||
|
|
||||||
|
sled::EventBus bus;
|
||||||
|
Subscriber subscriber;
|
||||||
|
|
||||||
|
bus.Subscribe(&subscriber, &Subscriber::OnEvent1);
|
||||||
|
bus.Subscribe(&subscriber, &Subscriber::OnEvent2);
|
||||||
|
|
||||||
|
thread->BlockingCall([&] {
|
||||||
|
bus.Post(Event1{1});
|
||||||
|
bus.Post(Event2{"1"});
|
||||||
|
});
|
||||||
|
|
||||||
|
CHECK_EQ(subscriber.a, 1);
|
||||||
|
CHECK_EQ(subscriber.str, "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("thread_pool")
|
||||||
|
{
|
||||||
|
constexpr int kPublishCount = 10;
|
||||||
|
constexpr int kSubscriberCount = 1000;
|
||||||
|
|
||||||
|
struct AtomicEvent {
|
||||||
|
std::atomic<int> &data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AotmicEventSubscriber : public sled::EventBus::Subscriber {
|
||||||
|
virtual ~AotmicEventSubscriber() = default;
|
||||||
|
|
||||||
|
void OnEvent(AtomicEvent event) { event.data.fetch_add(1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::atomic<int> value(0);
|
||||||
|
AtomicEvent atomic_event{value};
|
||||||
|
|
||||||
|
sled::WaitGroup wg(kPublishCount);
|
||||||
|
sled::ThreadPool pool(kPublishCount);
|
||||||
|
sled::EventBus bus;
|
||||||
|
std::vector<AotmicEventSubscriber> subscribers(kSubscriberCount);
|
||||||
|
|
||||||
|
for (auto &sub : subscribers) { bus.Subscribe(&sub, &AotmicEventSubscriber::OnEvent); }
|
||||||
|
std::atomic<int> invoke_count(0);
|
||||||
|
for (int i = 0; i < kPublishCount; i++) {
|
||||||
|
pool.PostTask([wg, atomic_event, &bus, &invoke_count]() {
|
||||||
|
bus.Post(atomic_event);
|
||||||
|
invoke_count.fetch_add(1);
|
||||||
|
wg.Done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
wg.Wait();
|
||||||
|
|
||||||
|
CHECK_EQ(invoke_count.load(), kPublishCount);
|
||||||
|
CHECK_EQ(value.load(), kPublishCount * kSubscriberCount);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include <sled/random.h>
|
#include <sled/random.h>
|
||||||
#include <sled/testing/benchmark.h>
|
#include <sled/testing/benchmark.h>
|
||||||
|
PICOBENCH_SUITE("Random");
|
||||||
|
|
||||||
PICOBENCH([](picobench::state &s) {
|
PICOBENCH([](picobench::state &s) {
|
||||||
sled::Random rand(s.user_data());
|
sled::Random rand(s.user_data());
|
||||||
|
@ -4,12 +4,26 @@ namespace sigslot {
|
|||||||
|
|
||||||
#ifdef _SIGSLOT_HAS_POSIX_THREADS
|
#ifdef _SIGSLOT_HAS_POSIX_THREADS
|
||||||
|
|
||||||
pthread_mutex_t *
|
sled::RecursiveMutex *
|
||||||
multi_threaded_global::get_mutex()
|
multi_threaded_global::get_mutex()
|
||||||
{
|
{
|
||||||
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static sled::RecursiveMutex g_mutex;
|
||||||
return &g_mutex;
|
return &g_mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sled::Mutex *
|
||||||
|
// multi_threaded_global::get_mutex()
|
||||||
|
// {
|
||||||
|
// static sled::Mutex g_mutex;
|
||||||
|
// return &g_mutex;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pthread_mutex_t *
|
||||||
|
// multi_threaded_global::get_mutex()
|
||||||
|
// {
|
||||||
|
// static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
// return &g_mutex;
|
||||||
|
// }
|
||||||
|
|
||||||
#endif// _SIGSLOT_HAS_POSIX_THREADS
|
#endif// _SIGSLOT_HAS_POSIX_THREADS
|
||||||
}// namespace sigslot
|
}// namespace sigslot
|
||||||
|
@ -94,20 +94,19 @@
|
|||||||
// If signalx is single threaded the user must ensure that disconnect, connect
|
// If signalx is single threaded the user must ensure that disconnect, connect
|
||||||
// or signal is not happening concurrently or data race may occur.
|
// or signal is not happening concurrently or data race may occur.
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef SLED_SIGSLOT_H
|
#ifndef SLED_SIGSLOT_H
|
||||||
#define SLED_SIGSLOT_H
|
#define SLED_SIGSLOT_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sled/synchronization/mutex.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
// On our copy of sigslot.h, we set single threading as default.
|
// On our copy of sigslot.h, we set single threading as default.
|
||||||
#define SIGSLOT_DEFAULT_MT_POLICY single_threaded
|
#define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
|
||||||
|
|
||||||
#if defined(SIGSLOT_PURE_ISO) \
|
#if defined(SIGSLOT_PURE_ISO) || (!defined(WEBRTC_WIN) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS))
|
||||||
|| (!defined(WEBRTC_WIN) && !defined(__GNUG__) \
|
|
||||||
&& !defined(SIGSLOT_USE_POSIX_THREADS))
|
|
||||||
#define _SIGSLOT_SINGLE_THREADED
|
#define _SIGSLOT_SINGLE_THREADED
|
||||||
#elif defined(WEBRTC_WIN)
|
#elif defined(WEBRTC_WIN)
|
||||||
#define _SIGSLOT_HAS_WIN32_THREADS
|
#define _SIGSLOT_HAS_WIN32_THREADS
|
||||||
@ -167,10 +166,7 @@ class multi_threaded_local {
|
|||||||
public:
|
public:
|
||||||
multi_threaded_local() { InitializeCriticalSection(&m_critsec); }
|
multi_threaded_local() { InitializeCriticalSection(&m_critsec); }
|
||||||
|
|
||||||
multi_threaded_local(const multi_threaded_local &)
|
multi_threaded_local(const multi_threaded_local &) { InitializeCriticalSection(&m_critsec); }
|
||||||
{
|
|
||||||
InitializeCriticalSection(&m_critsec);
|
|
||||||
}
|
|
||||||
|
|
||||||
~multi_threaded_local() { DeleteCriticalSection(&m_critsec); }
|
~multi_threaded_local() { DeleteCriticalSection(&m_critsec); }
|
||||||
|
|
||||||
@ -187,31 +183,51 @@ private:
|
|||||||
// The multi threading policies only get compiled in if they are enabled.
|
// The multi threading policies only get compiled in if they are enabled.
|
||||||
class multi_threaded_global {
|
class multi_threaded_global {
|
||||||
public:
|
public:
|
||||||
void lock() { pthread_mutex_lock(get_mutex()); }
|
void lock()
|
||||||
|
{
|
||||||
|
get_mutex()->Lock();
|
||||||
|
// pthread_mutex_lock(get_mutex());
|
||||||
|
}
|
||||||
|
|
||||||
void unlock() { pthread_mutex_unlock(get_mutex()); }
|
void unlock()
|
||||||
|
{
|
||||||
|
get_mutex()->Unlock();
|
||||||
|
// pthread_mutex_unlock(get_mutex());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static pthread_mutex_t *get_mutex();
|
static sled::RecursiveMutex *get_mutex();
|
||||||
|
// static sled::Mutex *get_mutex();
|
||||||
|
// static pthread_mutex_t *get_mutex();
|
||||||
};
|
};
|
||||||
|
|
||||||
class multi_threaded_local {
|
class multi_threaded_local {
|
||||||
public:
|
public:
|
||||||
multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); }
|
// multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); }
|
||||||
|
//
|
||||||
|
// multi_threaded_local(const multi_threaded_local &)
|
||||||
|
// {
|
||||||
|
// pthread_mutex_init(&m_mutex, nullptr);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ~multi_threaded_local() { pthread_mutex_destroy(&m_mutex); }
|
||||||
|
|
||||||
multi_threaded_local(const multi_threaded_local &)
|
void lock()
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&m_mutex, nullptr);
|
mutex_.Lock();
|
||||||
|
// pthread_mutex_lock(&m_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
~multi_threaded_local() { pthread_mutex_destroy(&m_mutex); }
|
void unlock()
|
||||||
|
{
|
||||||
void lock() { pthread_mutex_lock(&m_mutex); }
|
mutex_.Unlock();
|
||||||
|
// pthread_mutex_unlock(&m_mutex);
|
||||||
void unlock() { pthread_mutex_unlock(&m_mutex); }
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pthread_mutex_t m_mutex;
|
sled::RecursiveMutex mutex_;
|
||||||
|
// sled::Mutex mutex_;
|
||||||
|
// pthread_mutex_t m_mutex;
|
||||||
};
|
};
|
||||||
#endif// _SIGSLOT_HAS_POSIX_THREADS
|
#endif// _SIGSLOT_HAS_POSIX_THREADS
|
||||||
|
|
||||||
@ -229,10 +245,8 @@ class _signal_base_interface;
|
|||||||
|
|
||||||
class has_slots_interface {
|
class has_slots_interface {
|
||||||
private:
|
private:
|
||||||
typedef void (*signal_connect_t)(has_slots_interface *self,
|
typedef void (*signal_connect_t)(has_slots_interface *self, _signal_base_interface *sender);
|
||||||
_signal_base_interface *sender);
|
typedef void (*signal_disconnect_t)(has_slots_interface *self, _signal_base_interface *sender);
|
||||||
typedef void (*signal_disconnect_t)(has_slots_interface *self,
|
|
||||||
_signal_base_interface *sender);
|
|
||||||
typedef void (*disconnect_all_t)(has_slots_interface *self);
|
typedef void (*disconnect_all_t)(has_slots_interface *self);
|
||||||
|
|
||||||
const signal_connect_t m_signal_connect;
|
const signal_connect_t m_signal_connect;
|
||||||
@ -240,9 +254,7 @@ private:
|
|||||||
const disconnect_all_t m_disconnect_all;
|
const disconnect_all_t m_disconnect_all;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
has_slots_interface(signal_connect_t conn,
|
has_slots_interface(signal_connect_t conn, signal_disconnect_t disc, disconnect_all_t disc_all)
|
||||||
signal_disconnect_t disc,
|
|
||||||
disconnect_all_t disc_all)
|
|
||||||
: m_signal_connect(conn),
|
: m_signal_connect(conn),
|
||||||
m_signal_disconnect(disc),
|
m_signal_disconnect(disc),
|
||||||
m_disconnect_all(disc_all)
|
m_disconnect_all(disc_all)
|
||||||
@ -253,23 +265,16 @@ protected:
|
|||||||
virtual ~has_slots_interface() {}
|
virtual ~has_slots_interface() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void signal_connect(_signal_base_interface *sender)
|
void signal_connect(_signal_base_interface *sender) { m_signal_connect(this, sender); }
|
||||||
{
|
|
||||||
m_signal_connect(this, sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
void signal_disconnect(_signal_base_interface *sender)
|
void signal_disconnect(_signal_base_interface *sender) { m_signal_disconnect(this, sender); }
|
||||||
{
|
|
||||||
m_signal_disconnect(this, sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
void disconnect_all() { m_disconnect_all(this); }
|
void disconnect_all() { m_disconnect_all(this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class _signal_base_interface {
|
class _signal_base_interface {
|
||||||
private:
|
private:
|
||||||
typedef void (*slot_disconnect_t)(_signal_base_interface *self,
|
typedef void (*slot_disconnect_t)(_signal_base_interface *self, has_slots_interface *pslot);
|
||||||
has_slots_interface *pslot);
|
|
||||||
typedef void (*slot_duplicate_t)(_signal_base_interface *self,
|
typedef void (*slot_duplicate_t)(_signal_base_interface *self,
|
||||||
const has_slots_interface *poldslot,
|
const has_slots_interface *poldslot,
|
||||||
has_slots_interface *pnewslot);
|
has_slots_interface *pnewslot);
|
||||||
@ -286,13 +291,9 @@ protected:
|
|||||||
~_signal_base_interface() {}
|
~_signal_base_interface() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void slot_disconnect(has_slots_interface *pslot)
|
void slot_disconnect(has_slots_interface *pslot) { m_slot_disconnect(this, pslot); }
|
||||||
{
|
|
||||||
m_slot_disconnect(this, pslot);
|
|
||||||
}
|
|
||||||
|
|
||||||
void slot_duplicate(const has_slots_interface *poldslot,
|
void slot_duplicate(const has_slots_interface *poldslot, has_slots_interface *pnewslot)
|
||||||
has_slots_interface *pnewslot)
|
|
||||||
{
|
{
|
||||||
m_slot_duplicate(this, poldslot, pnewslot);
|
m_slot_duplicate(this, poldslot, pnewslot);
|
||||||
}
|
}
|
||||||
@ -323,8 +324,7 @@ public:
|
|||||||
_opaque_connection(DestT *pd, void (DestT::*pm)(Args...)) : pdest(pd)
|
_opaque_connection(DestT *pd, void (DestT::*pm)(Args...)) : pdest(pd)
|
||||||
{
|
{
|
||||||
typedef void (DestT::*pm_t)(Args...);
|
typedef void (DestT::*pm_t)(Args...);
|
||||||
static_assert(sizeof(pm_t) <= sizeof(pmethod),
|
static_assert(sizeof(pm_t) <= sizeof(pmethod), "Size of slot function pointer too large.");
|
||||||
"Size of slot function pointer too large.");
|
|
||||||
|
|
||||||
std::memcpy(pmethod, &pm, sizeof(pm_t));
|
std::memcpy(pmethod, &pm, sizeof(pm_t));
|
||||||
|
|
||||||
@ -360,8 +360,7 @@ private:
|
|||||||
{
|
{
|
||||||
typedef void (DestT::*pm_t)(Args...);
|
typedef void (DestT::*pm_t)(Args...);
|
||||||
pm_t pm;
|
pm_t pm;
|
||||||
static_assert(sizeof(pm_t) <= sizeof(pmethod),
|
static_assert(sizeof(pm_t) <= sizeof(pmethod), "Size of slot function pointer too large.");
|
||||||
"Size of slot function pointer too large.");
|
|
||||||
std::memcpy(&pm, self->pmethod, sizeof(pm_t));
|
std::memcpy(&pm, self->pmethod, sizeof(pm_t));
|
||||||
(static_cast<DestT *>(self->pdest)->*(pm))(args...);
|
(static_cast<DestT *>(self->pdest)->*(pm))(args...);
|
||||||
}
|
}
|
||||||
@ -373,8 +372,7 @@ protected:
|
|||||||
typedef std::list<_opaque_connection> connections_list;
|
typedef std::list<_opaque_connection> connections_list;
|
||||||
|
|
||||||
_signal_base()
|
_signal_base()
|
||||||
: _signal_base_interface(&_signal_base::do_slot_disconnect,
|
: _signal_base_interface(&_signal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate),
|
||||||
&_signal_base::do_slot_duplicate),
|
|
||||||
m_current_iterator(m_connected_slots.end())
|
m_current_iterator(m_connected_slots.end())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -385,8 +383,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
_signal_base(const _signal_base &o)
|
_signal_base(const _signal_base &o)
|
||||||
: _signal_base_interface(&_signal_base::do_slot_disconnect,
|
: _signal_base_interface(&_signal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate),
|
||||||
&_signal_base::do_slot_duplicate),
|
|
||||||
m_current_iterator(m_connected_slots.end())
|
m_current_iterator(m_connected_slots.end())
|
||||||
{
|
{
|
||||||
lock_block<mt_policy> lock(this);
|
lock_block<mt_policy> lock(this);
|
||||||
@ -409,8 +406,7 @@ public:
|
|||||||
while (!m_connected_slots.empty()) {
|
while (!m_connected_slots.empty()) {
|
||||||
has_slots_interface *pdest = m_connected_slots.front().getdest();
|
has_slots_interface *pdest = m_connected_slots.front().getdest();
|
||||||
m_connected_slots.pop_front();
|
m_connected_slots.pop_front();
|
||||||
pdest->signal_disconnect(
|
pdest->signal_disconnect(static_cast<_signal_base_interface *>(this));
|
||||||
static_cast<_signal_base_interface *>(this));
|
|
||||||
}
|
}
|
||||||
// If disconnect_all is called while the signal is firing, advance the
|
// If disconnect_all is called while the signal is firing, advance the
|
||||||
// current slot iterator to the end to avoid an invalidated iterator from
|
// current slot iterator to the end to avoid an invalidated iterator from
|
||||||
@ -447,8 +443,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
m_connected_slots.erase(it);
|
m_connected_slots.erase(it);
|
||||||
}
|
}
|
||||||
pclass->signal_disconnect(
|
pclass->signal_disconnect(static_cast<_signal_base_interface *>(this));
|
||||||
static_cast<_signal_base_interface *>(this));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
@ -456,8 +451,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void do_slot_disconnect(_signal_base_interface *p,
|
static void do_slot_disconnect(_signal_base_interface *p, has_slots_interface *pslot)
|
||||||
has_slots_interface *pslot)
|
|
||||||
{
|
{
|
||||||
_signal_base *const self = static_cast<_signal_base *>(p);
|
_signal_base *const self = static_cast<_signal_base *>(p);
|
||||||
lock_block<mt_policy> lock(self);
|
lock_block<mt_policy> lock(self);
|
||||||
@ -472,8 +466,7 @@ private:
|
|||||||
// If we're currently using this iterator because the signal is firing,
|
// If we're currently using this iterator because the signal is firing,
|
||||||
// advance it to avoid it being invalidated.
|
// advance it to avoid it being invalidated.
|
||||||
if (self->m_current_iterator == it) {
|
if (self->m_current_iterator == it) {
|
||||||
self->m_current_iterator =
|
self->m_current_iterator = self->m_connected_slots.erase(it);
|
||||||
self->m_connected_slots.erase(it);
|
|
||||||
} else {
|
} else {
|
||||||
self->m_connected_slots.erase(it);
|
self->m_connected_slots.erase(it);
|
||||||
}
|
}
|
||||||
@ -483,9 +476,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_slot_duplicate(_signal_base_interface *p,
|
static void
|
||||||
const has_slots_interface *oldtarget,
|
do_slot_duplicate(_signal_base_interface *p, const has_slots_interface *oldtarget, has_slots_interface *newtarget)
|
||||||
has_slots_interface *newtarget)
|
|
||||||
{
|
{
|
||||||
_signal_base *const self = static_cast<_signal_base *>(p);
|
_signal_base *const self = static_cast<_signal_base *>(p);
|
||||||
lock_block<mt_policy> lock(self);
|
lock_block<mt_policy> lock(self);
|
||||||
@ -493,9 +485,7 @@ private:
|
|||||||
connections_list::iterator itEnd = self->m_connected_slots.end();
|
connections_list::iterator itEnd = self->m_connected_slots.end();
|
||||||
|
|
||||||
while (it != itEnd) {
|
while (it != itEnd) {
|
||||||
if (it->getdest() == oldtarget) {
|
if (it->getdest() == oldtarget) { self->m_connected_slots.push_back(it->duplicate(newtarget)); }
|
||||||
self->m_connected_slots.push_back(it->duplicate(newtarget));
|
|
||||||
}
|
|
||||||
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
@ -540,16 +530,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
has_slots &operator=(has_slots const &);
|
has_slots &operator=(has_slots const &);
|
||||||
|
|
||||||
static void do_signal_connect(has_slots_interface *p,
|
static void do_signal_connect(has_slots_interface *p, _signal_base_interface *sender)
|
||||||
_signal_base_interface *sender)
|
|
||||||
{
|
{
|
||||||
has_slots *const self = static_cast<has_slots *>(p);
|
has_slots *const self = static_cast<has_slots *>(p);
|
||||||
lock_block<mt_policy> lock(self);
|
lock_block<mt_policy> lock(self);
|
||||||
self->m_senders.insert(sender);
|
self->m_senders.insert(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_signal_disconnect(has_slots_interface *p,
|
static void do_signal_disconnect(has_slots_interface *p, _signal_base_interface *sender)
|
||||||
_signal_base_interface *sender)
|
|
||||||
{
|
{
|
||||||
has_slots *const self = static_cast<has_slots *>(p);
|
has_slots *const self = static_cast<has_slots *>(p);
|
||||||
lock_block<mt_policy> lock(self);
|
lock_block<mt_policy> lock(self);
|
||||||
@ -627,22 +615,13 @@ using signal0 = signal_with_thread_policy<mt_policy>;
|
|||||||
template<typename A1, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
template<typename A1, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
||||||
using signal1 = signal_with_thread_policy<mt_policy, A1>;
|
using signal1 = signal_with_thread_policy<mt_policy, A1>;
|
||||||
|
|
||||||
template<typename A1,
|
template<typename A1, typename A2, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
||||||
typename A2,
|
|
||||||
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
|
||||||
using signal2 = signal_with_thread_policy<mt_policy, A1, A2>;
|
using signal2 = signal_with_thread_policy<mt_policy, A1, A2>;
|
||||||
|
|
||||||
template<typename A1,
|
template<typename A1, typename A2, typename A3, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
||||||
typename A2,
|
|
||||||
typename A3,
|
|
||||||
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
|
||||||
using signal3 = signal_with_thread_policy<mt_policy, A1, A2, A3>;
|
using signal3 = signal_with_thread_policy<mt_policy, A1, A2, A3>;
|
||||||
|
|
||||||
template<typename A1,
|
template<typename A1, typename A2, typename A3, typename A4, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
||||||
typename A2,
|
|
||||||
typename A3,
|
|
||||||
typename A4,
|
|
||||||
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
|
||||||
using signal4 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4>;
|
using signal4 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4>;
|
||||||
|
|
||||||
template<typename A1,
|
template<typename A1,
|
||||||
@ -670,8 +649,7 @@ template<typename A1,
|
|||||||
typename A6,
|
typename A6,
|
||||||
typename A7,
|
typename A7,
|
||||||
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
||||||
using signal7 =
|
using signal7 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>;
|
||||||
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>;
|
|
||||||
|
|
||||||
template<typename A1,
|
template<typename A1,
|
||||||
typename A2,
|
typename A2,
|
||||||
@ -682,8 +660,7 @@ template<typename A1,
|
|||||||
typename A7,
|
typename A7,
|
||||||
typename A8,
|
typename A8,
|
||||||
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
|
||||||
using signal8 =
|
using signal8 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>;
|
||||||
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>;
|
|
||||||
|
|
||||||
}// namespace sigslot
|
}// namespace sigslot
|
||||||
|
|
||||||
|
16
src/sled/sigslot_test.cc
Normal file
16
src/sled/sigslot_test.cc
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <sled/sigslot.h>
|
||||||
|
|
||||||
|
struct DeleteSelf : public sigslot::has_slots<> {
|
||||||
|
void DeleteThis() {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_SUITE("sigslot") {
|
||||||
|
TEST_CASE("delete this") {
|
||||||
|
DeleteSelf* d = new DeleteSelf();
|
||||||
|
sigslot::signal0<> sig;
|
||||||
|
sig.connect(d, &DeleteSelf::DeleteThis);
|
||||||
|
sig.emit();
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,9 @@ namespace async {}
|
|||||||
#include "inja.hpp"
|
#include "inja.hpp"
|
||||||
#include "rx.h"
|
#include "rx.h"
|
||||||
|
|
||||||
|
// event_bus
|
||||||
|
#include "sled/event_bus/event_bus.h"
|
||||||
|
|
||||||
// filesystem
|
// filesystem
|
||||||
#include "sled/filesystem/path.h"
|
#include "sled/filesystem/path.h"
|
||||||
#include "sled/filesystem/temporary_file.h"
|
#include "sled/filesystem/temporary_file.h"
|
||||||
|
@ -38,6 +38,6 @@ Base64Decode(picobench::state &state)
|
|||||||
(void) sled::Base64::Decode(base64_input);
|
(void) sled::Base64::Decode(base64_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PICOBENCH_SUITE("Base64");
|
||||||
PICOBENCH(Base64Decode);
|
PICOBENCH(Base64Decode);
|
||||||
PICOBENCH(Base64Encode);
|
PICOBENCH(Base64Encode);
|
||||||
|
@ -146,46 +146,90 @@ private:
|
|||||||
marl::ConditionVariable cv_;
|
marl::ConditionVariable cv_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// class ConditionVariable final {
|
class SCOPED_CAPABILITY SharedMutex final {
|
||||||
// public:
|
public:
|
||||||
// static constexpr TimeDelta kForever = TimeDelta::PlusInfinity();
|
enum class Mode {
|
||||||
// ConditionVariable() = default;
|
kReaderPriority,
|
||||||
// ConditionVariable(const ConditionVariable &) = delete;
|
kWriterPriority,
|
||||||
// ConditionVariable &operator=(const ConditionVariable &) = delete;
|
};
|
||||||
//
|
|
||||||
// template<typename Predicate>
|
inline SharedMutex(Mode mode = SharedMutex::Mode::kWriterPriority) : mode_(mode) {}
|
||||||
// inline bool Wait(LockGuard<Mutex> &guard, Predicate pred)
|
|
||||||
// {
|
inline void Lock() SLED_EXCLUSIVE_LOCK_FUNCTION()
|
||||||
// std::unique_lock<std::mutex> lock(guard.mutex_->impl_, std::adopt_lock);
|
{
|
||||||
// cv_.wait(lock, pred);
|
wait_w_count_.fetch_add(1);
|
||||||
// return true;
|
|
||||||
// }
|
sled::MutexLock lock(&mutex_);
|
||||||
//
|
if (Mode::kReaderPriority == mode_) {
|
||||||
// template<typename Predicate>
|
// 读取优先,必须在没有任何读取的消费者的情况下才能持有锁
|
||||||
// inline bool
|
cv_.Wait(lock, [this] { return r_count_ == 0 && w_count_ == 0 && wait_r_count_.load() == 0; });
|
||||||
// WaitFor(LockGuard<Mutex> &guard, TimeDelta timeout, Predicate pred)
|
w_count_++;
|
||||||
// {
|
} else {
|
||||||
// std::unique_lock<std::mutex> lock(guard.mutex_->impl_, std::adopt_lock);
|
// 写入优先,只要没有持有读锁的消费者,就可以加锁
|
||||||
// if (timeout == kForever) {
|
cv_.Wait(lock, [this] { return r_count_ == 0 && w_count_ == 0; });
|
||||||
// cv_.wait(lock, pred);
|
w_count_++;
|
||||||
// return true;
|
cv_.Wait(lock, [this] { return r_count_ == 0; });
|
||||||
// } else {
|
}
|
||||||
// return cv_.wait_for(lock, std::chrono::milliseconds(timeout.ms()),
|
wait_w_count_.fetch_sub(1);
|
||||||
// pred);
|
}
|
||||||
// }
|
|
||||||
// }
|
inline void Unlock() SLED_UNLOCK_FUNCTION()
|
||||||
//
|
{
|
||||||
// // template<typename Predicate>
|
sled::MutexLock lock(&mutex_);
|
||||||
// // bool WaitUntil(Mutex *mutex, TimeDelta timeout, Predicate pred)
|
w_count_--;
|
||||||
// // {}
|
if (w_count_ == 0) { cv_.NotifyAll(); }
|
||||||
//
|
}
|
||||||
// inline void NotifyOne() { cv_.notify_one(); }
|
|
||||||
//
|
inline void LockShared() SLED_SHARED_LOCK_FUNCTION()
|
||||||
// inline void NotifyAll() { cv_.notify_all(); }
|
{
|
||||||
//
|
wait_r_count_.fetch_add(1);
|
||||||
// private:
|
sled::MutexLock lock(&mutex_);
|
||||||
// std::condition_variable cv_;
|
if (Mode::kReaderPriority == mode_) {
|
||||||
// };
|
cv_.Wait(lock, [this] { return w_count_ == 0; });
|
||||||
|
r_count_++;
|
||||||
|
} else {
|
||||||
|
cv_.Wait(lock, [this] { return w_count_ == 0 && wait_w_count_.load() == 0; });
|
||||||
|
r_count_++;
|
||||||
|
}
|
||||||
|
wait_r_count_.fetch_sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void UnlockShared() SLED_UNLOCK_FUNCTION()
|
||||||
|
{
|
||||||
|
sled::MutexLock lock(&mutex_);
|
||||||
|
r_count_--;
|
||||||
|
if (r_count_ == 0) { cv_.NotifyAll(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Mode mode_;
|
||||||
|
sled::Mutex mutex_;
|
||||||
|
sled::ConditionVariable cv_;
|
||||||
|
int r_count_{0};
|
||||||
|
int w_count_{0};
|
||||||
|
std::atomic<int> wait_r_count_{0};
|
||||||
|
std::atomic<int> wait_w_count_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
class SharedMutexReadLock final {
|
||||||
|
public:
|
||||||
|
explicit SharedMutexReadLock(SharedMutex *mutex) : mutex_(mutex) { mutex_->LockShared(); }
|
||||||
|
|
||||||
|
~SharedMutexReadLock() { mutex_->UnlockShared(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SharedMutex *mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SharedMutexWriteLock final {
|
||||||
|
public:
|
||||||
|
explicit SharedMutexWriteLock(SharedMutex *mutex) : mutex_(mutex) { mutex_->Lock(); }
|
||||||
|
|
||||||
|
~SharedMutexWriteLock() { mutex_->Unlock(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SharedMutex *mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
|
||||||
|
@ -13,4 +13,5 @@ ThreadPoolBench(picobench::state &state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BENCHMARK(ThreadPoolBench)->RangeMultiplier(10)->Range(10, 10000);
|
// BENCHMARK(ThreadPoolBench)->RangeMultiplier(10)->Range(10, 10000);
|
||||||
|
PICOBENCH_SUITE("TheadPool");
|
||||||
PICOBENCH(ThreadPoolBench);
|
PICOBENCH(ThreadPoolBench);
|
||||||
|
@ -7,4 +7,5 @@ SystemTimeNanos(picobench::state &state)
|
|||||||
for (auto _ : state) { (void) sled::SystemTimeNanos(); }
|
for (auto _ : state) { (void) sled::SystemTimeNanos(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PICOBENCH_SUITE("SystemTime");
|
||||||
PICOBENCH(SystemTimeNanos);
|
PICOBENCH(SystemTimeNanos);
|
||||||
|
@ -57,6 +57,22 @@
|
|||||||
#define DOCTEST_TOSTR_IMPL(x) #x
|
#define DOCTEST_TOSTR_IMPL(x) #x
|
||||||
#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
|
#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
|
||||||
|
|
||||||
|
#ifdef REQUIRE
|
||||||
|
#undef REQUIRE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHECK
|
||||||
|
#undef CHECK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHECK_EQ
|
||||||
|
#undef CHECK_EQ
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHECK_NE
|
||||||
|
#undef CHECK_NE
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DOCTEST_VERSION_STR \
|
#define DOCTEST_VERSION_STR \
|
||||||
DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
|
DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
|
||||||
DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
|
DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
|
||||||
|
@ -41,7 +41,7 @@ TaskQueueTimeoutFactory::TaskQueueTimeout::Start(DurationMs duration_ms, Timeout
|
|||||||
precision_,
|
precision_,
|
||||||
SafeTask(safety_flag_,
|
SafeTask(safety_flag_,
|
||||||
[timeout_id, this]() {
|
[timeout_id, this]() {
|
||||||
LOGV("timer", "Timeout expired: {}", timeout_id);
|
LOGV("timer", "Timeout expired id={}", timeout_id);
|
||||||
SLED_DCHECK_RUN_ON(&parent_.thread_checker_);
|
SLED_DCHECK_RUN_ON(&parent_.thread_checker_);
|
||||||
SLED_DCHECK(posted_task_expiration_ != std::numeric_limits<TimeMs>::max(), "");
|
SLED_DCHECK(posted_task_expiration_ != std::numeric_limits<TimeMs>::max(), "");
|
||||||
posted_task_expiration_ = std::numeric_limits<TimeMs>::max();
|
posted_task_expiration_ = std::numeric_limits<TimeMs>::max();
|
||||||
|
@ -34,4 +34,5 @@ ParseURI(picobench::state &s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PICOBENCH_SUITE("URI");
|
||||||
PICOBENCH(ParseURI);
|
PICOBENCH(ParseURI);
|
||||||
|
Loading…
Reference in New Issue
Block a user