Is boost::object_pool synchronized?
C++ doesn't specify anything about thread-safety, so if it isn't mentioned it likely doesn't deal with threading. Sometimes, Boost provides things that can be thread-safe out of the box, this is not one of them.
Wrap access to the pool in a mutex.
boost::object_pool is not synchronized for concurrent access and freeing of objects to and from pool. but if you want pool with synchronization, singleton_pool from boost is the one. There are few restrictions on how to start using singleton_pool, but they are pretty fair and applicable for all applications. Please see below notes from boot documentation from here and here.
Object Usage vs. Singleton Usage
Object Usage is the method where each Pool is an object that may be created and destroyed. Destroying a Pool implicitly frees all chunks that have been allocated from it.
Singleton Usage is the method where each Pool is an object with static duration; that is, it will not be destroyed until program exit.
Pool objects with Singleton Usage may be shared; thus, Singleton Usage
implies thread-safety as well. System memory allocated by Pool objects
with Singleton Usage may be freed through release_memory or
purge_memory.
singleton_pool usages restrictions
The underlying pool p referenced by the static functions in singleton_pool is actually declared in a way that it is:
Thread-safe if there is only one thread running before main() begins and after main() ends -- all of the static functions of singleton_pool synchronize their access to p.
Guaranteed to be constructed before it is used -- thus, the simple static object in the synopsis above would actually be an incorrect implementation. The actual implementation to guarantee this is considerably more complicated.
Note that a different underlying pool p exists for each different set of template parameters, including implementation-specific ones.
Related
I want to extend lifetime of the boost::log::core for termination process.
I know that this is not recommended in the documentation. But I tried to use Schwarz counter for core to keep it until last destructor of global variable used it.
Core uses the shared pointer with Meyer's singleton. is it possible to implement Schwarz counter or nifty initialization core ?
The core::get() method returns a shared_ptr to the core, which is what implements the Schwarz counter. You can call this method during the normal operation of the program (i.e. while main() is executing) and save that pointer in your data structures that are guaranteed to be present during termination. While the shared_ptr exists, you can access the core through that pointer (but not necessarily through core::get()).
Note that all loggers provided by the library also save the pointer to the core internally. For example, if you're performing termination in an object destructor, make a logger a member of that object and you will be able to emit simple log records during the destruction.
Note that the core is not the only singleton the library maintains, and other singletons are not protected from destruction by this method. For example, you cannot use global loggers during program termination.
As was previously discussed in this question, a pre-C++11 implementation can execute code in the way when several threads simultaneously call constructor for the same object with static storage duration.
In boost::mutex implementation there's initialize function that is called from its constructor and contains the following code:
void initialize()
{
active_count=0;
event=0;
}
Well, it seems for me that it's UB since we can have situation when several threads simultaneously write 0 to the same memory region, isn't it?
Yes. If you simultaneously construct a mutex in the same memory location from different threads then you're invoking UB.
Of course, that scenario is really really hard to achieve.
Update
Ok, it has become apparent that the question is about initialization of function-local statics pre c++11. Although this has nothing to do with boost::mutex, per se, I can confirm that, indeed, boost::mutex construction is also unsafe for cases like that.
(Mutexes that coordinate access to a shared resource typically need to precede access to the resource. When the mutex itself is a shared resource before it is created, you're doing it wrong.
You need existing synchronization to coordinate access to the are in which you construct new mutexes if you even need to do something like this.)
I am new to multithreading world and started getting into it. I found threading requires synchronization. Volatile is no more a reliable thing. I would like to know if synchronization object are cacheable by compiler or at any stage?
Platform/languages used : c++, win32, Windows
In c++, volatile keyword is used for objects which can not be cached by CPUs. But today's compilers do not strictly follow this. Is there is other way around to make synchronization objects non-cacheable (or other optimizations are not applied on those objects).
tl;dr: Are synchronization objects cacheable? If yes, how can you make it non-cacheable ?
I'm not sure I follow your question: compiler cache has almost nothing to do with multithreading. The only thing that a compiler cache would do is to increase your compilation speed by caching previous compilations.
Synchronization objects can be "cached" since they're any arbitrary object that you've decided to use for synchronization, but that has little effect on concurrency. The only thing that you need to care about when synchronizing is that when you have multiple threads contending for a resource, they must all synchronize on the same object in order to get read/write access to the resource.
I'm going to take a wild guess, based on your mentioning of volatile, and assume that you're worried a synchronization object may be cached in a thread's local cache and changes to the synchronization object from one thread may not be visible to another thread. This, however, is a flawed idea:
When you call lock() or synchronize() (depending on the language), all you need to care about is that the lock is performed on the same object regardless of the internal state of the object.
Once you've acquired a lock on an object, any resource that you're modifying within that lock scope will be modified by only one thread.
Generally, you should use a synchronization object that will not change (ideally a readonly, const or final) and we're only talking about the reference here, not the content of the object itself. Here is an example:
object sync = new object();
string something = "hello":
void ModifySomething()
{
sync = new object();// <-- YOU SHOULD NEVER DO THIS!!
lock(sync)
{
something = GenerateRandomString();
}
}
Now notice that every time a thread calls ModifySomething, the synchronization object will be replaced by an new object and the threads will never synchronize on the same object, therefore there may be concurrent writes to something.
The question doesn't make much sense without specifying a run-time environment.
In the case of, Java, say, a synchronization object (an object used for synchronization) is just like any other object. The object is target of the synchronization, so volatile (which applies to member variables) is only needed if the variable containing the synchronization object can change. I would avoid a program design that needs such constructs.
Remember (again, in Java), it is the evaluation of an expression -- generally a variable access -- that results in the synchronization object to use. This evaluation is no different than any other in this aspect.
At the end of the day, however, it is just using the synchronization tools of a particular run-time/environment in a manner in which they are well-defined and well-behaving.
Happy coding.
Java, for instance, guarantees that synchronized(x) { foo }, where x is a particular object, will create a mutually exclusive critical region in which foo is executed. To do this it must do internal work to ensure the book-keeping data is flushed correctly across all processors/caches. However, these details are generally outside the scope of the run-time in terms of using the synchronization construct.
Synchronization objects are necessarily managed by the OS, which also manages threads and caches. Therefore, it's the OS responsibility to deal with caches. If it somehow knows that a synchronization object is used only on a single CPU (e.g. because it didn't allocate the second CPU to your process), the OS may very well decide to keep the synchronization object in the fist CPU's cache. If it needs to be shared across CPU's, then that will happen too.
One practical consequence is that you'll always initialize synchronization objects. In C++, that's natural (the constructor takes care of that) but in other languages you must explicitly do so. The OS has to keep track of the synchronization objects.
I have the following sample C++ code:
class Factory
{
public:
static Factory& createInstance()
{
static Factory fac;
return fac;
}
private:
Factory()
{
//Does something non-trivial
}
};
Let's assume that createInstance is called by two threads at the same time. So will the resulting object be created properly? What happens if the second thread enters the createInstance call when the first thread is in the constructor of Factory?
C++11 and above: local static creation is thread-safe.
The standard guarantees that:
The creation is synchronized.
Should the creation throws an exception, the next time the flow of execution passes the variable definition point, creation will be attempted again.
It is generally implemented with double-checking:
first a thread-local flag is checked, and if set, then the variable is accessed.
if not yet set, then a more expensive synchronized path is taken, and if the variable is created afterward, the thread-local flag is set.
C++03 and C++98: the standard knows no thread.
There are no threads as far as the Standard is concerned, and therefore there is no provision in the Standard regarding synchronization across threads.
However some compilers implement more than the standard mandates, either in the form of extensions or by giving stronger guarantees, so check out for the compilers you're interested in. If they are good quality ones, chances are that they will guarantee it.
Finally, it might not be necessary for it to be thread-safe. If you call this method before creating any thread, then you ensures that it will be correctly initialized before the real multi-threading comes into play, and you'll neatly side-step the issue.
Looking at this page, I'd say that this is not thread-safe, because the constructor could get called multiple times before the variable is finally assigned. An InterlockedCompareExchange() might be needed, where you create a local copy of the variable, then atomically assign the pointer to a static field via the interlocked function, if the static variable is null.
Of course it's thread safe! Unless you are a complete lunatic and spawn threads from constructors of static objects, you won't have any threads until after main() is called, and the createInstance method is just returning a reference to an already constructed object, there's no way this can fail. ISO C++ guarantees that the object will be constructed before the first use after main() is called: there's no assurance that will be before main is called, but is has to be before the first use, and so all systems will perform the initialisation before main() is called. Of course ISO C++ doesn't define behaviour in the presence of threads or dynamic loading, but all compilers for host level machines provide this support and will try to preserve the semantics specified for singly threaded statically linked code where possible.
The instantiation (first call) itself is threadsafe.
However, subsequent access will not be, in general. For instance, suppose after instantiation, one thread calls a mutable Factory method and another calls some accessor method in Factory, then you will be in trouble.
For example, if your factory keeps a count of the number of instances created, you will be in trouble without some kind of mutex around that variable.
However, if Factory is truly a class with no state (no member variables), then you will be okay.
I have a question about boost::shared_ptr<T>.
There are lots of thread.
using namespace boost;
class CResource
{
// xxxxxx
}
class CResourceBase
{
public:
void SetResource(shared_ptr<CResource> res)
{
m_Res = res;
}
shared_ptr<CResource> GetResource()
{
return m_Res;
}
private:
shared_ptr<CResource> m_Res;
}
CResourceBase base;
//----------------------------------------------
// Thread_A:
while (true)
{
//...
shared_ptr<CResource> nowResource = base.GetResource();
nowResource.doSomeThing();
//...
}
// Thread_B:
shared_ptr<CResource> nowResource;
base.SetResource(nowResource);
//...
Q1
If Thread_A do not care the nowResource is the newest, will this part of code have problem?
I mean when Thread_B do not SetResource() completely, Thread_A get a wrong smart point by GetResource()?
Q2
What does thread-safe mean?
If I do not care about whether the resource is newest, will the shared_ptr<CResource> nowResource crash the program when the nowResource is released or will the problem destroy the shared_ptr<CResource>?
boost::shared_ptr<> offers a certain level of thread safety. The reference count is manipulated in a thread safe manner (unless you configure boost to disable threading support).
So you can copy a shared_ptr around and the ref_count is maintained correctly. What you cannot do safely in multiple threads is modify the actual shared_ptr object instance itself from multiple threads (such as calling reset() on it from multiple threads). So your usage is not safe - you're modifying the actual shared_ptr instance in multiple threads - you'll need to have your own protection.
In my code, shared_ptr's are generally locals or parameters passed by value, so there's no issue. Getting them from one thread to another I generally use a thread-safe queue.
Of course none of this addresses the thread safety of accessing the object pointed to by the shared_ptr - that's also up to you.
From the boost documentation:
shared_ptr objects offer the same
level of thread safety as built-in
types. A shared_ptr instance can be
"read" (accessed using only const
operations) simultaneously by multiple
threads. Different shared_ptr
instances can be "written to"
(accessed using mutable operations
such as operator= or reset)
simultaneously by multiple threads
(even when these instances are copies,
and share the same reference count
underneath.)
Any other simultaneous accesses result in undefined behavior.
So your usage is not safe, since it uses simultaneous read and write of m_res. Example 3 in the boost documentation also illustrates this.
You should use a separate mutex that guards the access to m_res in SetResource/GetResource.
Well, tr1::shared_ptr (which is based on boost) documentation tells a different story, which implies that resource management is thread safe, whereas access to the resource is not.
"...
Thread Safety
C++0x-only features are: rvalue-ref/move support, allocator support, aliasing constructor, make_shared & allocate_shared. Additionally, the constructors taking auto_ptr parameters are deprecated in C++0x mode.
The Thread Safety section of the Boost shared_ptr documentation says "shared_ptr objects offer the same level of thread safety as built-in types." The implementation must ensure that concurrent updates to separate shared_ptr instances are correct even when those instances share a reference count e.g.
shared_ptr a(new A);
shared_ptr b(a);
// Thread 1 // Thread 2
a.reset(); b.reset();
The dynamically-allocated object must be destroyed by exactly one of the threads. Weak references make things even more interesting. The shared state used to implement shared_ptr must be transparent to the user and invariants must be preserved at all times. The key pieces of shared state are the strong and weak reference counts. Updates to these need to be atomic and visible to all threads to ensure correct cleanup of the managed resource (which is, after all, shared_ptr's job!) On multi-processor systems memory synchronisation may be needed so that reference-count updates and the destruction of the managed resource are race-free.
..."
see
http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr
m_Res is not threadsafe ,because it simultaneous read/write,
you need boost::atomic_store/load function to protects it.
//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write
Add, your class has a Cyclic-references condition; the shared_ptr<CResource> m_Res can't be a member of CResourceBase. You can use weak_ptr instead.