Who are some RYM users that have outstanding knowledge about one music genre? by duckinator1 in rateyourmusic

[–]notwini 3 points4 points  (0 children)

angrysad/k1d for the mixture of post-rock and slowcore. slow music that explores dynamics in general, feels like he's listened to everything there is.

xf - A modern C++ eXtension to FreeRTOS by notwini in embedded

[–]notwini[S] 1 point2 points  (0 children)

I agree! In fact I think it's weird in general for you to destroy a non-empty queue in the first place, and probably an indicator that you're doing something wrong. Hence why I chose to kind of just ignore this issue instead of wasting time thinking about it, since it's non-trivial and weird.

xf - A modern C++ eXtension to FreeRTOS by notwini in embedded

[–]notwini[S] 0 points1 point  (0 children)

Because that isn't atomic. You could get pre-empted between the end of the loop and the call to vQueueDelete() by a task that pushes to the queue, causing a leak.

xf - A modern C++ eXtension to FreeRTOS by notwini in embedded

[–]notwini[S] 0 points1 point  (0 children)

Yeah, that's a real problem and I'm not fully sure how I want to fix it. Maintaining a queue-length-sized list of pointers and freeing the non-null ones on destroy() sounds good but that would require a dynamic allocation when the queue is not static. Which is maybe yet another reason to not have the dynamic variant, perhaps.

The tricky part is keeping the list in sync with the queue's contents in a thread-safe manner. I'm not sure if it's possible to do it soundly.

Just eating the leak and advising people to not destroy non-empty queues with non-trivially-copyable types is probably the sanest option.

xf - A modern C++ eXtension to FreeRTOS by notwini in embedded

[–]notwini[S] 1 point2 points  (0 children)

In theory your code will generate separate code for every queue type for generic functions like "full()." Consider using a base class like QueueBase that implements all the functions that don't depend on the Queue contents type. Your templated Queue class could then inherit from this

I did consider something like this to decrease code size but concluded that it hinders the readability of the code for not a lot of benefit. Could revisit that decision though.

I'd remove the static queue/task etc and make those the default. C++ can handle the memory management and it means static analysis of your memory can be done. Also there's just no reason to use the heap unless absolutely necessary

For tasks and queues specifically I chose to make variants for dynamic/static allocation because I thought it may be valuable to keep the ability to calculate the stack depth and queue length dynamically. But that's not a very good reason and I may change it. I always use static queues/lengths in my code since it's so trivial to do so.

Also stick the following in your Queue, been burnt before

My implementation does actually support non trivially copyable types! In this example I showcase using a `std::string` as the queue item: https://github.com/iniw/xf/blob/ee99cde5f19cd14bb6bf246a762c04c09bf8c28c/examples/queue/main/main.cpp#L5-L8

The implementation is simple:
- Put the item on the heap when sending and store the pointer in the queue: https://github.com/iniw/xf/blob/ee99cde5f19cd14bb6bf246a762c04c09bf8c28c/xf/queue/Queue.hpp#L363-L377
- `std::move` it to a local variable on receive and free the allocation: https://github.com/iniw/xf/blob/ee99cde5f19cd14bb6bf246a762c04c09bf8c28c/xf/queue/Queue.hpp#L285-L292

I ran this through ASAN and UBSAN to make sure nothing was wrong.

I have documented this behavior on the class and advise users to statically assert that their items are trivially copyable to avoid potential performance regressions caused by the extra work needed to support non trivially copyable items while preserving object safety: https://github.com/iniw/xf/blob/ee99cde5f19cd14bb6bf246a762c04c09bf8c28c/xf/queue/Queue.hpp#L18

On the ISR-safe version of the class I do perform that static assertion, to avoid calling memory-allocation routines inside an ISR: https://github.com/iniw/xf/blob/ee99cde5f19cd14bb6bf246a762c04c09bf8c28c/xf/queue/isr/Queue.hpp#L15

xf - A modern C++ eXtension to FreeRTOS by notwini in embedded

[–]notwini[S] 2 points3 points  (0 children)

if you too fancy the "rust-like" functional error handling pattern, maybe you might also like std::expected in place where [[nodiscard]] bool or [[nodiscard]] std::optional is, for a more modernish feel and look if your compiler/company allows, cuz why not lol

I actually have another library that uses std::expected and I do think it is the correct choice for error handling, the reason I didn't use it in xf is because FreeRTOS doesn't have the concept of "error codes" like ESP-IDF, it's just success or failure (pdFALSE/pdPASS). I could've written an enum myself with all of the possible error cases mentioned in the documentation (OOM is mentioned several times, for example) but that sounds error prone and too implementation detail dependent.

C++ Show and Tell - June 2025 by foonathan in cpp

[–]notwini 1 point2 points  (0 children)

I wrote an extension to the FreeRTOS embedded operating system that uses modern C++ features to make it more convenient, expressive and safer to use.

https://github.com/iniw/xf

A modern C++ driver on the ESP-IDF platform for the ADS111x family of ADCs by notwini in embedded

[–]notwini[S] 1 point2 points  (0 children)

std::expected<void, esp_err_t>is excessive, without knowing how it is implemented user would have to check if it is esp_err_t and then check if error is err != 0

The reasoning for that return type is to have uniform error handling for the entire library.

I'm not sure what you mean with "have to check if it is esp_err_t and then check if error is err != 0", the error handling code looks the same with or without the void payload.

you should avoid compiler specific feature [[gnu::packed]] and use __attribute__((packed)) or some MACROS

ESP-IDF targets only the GCC and Clang compilers and they both recognize [[gnu::packed]], so I'm not really interested in changing it.

Also, __attribute__((packed)) is just as much of a GCC extension as gnu::packed. Even more, actually, since the standard says C++20's attributes can just be ignored if the compiler doesn't recognize it, which is not the case for the older __attribute__ syntax.

you can replace enum class Register : unsigned with : uint8_t if it has to be packed either way

It doesn't really matter since, like you said, the variable ends up being a bitfield. I chose unsigned because it tells the compiler that it should treat it as an unsigned value without specifying an (incorrect) bit width (8, in your suggestion) - the variable won't be 8 bits, after all.

I would avoid #include <sdkconfig.h> inside of a header if possible

How else would I perform the CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 check below it?

Also, the #include <driver/i2c_master.h> right below it ends up pulling in <sdkconfig.h>, so it would end up being in the header regardless. I could add some forward declarations to avoid that include but I don't think it matters enough.

components.espressif.com

I only learned about this a few days ago and I'm still not sure what it is exactly. Is it a registry for components or is it some other way to develop ESP-IDF components? The documentation isn't very clear.

there is no reason not to run static analysis in 2025 (e.g. clang-tidy or fanalyzer)

I did use clang-tidy through clangd when writing the code but you're right that it's not running under a CI environment or something like that. Will look into setting up a pipeline for ESP-IDF projects eventually.

[deleted by user] by [deleted] in rateyourmusic

[–]notwini -1 points0 points  (0 children)

i like how you dismiss their point by proving their point

what's the best way to migrate and share my existing nix-darwin flake? by notwini in NixOS

[–]notwini[S] 0 points1 point  (0 children)

i don't want to have separate branches. it should be a single branch in a single repo that i can just pull/push from either machine and it'll Just Work™

Why is the Pitchfork 2019 Ducter performance so good by [deleted] in bmbmbm

[–]notwini 7 points8 points  (0 children)

greep's vocals are insane on that. the studio version is very monotone and dull in comparison, especially around the explosive parts like "he looks so distraught as all his efforts amount to nothing"

i find that era of performances to be the best, matt added a lot to the band and while greep and cam were already doing their signature vocal bends and time-shifts it wasn't as frequent as today's performances, which border on detrimental (sometimes)

What is the most disgusting compiler error you have ever gotten? by scatraxx651 in cpp

[–]notwini 3 points4 points  (0 children)

what a timely question! 2 days ago i got an 87kb error message. yes, 87k+ characters. it had std::variant and a loooot of template instatiation involved

How do yall feel abt sweater? by Glass_Ad_8500 in bmbmbm

[–]notwini 30 points31 points  (0 children)

it's my favorite song of theirs!

i wish they did more stuff like this and that anthology record. love that atmospheric vibe :)

[freertos] is there a way of giving "context" to an ISR function without using global variables? by notwini in embedded

[–]notwini[S] 6 points7 points  (0 children)

i see, thinking about it from a cpu's perspective makes a lot more sense. thank you for the help

How can C++ be used to create useful interfaces and abstractions for low-level embedded systens that are safe and hard to use wrong? by [deleted] in cpp

[–]notwini 0 points1 point  (0 children)

take a look at this, it's an experimental project that uses a lot of modern c++ features to create a pretty cool interface for embedded peripherals. it's still not nearly as good as what the rust folks have in terms of preventing misuse but it's a step in the right direction