Basically what I want is sort of the opposite of std::call_once, I need to have some code, inside function foo for example, run only at the last call of foo preferably without some sort of lazy call mechanisms.
void foo()
{
...
if( magic )
do stuff
}
foo();
foo();
foo(); // magic will only be true here
Is something like this possible?
This magic would be magic, it's not possible in this world.
However, I guess, your problem is how to do required cleanup, and that is possible. There are at least three distinct mechanism that I can think of:
Register a cleanup handler with atexit().
Define a function with __attribute__((destructor)).
Put your cleanup in the destructor of a class and create a static object of that class.
No, it is impossible. The only way to know for sure that nobody will ever call foo again is a) solve the Halting Problem b) call foo on program termination.
Related
Here is the code:
class SomeType {
public:
SomeType() {}
~SomeType() {}
std::string xxx;
}
bool funtion_ab() {
SomeType(); // This is a right val;
// The right val destructs here when I test the code. I want to make sure that it would always destructs here.
int a = 0, b = 10;
....// other code
return true;
}
Please tell me if you know the truth. Thank you!
What you have is called a temporary object. From §6.7.7,
Temporary objects are created
when a prvalue is converted to an xvalue
or, more specifically,
[Note 3: Temporary objects are materialized:
...
when a prvalue that has type other than cv void appears as a discarded-value expression ([expr.context]).
— end note]
and, on the lifetime, the same section has this to say
Temporary objects are destroyed as the last step in evaluating the full-expression ([intro.execution]) that (lexically) contains the point where they were created.
You can read more about the expression semantics, but in your case "full-expression" is fairly unambiguous.
SomeType();
The "full-expression" containing your constructor call is... the constructor call itself. So the destructor will be called immediately after evaluating the constructor. There are some exceptions to this rule (such as if the temporary object is thrown as an exception or is bound as a reference), but none of those apply here.
As noted in the comments, compilers are free to inline your constructor and destructor calls and then are free to notice that they do nothing and omit them entirely. Optimizers can do fun stuff with your code, provided it doesn't change the semantics. But a strict reading of the standard states that the destructor is called exactly where you suggested.
Look at the second answer here:
What is the need for enable_shared_from_this?
it says:
"Short answer: you need enable_shared_from_this when you need to use inside the object itself existing shared pointer guarding this object.
Out of the object you can simply assign and copy a shared_ptr because you deal with the shared_ptr variable as is."
and later down in the last line it says:
"And when and why one can need a shared pointer to this instead of just this it is quite other question. For example, it is widely used in asynchronous programming for callbacks binding."
Here in this post I want to ask exactly this other question. What is an use case for "enable_shared_from_this" and "shared_from_this"?
A simple use-case would be to ensure this survives till the end of some asynchronous, or delayed operation:
class My_type : public std::enable_shared_from_this<My_type> {
public:
void foo() {}
void perform_foo() {
auto self = shared_from_this();
std::async(std::launch::async, [self, this]{ foo(); });
}
};
boost::asio uses this technique a lot in their examples:
https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/example/cpp11/allocation/server.cpp
ALL,
I have a function with the following signature:
void foo(const std::vector<Bar *> &myvec);
Inside this function I need to loop thru the members of the vector and perform some operations.
So, I tried this:
for( std::vector<Bar *>::const_iterator it = myvec.begin(); it < myvec.end(); ++it )
{
// modify properties of Bar * pointer
(*it)->SetSomeValue( baz );
}
however this code asserts since the iterator is constant.
Now obviously the vector is constant, which means that the function shouldn't be modifying myvec.
What's the best solution here?
Can I use const_cast here to remove constness? It would be kind of hack-ish, but if it works.
But I feel there must be a better solution.
TIA!!
You should use the myvec.cbegin() method instead of myvec.begin(), to ensure that you are not modifying the object the iterator points to.
Of course, for myvec.end(), use myvec.cend() accordingly.
The iterator itself doesn't need to be a const_iterator, in the contrary, you want to modify the objects it gives you - set_...() sounds like a non-const activity.
A couple codebases I use include classes that manually call new and delete in the following pattern:
class Worker {
public:
void DoWork(ArgT arg, std::function<void()> done) {
new Worker(std::move(arg), std::move(done)).Start();
}
private:
Worker(ArgT arg, std::function<void()> done)
: arg_(std::move(arg)),
done_(std::move(done)),
latch_(2) {} // The error-prone Latch interface isn't the point of this question. :)
void Start() {
Async1(<args>, [=]() { this->Method1(); });
}
void Method1() {
StartParallel(<args>, [=]() { this->latch_.count_down(); });
StartParallel(<other_args>, [=]() { this->latch_.count_down(); });
latch_.then([=]() { this->Finish(); });
}
void Finish() {
done_();
// Note manual memory management!
delete this;
}
ArgT arg_
std::function<void()> done_;
Latch latch_;
};
Now, in modern C++, explicit delete is a code smell, as, to some extent is delete this. However, I think this pattern (creating an object to represent a chunk of work managed by a callback chain) is fundamentally a good, or at least not a bad, idea.
So my question is, how should I rewrite instances of this pattern to encapsulate the memory management?
One option that I don't think is a good idea is storing the Worker in a shared_ptr: fundamentally, ownership is not shared here, so the overhead of reference counting is unnecessary. Furthermore, in order to keep a copy of the shared_ptr alive across the callbacks, I'd need to inherit from enable_shared_from_this, and remember to call that outside the lambdas and capture the shared_ptr into the callbacks. If I ever wrote the simple code using this directly, or called shared_from_this() inside the callback lambda, the object could be deleted early.
I agree that delete this is a code smell, and to a lesser extent delete on its own. But I think that here it is a natural part of continuation-passing style, which (to me) is itself something of a code smell.
The root problem is that the design of this API assumes unbounded control-flow: it acknowledges that the caller is interested in what happens when the call completes, but signals that completion via an arbitrarily-complex callback rather than simply returning from a synchronous call. Better to structure it synchronously and let the caller determine an appropriate parallelization and memory-management regime:
class Worker {
public:
void DoWork(ArgT arg) {
// Async1 is a mistake; fix it later. For now, synchronize explicitly.
Latch async_done(1);
Async1(<args>, [&]() { async_done.count_down(); });
async_done.await();
Latch parallel_done(2);
RunParallel([&]() { DoStuff(<args>); parallel_done.count_down(); });
RunParallel([&]() { DoStuff(<other_args>); parallel_done.count_down(); };
parallel_done.await();
}
};
On the caller-side, it might look something like this:
Latch latch(tasks.size());
for (auto& task : tasks) {
RunParallel([=]() { DoWork(<args>); latch.count_down(); });
}
latch.await();
Where RunParallel can use std::thread or whatever other mechanism you like for dispatching parallel events.
The advantage of this approach is that object lifetimes are much simpler. The ArgT object lives for exactly the scope of the DoWork call. The arguments to DoWork live exactly as long as the closures containing them. This also makes it much easier to add return-values (such as error codes) to DoWork calls: the caller can just switch from a latch to a thread-safe queue and read the results as they complete.
The disadvantage of this approach is that it requires actual threading, not just boost::asio::io_service. (For example, the RunParallel calls within DoWork() can't block on waiting for the RunParallel calls from the caller side to return.) So you either have to structure your code into strictly-hierarchical thread pools, or you have to allow a potentially-unbounded number of threads.
One option is that the delete this here is not a code smell. At most, it should be wrapped into a small library that would detect if all the continuation callbacks were destroyed without calling done_().
I get a warning C4355: 'this' : used in base member initializer list from Visual C++ 2010:
I have a class holding a handle, and I want to automatically close the handle even if the ctor for the class fails (so its dtor is not called). However, I don't want to bother making a whole handle-wrapping class, and would rather hold it in a smart pointer. And so I wrote this:
foo.h
~~~~~
class Foo
{
...
Log &_log;
std::unique_ptr<void, std::function<void (void *)>> _handle;
...
}
foo.cpp
~~~~~~~
#include <windows.h>
Foo::Foo(Log &lg, ...) : _log(lg), ... _handle(nullptr, [&](void *h){ if (h) { if (!CloseHandle(h)) LOG(_log, "Could not close port: " << LastWinErr()); h = nullptr; } })
{
HANDLE h(CreateFile( ...
if (h == ...
_handle.reset(h);
... // Bunch of other stuff that could potentially throw
}
Previously to the closure I was initializing _handle with something like _handle(nullptr, bind(PortDeleter, placeholders::_1, ref(_log))), but that requires a separate definition.
My questions: is the warning a concern for this specific instance? Either way, what is the detailed reason? Is there a trivial way to avoid it?
The short is, if you pass your this pointer around and it's used to access member functions or variables in the initializer list or in the destructor, Bad Things Happen™. If you know that isn't going to happen, then feel free to ignore the warning. Of course, it's also a good warning- if any of the functions or variables that you access in the destructor belong to the class, then this is unsafe, as you may be accessing them prior to their construction/after their destruction. The problem is not critical if you know your initialization/destruction orders, but generally a bad move as this makes maintenance rather fiddly at best. As you could capture the constructor parameter instead, I'd have to recommend that.