InterlockedCompareExchangePointer takes the wrong type? - winapi

This function is comparing and exchanging the pointer itself but takes a pointer to volatile data rather than taking a volatile pointer. Can it really be this wrong? do I need to use #ifdef and InterlockedCompareExchange[64] instead? Or I am misunderstanding somehow?

The types are correct. In your head you can change the PVOID type to something else and it should make more sense, (SIZE_T volatile *, SIZE_T, SIZE_T) etc.

Related

using std::max causes a link error?

Consider a library that defines in a header file
struct Proj {
struct Depth {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
struct Video {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
};
The library gets compiled, and I'm now developing an application that links against this library. I thought for a long time it was some kind of visibility problem, but even after adding B_EXPORT (standard visibility stuff from CMake) everywhere with no change, I finally found the problem.
template <class Projection>
struct SomeApplication {
SomeApplication() {
unsigned height = std::max(// or std::max<unsigned>
Projection::Depth::Height,
Projection::Video::Height
);
}
};
I can't even reproduce the problem with a small dummy library / sample application. But using std::max in the application causes the link error, whereas if I just do it myself
unsigned height = Projection::Depth::Height;
if (height < Projection::Video::Height)
height = Projection::Video::Height;
Everything works out. AKA there don't appear to be any specific issues with the visibility in terms of just using Projection::XXX.
Any thoughts on what could possibly cause this? This is on OSX, so this doesn't even apply.
The problem is that Width and Height are declared, not defined in your structs. Effectively, this means there is no storage allocated for them.
Now recall the signature for std::max:
template<typename T>
const T& max(const T&, const T&);
Note the references: this means the addresses of the arguments are to be taken. But, since Width and Height are only declared, they don't have any storage! Hence the linker error.
Now let's consider the rest of your question.
Your hand-written max works because you never take any pointers or references to the variables.
You might be unable to reproduce this on a toy example because, depending on the optimization level in particular, a sufficiently smart compiler might evaluate max at compile time and save the trouble of taking the addresses at runtime. For instance, compare the disasm for no optimization vs -O2 for gcc 7.2: the evaluation is indeed done at compile-time!
As for the fix, it depends. You have several options, to name a few:
Use constexpr getter functions instead of variables. In this case the values they return will behave more like temporary objects, allowing the addresses to be taken (and the compiler will surely optimize that away). This is the approach I'd suggest in general.
Use namespaces instead of structs. In this case the variables will also be defined in addition to being declared. The caveat is that you might get duplicate symbol errors if they are used in more than one translation unit. The fix for that is only in form of C++17 inline variables.
...speaking of which, C++17 also changes the rules for constexpr static member variables (they become inline by default), so you won't get this error if you just switch to this standard.

Unreference shared_ptr

I know 2 ways:
// Declared somewhere but not on stack
shared_ptr<X> xptr = make_shared<X>();
xptr = nullptr; //#1
xptr.reset(); //#2
As for me #1 looks better, but what is better from the point of C++
Neither is objectively better. In almost every case, the difference is purely aesthetic.
The only exception that I can think of is writing a generic function template that works with both smart, and bare pointers. only ptr = nullptr is valid syntax for bare pointers.
The assignment and reset member function differ in behaviour only when the pointer is not null.

Use a char array in a std::string in C++11

I'm not sure if this is safe, what will happen when the string gets out of scope?:
std::string tmp_str( strdup("wlan0"));
I know that strdup uses malloc to allocate new space for the string which will be used by tmp_string.
I'm not interested in a solution, I would like to know if there will be any issue using strdup.
The std::string class copies the string, not the pointer to the string. That means that the memory allocated by strdup will be lost forever for your process.
There's simply no need to use strdup in that way. And besides that, string literals will exist for the life-time of the program, so pointers to them will never become invalid.

Why are C++ smart pointers so unrestricted, i.e. may be reassigned or reset?

In both C++11 and boost, smart pointers can be nullptr. I wonder why. That means that smart pointers must be checked for being nullptr every time they are passed to interface method from uncontrolled client code. Obviously, such check is performed in run time.
What if there would be smart pointers that can be created only via make_shared or make_unique and cannot be reset or reassigned to nullptr or raw pointer? This approach allows to ensure that pointer is not nullptr in compile time.
For example, in Java we always must check if object is not null (bad). But in Swift, we can explicitly make sure that argument (or variable) is not null in compile time (good).
UPD:
Well, thank you much for answers and comments. I got idea. But is there any popular libraries that supports non-nullity compile time guarantee alongside ownership, maybe smart pointer wrappers?
std smart pointers exist for one reason—to implement the concept of ownership. Their responsibility is to clearly define who owns the pointee (i.e. who and how ensures its safe destruction).
Large parts of std are really composed of low-level basic building blocks. While they can be used straight away in client code, they are not supposed to be an all-encompassing solution. They give you single-purpose tools which you cna mix & match to create something you need.
The std smart pointers are eactly "raw pointers + ownership." Raw pointers can be null and can be reseated, so std smart pointers can as well. Nothing prevents you from creating your own "std smart pointer + non-nullity" class(es) and using them in your code.
On the other hand, there are very valid use cases for a null smart pointer. If std smart pointers enforce non-nullity, and you needed null-supporting smart pointers, you'd have a much harder time implementing that. It's easier to add a validity constraint than to remove it when you can only do it by adding to the original class.
For std::unique_ptr is impossible to require no null, consider this:
std::unique_ptr<int> p = std::make_unique<int>();
std::unique_ptr<int> q = std::move(p);
What value will have p and q? If we ban null option this become impossible to implement. Even if we consider destroying move, we will have even worse situation. This is because you will be not allowed to test p, any use will be UB.
For std::share_ptr It could be possible to require it but this will heavy hinder any other use that could used nullable pointers. Standard library is too generic to allow that limitation.
Overall idea of having compile time guarantee of existing object pointed by pointer is very valuable but you try used wrong tool for this. Usually this is done by using & not pointers.
To solve your needs I suggest creating warper around std::share_ptr:
template<typename T>
class always_ptr
{
std::shared_ptr<T> _ptr;
public:
always_ptr() = delete; //no default constructor
always_ptr(const always_ptr& a) : _ptr{ a._ptr } { }
explicit always_ptr(T* p)
{
if (!p) throw std::Exception(); //only way to guarantee this is not null
_ptr = std::shared_ptr<T>(p);
}
T* get() { return _ptr.get(); }
T& operator*() { return *_ptr; }
T* operator->() { return _ptr.get(); }
explicit operator bool() const { return true; } //always true
};

How to force GCC to pass 128bits/256bits struct as function param in xmm/ymm register?

How to force GCC to pass 128bits/256bits struct as function param in xmm/ymm register?
ie. if my struct is 256bits wide (UnsignedLongLongStruct below)
(I know if I use intrinsics to make a packed integer, gcc is smart enough to put it into %ymm register, but can I do it with struct ?)
typedef struct {
unsigned long long ull1;
unsigned long long ull2;
unsigned long long ull3;
unsigned long long ull4;
} UnsignedLongLongStruct;
void func1( UnsignedLongLongStruct unsignedLongLongStruct ) {
....
}
TL;DR: It seems the calling conventions explicitly mention __m256 and friends to be placed in the umm regs.
In X86-64 System V ABI, point 3.2.3, you can check how parameters are passed. My reading is that only __m256 arguments will be turned into one SSE and 3 SSEUP 8-byte chunks, which allows them to be passed in a ymm register.
This will make it so that your argument gets passed in memory, which is what we see in clang, gcc, and icc: Test program on godbolt
In order to pass it as a register, as I read the calling conventions, it seem that you have to pass it as a __m256 (or a variant of it).
The calling conventions are a bit of a mess across different platforms and compilers. You should pass the input to your function by value as an __m256.
If it's a trivial function and you want to ensure GCC inlines it, you could declare it with the always_inline attribute to avoid any unnecessary loads/stores:
inline __attribute__((always_inline)) __m256 foo(__m256 const input);

Resources