Init once with lambda function pointer, self-modifying (C++) - c++

I was wondering if it's possible to create inline lambda initialization function, so after initialization it would replace itself with dummy initialization. Some sort of lazy initialization algorithm with as less pain as possible. Here is some pseudo code what I would like to achieve:
SomeData* data = nullptr;
auto initF = [&]
{
data = initData();
initF = [&] {};
};
so in for loop it would look like this:
for(int i = 0; i < count; i++) {
initF();
data[i] = ....;
}
Basically if count is 0 - initF would not be ever called, but once called - pointer becomes initialized and can be used after that.

Well, your code almost works. Since initF essentially has to change types, from something that actually does work to just a no-op, you can use a std::function:
int data;
std::function<void()> calcData = [&]() {
data = 5; // something expensive
calcData = []() { }
};
I think you can go further and just eliminate data's separate existence, so you just have the function.
std::function<int&()> data = [&]() -> int& {
return (data = [res = 5]() mutable -> int& { return res; })();
// ^^^ the variable becomes a "hidden" data member of the closure
}
This eliminates the chance of accidentally using the variable before you call the initializer.

Use a smart pointer to a closure.
std::shared_ptr<std::function<void(void)>> initf;
Then use std::call_once to initialize it (with some lambda expression), or some static constructor initializing it, e.g.
//untested
initf.reset (& [&] () { initf = [&]() {
auto oldinitf=initf; static int cnt;
cnt++;
std::cout << "cnt=" << cnt << std::endl;
if (oldinitf)
(oldinitf.get()) ();
});
Read also about the Y fix-point combinator in the untyped λ-calculus.
Queinnec's book Lisp in Small Pieces (and Rice's theorem) is related to your question.
Observe that circular references in memory require an indirection at least (so are unfriendly to reference counting approaches).
On Linux you could generate some similar C++ code at runtime (using raw function pointers), compile it into a temporary plugin, and then use dlopen with dlsym (I did that several years ago in GCC MELT, now obsolete). See C++ dlopen minihowto and look into RefPerSys as an example (of a C++ program generating then running C++ code). Look also into JIT compiling libraries such as libgccjit, asmjit, etc...
Observe that such tricks are easier with SBCL, once you made the efforts of learning Common Lisp. SBCL is generating machine code at most REPL interactions.

Related

Is it unsafe to co_yield a pointer to a local coroutine variable?

It's common knowledge that returning a pointer to a stack variable is generally a bad idea:
int* foo() {
int i = 0;
return &i;
}
int main() {
int* p = foo();
}
In the example above, my understanding is that the int is destroyed and so p is a dangling pointer.
I am wondering about the extent to which this applies to the newly introduced coroutines of C++20:
generator<span<byte>> read(stream& s) {
array<byte, 4096> b;
while (s.is_open()) {
const size_t n = s.read_some(b);
co_yield span(b, n);
}
}
int main() {
stream s;
for (span<byte> v : read(s)) {
/* ... */
}
}
In this example, the coroutine read yields a span view into the local buffer b. Internally, that view stores a pointer to the buffer. Will that pointer ever be dangling when v is used with the body of the range-for loop?
For context, the coroutine code in the second example is modeled after the code in my own project. There, AddressSanitizer ends the program with a "use-after-free" error. Ordinarily I'd consider that enough to answer my question, but since coroutine development is still coming along at this point in time (my project is using boost::asio::experimental::coro, emphasis on "experimental"), I was wondering if the error was caused by a bug with generator's implementation or if returning pointers in this way is fundamentally incorrect (similar to the first example).
With language coroutines, this has to be safe: the lifetime of b must continue until the generator is finished, so pointers to it must be useful that long.

Changing variable names in the middle of a function

Suppose I have some object with an initial name such as quantities_of_widgets.
std::vector<int> quantities_of_widgets = GetQuantities();
I then perform an operation on quantities_of_widgets in-place. The vector quantities_of_widgets no longer represents "a vector of some quantities of things called widgets".
PerformOperationInPlace(quantities_of_widgets);
After this operation, a more appropriate name for the variable would be weights_of_widgets. That would certainly make the code more readable.
I can "change" the name by moving quantities_of_widgets to a new vector weights_of_widgets. This is a terrible idea. The move isn't free, it messes with memory continuity, etc.
std::vector<int> weights_of_widgets = std::move(quantities_of_widgets);
I could also document the meaning of the variable in comments. I might write
std::vector<int> widgets = GetQuantities(); // widgets represents quantities
PerformOperationInPlace(widgets); // widgets represents weights
UseWeights(widgets);
However, comments are less permanent and less readable. It becomes more difficult to keep track of the meaning of variables over multiple lines of code. If widgets is used 20 lines down in the middle of a large expression, I'd have trouble documenting the meaning of the variable at that point.
SomeBigFunction(Func1(widgets, some_other_object_1), some_other_object_2);
I could try aliasing, but I want to make the old name invalid to help with maintainability. Is there a way to change the name of a variable with no run-time cost?
Worrying about such small overhead is almost certainly not worth the effort in all but the most extreme scenarios. However, for the sake of completeness:
The only way to get truly overhead-free renaming of types with non-trivial destructors is via copy-elision.
In this context, you could make use of it via an immediately evaluated lambda and NRVO.
#include <vector>
std::vector<int> GetQuantities(int v);
void PerformOperationInPlace(std::vector<int>&);
void UseWeights(const std::vector<int>&);
template<typename T>
T rename(T&& rhs) {
return rhs;
}
void foo(int x) {
std::vector<int> quantities_of_widgets = GetQuantities(x);
PerformOperationInPlace(quantities_of_widgets);
UseWeights(quantities_of_widgets);
}
void bar(int x) {
std::vector<int> weights_of_widgets = [&]{
std::vector<int> quantities_of_widgets = GetQuantities(x);
PerformOperationInPlace(quantities_of_widgets);
return quantities_of_widgets;
}();
UseWeights(weights_of_widgets);
}
foo() and bar() compile down to effectively the exact same final assembly: (see on godbolt)
The only limitation is that the variable that will be renamed has to be declared within the lambda. Beyond that, implicit capture by reference makes the lambda effectively the same thing as a scope.
It is best to document code by itself. Comments have tendency do degrade.
So I would do this this way:
// name of this function terrible, it should be more like
// ExtractWeightsOfWidgetsFrom or something similar
std::vector<int> OperationInPlace(std::vector<int> data) {
// note argument is a copy!
....
return data;
}
void someCode() {
auto quantities_of_widgets = GetQuantities();
...
auto weights_of_widgets = PerformOperationInPlace(std::move(quantities_of_widgets));
// here `quantities_of_widgets` is empty since contents has been moved
// many tools will report an error if you use this value after that point
....
}
or even better I would just extract more functions:
void someCode() {
auto quantities_of_widgets = GetQuantities();
...
ProcesWeightsOfWidgets(
PerformOperationInPlace(std::move(quantities_of_widgets));
// in this version someCode ends here
}

C++ understanding RVO (as compared to returning local variable reference)

It's my first year of using C++ and learning on the way. I'm currently reading up on Return Value Optimizations (I use C++11 btw). E.g. here https://en.wikipedia.org/wiki/Return_value_optimization, and immediately these beginner examples with primitive types spring to mind:
int& func1()
{
int i = 1;
return i;
}
//error, 'i' was declared with automatic storage (in practice on the stack(?))
//and is undefined by the time function returns
...and this one:
int func1()
{
int i = 1;
return i;
}
//perfectly fine, 'i' is copied... (to previous stack frame... right?)
Now, I get to this and try to understand it in the light of the other two:
Simpleclass func1()
{
return Simpleclass();
}
What actually happens here? I know most compilers will optimise this, what I am asking is not 'if' but:
how the optimisation works (the accepted response)
does it interfere with storage duration: stack/heap (Old: Is it basically random whether I've copied from stack or created on heap and moved (passed the reference)? Does it depend on created object size?)
is it not better to use, say, explicit std::move?
You won't see any effect of RVO when returning ints.
However, when returning large objects like this:
struct Huge { ... };
Huge makeHuge() {
Huge h { x, y, x };
h.doSomething();
return h;
}
The following code...
auto h = makeHuge();
... after RVO would be implemented something like this (pseudo code) ...
h_storage = allocate_from_stack(sizeof(Huge));
makeHuge(addressof(h_storage));
auto& h = *properly_aligned(h_storage);
... and makeHuge would compile to something like this...
void makeHuge(Huge* h_storage) // in fact this address can be
// inferred from the stack pointer
// (or just 'known' when inlining).
{
phuge = operator (h_storage) new Huge(x, y, z);
phuge->doSomething();
}

Disable uninitialized warning for a local variable

C++ compilers emit warnings when a local variable may be uninitialized on first usage. However, sometimes, I know that the variable will always be written before being used, so I do not need to initialize it. When I do this, the compiler emits a warning, of course. Since my team is building with -Werror, the code will not compile. How can I turn off this warning for specific local variables. I have the following restrictions:
I am not allowed to change compiler flags
The solution must work on all compilers (i.e., no gnu-extensions or other compiler specific attributes)
I want to use this only on specific local variables. Other uninitialized locals should still trigger a warning
The solution should not generate any instructions.
I cannot alter the class of the local variable. I.e., I cannot simply add a "do nothing" constructor.
Of course, the easiest solution would be to initialize the variable. However, the variable is of a type that is costly to initialize (even default initialization is costly) and the code is used in a very hot loop, so I do not want to waste the CPU cycles for an initialization that is guaranteed to be overwritten before it is read anyway.
So is there a platform-independent, compiler-independent way of telling the compiler that a local variable does not need to be initialized?
Here is some example code that might trigger such a warning:
void foo(){
T t;
for(int i = 0; i < 100; i++){
if (i == 0) t = ...;
if (i == 1) doSomethingWith(t);
}
}
As you see, the first loop cycle initializes t and the second one uses it, so t will never be read uninitialized. However, the compiler is not able to deduce this, so it emits a warning. Note that this code is quite simplified for the sake of brevity.
My answer will recommend another approach: instead of disabling the warning code, just do some reformulation on the implementation. I see two approaches:
First Option
You can use pointers instead of a real object and guarantee that it will be initialized just when you need it, something like:
std::unique_ptr<T> t;
for(int i=0; i<100; i++)
{
if(i == 0) if(t.empty()) t = std::unique_ptr<T>(new T); *t = ...;
if(i == 1) if(t.empty()) t = std::unique_ptr<T>(new T); doSomethingWith(*t);
}
It's interesting to note that probably when i==0, you don't need to construct t using the default constructor. I can't guess how your operator= is implemented, but I supose that probably you are assigning an object that's already allocated in the code that you are omitting in the ... segment.
Second Option
As your code experiences such a huge performance loss, I can infer that T will never be an basic tipe (ints, floats, etc). So, instead of using pointers, you can reimplement your class T in a way that you use an init method and avoid initializing it on the constructor. You can use some boolean to indicate if the class needs initalization or not:
class FooClass()
{
public:
FooClass() : initialized(false){ ... }
//Class implementation
void init()
{
//Do your heavy initialization code here.
initialized = true;
}
bool initialized() const { return initialized; }
private:
bool initialized;
}
Than you will be able to write it like this:
T t;
for(int i=0; i<100; i++)
{
if(i == 0) if(!t.initialized()) t.init(); t = ...;
if(i == 1) if(!t.initialized()) t.init(); doSomethingWith(t);
}
If the code is not very complex, I usually unroll one of the iterations:
void foo(){
T t;
t = ...;
for(int i = 1; i < 100; i++){
doSomethingWith(t);
}
}

Is qsort thread safe?

I have some old code that uses qsort to sort an MFC CArray of structures but am seeing the occasional crash that may be down to multiple threads calling qsort at the same time. The code I am using looks something like this:
struct Foo
{
CString str;
time_t t;
Foo(LPCTSTR lpsz, time_t ti) : str(lpsz), t(ti)
{
}
};
class Sorter()
{
public:
static void DoSort();
static int __cdecl SortProc(const void* elem1, const void* elem2);
};
...
void Sorter::DoSort()
{
CArray<Foo*, Foo*> data;
for (int i = 0; i < 100; i++)
{
Foo* foo = new Foo("some string", 12345678);
data.Add(foo);
}
qsort(data.GetData(), data.GetCount(), sizeof(Foo*), SortProc);
...
}
int __cdecl SortProc(const void* elem1, const void* elem2)
{
Foo* foo1 = (Foo*)elem1;
Foo* foo2 = (Foo*)elem2;
// 0xC0000005: Access violation reading location blah here
return (int)(foo1->t - foo2->t);
}
...
Sorter::DoSort();
I am about to refactor this horrible code to use std::sort instead but wondered if the above is actually unsafe?
EDIT: Sorter::DoSort is actually a static function but uses no static variables itself.
EDIT2: The SortProc function has been changed to match the real code.
Your problem doesn't necessarily have anything to do with thread saftey.
The sort callback function takes in pointers to each item, not the item itself. Since you are sorting Foo* what you actually want to do is access the parameters as Foo**, like this:
int __cdecl SortProc(const void* elem1, const void* elem2)
{
Foo* foo1 = *(Foo**)elem1;
Foo* foo2 = *(Foo**)elem2;
if(foo1->t < foo2->t) return -1;
else if (foo1->t > foo2->t) return 1;
else return 0;
}
Your SortProc isn't returning correct results, and this likely leads to memory corruption by something assuming that the data is, well, sorted after you get done sorting it. You could even be leading qsort into corruption as it tries to sort, but that of course varies by implementation.
The comparison function for qsort must return negative if the first object is less than the second, zero if they are equal, and positive otherwise. Your current code only ever returns 0 or 1, and returns 1 when you should be returning negative.
int __cdecl Sorter::SortProc(const void* ap, const void* bp) {
Foo const& a = *(Foo const*)ap;
Foo const& b = *(Foo const*)bp;
if (a.t == b.t) return 0;
return (a.t < b.t) ? -1 : 1;
}
C++ doesn't really make any guarantees about thread safety. About the most you can say is that either multiple readers OR a single writer to a data structure will be OK. Any combination of readers and writers, and you need to serialise the access somehow.
Since you tagged your question with MFC tag I suppose you should select Multi-threaded Runtime Library in Project Settings.
Right now, your code is thread-safe, but useless, as the DoSort-method only uses local variables, and doesn't even return anything. If the data you are sorting is a member of Sorter, then it is not safe to call the function from multiple threads. In gerenal, read up on reentrancy, this may give you an idea of what you need to look out for.
what make it thread safe is, whether your object are thread safe, for example to make qsort thread-safe you must ensure that anything that write or read to or from and to the object are thread safe.
The pthreads man page lists the standard functions which are not required to be thread-safe. qsort is not among them, so it is required to be thread-safe in POSIX.
http://www.kernel.org/doc/man-pages/online/pages/man7/pthreads.7.html
I can't find the equivalent list for Windows, though, so this isn't really an answer to your question. I'd be a bit surprised if it was different.
Be aware what "thread-safe" means in this context, though. It means you can call the same function concurrently on different arrays -- it doesn't mean that concurrent access to the same data via qsort is safe (it isn't).
As a word of warning, you may find std::sort is not as fast as qsort. If you do find that try std::stable_sort.
I once wrote a BWT compressor based on the code presented my Mark Nelson in Dr Dobbs and when I turned it into classes I found that regular sort was a lot slower. stable_sort fixed the speed problems.