I have a class which stores a callback in std::function
and does some operations then notify the callback target with the results . if the target sees the results invaild or doesn't want to continue doing the work it will delete the caller class which contains the std::function
callback .
I know if std::function
doesn't access its members after deletetion this will be safe but I didin't see such guarantee . The thing I have is that the caller class doesn't access its members after invoking the callback , but the callback can choose to do more work again and in this case it won't delete the caller .
this example illustrates the problem :
using callback = std::function<void(Caller& c, bool failed)>;
class Caller
{
callback cb;
bool Work()
{
return true;
}
public:
Caller(const callback& cb) : cb{ cb } {}
void DoWork()
{
bool result = Work();
cb(*this, result);
}
};
int main(int argc, char **argv)
{
for (int i = 0; i < 1000; ++i)
{
Caller *c = new Caller{
[](Caller& c, bool failed)
{
if (failed)
delete &c;
else
c.DoWork();
}
};
c->DoWork();
}
}
I compiled the code on windows using msvc and it's working without issuses (or may be some hidden heap corruption ?)
I don't want suggestion to use another design as the real code I'm using is complicating and the caller class is like a proky between the worker and the callback and is allocated per operation , also refactoring the code will be much work
EDIT : I know it is'nt the best c++ practice but I'm dealing with c api particularly iocp. my code works like this : the io object (socket) issue an io request which requires allocating memory for the overlapped structure and op data , this structure will hold the callback and when the op is done it will invoke the callback and if there is an error the callback may not continue otherwise it will issue the next request . after invoking the callback the structure will delete itself and the new operation started from the callback will continue like this .
now suppose I have a sessionn of half-duplex protocol, like http, then there is only one operation at a time so I may use the same stucture for all operations without allocating again , so when the second operation starts I destruct the old strucutre and construct in place the new one and this is done inside the callback of the first structre