Skip to content
Merged

Dev #93

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
3 changes: 3 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ IncludeCategories:
- Regex: '^["<]libstored/'
Priority: 1
SortPriority: 0
- Regex: '^<(cassert|assert\.h)>$'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 2
SortPriority: 0
Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2020-2025 Jochem Rutgers
# SPDX-FileCopyrightText: 2020-2026 Jochem Rutgers
#
# SPDX-License-Identifier: CC0-1.0

Expand All @@ -19,7 +19,7 @@ jobs:
fail-fast: false
matrix:
gcc: [12, 13, 14]
cxx: [C++03, C++11, C++14, C++17]
cxx: [C++03, C++11, C++14, C++17, C++20, C++23]
zmq: [zmq, nozmq]
include:
- gcc: 13
Expand All @@ -32,7 +32,7 @@ jobs:
CXX: g++-${{matrix.gcc}}
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: bootstrap
run: |
sudo apt update
Expand All @@ -49,7 +49,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: bootstrap
run: |
sudo apt update
Expand All @@ -68,7 +68,7 @@ jobs:
fail-fast: false
matrix:
compiler: [msvc, gcc]
cxx: [C++03, C++11, C++14, C++17]
cxx: [C++03, C++11, C++14, C++17, C++20, C++23]
zmq: [zmq, nozmq]
exclude:
- compiler: msvc
Expand All @@ -86,10 +86,10 @@ jobs:
# zth: zth
steps:
- name: checkout
uses: actions/checkout@v4
- uses: actions/setup-python@v5
uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
python-version: '3.13'
- name: bootstrap
run: |
dist\win32\bootstrap.cmd
Expand All @@ -104,7 +104,7 @@ jobs:
runs-on: macos-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: bootstrap
run: dist/macos/bootstrap.sh
- name: venv
Expand All @@ -120,7 +120,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: bootstrap
run: |
sudo apt update
Expand All @@ -137,7 +137,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: bootstrap
run: |
sudo apt update
Expand All @@ -153,7 +153,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: bootstrap
run: |
sudo apt update
Expand Down
13 changes: 0 additions & 13 deletions .reuse/dep5

This file was deleted.

19 changes: 17 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@


..
SPDX-FileCopyrightText: 2020-2025 Jochem Rutgers
SPDX-FileCopyrightText: 2020-2026 Jochem Rutgers

SPDX-License-Identifier: CC0-1.0

Expand All @@ -24,14 +24,29 @@ The format is based on `Keep a Changelog`_, and this project adheres to
Added
`````

...

.. _Unreleased: https://github.com/DEMCON/libstored/compare/v2.2.0...HEAD



`2.2.0`_ - 2026-03-27
---------------------

Added
`````

- ``libstored.protocol.ArqLayer`` for general-purpose ARQ.

Fixed
`````

- ``ZmqClient`` assertion during cleanup
- ``AsyncioWorker`` coro scheduling from MainThread asyncio loop.
- Fix stopping fast poll in ``ZmqClient`` when all objects are stopped polling.
- ``libstored.gui`` performance on Windows.

.. _Unreleased: https://github.com/DEMCON/libstored/compare/v2.1.0...HEAD
.. _2.2.0: https://github.com/DEMCON/libstored/releases/tag/v2.2.0



Expand Down
23 changes: 23 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# SPDX-FileCopyrightText: 2020-2026 Jochem Rutgers
#
# SPDX-License-Identifier: CC0-1.0

version = 1

[[annotations]]
path = "extern/material.io/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "Google"
SPDX-License-Identifier = "Apache-2.0"

[[annotations]]
path = "presentation/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2020-2026 Jochem Rutgers"
SPDX-License-Identifier = "CC-BY-4.0"

[[annotations]]
path = ".vscode/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2020-2026 Jochem Rutgers"
SPDX-License-Identifier = "CC0-1.0"
8 changes: 5 additions & 3 deletions dist/common/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# SPDX-FileCopyrightText: 2020-2025 Jochem Rutgers
# SPDX-FileCopyrightText: 2020-2026 Jochem Rutgers
#
# SPDX-License-Identifier: MPL-2.0

Expand All @@ -18,9 +18,9 @@ trap gotErr ERR
function show_help {
echo -e "Usage: $0 [<opt>...] [--] [<other cmake arguments>]\n"
echo "where opt is:"
echo " Debug RelWithDebInfo Release"
echo " Debug RelWithDebInfo Release"
echo " Set CMAKE_BUILD_TYPE to this value"
echo " C++98 C++03 C++11 C++14 C++17 C++20"
echo " C++98 C++03 C++11 C++14 C++17 C++20 C++23"
echo " Set the C++ standard"
echo " conf Configure only, don't build"
echo " dev Enable development-related options"
Expand Down Expand Up @@ -77,6 +77,8 @@ while [[ ! -z ${1:-} ]]; do
cmake_opts="${cmake_opts} -DCMAKE_CXX_STANDARD=17 -DCMAKE_C_STANDARD=11";;
C++20)
cmake_opts="${cmake_opts} -DCMAKE_CXX_STANDARD=20 -DCMAKE_C_STANDARD=11";;
C++23)
cmake_opts="${cmake_opts} -DCMAKE_CXX_STANDARD=23 -DCMAKE_C_STANDARD=11";;
conf)
do_build=0;;
dev)
Expand Down
2 changes: 1 addition & 1 deletion dist/common/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ breathe
sphinxcontrib-wavedrom

# Other
reuse
reuse >= 6.0.0
cmake_format
10 changes: 7 additions & 3 deletions dist/win32/build.cmd
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@echo off

rem SPDX-FileCopyrightText: 2020-2025 Jochem Rutgers
rem SPDX-FileCopyrightText: 2020-2026 Jochem Rutgers
rem
rem SPDX-License-Identifier: MPL-2.0

Expand Down Expand Up @@ -85,6 +85,10 @@ if %1 == C++20 (
set cmake_opts=%cmake_opts% -DCMAKE_CXX_STANDARD=20 -DCMAKE_C_STANDARD=11
goto next_param
)
if %1 == C++23 (
set cmake_opts=%cmake_opts% -DCMAKE_CXX_STANDARD=23 -DCMAKE_C_STANDARD=11
goto next_param
)
if %1 == conf (
set do_build=0
goto next_param
Expand Down Expand Up @@ -229,10 +233,10 @@ exit /b 0
echo Usage: %0 [^<opt^>...] [--] [^<other cmake arguments^>]
echo.
echo where opt is:
echo Debug RelWithDebInfo Release
echo Debug RelWithDebInfo Release
echo Set CMAKE_BUILD_TYPE to this value
echo gcc Use gcc instead of default compiler
echo C++98 C++03 C++11 C++14 C++17 C++20
echo C++98 C++03 C++11 C++14 C++17 C++20 C++23
echo Set the C++ standard
echo conf Configure only, don't build
echo dev Enable development-related options
Expand Down
45 changes: 24 additions & 21 deletions python/libstored/asyncio/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,34 +335,37 @@ def run_sync(*args, block: bool = True, sync: bool | None = None, **kwargs) -> t
sync is None or (loop is None) == sync or not block
), "sync argument contradicts current context"

if loop is not None and not sync:
w = None
logger = None
if isinstance(self, Work):
logger = self.logger
w = self.worker
if loop is not w.loop:
logger.debug("Running %s in worker %s", f.__qualname__, str(w))
else:
logger.debug("Running %s in current worker", f.__qualname__)
else:
if hasattr(self, "logger"):
logger = self.logger
logger.debug("Running %s in default worker", f.__qualname__)
global default_worker
w = default_worker

if w is None or not w.is_running():
if hasattr(self, "logger"):
logger = self.logger
logger.debug("No worker running, creating new one")
w = AsyncioWorker()

if loop is not None and not sync and loop is w.loop:
# We are in an event loop, just start the coro.
coro = f(*args, **kwargs)
if block:
return coro
else:
return asyncio.ensure_future(coro)
else:
# We are not in an event loop, run the coro in the (default) worker.
w = None
logger = None
if isinstance(self, Work):
logger = self.logger
logger.debug("Running %s in worker %s", f.__qualname__, str(self.worker))
w = self.worker
else:
if hasattr(self, "logger"):
logger = self.logger
logger.debug("Running %s in default worker", f.__qualname__)
global default_worker
w = default_worker

if w is None or not w.is_running():
if hasattr(self, "logger"):
logger = self.logger
logger.debug("No worker running, creating new one")
w = AsyncioWorker()

# We are not in the (proper) event loop, run the coro in the (default) worker.
future = w.execute(f(*args, **kwargs))
if block:
return lexc.DeadlockChecker(future).result()
Expand Down
2 changes: 1 addition & 1 deletion python/libstored/asyncio/zmq.py
Original file line number Diff line number Diff line change
Expand Up @@ -3045,7 +3045,7 @@ async def _poll(self, o: Object, interval_s: float | None):
await self._fast_poll_macro.remove(o)
await self.alias(o, temporary=True, permanentRef=self._fast_poll_macro)

if len(self._fast_poll_macro) == 0:
if len(self._fast_poll_macro) <= 1: # time is always included, so check for <= 1
await self._poll_fast_stop()

# Stop trace, if any
Expand Down
10 changes: 6 additions & 4 deletions python/libstored/gui/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2020-2025 Jochem Rutgers
# SPDX-FileCopyrightText: 2020-2026 Jochem Rutgers
#
# SPDX-License-Identifier: MPL-2.0

Expand Down Expand Up @@ -30,7 +30,6 @@
from .. import exceptions as lexc
from .. import protocol as lprot


#####################################################################
# Style
#
Expand Down Expand Up @@ -694,6 +693,7 @@ def set_objects(self, objects: list[laio_zmq.Object]):
for o in self._objects:
o.destroy()
self._objects = []
self._filtered_objects = []

for o in natsort.natsorted(objects, key=lambda o: o.name, alg=natsort.ns.IGNORECASE):
object_row = ObjectRow(self._app, self, o, show_plot=self._show_plot)
Expand Down Expand Up @@ -1193,8 +1193,8 @@ def __init__(

self.root.title(f"libstored GUI")
icon_path = os.path.join(os.path.dirname(__file__), "twotone_bug_report_black_48dp.png")
icon = tk.PhotoImage(file=icon_path)
self.root.iconphoto(False, icon)
self._icon = tk.PhotoImage(file=icon_path)
self.root.iconphoto(False, self._icon)

global plotter
if Plotter.available and plotter is None:
Expand Down Expand Up @@ -1337,6 +1337,8 @@ def cleanup(self):
plotter = None

self.disconnect_all()
self._objects.set_objects([])
self._polled_objects.set_objects([])
self.logger.debug("Close client")
self._close_async()
super().cleanup()
Expand Down
6 changes: 3 additions & 3 deletions src/protocol.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2020-2025 Jochem Rutgers
// SPDX-FileCopyrightText: 2020-2026 Jochem Rutgers
//
// SPDX-License-Identifier: MPL-2.0

Expand Down Expand Up @@ -1394,7 +1394,7 @@ void Crc8Layer::decode(void* buffer, size_t len)
uint8_t* buffer_ = static_cast<uint8_t*>(buffer);
uint8_t crc = init;
for(size_t i = 0; i < len - 1; i++)
crc = compute(crc, buffer_[i]);
crc = compute(buffer_[i], crc);

if(crc != buffer_[len - 1])
// Invalid.
Expand All @@ -1407,7 +1407,7 @@ void Crc8Layer::encode(void const* buffer, size_t len, bool last)
{
uint8_t const* buffer_ = static_cast<uint8_t const*>(buffer);
for(size_t i = 0; i < len; i++)
m_crc = compute(m_crc, buffer_[i]);
m_crc = compute(buffer_[i], m_crc);

base::encode(buffer, len, false);

Expand Down
10 changes: 10 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,16 @@ if(LIBSTORED_HAVE_LIBZMQ
)
endif()

if(LIBSTORED_PYLIBSTORED)
add_test(NAME test_async
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}/../python
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_async.py
)

set_tests_properties(test_async PROPERTIES TIMEOUT 60)
add_launch_json_py(test_async ${CMAKE_CURRENT_SOURCE_DIR}/test_async.py)
endif()

if(VIVADO_CMD)
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test_fpga/vivado/test_fpga/test_fpga.xpr)
execute_process(
Expand Down
Loading
Loading