💾 Archived View for clehaxze.tw › gemlog › 2023 › 01-27-gnunetpp-janurary-update.gmi captured on 2023-03-20 at 17:41:17. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
It's mostly bugfixes and extending GNUnet++ to handel multithreaded enviroments. Last month I started working on peerinfo support. But ended up focusing on other stuff.
GNUnet in of itself is single threaded and runs on it's own event loop. But to support more complex applications, GNUnet++ needs to support multi-threading. To be particular, GNUnet++ needs to allow other threads to queue tasks onto the GNUnet thread. Unfortunately, calling `GNUNET_SCHEDULER_add_now` from a different thread don't just work. The reason is that the scheduler calls `poll()` to wait for events. But adding a task does not trigger `poll()` to wake up. This isn't a problem under the single threaded enviroment, because only thread that adds task is the same thread that calls `poll()`. Thus it only needs to check if there's more task to run before calling `poll`.
The solution is also quite simple. While initializing, GNUnet++ will create a pipe. The read end of the pipe will be added to the scheduler. Whenever a task is added, GNUnet++ will write a byte to the pipe. This will trigger `poll()` to wake up and check if there's more task to run. I blieve this is the same technique `libgnunet-workers` uses.
Ideally we would move GNUnet to use `epoll` instead of `poll`. But that's a much bigger change. And since GNUnet is a microservice architecture (connections gets amortized by design), it probably won't be as big as a problem as it is for web servers.
I finally got around to writing unit tests for GNUnet++. Mostly out of horror of discovering the piles of bugs I have during play. I'm using Drogon's testing framework for the job as it's the only one I know of supports testing async C++ (and I wrote it). It's mostly testing core functionality like crypto and scheduler. I'll add more as I go.
One fun thing to know. C++ concepts are quite more vercitile then I thought! For example, I want to test if a type supports the UFO operator `<=>`. This would be annoying to do in C++17 using TMP. But in C++20, I can just use concepts.
template <typename T> concept SupportsUFO = requires(T v) { a <=> b }; static_assert(SupportsUFO<MyType>);
To check if a type supports all comparsion operators, I can just spam concepts together.
template <typename T> concept SupportsAllComparsion = requires(T v) { { a <=> b }; { a < b } -> std::same_as<bool>; { a > b } -> std::same_as<bool>; { a <= b } -> std::same_as<bool>; { a >= b } -> std::same_as<bool>; { a == b } -> std::same_as<bool>; { a != b } -> std::same_as<bool>; }; static_assert(SupportsAllComparsion<MyType>);
Which would have been a pain to do in older C++.
Started getting Peerinfo and Peerstore support. But it's in a very early stage. I also started looking at wrapping signing and encryption API. But that part is complicated and needs more thought.
Haven't upload this yet. Kanine (pernounce: Can-9) is a fun project I work on in my spare time. It's a bridge from bare TCP to CADET. In the process I also learned some limitations of CADET. Namely
Which is mostly fine, just more states I need to handle in Kanine to properly simulate TCP. But note worthy.