1 // Copyright (C) 2018 Intel Corporation
3 // SPDX-License-Identifier: Apache-2.0
6 #include "memory/memory_descriptor_view.hpp"
10 #include <util/algorithm.hpp>
11 #include <util/range.hpp>
12 #include <util/zip_range.hpp>
14 #include "memory/memory_descriptor.hpp"
19 struct MemoryDescriptorView::Connector final
21 // We use linear searches here because number of listeners and views usually
23 struct ListenerDesc final
25 MemoryDescriptorView* owner;
26 std::vector<IMemoryDescriptorViewListener*> listeners;
29 std::vector<ListenerDesc> listeners;
31 struct OwnerComparator final
33 const MemoryDescriptorView* owner;
34 bool operator()(const ListenerDesc& desc) const
36 ASSERT(nullptr != owner);
37 ASSERT(nullptr != desc.owner);
38 return owner == desc.owner;
42 void addListener(MemoryDescriptorView* view, IMemoryDescriptorViewListener* listener)
44 ASSERT(nullptr != view);
45 ASSERT(nullptr != listener);
46 ASSERT(!contains(view, listener));
47 findDesc(view).listeners.push_back(listener);
50 void removeListener(MemoryDescriptorView* view, IMemoryDescriptorViewListener* listener)
52 ASSERT(nullptr != view);
53 ASSERT(nullptr != listener);
54 ASSERT(contains(view, listener));
55 auto& desc = findDesc(view);
56 util::unstable_erase(desc.listeners, util::find(desc.listeners, listener));
57 ASSERT(!contains(view, listener));
60 void onDestroy(MemoryDescriptorView* view)
62 ASSERT(nullptr != view);
63 auto it = util::find_if(listeners, OwnerComparator{view});
64 if (listeners.end() != it)
66 for (auto& listener: it->listeners)
68 ASSERT(nullptr != listener);
71 util::unstable_erase(listeners, it);
75 bool contains(const MemoryDescriptorView* view, const IMemoryDescriptorViewListener* listener) const
77 ASSERT(nullptr != view);
78 ASSERT(nullptr != listener);
79 auto it = util::find_if(listeners, OwnerComparator{view});
80 if (listeners.end() == it)
84 return it->listeners.end() != util::find(it->listeners, listener);
87 ListenerDesc& findDesc(MemoryDescriptorView* view)
89 ASSERT(nullptr != view);
90 auto it = util::find_if(listeners, OwnerComparator{view});
91 if(listeners.end() != it)
95 listeners.push_back(ListenerDesc{view, {}});
96 return listeners.back();
99 std::size_t listenersCount() const
102 for (auto& desc: listeners)
104 ret += desc.listeners.size();
111 ASSERT(0 == listenersCount());
116 MemoryDescriptorView::MemoryDescriptorView()
121 MemoryDescriptorView::MemoryDescriptorView(MemoryDescriptor& descriptor,
122 const memory::DynMdSpan& span,
123 RetargetableState retargetable):
124 m_parent(&descriptor),
126 m_retargetable(retargetable),
127 m_connector(std::make_shared<Connector>())
129 checkSpans(descriptor);
132 MemoryDescriptorView::MemoryDescriptorView(MemoryDescriptorView& parent,
133 const memory::DynMdSpan& span):
134 m_parent_view(&parent),
136 m_retargetable(parent.retargetableState()),
137 m_connector(parent.m_connector)
142 MemoryDescriptorView::~MemoryDescriptorView()
144 if (nullptr != m_connector)
146 m_connector->onDestroy(this);
150 void MemoryDescriptorView::retarget(MemoryDescriptor& newParent,
151 const memory::DynMdSpan& newSpan)
153 ASSERT(isRetargetable());
154 ASSERT(nullptr != m_parent);
155 ASSERT(nullptr == m_parent_view);
156 ASSERT(nullptr != m_connector);
157 const auto size = m_span.size();
158 ASSERT(newSpan.size() == size);
159 checkSpans(newParent);
161 for (auto& desc: m_connector->listeners)
163 auto owner = desc.owner;
164 ASSERT(nullptr != owner);
165 for (auto listener: desc.listeners)
167 ASSERT(nullptr != listener);
168 const auto origSpan = owner->span();
169 const auto origin = origSpan.origin();
170 const auto updatedSpan = util::make_span(origin, origSpan.size());
173 ASSERT(updatedSpan == newSpan);
175 listener->retarget(*m_parent, origSpan, newParent, updatedSpan);
180 m_parent = &newParent;
182 for (auto& desc: m_connector->listeners)
184 for (auto listener: desc.listeners)
186 ASSERT(nullptr != listener);
187 listener->retargetComplete();
192 MemoryDescriptorView::RetargetableState MemoryDescriptorView::retargetableState() const
194 return m_retargetable;
197 bool MemoryDescriptorView::isRetargetable() const
199 return m_retargetable == Retargetable;
202 void MemoryDescriptorView::addListener(IMemoryDescriptorViewListener* listener)
204 ASSERT(nullptr != listener);
205 ASSERT(nullptr != m_connector);
206 m_connector->addListener(this, listener);
209 void MemoryDescriptorView::removeListener(IMemoryDescriptorViewListener* listener)
211 ASSERT(nullptr != listener);
212 ASSERT(nullptr != m_connector);
213 m_connector->removeListener(this, listener);
216 memory::DynMdSpan MemoryDescriptorView::span() const
218 ASSERT(nullptr != *this);
219 if (nullptr != m_parent_view)
221 return m_span + m_parent_view->span().origin();
226 memory::DynMdSize MemoryDescriptorView::size() const
228 ASSERT(nullptr != *this);
229 return m_span.size();
232 std::size_t MemoryDescriptorView::elementSize() const
234 ASSERT(nullptr != getDescriptor());
235 return getDescriptor()->elementSize();
238 MemoryDescriptor* MemoryDescriptorView::getDescriptor()
240 if (nullptr != m_parent_view)
242 return m_parent_view->getDescriptor();
247 const MemoryDescriptor* MemoryDescriptorView::getDescriptor() const
249 if (nullptr != m_parent_view)
251 return m_parent_view->getDescriptor();
256 MemoryDescriptorView* MemoryDescriptorView::getParentView()
258 return m_parent_view;
261 const MemoryDescriptorView* MemoryDescriptorView::getParentView() const
263 return m_parent_view;
266 memory::DynMdView<void> MemoryDescriptorView::getExternalView() const
268 auto parent = getDescriptor();
269 ASSERT(nullptr != parent);
270 auto data = parent->getExternalView();
275 return data.slice(span());
278 MemoryDescriptorView::AccessHandle MemoryDescriptorView::access(const memory::DynMdSpan& span, MemoryAccessType accessType)
280 ASSERT(nullptr != getDescriptor());
281 return getDescriptor()->access(span + this->span().origin(), accessType);
284 void MemoryDescriptorView::commit(MemoryDescriptorView::AccessHandle handle)
286 ASSERT(nullptr != getDescriptor());
287 getDescriptor()->commit(handle);
290 bool operator==(std::nullptr_t, const MemoryDescriptorView& ref)
292 return ref.getDescriptor() == nullptr;
295 bool operator==(const MemoryDescriptorView& ref, std::nullptr_t)
297 return ref.getDescriptor() == nullptr;
300 bool operator!=(std::nullptr_t, const MemoryDescriptorView& ref)
302 return ref.getDescriptor() != nullptr;
305 bool operator!=(const MemoryDescriptorView& ref, std::nullptr_t)
307 return ref.getDescriptor() != nullptr;
310 void MemoryDescriptorView::checkSpans(MemoryDescriptor& descriptor) const
312 ASSERT(descriptor.dimensions().dims_count() == m_span.dims_count());
313 for (auto i: util::iota(m_span.dims_count()))
315 auto& val = m_span[i];
316 ASSERT(val.begin >= 0);
317 ASSERT(val.end <= descriptor.dimensions()[i]);
321 void* getViewDataPtr(ade::MemoryDescriptorView& view, std::size_t offset)
323 ASSERT(nullptr != view);
324 auto data = view.getExternalView().mem;
325 ASSERT(nullptr != data);
326 const auto newSize = data.size - offset;
328 return data.Slice(offset, newSize).data;
331 void copyFromViewMemory(void* dst, ade::MemoryDescriptorView& view)
333 ASSERT(nullptr != dst);
334 ASSERT(nullptr != view);
335 copyFromViewMemory(dst, view.getExternalView());
338 void copyToViewMemory(const void* src, ade::MemoryDescriptorView& view)
340 ASSERT(nullptr != src);
341 ASSERT(nullptr != view);
342 copyToViewMemory(src, view.getExternalView());
345 void copyFromViewMemory(void* dst, ade::memory::DynMdView<void> view)
347 ASSERT(nullptr != dst);
348 ASSERT(nullptr != view);
349 const auto size = view.sizeInBytes();
350 util::raw_copy(view.mem, util::memory_range(dst, size));
353 void copyToViewMemory(const void* src, ade::memory::DynMdView<void> view)
355 ASSERT(nullptr != src);
356 ASSERT(nullptr != view);
357 const auto size = view.sizeInBytes();
358 util::raw_copy(util::memory_range(src, size), view.mem);