Stroika classes respect several different levels of thread safety:
This is by FAR the most common, and represents how the C++ standard library approaches thread safety.
Internally-Synchronized-Thread-Safety
Certain utiltiies that are meant for sharing data between threads, manage their state/syncrhonization fully internally.
C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter
Standard C++ thread safety for the envelope, but whether underlying shared rep is synchronized depends on how that rep was allocated.
From [ http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3690.pdf section 17.6.5.9 /3 ]
A C++ standard library function shall not directly or indirectly modify objects (1.10) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function's non-const arguments, including this.
So basically this means you can call multiple read operations on the object without concern (threadsafe), but mixing read and write must be somehow externally synchronized (suggestion - see Execution::Synchronized<>, or std::mutex<>)
Most Stroika code follows this principle.
Most such Stroika classes also protect their internal representation integrity with Debug::AssertExternallySynchronized in Debug builds
Callers can freely mix readers and writers. The class automatically manages assuring maintainance of a consistent internal state.
Note also that this automatic synchonization MAY be maintained using mutexes, or possibly via transactional memories, or other techniques.
This (the envelope 'Ptr' class) has all the constraints of C++-Standard-Thread-Safety.
The underlying rep stream is internally synchronized, so it can be used safely from multiple threads, without any additional checking/worries.
This (the envelope 'Ptr' class) has all the constraints of C++-Standard-Thread-Safety.
Plus, the caller must somehow arrange to synchonize access to the underlying object pointed to by the Ptr. So if the underlying object (e.g. Stream) is shared (more than one thread accessing a copy of its rep) the caller must somehow synchonize those accesses.
Typically the rep will check via Debug::AssertExternallySynchronized.
This (the envelope 'Ptr' class) has all the constraints of C++-Standard-Thread-Safety.
This threadsafety means the object is:
You just cannot tell which based on the type itself (you need to know the type of the underlying contained letter object).
If or the type of syncrhonization required on the underlying 'letter' or 'rep' depends on the source of that object. See the OBJECT::New () static method used to construct that shared rep object.
template <typename ELEMENT_TYPE> class InputStream<ELEMENT_TYPE>::Ptr
The underlying shared part of the input stream could be internally synhconized or not, depending on how it was created.
For this abstract class, the thread safety rules are left ambiguous. The type of syncrhonization required for this object depends on the (concrete) subtype.
Depending on the subclass, this might be:
template <typename ELEMENT_TYPE> class OutputStream<ELEMENT_TYPE>::_IRep;
Some sub-types will be internally syncrhonized, and others C++-Standard-Thread-Safety