I need to spawn a thread when a certain trigger event is received inside of a class Foo. The trigger event is received by a Winsock server class that has a reference to the variable triggerEvent
.
bool Foo::HandleEvents()
{
while (1)
{
// Other things are done at the top of this loop
switch (triggerEvent)
{
case 'h':
{
// I instantiate an object here to do
// what I need to do in the thread.
// I use a pointer that is a private
// member of Foo.
thingMaker = new ThingMaker(params);
// Spawn a new thread here calling a
// function of ThingMaker and using thingMaker
break;
}
case ...: return true;
default: break;
}
}
}
Since the thread is local to its case in the switch
, I lose access to it on break
. I can't call join()
because I'm dealing with real-time processing and cannot wait for the thread to finish unless I know it's already done.
I recently asked a question about threading here regarding the same application and was told detach()
is bad practice; I also think my question was too vague as the solution offered ended up not fitting my needs and my application has since changed in architecture.
I have also tried to encapsulate the thread in short-life manager class that creates instances of ThingMaker but to no avail.
How do I go about this? I suspect my main issue is scope, but my options are limited. Foo::HandleEvents()
cannot be delayed at all or else I lose critical data.
You could use a std::map
(or one of the other similar containers):
class Foo
{
bool HandleEvents();
std::map<ThingMaker*, std::thread> m_map;
};
bool Foo::HandleEvents()
{
while (1)
{
switch (triggerEvent)
{
case 'h':
{
thingMaker = new ThingMaker(params);
m_map[thingMaker] = std::thread(function_ptr, thingMaker);
} break;
case 't': // termination event trigger
{
m_map[thingMaker].second.join();
m_map.erase(thingMaker);
delete thingMaker;
} break;
case ...: return true;
default: break;
}
}
}
Since this obviously isn't your full code you'd have to adjust the above code to fit your needs, but you could swap the map's key/value in the template, or use the thread ID instead if that would make more sense (e.g. std::map<std::thread::id, ThingMaker*>
, etc.), but something like a map
avoids iterating over an array and join
ing on each thread or having to implement a full thread pool implementation if you don't necessarily need one.
Side note: the use of detach
is not bad, in fact it's quite useful; detaching a thread signals to the kernel that the thread can be "cleaned up" as soon as it's done executing (which releases certain resources and handles). Calling detach
on a thread is useful when you know you will no longer need access to the underlying thread handle (like in an extremely short lived thread). It's neither bad nor good, simply a tool to utilize (like the infamous goto
statement).
Hope that can help.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments