Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
SharedMemoryStream.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Streams_SharedMemoryStream_h_
5#define _Stroika_Foundation_Streams_SharedMemoryStream_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <vector>
10
12#include "Stroika/Foundation/Common/Common.h"
15
16/*
17 * \file
18 *
19 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
20 */
21
22namespace Stroika::Foundation::Streams::SharedMemoryStream {
23
24 template <typename ELEMENT_TYPE>
25 class Ptr;
26
27 /**
28 * \brief Options to configure a new SharedMemoryStream; defaults should always work fine, but options can allow for better performance (at a loss of some functionality)
29 */
30 struct Options {
31 /**
32 * \brief controls if the shared stream is automatically synchronized internally so that it can be used by two different threads safely, without any locking (applies to letter, not envelope of shared_ptr)
33 */
34 Execution::InternallySynchronized fInternallySynchronized{Execution::InternallySynchronized::eInternallySynchronized};
35
36 /**
37 * \brief Controls if the SharedMemoryStream maintains history. Doing so allows the Ptr<>::As<> methods to work. Not doing so, allows potentially significant memory savings on larger streams.
38 */
39 bool fSeekable{true};
40 };
41
42 /**
43 * \brief SharedMemoryStream<> is an InputOutputStream<> like MemoryStream<>, but supporting concurrency (like an in memory structured pipe)
44 *
45 * SharedMemoryStream is Seekable by default (see Options::fSeekable)
46 *
47 * Since SharedMemoryStream keeps its (reachable) data all in memory, it has the limitation that
48 * attempts to seek or write more than will fit in RAM will fail (with an exception).
49 *
50 * \note SharedMemoryStream is suitable for synchronized reading and writing between two threads (producer / consumer pattern).
51 * Reads will block at the end of the stream until some thread calls SharedMemoryStream><>::CloseWrite ()
52 *
53 * @see MemoryStream
54 *
55 * \note SharedMemoryStreams is seekable by default, but if options are specified to allow it to not be seekable, it may save some memory on
56 * larger streams.
57 *
58 * @see ExternallyOwnedMemoryInputStream
59 *
60 * \par Example Usage
61 * \code
62 * SharedMemoryStream::Ptr<unsigned int> pipe = SharedMemoryStream::New<unsigned int> ();
63 * unsigned sum{};
64 * static constexpr unsigned int kStartWith{1};
65 * static constexpr unsigned int kUpToInclusive_{1000};
66 * Thread::Ptr consumer = Thread::New ([&]() {
67 * while (auto o = pipe.Read ()) {
68 * sum += *o;
69 * }
70 * },
71 * Thread::eAutoStart);
72 * Thread::Ptr producer = Thread::New ([&]() {
73 * for (unsigned int i = kStartWith; i <= kUpToInclusive_; ++i) {
74 * pipe.Write (i);
75 * };
76 * pipe.CloseWrite (); // critical or consumer hangs on final read
77 * },
78 * Thread::eAutoStart);
79 * Thread::WaitForDone ({consumer, producer});
80 * Assert (sum == (1 + kUpToInclusive_) * (kUpToInclusive_ - 1 + 1) / 2); // not a race
81 * \endcode
82 *
83 * \note \em Thread-Safety <a href='#C++-Standard-Thread-Safety-For-Envelope-Letter-Internally-Synchronized'>C++-Standard-Thread-Safety-For-Envelope-Letter-Internally-Synchronized</a> OR
84 * <a href='#C++-Standard-Thread-Safety-For-Envelope-Plus-Must-Externally-Synchronize-Letter'>C++-Standard-Thread-Safety-For-Envelope-Plus-Must-Externally-Synchronize-Letter</a>
85 * depending on Options object provided to New ()
86 */
87 template <typename ELEMENT_TYPE>
88 Ptr<ELEMENT_TYPE> New (Options options = {});
89 template <typename ELEMENT_TYPE, typename COPY_FROM>
90 Ptr<ELEMENT_TYPE> New (const COPY_FROM& copyFrom, Options options = {})
91 requires (same_as<ELEMENT_TYPE, byte> and Common::IAnyOf<COPY_FROM, Memory::BLOB, span<const ELEMENT_TYPE>>);
92
93 namespace Private_ {
94 template <typename ELEMENT_TYPE>
95 class IRep_;
96 }
97
98 /**
99 * Ptr is a copyable smart pointer to a SharedMemoryStream.
100 *
101 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter">C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter/a>
102 */
103 template <typename ELEMENT_TYPE>
104 class Ptr : public InputOutputStream::Ptr<ELEMENT_TYPE> {
105 private:
106 using inherited = typename InputOutputStream::Ptr<ELEMENT_TYPE>;
107
108 public:
109 /**
110 */
111 Ptr () = default;
112 Ptr (const Ptr& from) = default;
113 Ptr (const shared_ptr<Private_::IRep_<ELEMENT_TYPE>>& from);
114
115 public:
116 nonvirtual Ptr& operator= (const Ptr& rhs) = default;
117
118 public:
119 /**
120 */
121 nonvirtual Options GetOptions () const;
122
123 public:
124 /**
125 * Convert the current contents of this SharedMemoryStream into one of the "T" representations.
126 *
127 * Only specifically specialized variants are supported. T can be one of:
128 * o vector<ElementType>
129 *
130 * And if ElementType is byte, then T can also be one of:
131 * o Memory::BLOB
132 * o string
133 *
134 * And if ElementType is Characters::Character, then T can also be one of:
135 * o String
136 *
137 * \pre GetOptions ().fSeekable
138 */
139 template <typename T>
140 nonvirtual T As () const
141 requires (same_as<T, vector<ELEMENT_TYPE>> or (same_as<ELEMENT_TYPE, byte> and Common::IAnyOf<T, Memory::BLOB, string>) or
142 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<T, Characters::String>));
143
144 private:
145 /**
146 * \pre *this != nullptr
147 */
148 nonvirtual const Private_::IRep_<ELEMENT_TYPE>& GetRepConstRef_ () const;
149
150 private:
151 friend class SharedMemoryStream;
152 };
153
154}
155
156/*
157 ********************************************************************************
158 ***************************** Implementation Details ***************************
159 ********************************************************************************
160 */
161#include "SharedMemoryStream.inl"
162
163#endif /*_Stroika_Foundation_Streams_SharedMemoryStream_h_*/
InputOutputStream is single stream object that acts much as a InputStream::Ptr and an OutputStream::P...
A Streams::Ptr<ELEMENT_TYPE> is a smart-pointer to a stream of elements of type T.
Definition Stream.h:170
Options to configure a new SharedMemoryStream; defaults should always work fine, but options can allo...
Execution::InternallySynchronized fInternallySynchronized
controls if the shared stream is automatically synchronized internally so that it can be used by two ...
bool fSeekable
Controls if the SharedMemoryStream maintains history. Doing so allows the Ptr<>::As<> methods to work...