I'm running into a problem where I can't get rid of the last shared pointer and I kinda need it actually.
So what I have is a manager and some worker threads. The manager keeps a collection of shared pointers to different resources. A worker may ask the manager for a shared pointer to a resource. There will always be 1 or more workers with a shared pointer to the resource. My end goal is that when all workers are done with the resource, the resource is deleted. However, in this scheme, the manager always maintains a shared pointer to the resource so even when no workers are hanging on to the shared pointer, the resource won't get deleted b/c the ref count should always be at least 1 since the manager is hanging onto it. I need the manager to hang on to a shared pointer to the reference so that if any worker comes asking for a shared pointer, the manager will be able to provide it one.
edit: When the resource is created a worker already has it. So at its creation its ref count should be two (manager has it, and a single worker has it). When the ref count hits one (only the manager has it), I would like it to be deleted. If the resource had already been deleted and a worker comes looking for it, the resource shall be recreated.
edit2: some code:
SomeSharedPointer Manager::getResource(String unique_id)
{ // if unique id exists, return its mapped shared pointer, if unique id doesn't exist, create the resource, assign it a shared pointer, and stick it in the map
}
class Worker
{
SomeSharedPointer my_sp;
Worker()
{
String someUniqueId = "http://blah.com"
my_sp = Manager::getResource(someUniqueId);
// do some work on the resource
}
~Worker()
{
my_sp.reset(); // done with resource
}
}
Why is the manager holding a shared_ptr (strong reference) to the object if it doesn't need to retain control, only pass it on? Not seeing your code, it seems like having the manager hold a weak_ptr and then pass that on to the workers, who lock it into a shared_ptr on their end. That will allow the manager to pass on references without owning one of its own.
class Worker
{
SomeSharedPointer my_sp;
Worker()
{
String someUniqueId = "http://blah.com"
weak_ptr wp = Manager::getResource(someUniqueId);
my_sp = wp.lock();
// do some work on the resource
}
~Worker()
{
//my_sp.reset(); // handled automatically, as part of how shared pointers work
}
}
If a worker finishes and releases the resource, it will be destroyed and the manager will no longer be able to hand out references (which can be tested in getResource and reloaded). This doesn't seem quite optimal, but is part of your design, so it should work like that well.
Edit: You could also have getResource return a shared pointer, and have the manager hold the weak pointer, attempt to lock, do checking/reloading internally, and then return the shared pointer. As weak_ptrs can't be directly created, that may work somewhat better.
On the other hand, you could provide a function to compliment the one providing the workers with the pointer that releases it and does count checking in the manager.
Use a weak pointer in the manager and shared pointer in the workers, when a worker comes asking for the pointer create a shared pointer using the lock method.
as in boost::shared_ptr fptr = weakfoo.lock();
if shared pointer is empty, the pointer has either been released by the last worker or has not been created yet and needs creating
I would definitely avoid any solutions that involve looking at the ref count... only pain will ensue :)
I think the following is key:
I need the manager to hang on to a shared pointer to the reference so that if any worker comes asking for a shared pointer, the manager will be able to provide it one.
You need to decide at which point no more workers can come asking for the shared pointer. Once you know that's the case, the master can simply reset its instance of the shared pointer, thereby releasing the reference.
Related
I have a resource managed by an external system with the following API:
struct api {
resource* acquire();
void release(resource*);
};
My code requires to temporarily share one of these resources across multiple threads, so I need to put the resource in a shared_ptr to get a reference count:
std::shared_ptr<resource> res = m_api.acquire();
This API requires the resources being freed from the same thread in which they were acquired.
My problem is giving it back when all the threads are done with that resource, as std::shared_ptr does not have release.
1/ I cannot just let the pointers wither on their own when they aren't used as I don't know which thread will be the last if I do that (and it needs to be the main thread).
2/ I need to add a custom deleter which stores a api*, which is too costly in this case - I can already barely afford a "simple" std::shared_ptr with its default deleter.
What are my solutions, if possible without having to reimplement an atomic reference count myself ?
I am running a thread pool where a function that is being called in the threads needs the mongocxx::pool pool variable so it can call pool.acquire() to get a client. I can't seem to pass the pool variable. How can I pass the pool variable. Or can I some how make pool global through out my application?
I am following this example https://github.com/mongodb/mongo-cxx-driver/blob/master/examples/mongocxx/pool.cpp
The mongocxx::pool class isn't copyable, so you can't pass it around (though you could std::move it around, though that probably is not useful for your case). If you want a shared instance, you need to keep it on the heap and provide a way for different parts of the code to access that shared resource, perhaps via shared_ptr. Have a look at the instance_management example in the sources for one example of how to manage a pool, via a singleton.
I have a class which calls an asynchronous task using std::async in his constructor for loading its content. ( I want the loading of the object done asynchronously )
The code looks like this:
void loadObject(Object* object)
{
// ... load object
}
Object::Object():
{
auto future = std::async(std::launch::async, loadObject, this);
}
I have several instances of these objects getting created and deleted on my main thread, they can get deleted any time, even before their loading has finished.
I'd like to know if it is dangerous to having object getting destroyed when it is still getting handled on another thread. And how can I stop the thread if the object gets destroyed ?
EDIT: The std::future destructor does not block my code with the VS2013's compiler that I am using due to a bug.
As MikeMB already mentioned, your constructor doesn't finish until the load has been completed. Check this question for how to overcome that: Can I use std::async without waiting for the future limitation?
I'd like to know if it is dangerous to having object getting destroyed when it is still getting handled on another thread.
Accessing object's memory after deletion is certainly dangerous, yes. The behaviour will be undefined.
how can I stop the thread if the object gets destroyed ?
What I recommend you to take care of first, is to make sure that the object doesn't get destroyed while it's still being pointed at by something that is going to use it.
One approach is to use a member flag signifying completed load that is updated in the async task and checked in the destructor and synchronize the access with a condition variable. That will allow the destructor to block until the async task is complete.
Once you've managed to prevent the object from being destroyed, you can use another synchronized member flag to signify that the object is being destroyed and skip the loading if it's set. That'll add synchronization overhead but may be worth it if loading is expensive.
Another approach which avoids blocking destructor is to pass a std::shared_ptr to the async task and require all Object instances to be owned by a shared pointer. That limitation may not be very desireably and you'll need to inherit std::enable_shared_from_this to get the shared pointer in the constructor.
There is nothing asynchronous happening in your code, because the constructor blocks until loadObject() returns (The destructor of a future returned by std::async implicitly joins).
If it would not, it would depend on how you have written your code (and especially your destructor), but most probably, your code would incur undefined behavior.
Yes it is dangerous to having object getting destroyed when it is still getting handled on another thread
You can implement a lot of strategies actually depending on requirements and desired behaviour.
I would implement sort of pimpl strategy here, that means that all actual data will be stored in the pointer that your object holds. You will load all the data to the data-pointer-object and store it in the public-object atomically.
Techincally speaking object should be fully constrcuted and ready to use by the time the constrcutor is finished. In your case data-pointer-object will still probably be not ready to use. And you should make your class to handle correctly that state.
So here we go:
class Object
{
std::shared_ptr<Object_data> d;
Object::Object():
d(std::make_shared<Object_data>())
{
some_futures_matser.add_future(std::async(std::launch::async, loadObject, d));
}
}
Then you make atomic flag in your data-object that will signal that loading is complete and object is ready to use.
class Object_data
{
// ...
std::atomic<bool> loaded {false};
};
loadObject(std::shared_ptr<Object_data> d)
{
/// some load code here
d->loaded = true;
}
You have to check if your object is constrcuted every time when you acces it (with thread safe way) through loaded flag
I've got a "config" class that has a bunch of attributes that "mirror" configuration settings. A single instance of the class is shared throughout the code (using boost shared_ptr objects) and its attributes read by multiple threads (around 100).
Occasionally, the settings may change and a "monitor" thread updates the appropriate attributes in the object.
For integer and bool attributes, I'm using boost atomic so that when an update happens and the monitor thread sets the value, none of the read threads read it in a partially updated state.
However, for string attributes, I'm worried that making them atomic would hurt performance significantly. It seems like a good way to do it would be to have the string attributes actually be pointers to strings, and then when an update happens, a new string object could be built, and then the write to the shared object (the string pointer) would only be writing the address of the new string object to point to. So I assume that write time would be far shorter than writing a whole new string value to a shared string object.
Doing that, however, means I think I'd want to use shared_ptrs for the string attribs, so that a string object holding the previous value is automatically deleted once all read threads are using the updated string pointer attribute.
So to give an example:
class Config
{
public:
boost::atomic<boost::shared_ptr<std::string> > configStr1;
void updateValueInMonitorThread(std::string newValue)
{
boost::shared_ptr<string> newValuePtr;
newValuePtr = newValue;
configStr1 = newValuePtr;
}
};
void threadThatReadsConfig(boost::shared_ptr<Config> theConfig)
{
std::map<std::string, std::string> thingImWorkingOn;
thingImWorkingOn[*(theConfig->configStr1.load())] = "some value";
}
Is that overkill? Is there a better way to do it? I really don't like the way the reading threads have to access the value by dereferencing it and calling .load(). Also, is it even threadsafe, or does that stuff actually negate the safety features of the atomic and/or shared_ptr type?
I know I could use a mutex and read lock it when accessed in a "getter" and write lock it when the monitor thread updates the string's value, but I'd like to avoid that as I'm trying to keep the config class simple and it's going to have dozens, possibly hundreds of these string attributes.
Thanks in advance for any suggestions/info!
You are already giving each consumer a shared_ptr to the configuration object. So the threads won't notice if the configuration object isn't always the same object.
That is, when the main configuration changes, generate an entirely new configuration object. That seems like a lot of copying, but I'll bet it happens sufficiently rarely that you won't notice the overhead. Then you can swap the new configuration object in for the old one, and when all the consumers of the old object finish with it, it will disappear.
Obviously, this changes the semantics of the use of a configuration object. A long-running thread which would like to be able to notice configuration changes will have to periodically refresh its configuration object. The easiest way to do that would be just to acquire a new configuration object on every use of configuration data; again, that's unlikely to be too expensive, unless you use a configuration string in a hard loop.
On the plus side, you can make the entire configuration object const, which might allow for some optimizations.
The classical method of using mutex variables to set a lock on shared resources (here your string objects) is not only the best but the most efficient way of handling such situations, otherwise you may get into trouble because of incomplete protection or you may end-up with a solution that has more overhead. In some applications you may improve efficiency by using separate mutex locks for separate objects so that if an object is updating, others remain accessible.
I have an object (Client * client) which starts multiple threads to handle various tasks (such as processing incoming data). The threads are started like this:
// Start the thread that will process incoming messages and stuff them into the appropriate queues.
mReceiveMessageThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)receiveRtpMessageFunction, this, 0, 0);
These threads all have references back to the initial object, like so:
// Thread initialization function for receiving RTP messages from a newly connected client.
static int WINAPI receiveRtpMessageFunction(LPVOID lpClient)
{
LOG_METHOD("receiveRtpMessageFunction");
Client * client = (Client *)lpClient;
while(client ->isConnected())
{
if(client ->receiveMessage() == ERROR)
{
Log::log("receiveRtpMessageFunction Failed to receive message");
}
}
return SUCCESS;
}
Periodically, the Client object gets deleted (for various good and sufficient reasons). But when that happens, the processing threads that still have references to the (now deleted) object throw exceptions of one sort or another when trying to access member functions on that object.
So I'm sure that there's a standard way to handle this situation, but I haven't been able to figure out a clean approach. I don't want to just terminate the thread, as that doesn't allow for cleaning up resources. I can't set a property on the object, as it's precisely properties on the object that become inaccessible.
Thoughts on the best way to handle this?
I would solve this problem by introducing a reference count to your object. The worker thread would hold a reference and so would the creator of the object. Instead of using delete, you decrement from the reference count and whoever drops the last reference is the one that actually calls delete.
You can use existing reference counting mechanisms (shared_ptr etc.), or you can roll your own with the Win32 APIs InterlockedIncrement() and InterlockedDecrement() or similar (maybe the reference count is a volatile DWORD starting out at 1...).
The only other thing that's missing is that when the main thread releases its reference, it should signal to the worker thread to drop its own reference. One way you can do this is by an event; you can rewrite the worker thread's loop as calls to WaitForMultipleObjects(), and when a certain event is signalled, you take that to mean that the worker thread should clean up and drop the reference.
You don't have much leeway because of the running threads.
No combination of shared_ptr + weak_ptr may save you... you may call a method on the object when it's valid and then order its destruction (using only shared_ptr would).
The only thing I can imagine is to first terminate the various processes and then destroy the object. This way you ensure that each process terminate gracefully, cleaning up its own mess if necessary (and it might need the object to do that).
This means that you cannot delete the object out of hand, since you must first resynchronize with those who use it, and that you need some event handling for the synchronization part (since you basically want to tell the threads to stop, and not wait indefinitely for them).
I leave the synchronization part to you, there are many alternatives (events, flags, etc...) and we don't have enough data.
You can deal with the actual cleanup from either the destructor itself or by overloading the various delete operations, whichever suits you.
You'll need to have some other state object the threads can check to verify that the "client" is still valid.
One option is to encapsulate your client reference inside some other object that remains persistent, and provide a reference to that object from your threads.
You could use the observer pattern with proxy objects for the client in the threads. The proxies act like smart pointers, forwarding access to the real client. When you create them, they register themselves with the client, so that it can invalidate them from its destructor. Once they're invalidated, they stop forwarding and just return errors.
This could be handled by passing a (boost) weak pointer to the threads.