[SOLVED] C++: which type of cast is best for audio callbacks?
Moderators: MattKingUSA, khz
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
Sadko4u is an assembly guy, don't listen to his C++ advice. Only use reinterpret_cast if all other casts fail. I only use reinterpret_cast during serialization to get access to raw bytes and C++ guarantees that you can cast a pointer to char*. Almost everything else is UB.
Also, I would suggest to wrap your pointers into some class because pointer arithmetic is extremely unsafe. GSL has span<T> which provides a safe interface over a pointer. My audio library which sadko really really hates uses std::vector.
Also, I would suggest to wrap your pointers into some class because pointer arithmetic is extremely unsafe. GSL has span<T> which provides a safe interface over a pointer. My audio library which sadko really really hates uses std::vector.
- sadko4u
- Established Member
- Posts: 987
- Joined: Mon Sep 28, 2015 9:03 pm
- Has thanked: 2 times
- Been thanked: 360 times
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
That's true. Assembly is very useful for time-critical operations.FaTony wrote:Sadko4u is an assembly guy, don't listen to his C++ advice.
And what about such example (?):FaTony wrote: Only use reinterpret_cast if all other casts fail. I only use reinterpret_cast during serialization to get access to raw bytes and C++ guarantees that you can cast a pointer to char*. Almost everything else is UB.
Code: Select all
uint32_t *rgba(uint8_t *ptr)
{
return static_cast<uint32_t *>(ptr);
}
Oh, please, no. Don't do extra work where it is not necessary. Wrap a wrapper that is wrapped by wrapper that wraps a wrapper to the pointer.FaTony wrote: Also, I would suggest to wrap your pointers into some class because pointer arithmetic is extremely unsafe. GSL has span<T> which provides a safe interface over a pointer.
I don't hate it, i just criticize it because it's not optimal because... it's too abstract. Remember 'The Three Big Lies' from video? That's it.FaTony wrote: My audio library which sadko really really hates uses std::vector.
You're C++ guy, you like to write huge templates that 'will solve any needs'. I'm assembly guy, I like to implement algorithms that work at least 3x time faster (and even much faster on bulk data) than the code written with C++ for 'the most important needs'.
LSP (Linux Studio Plugins) Developer and Maintainer.
-
- Established Member
- Posts: 2335
- Joined: Mon Jul 01, 2013 8:13 am
- Has thanked: 9 times
- Been thanked: 454 times
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
When you do a type conversation, a reinterpret_cast is perfectly valid, and needed. In fact, that is the reason, why we have the reinterpret_cast in C++.sadko4u wrote:And what about such example (?):
Code: Select all
uint32_t *rgba(uint8_t *ptr) { return static_cast<uint32_t *>(ptr); }
But, when no type conversation is needed, using a reinterpret_cast, instead of a static_cast is "bad codding style".
That, exactly, shows the difference, if you know what you do, or not.
EOF
On the road again.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
UB at it's finest. http://eel.is/c++draft/basic.lval#8sadko4u wrote:And what about such example (?):Code: Select all
uint32_t *rgba(uint8_t *ptr) { return reinterpret_cast<uint32_t *>(ptr); // Changed this to reinterpret_cast because that's what you're advocating. }
You've just violated a strict aliasing rule.
The standard conforming code would be this:
Code: Select all
std::vector<std::uint32_t> rgba(std::uint8_t* ptr, std::size_t size)
{
if ((size % 4) != 0)
{
throw std::invalid_argument{"rgba: size is invalid."};
}
std::vector<std::uint32_t> result;
result.reserve(size / 4);
for (std::size_t i = 0; i < size; i += 4)
{
std::uint32_t value = static_cast<std::uint32_t>(ptr[i]) << 24 +
static_cast<std::uint32_t>(ptr[i + 1]) << 16 +
static_cast<std::uint32_t>(ptr[i + 2]) << 8 +
ptr[i + 3];
result.push_back(value);
}
return result;
}
- Properly qualified types. Almost everything in C++ is inside the namespace std. uint8_t and others become available in global namespace if you include <stdint.h> which is deprecated or type "using namespace std;" which is a bad practice.
- I wanted to return std::pair<std::uint32_t*, std::size_t> to keep the raw pointer spirit of original code but quickly found that it would be horrible.
- static_cast<std::uint32_t> is important because std::uint8_t would be promoted to int before the shift which is not signed and can be 16 bit wide.
- sadko4u
- Established Member
- Posts: 987
- Joined: Mon Sep 28, 2015 9:03 pm
- Has thanked: 2 times
- Been thanked: 360 times
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
While writing such things please explain where did you find UB in the example. C++ can not return pointer to the data interpreted as the same data with the different type? That's sad for such 'powerful' and 'flexible' language.FaTony wrote: UB at it's finest. http://eel.is/c++draft/basic.lval#8
OK, please show the place where I violated the strict aliasing rule in this short cast example. I'll ask in a bit another form: what's the problem if we don't work with the original pointer?FaTony wrote: You've just violated a strict aliasing rule.
Oh man, the better way you should never show this code. You didn't understand right the problem and began to immediately write such unoptimal code. That's sad, because:FaTony wrote: The standard conforming code would be this:Code: Select all
std::vector<std::uint32_t> rgba(std::uint8_t* ptr, std::size_t size) { if ((size % 4) != 0) { throw std::invalid_argument{"rgba: size is invalid."}; } std::vector<std::uint32_t> result; result.reserve(size / 4); for (std::size_t i = 0; i < size; i += 4) { std::uint32_t value = static_cast<std::uint32_t>(ptr[i]) << 24 + static_cast<std::uint32_t>(ptr[i + 1]) << 16 + static_cast<std::uint32_t>(ptr[i + 2]) << 8 + ptr[i + 3]; result.push_back(value); } return result; }
- Properly qualified types. Almost everything in C++ is inside the namespace std. uint8_t and others become available in global namespace if you include <stdint.h> which is deprecated or type "using namespace std;" which is a bad practice.
- I wanted to return std::pair<std::uint32_t*, std::size_t> to keep the raw pointer spirit of original code but quickly found that it would be horrible.
- static_cast<std::uint32_t> is important because std::uint8_t would be promoted to int before the shift which is not signed and can be 16 bit wide.
- It does not solve the original problem
- It uses dynamic allocation of memory
- It throws exceptions
- It returns instance to the object in stack, so probably the calling code will call the copy constructor for std::vector to copy data, so you get the second dynamic allocation of memory.
- It performs some binary math on data that (probably) shouldn't ever be
- static_cast<std::uint32_t>(ptr) - this is the shame. std::uint32_t(ptr) is shorter and mostly recommended.
- static_cast<std::uint32_t>(ptr) << 24 + static_cast<std::uint32_t>(ptr[i + 1]) << 16 - this is the shame, too. Because shift operations have lower priority rather than additions, so at the output you'll get bullshit. Also, OR (|) operation works faster at low-level rather than PLUS (+);
As I suggested from previous discussions, you're very bad low-level optimizer.
That's why criticise the library mentioned by you in this topic and never will use it.
LSP (Linux Studio Plugins) Developer and Maintainer.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
Only char and unsigned char are allowed to alias. std::uint8_t and std::uint32_t are not. Unlike other languages C++ let's you shoot yourself in the foot and do reinterpret_cast.sadko4u wrote:While writing such things please explain where did you find UB in the example. C++ can not return pointer to the data interpreted as the same data with the different type? That's sad for such 'powerful' and 'flexible' language.
You don't have the guarantee. It may work on the particular platform but otherwise it may break.sadko4u wrote:OK, please show the place where I violated the strict aliasing rule in this short cast example. I'll ask in a bit another form: what's the problem if we don't work with the original pointer?
I thought your problem was to convert bytes to RGBA array. It solves exactly it.sadko4u wrote:Oh man, the better way you should never show this code. You didn't understand right the problem and began to immediately write such unoptimal code. That's sad, because:
It does not solve the original problem
How else would you write a function with wide contract? You haven't told us anything else about your function.sadko4u wrote:It uses dynamic allocation of memory
Yes, because it is idiomatic. Almost all of the standard library uses exceptions.sadko4u wrote:It throws exceptions
Wrong. The compiler will perforrn Named Return Value Optimization. If it doesn't, it will call a move constructor. No copy will ever be made.sadko4u wrote:It returns instance to the object in stack, so probably the calling code will call the copy constructor for std::vector to copy data, so you get the second dynamic allocation of memory.
Because you can't do anything else while being standard conforming.sadko4u wrote:It performs some binary math on data that (probably) shouldn't ever be
sadko4u wrote:static_cast<std::uint32_t>(ptr) << 24 + static_cast<std::uint32_t>(ptr[i + 1]) << 16 - this is the shame, too. Because shift operations have lower priority rather than additions, so at the output you'll get bullshit. Also, OR (|) operation works faster at low-level rather than PLUS (+);
This is exactly why I avoid writing low level code and prefer to use classes which have a clean, well designed interface.
sadko4u wrote:As I suggested from previous discussions, you're very bad low-level optimizer.
I never claimed to be. I prefer correctness, portability and abstractness first and I design reusable components which can solve many cases.
sadko4u wrote:That's why criticise the library mentioned by you in this topic and never will use it.
I don't care. The common complaint I get is that my libs are [A]GPL and people love to write proprietary software and really hate [A]GPL. I couldn't care about them.
- sadko4u
- Established Member
- Posts: 987
- Joined: Mon Sep 28, 2015 9:03 pm
- Has thanked: 2 times
- Been thanked: 360 times
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
No! The problem was quite different: we want to interpret RGBA bytes as array of integers, currently without any modifications. What will be done with them after - we don't care.FaTony wrote:I thought your problem was to convert bytes to RGBA array. It solves exactly it.
Right! I didn't told anything about function. Because this function just demonstrates that static_cast doesn't work on this example. But this example can be related to the real task that needs to interpret raw data as pointer to beginning of an array of elements of some type.FaTony wrote: How else would you write a function with wide contract? You haven't told us anything else about your function.
It's not idiomatic, it's idiotic. Because it is not binary-compatible with other environment if the function will be placed in a shared library. Some code imports your library, calls the function and crashes without any possibility to handle the error.FaTony wrote: Yes, because it is idiomatic. Almost all of the standard library uses exceptions.
Maybe it's true since C++11. In reality I wouldn't ever rely on a compiler.FaTony wrote: Wrong. The compiler will perforrn Named Return Value Optimization. If it doesn't, it will call a move constructor. No copy will ever be made.
Because the original problem doesn't require any math.FaTony wrote: Because you can't do anything else while being standard conforming.
This is exactly because of your misunderstanding of platform you're writing for.FaTony wrote: This is exactly why I avoid writing low level code and prefer to use classes which have a clean, well designed interface.
This is a common problem of C++ developers. They often write 'common code' and fight with templates instead of doing something useful. The availability to write nine-floor templates (and get tons of generated machine code, lol) and decrypt multi-screen error messages raises the feeling of self-importance. But! It's not a target. You're not writing code because you need to write it. You write the code to solve the specific problem, not for the show 'the most beautiful compilation unit'.FaTony wrote: I never claimed to be. I prefer correctness, portability and abstractness first and I design reusable components which can solve many cases.
This is bullshit. How is the quality of code relative to licensing policy?FaTony wrote:I don't care. The common complaint I get is that my libs are [A]GPL and people love to write proprietary software and really hate [A]GPL. I couldn't care about them.
UPD: About three big lies
LSP (Linux Studio Plugins) Developer and Maintainer.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
Well, if you don't mind a "bomb" pointer that will lead to UB and the 1st dereference - fine. Loads the gun and point it at foot and let the user pull the trigger.sadko4u wrote:No! The problem was quite different: we want to interpret RGBA bytes as array of integers, currently without any modifications. What will be done with them after - we don't care.
Again, if the task of reinterpreting raw data occurs in the first place, then the design is deeply flawed. Good interface will be type safe where you never need a reinterpret_cast.sadko4u wrote:Right! I didn't told anything about function. Because this function just demonstrates that static_cast doesn't work on this example. But this example can be related to the real task that needs to interpret raw data as pointer to beginning of an array of elements of some type.
C++ ABI compatibility is almost nonexistent. You will need to use the same compiler version and switches to be ABI compatible, Gentoo way.sadko4u wrote:It's not idiomatic, it's idiotic. Because it is not binary-compatible with other environment if the function will be placed in a shared library. Some code imports your library, calls the function and crashes without any possibility to handle the error.
Then why do you bother with C++ at all? Go write assembly and be happy.sadko4u wrote:Maybe it's true since C++11. In reality I wouldn't ever rely on a compiler.
I got very tired after writing the same algorithms many times because every game decided to invent their own scripting language. That's why I chose C++.sadko4u wrote:This is a common problem of C++ developers. They often write 'common code' and fight with templates instead of doing something useful. The availability to write nine-floor templates (and get tons of generated machine code, lol) and decrypt multi-screen error messages raises the feeling of self-importance. But! It's not a target. You're not writing code because you need to write it. You write the code to solve the specific problem, not for the show 'the most beautiful compilation unit'.
Because people first look at the license. I'm pretty sure nobody who has complained about GPL had seen the code.sadko4u wrote:This is bullshit. How is the quality of code relative to licensing policy?
I love that this site got an explanation why your code has UB.sadko4u wrote:UPD: About three big lies
- sadko4u
- Established Member
- Posts: 987
- Joined: Mon Sep 28, 2015 9:03 pm
- Has thanked: 2 times
- Been thanked: 360 times
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
This 'bomb' pointer is returned from third-party library and I have to do something with it. Why do you frustrate?FaTony wrote:Well, if you don't mind a "bomb" pointer that will lead to UB and the 1st dereference - fine. Loads the gun and point it at foot and let the user pull the trigger.
You mean that design of JACK interface is deeply flawed? I don't think so.FaTony wrote: Again, if the task of reinterpreting raw data occurs in the first place, then the design is deeply flawed. Good interface will be type safe where you never need a reinterpret_cast.
Don't think that your shared library will be used by programs written in C++ only. That's not true.sadko4u wrote:C++ ABI compatibility is almost nonexistent. You will need to use the same compiler version and switches to be ABI compatible, Gentoo way.
I'm not too dumb to write all in assembly code. Assembly should be used to optimize performance-critical parts of program. But compiler is not a magic pill, it can solve only 5-10% of job that should solve the developer.FaTony wrote: Then why do you bother with C++ at all? Go write assembly and be happy.
The same can be told about different languages: 'that's why I chose Perl' or 'That's why I chose Lua' or 'That's why I chose Python'. It's not an argument.FaTony wrote:I got very tired after writing the same algorithms many times because every game decided to invent their own scripting language. That's why I chose C++.
Oh, dear, license is the second thing what people are watching for.sadko4u wrote:Because people first look at the license. I'm pretty sure nobody who has complained about GPL had seen the code.
The link doesn't work. You still didn't explain why my code has UB. The ghost of UB is flying somewhere but still there are no facts.FaTony wrote: I love that this site got an explanation why your code has UB.
LSP (Linux Studio Plugins) Developer and Maintainer.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
Then I would change the library.sadko4u wrote:This 'bomb' pointer is returned from third-party library and I have to do something with it. Why do you frustrate?
Although it is better than std::uint8_t*, void* highlights how C API is always type unsafe and hacky. I try to avoid C APIs at all costs.sadko4u wrote:You mean that design of JACK interface is deeply flawed? I don't think so.
I don't care about C. I pass all kinds of classes and exceptions through my API. Want C? Don't use my code.sadko4u wrote:Don't think that your shared library will be used by programs written in C++ only. That's not true.
Dunno, I always look at license before looking at the code. If it's proprietary, I never look at it again.sadko4u wrote:Oh, dear, license is the second thing what people are watching for.
http://cellperformance.beyond3d.com/art ... asing.htmlsadko4u wrote:The link doesn't work. You still didn't explain why my code has UB. The ghost of UB is flying somewhere but still there are no facts.
The UB is when you try to access the same memory location from incompatible types.
- sadko4u
- Established Member
- Posts: 987
- Joined: Mon Sep 28, 2015 9:03 pm
- Has thanked: 2 times
- Been thanked: 360 times
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
Nuff said. I can call this case only 'C++ of the entire cerebral system'.FaTony wrote:Then I would change the library.
C is designed as low-level language. It's design is done so that you easily can translate each instruction into assembly code in mind. C++ is an attempt to mix low-level language with high-level paradigm keeping mostly all low-level tricks from C. What we get now - an ugly language that fall into hacky metaprogramming stage because there are no built-in mechanisms to combine memory allocation, construction/destruction, exception handling etc without writing tons of templated code. That's why I reject all new features of C++ and use it mostly as 'advanced C with some syntax sugar'.sadko4u wrote:Although it is better than std::uint8_t*, void* highlights how C API is always type unsafe and hacky. I try to avoid C APIs at all costs.
Alright, alright. Keep inventing your bicycle.FaTony wrote:I don't care about C. I pass all kinds of classes and exceptions through my API. Want C? Don't use my code.
Don't speak about people as if they were you. People are not idiots and they are seeking for proper solutions, event if they cost some tons of money.FaTony wrote:Dunno, I always look at license before looking at the code. If it's proprietary, I never look at it again.
Where in my example I DO access the same memory location from incompatible types?FaTony wrote:The UB is when you try to access the same memory location from incompatible types.
LSP (Linux Studio Plugins) Developer and Maintainer.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
You can easily write code without templates, it will work for your case only. Templates are needed if you want to use different types but have the same algorithms.sadko4u wrote:What we get now - an ugly language that fall into hacky metaprogramming stage because there are no built-in mechanisms to combine memory allocation, construction/destruction, exception handling etc without writing tons of templated code.
Ok, the lawyer mode. You didn't dereference the pointer in your code. But I don't think there is any useful value in a pointer that can't be derefenced. Your function should be called MakeUselessPointer.sadko4u wrote:Where in my example I DO access the same memory location from incompatible types?
- sadko4u
- Established Member
- Posts: 987
- Joined: Mon Sep 28, 2015 9:03 pm
- Has thanked: 2 times
- Been thanked: 360 times
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
I already do so. And I doubt that in nearest 10 years audio samples will be present in other form rather than in float or double format. Because floating-point format has a lot of advantages relative to the fixed-point format. So there is no need to generalize sample to the template argument. It doesn't yield to optimal code generation that is required for DSP.FaTony wrote:You can easily write code without templates, it will work for your case only. Templates are needed if you want to use different types but have the same algorithms.
You may call it as you wish. Without context around the code it's not possible to say, is UB there or not. Also, if there is no access to the data via original pointer, there is no UB at all.FaTony wrote:Ok, the lawyer mode. You didn't dereference the pointer in your code.
Let me repeat again: this function is written to demonstrate that static_cast won't work in this context.FaTony wrote:But I don't think there is any useful value in a pointer that can't be derefenced. Your function should be called MakeUselessPointer.
LSP (Linux Studio Plugins) Developer and Maintainer.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: [SOLVED] C++: which type of cast is best for audio callbacks?
I'm tired. Go continue having UB, I don't care anymore.