11
22namespace winrt ::impl
33{
4- template <typename Container>
4+ template <typename T, typename Container>
5+ using multi_threaded_vector = vector_impl<T, Container, multi_threaded_collection_base>;
6+
7+ template <typename Container, typename ThreadingBase = single_threaded_collection_base>
58 struct inspectable_observable_vector :
6- observable_vector_base<inspectable_observable_vector<Container>, Windows::Foundation::IInspectable>,
7- implements<inspectable_observable_vector<Container>,
8- wfc::IObservableVector<Windows::Foundation::IInspectable>, wfc::IVector<Windows::Foundation::IInspectable>, wfc::IVectorView<Windows::Foundation::IInspectable>, wfc::IIterable<Windows::Foundation::IInspectable>>
9+ observable_vector_base<inspectable_observable_vector<Container, ThreadingBase>, Windows::Foundation::IInspectable>,
10+ implements<inspectable_observable_vector<Container, ThreadingBase>,
11+ wfc::IObservableVector<Windows::Foundation::IInspectable>, wfc::IVector<Windows::Foundation::IInspectable>, wfc::IVectorView<Windows::Foundation::IInspectable>, wfc::IIterable<Windows::Foundation::IInspectable>>,
12+ ThreadingBase
913 {
1014 static_assert (std::is_same_v<Container, std::remove_reference_t <Container>>, " Must be constructed with rvalue." );
1115
@@ -23,23 +27,30 @@ namespace winrt::impl
2327 return m_values;
2428 }
2529
30+ using ThreadingBase::acquire_shared;
31+ using ThreadingBase::acquire_exclusive;
32+
2633 private:
2734
2835 Container m_values;
2936 };
3037
31- template <typename T, typename Container>
38+ template <typename Container>
39+ using multi_threaded_inspectable_observable_vector = inspectable_observable_vector<Container, multi_threaded_collection_base>;
40+
41+ template <typename T, typename Container, typename ThreadingBase = single_threaded_collection_base>
3242 struct convertible_observable_vector :
33- observable_vector_base<convertible_observable_vector<T, Container>, T>,
34- implements<convertible_observable_vector<T, Container>,
43+ observable_vector_base<convertible_observable_vector<T, Container, ThreadingBase >, T>,
44+ implements<convertible_observable_vector<T, Container, ThreadingBase >,
3545 wfc::IObservableVector<T>, wfc::IVector<T>, wfc::IVectorView<T>, wfc::IIterable<T>,
36- wfc::IObservableVector<Windows::Foundation::IInspectable>, wfc::IVector<Windows::Foundation::IInspectable>, wfc::IVectorView<Windows::Foundation::IInspectable>, wfc::IIterable<Windows::Foundation::IInspectable>>
46+ wfc::IObservableVector<Windows::Foundation::IInspectable>, wfc::IVector<Windows::Foundation::IInspectable>, wfc::IVectorView<Windows::Foundation::IInspectable>, wfc::IIterable<Windows::Foundation::IInspectable>>,
47+ ThreadingBase
3748 {
3849 static_assert (!std::is_same_v<T, Windows::Foundation::IInspectable>);
3950 static_assert (std::is_same_v<Container, std::remove_reference_t <Container>>, " Must be constructed with rvalue." );
4051
41- using container_type = convertible_observable_vector<T, Container>;
42- using base_type = observable_vector_base<convertible_observable_vector<T, Container>, T>;
52+ using container_type = convertible_observable_vector<T, Container, ThreadingBase >;
53+ using base_type = observable_vector_base<convertible_observable_vector<T, Container, ThreadingBase >, T>;
4354
4455 explicit convertible_observable_vector (Container&& values) : m_values(std::forward<Container>(values))
4556 {
@@ -55,6 +66,9 @@ namespace winrt::impl
5566 return m_values;
5667 }
5768
69+ using ThreadingBase::acquire_shared;
70+ using ThreadingBase::acquire_exclusive;
71+
5872 auto First ()
5973 {
6074 struct result
@@ -68,6 +82,7 @@ namespace winrt::impl
6882
6983 operator wfc::IIterator<Windows::Foundation::IInspectable>()
7084 {
85+ auto guard = container->acquire_shared ();
7186 return make<iterator>(container);
7287 }
7388 };
@@ -115,6 +130,7 @@ namespace winrt::impl
115130
116131 uint32_t GetMany (uint32_t const startIndex, array_view<Windows::Foundation::IInspectable> values) const
117132 {
133+ auto guard = this ->acquire_shared ();
118134 if (startIndex >= m_values.size ())
119135 {
120136 return 0 ;
@@ -202,11 +218,6 @@ namespace winrt::impl
202218 impl::collection_version::iterator_type,
203219 implements<iterator, Windows::Foundation::Collections::IIterator<Windows::Foundation::IInspectable>>
204220 {
205- void abi_enter ()
206- {
207- check_version (*m_owner);
208- }
209-
210221 explicit iterator (container_type* const container) noexcept :
211222 impl::collection_version::iterator_type(*container),
212223 m_current(container->get_container ().begin()),
@@ -217,6 +228,8 @@ namespace winrt::impl
217228
218229 Windows::Foundation::IInspectable Current () const
219230 {
231+ auto guard = m_owner->acquire_shared ();
232+ check_version (*m_owner);
220233 if (m_current == m_end)
221234 {
222235 throw hresult_out_of_bounds ();
@@ -225,23 +238,29 @@ namespace winrt::impl
225238 return box_value (*m_current);
226239 }
227240
228- bool HasCurrent () const noexcept
241+ bool HasCurrent () const
229242 {
243+ auto guard = m_owner->acquire_shared ();
244+ check_version (*m_owner);
230245 return m_current != m_end;
231246 }
232247
233- bool MoveNext () noexcept
248+ bool MoveNext ()
234249 {
250+ auto guard = m_owner->acquire_exclusive ();
251+ check_version (*m_owner);
235252 if (m_current != m_end)
236253 {
237254 ++m_current;
238255 }
239256
240- return HasCurrent () ;
257+ return m_current != m_end ;
241258 }
242259
243260 uint32_t GetMany (array_view<Windows::Foundation::IInspectable> values)
244261 {
262+ auto guard = m_owner->acquire_exclusive ();
263+ check_version (*m_owner);
245264 uint32_t const actual = (std::min)(static_cast <uint32_t >(std::distance (m_current, m_end)), values.size ());
246265
247266 std::transform (m_current, m_current + actual, values.begin (), [&](auto && value)
@@ -262,6 +281,9 @@ namespace winrt::impl
262281
263282 Container m_values;
264283 };
284+
285+ template <typename T, typename Container>
286+ using multi_threaded_convertible_observable_vector = convertible_observable_vector<T, Container, multi_threaded_collection_base>;
265287}
266288
267289WINRT_EXPORT namespace winrt
@@ -272,6 +294,12 @@ WINRT_EXPORT namespace winrt
272294 return make<impl::input_vector<T, std::vector<T, Allocator>>>(std::move (values));
273295 }
274296
297+ template <typename T, typename Allocator = std::allocator<T>>
298+ Windows::Foundation::Collections::IVector<T> multi_threaded_vector (std::vector<T, Allocator>&& values = {})
299+ {
300+ return make<impl::multi_threaded_vector<T, std::vector<T, Allocator>>>(std::move (values));
301+ }
302+
275303 template <typename T, typename Allocator = std::allocator<T>>
276304 Windows::Foundation::Collections::IObservableVector<T> single_threaded_observable_vector (std::vector<T, Allocator>&& values = {})
277305 {
@@ -284,4 +312,17 @@ WINRT_EXPORT namespace winrt
284312 return make<impl::convertible_observable_vector<T, std::vector<T, Allocator>>>(std::move (values));
285313 }
286314 }
315+
316+ template <typename T, typename Allocator = std::allocator<T>>
317+ Windows::Foundation::Collections::IObservableVector<T> multi_threaded_observable_vector (std::vector<T, Allocator>&& values = {})
318+ {
319+ if constexpr (std::is_same_v<T, Windows::Foundation::IInspectable>)
320+ {
321+ return make<impl::multi_threaded_inspectable_observable_vector<std::vector<T, Allocator>>>(std::move (values));
322+ }
323+ else
324+ {
325+ return make<impl::multi_threaded_convertible_observable_vector<T, std::vector<T, Allocator>>>(std::move (values));
326+ }
327+ }
287328}
0 commit comments