Bug 1700051: part 26) Correct typo in comment of `mozInlineSpellWordUtil::BuildSoftTe...
[gecko.git] / dom / canvas / QueueParamTraits.h
blob1cf09dfd65eaf3fd307288c6c00420c978868ed5
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=4 et :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #ifndef _QUEUEPARAMTRAITS_H_
9 #define _QUEUEPARAMTRAITS_H_ 1
11 #include "ipc/EnumSerializer.h"
12 #include "mozilla/gfx/2D.h"
13 #include "mozilla/Assertions.h"
14 #include "mozilla/IntegerRange.h"
15 #include "mozilla/ipc/ProtocolUtils.h"
16 #include "mozilla/ipc/SharedMemoryBasic.h"
17 #include "mozilla/ipc/Shmem.h"
18 #include "mozilla/Logging.h"
19 #include "mozilla/TimeStamp.h"
20 #include "mozilla/TypeTraits.h"
21 #include "nsExceptionHandler.h"
22 #include "nsString.h"
23 #include "WebGLTypes.h"
25 namespace mozilla {
26 namespace webgl {
28 enum class QueueStatus {
29 // Operation was successful
30 kSuccess,
31 // The operation failed because the queue isn't ready for it.
32 // Either the queue is too full for an insert or too empty for a remove.
33 // The operation may succeed if retried.
34 kNotReady,
35 // The operation required more room than the queue supports.
36 // It should not be retried -- it will always fail.
37 kTooSmall,
38 // The operation failed for some reason that is unrecoverable.
39 // All values below this value indicate a fata error.
40 kFatalError,
41 // Fatal error: Internal processing ran out of memory. This is likely e.g.
42 // during de-serialization.
43 kOOMError,
46 inline bool IsSuccess(QueueStatus status) {
47 return status == QueueStatus::kSuccess;
50 inline bool operator!(const QueueStatus status) { return !IsSuccess(status); }
52 template <typename T>
53 struct RemoveCVR {
54 typedef typename std::remove_reference<typename std::remove_cv<T>::type>::type
55 Type;
58 inline size_t UsedBytes(size_t aQueueBufferSize, size_t aRead, size_t aWrite) {
59 return (aRead <= aWrite) ? aWrite - aRead
60 : (aQueueBufferSize - aRead) + aWrite;
63 inline size_t FreeBytes(size_t aQueueBufferSize, size_t aRead, size_t aWrite) {
64 // Remember, queueSize is queueBufferSize-1
65 return (aQueueBufferSize - 1) - UsedBytes(aQueueBufferSize, aRead, aWrite);
68 template <typename T>
69 struct IsTriviallySerializable
70 : public std::integral_constant<bool, std::is_arithmetic<T>::value &&
71 !std::is_same<T, bool>::value> {};
73 /**
74 * QueueParamTraits provide the user with a way to implement PCQ argument
75 * (de)serialization. It uses a PcqView, which permits the system to
76 * abandon all changes to the underlying PCQ if any operation fails.
78 * The transactional nature of PCQ operations make the ideal behavior a bit
79 * complex. Since the PCQ has a fixed amount of memory available to it,
80 * TryInsert operations operations are expected to sometimes fail and be
81 * re-issued later. We want these failures to be inexpensive. The same
82 * goes for TryRemove, which fails when there isn't enough data in
83 * the queue yet for them to complete.
85 * Their expected interface is:
87 * template<> struct QueueParamTraits<typename RemoveCVR<Arg>::Type> {
88 * // Write data from aArg into the PCQ.
89 * static QueueStatus Write(ProducerView& aProducerView, const Arg& aArg)
90 * {...};
92 * // Read data from the PCQ into aArg, or just skip the data if aArg is null.
93 * static QueueStatus Read(ConsumerView& aConsumerView, Arg* aArg) {...}
94 * };
96 template <typename Arg>
97 struct QueueParamTraits; // Todo: s/QueueParamTraits/SizedParamTraits/
99 /**
100 * The marshaller handles all data insertion into the queue.
102 class Marshaller {
103 public:
104 static QueueStatus WriteObject(uint8_t* aQueue, size_t aQueueBufferSize,
105 size_t aRead, size_t* aWrite, const void* aArg,
106 size_t aArgLength) {
107 const uint8_t* buf = reinterpret_cast<const uint8_t*>(aArg);
108 if (FreeBytes(aQueueBufferSize, aRead, *aWrite) < aArgLength) {
109 return QueueStatus::kNotReady;
112 if (*aWrite + aArgLength <= aQueueBufferSize) {
113 memcpy(aQueue + *aWrite, buf, aArgLength);
114 } else {
115 size_t firstLen = aQueueBufferSize - *aWrite;
116 memcpy(aQueue + *aWrite, buf, firstLen);
117 memcpy(aQueue, &buf[firstLen], aArgLength - firstLen);
119 *aWrite = (*aWrite + aArgLength) % aQueueBufferSize;
120 return QueueStatus::kSuccess;
123 static QueueStatus ReadObject(const uint8_t* aQueue, size_t aQueueBufferSize,
124 size_t* aRead, size_t aWrite, void* aArg,
125 size_t aArgLength) {
126 if (UsedBytes(aQueueBufferSize, *aRead, aWrite) < aArgLength) {
127 return QueueStatus::kNotReady;
130 if (aArg) {
131 uint8_t* buf = reinterpret_cast<uint8_t*>(aArg);
132 if (*aRead + aArgLength <= aQueueBufferSize) {
133 memcpy(buf, aQueue + *aRead, aArgLength);
134 } else {
135 size_t firstLen = aQueueBufferSize - *aRead;
136 memcpy(buf, aQueue + *aRead, firstLen);
137 memcpy(&buf[firstLen], aQueue, aArgLength - firstLen);
141 *aRead = (*aRead + aArgLength) % aQueueBufferSize;
142 return QueueStatus::kSuccess;
146 template <typename T>
147 inline Range<T> AsRange(T* const begin, T* const end) {
148 const auto size = MaybeAs<size_t>(end - begin);
149 MOZ_RELEASE_ASSERT(size);
150 return {begin, *size};
154 * Used to give QueueParamTraits a way to write to the Producer without
155 * actually altering it, in case the transaction fails.
156 * THis object maintains the error state of the transaction and
157 * discards commands issued after an error is encountered.
159 template <typename _Producer>
160 class ProducerView {
161 public:
162 using Producer = _Producer;
164 ProducerView(Producer* aProducer, size_t aRead, size_t* aWrite)
165 : mProducer(aProducer),
166 mRead(aRead),
167 mWrite(aWrite),
168 mStatus(QueueStatus::kSuccess) {}
170 template <typename T>
171 QueueStatus WriteFromRange(const Range<const T>& src) {
172 if (!mStatus) return mStatus;
173 mProducer->WriteFromRange(src);
174 return mStatus;
177 * Copy bytes from aBuffer to the producer if there is enough room.
178 * aBufferSize must not be 0.
180 template <typename T>
181 inline QueueStatus Write(const T* begin, const T* end) {
182 MOZ_RELEASE_ASSERT(begin <= end);
183 if (!mStatus) return mStatus;
184 WriteFromRange(AsRange(begin, end));
185 return mStatus;
188 template <typename T>
189 inline QueueStatus WritePod(const T& in) {
190 static_assert(std::is_trivially_copyable_v<T>);
191 const auto begin = reinterpret_cast<const uint8_t*>(&in);
192 return Write(begin, begin + sizeof(T));
196 * Serialize aArg using Arg's QueueParamTraits.
198 template <typename Arg>
199 QueueStatus WriteParam(const Arg& aArg) {
200 return mozilla::webgl::QueueParamTraits<
201 typename RemoveCVR<Arg>::Type>::Write(*this, aArg);
204 QueueStatus GetStatus() { return mStatus; }
206 private:
207 Producer* mProducer;
208 size_t mRead;
209 size_t* mWrite;
210 QueueStatus mStatus;
214 * Used to give QueueParamTraits a way to read from the Consumer without
215 * actually altering it, in case the transaction fails.
217 template <typename _Consumer>
218 class ConsumerView {
219 public:
220 using Consumer = _Consumer;
222 ConsumerView(Consumer* aConsumer, size_t* aRead, size_t aWrite)
223 : mConsumer(aConsumer),
224 mRead(aRead),
225 mWrite(aWrite),
226 mStatus(QueueStatus::kSuccess) {}
229 * Read bytes from the consumer if there is enough data. aBuffer may
230 * be null (in which case the data is skipped)
232 template <typename T>
233 inline QueueStatus Read(T* const destBegin, T* const destEnd) {
234 MOZ_ASSERT(destBegin);
235 MOZ_RELEASE_ASSERT(destBegin <= destEnd);
236 if (!mStatus) return mStatus;
238 const auto dest = AsRange(destBegin, destEnd);
239 const auto view = ReadRange<T>(dest.length());
240 if (!view) return mStatus;
241 const auto byteSize = ByteSize(dest);
242 if (byteSize) {
243 memcpy(dest.begin().get(), view->begin().get(), byteSize);
245 return mStatus;
248 /// Return a view wrapping the shmem.
249 template <typename T>
250 inline Maybe<Range<const T>> ReadRange(const size_t elemCount) {
251 if (!mStatus) return {};
252 const auto view = mConsumer->template ReadRange<T>(elemCount);
253 if (!view) {
254 mStatus = QueueStatus::kTooSmall;
256 return view;
259 template <typename T>
260 inline QueueStatus ReadPod(T* out) {
261 static_assert(std::is_trivially_copyable_v<T>);
262 const auto begin = reinterpret_cast<uint8_t*>(out);
263 return Read(begin, begin + sizeof(T));
267 * Deserialize aArg using Arg's QueueParamTraits.
268 * If the return value is not Success then aArg is not changed.
270 template <typename Arg>
271 QueueStatus ReadParam(Arg* aArg) {
272 MOZ_ASSERT(aArg);
273 return mozilla::webgl::QueueParamTraits<std::remove_cv_t<Arg>>::Read(*this,
274 aArg);
277 QueueStatus GetStatus() { return mStatus; }
279 private:
280 Consumer* mConsumer;
281 size_t* mRead;
282 size_t mWrite;
283 QueueStatus mStatus;
286 // ---------------------------------------------------------------
289 * True for types that can be (de)serialized by memcpy.
291 template <typename Arg>
292 struct QueueParamTraits {
293 template <typename U>
294 static QueueStatus Write(ProducerView<U>& aProducerView, const Arg& aArg) {
295 static_assert(mozilla::webgl::template IsTriviallySerializable<Arg>::value,
296 "No QueueParamTraits specialization was found for this type "
297 "and it does not satisfy IsTriviallySerializable.");
298 // Write self as binary
299 const auto begin = &aArg;
300 return aProducerView.Write(begin, begin + 1);
303 template <typename U>
304 static QueueStatus Read(ConsumerView<U>& aConsumerView, Arg* aArg) {
305 static_assert(mozilla::webgl::template IsTriviallySerializable<Arg>::value,
306 "No QueueParamTraits specialization was found for this type "
307 "and it does not satisfy IsTriviallySerializable.");
308 // Read self as binary
309 return aConsumerView.Read(aArg, aArg + 1);
313 // ---------------------------------------------------------------
315 template <>
316 struct QueueParamTraits<bool> {
317 using ParamType = bool;
319 template <typename U>
320 static QueueStatus Write(ProducerView<U>& aProducerView,
321 const ParamType& aArg) {
322 uint8_t temp = aArg ? 1 : 0;
323 return aProducerView.WriteParam(temp);
326 template <typename U>
327 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
328 uint8_t temp;
329 if (IsSuccess(aConsumerView.ReadParam(&temp))) {
330 MOZ_ASSERT(temp == 1 || temp == 0);
331 *aArg = temp ? true : false;
333 return aConsumerView.GetStatus();
337 // ---------------------------------------------------------------
339 // Adapted from IPC::EnumSerializer, this class safely handles enum values,
340 // validating that they are in range using the same EnumValidators as IPDL
341 // (namely ContiguousEnumValidator and ContiguousEnumValidatorInclusive).
342 template <typename E, typename EnumValidator>
343 struct EnumSerializer {
344 typedef E ParamType;
345 typedef typename std::underlying_type<E>::type DataType;
347 template <typename U>
348 static QueueStatus Write(ProducerView<U>& aProducerView,
349 const ParamType& aValue) {
350 MOZ_RELEASE_ASSERT(
351 EnumValidator::IsLegalValue(static_cast<DataType>(aValue)));
352 return aProducerView.WriteParam(DataType(aValue));
355 template <typename U>
356 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aResult) {
357 DataType value;
358 if (!aConsumerView.ReadParam(&value)) {
359 CrashReporter::AnnotateCrashReport(
360 CrashReporter::Annotation::IPCReadErrorReason, "Bad iter"_ns);
361 return aConsumerView.GetStatus();
363 if (!EnumValidator::IsLegalValue(static_cast<DataType>(value))) {
364 CrashReporter::AnnotateCrashReport(
365 CrashReporter::Annotation::IPCReadErrorReason, "Illegal value"_ns);
366 return QueueStatus::kFatalError;
369 *aResult = ParamType(value);
370 return QueueStatus::kSuccess;
374 using IPC::ContiguousEnumValidator;
375 using IPC::ContiguousEnumValidatorInclusive;
377 template <typename E, E MinLegal, E HighBound>
378 struct ContiguousEnumSerializer
379 : EnumSerializer<E, ContiguousEnumValidator<E, MinLegal, HighBound>> {};
381 template <typename E, E MinLegal, E MaxLegal>
382 struct ContiguousEnumSerializerInclusive
383 : EnumSerializer<E,
384 ContiguousEnumValidatorInclusive<E, MinLegal, MaxLegal>> {
387 // ---------------------------------------------------------------
389 template <>
390 struct QueueParamTraits<QueueStatus>
391 : public ContiguousEnumSerializerInclusive<
392 QueueStatus, QueueStatus::kSuccess, QueueStatus::kOOMError> {};
394 // ---------------------------------------------------------------
396 template <>
397 struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
398 using ParamType = webgl::TexUnpackBlobDesc;
400 template <typename U>
401 static QueueStatus Write(ProducerView<U>& view, const ParamType& in) {
402 MOZ_RELEASE_ASSERT(!in.image);
403 const bool isDataSurf = bool(in.dataSurf);
404 if (!view.WriteParam(in.imageTarget) || !view.WriteParam(in.size) ||
405 !view.WriteParam(in.srcAlphaType) || !view.WriteParam(in.unpacking) ||
406 !view.WriteParam(in.cpuData) || !view.WriteParam(in.pboOffset) ||
407 !view.WriteParam(in.imageSize) || !view.WriteParam(in.sd) ||
408 !view.WriteParam(isDataSurf)) {
409 return view.GetStatus();
411 if (isDataSurf) {
412 const auto& surf = in.dataSurf;
413 gfx::DataSourceSurface::ScopedMap map(surf, gfx::DataSourceSurface::READ);
414 if (!map.IsMapped()) {
415 return QueueStatus::kOOMError;
417 const auto& surfSize = surf->GetSize();
418 const auto stride = *MaybeAs<size_t>(map.GetStride());
419 if (!view.WriteParam(surfSize) || !view.WriteParam(surf->GetFormat()) ||
420 !view.WriteParam(stride)) {
421 return view.GetStatus();
424 const size_t dataSize = stride * surfSize.height;
425 const auto& begin = map.GetData();
426 if (!view.Write(begin, begin + dataSize)) {
427 return view.GetStatus();
430 return QueueStatus::kSuccess;
433 template <typename U>
434 static QueueStatus Read(ConsumerView<U>& view, ParamType* const out) {
435 bool isDataSurf;
436 if (!view.ReadParam(&out->imageTarget) || !view.ReadParam(&out->size) ||
437 !view.ReadParam(&out->srcAlphaType) ||
438 !view.ReadParam(&out->unpacking) || !view.ReadParam(&out->cpuData) ||
439 !view.ReadParam(&out->pboOffset) || !view.ReadParam(&out->imageSize) ||
440 !view.ReadParam(&out->sd) || !view.ReadParam(&isDataSurf)) {
441 return view.GetStatus();
443 if (isDataSurf) {
444 gfx::IntSize surfSize;
445 gfx::SurfaceFormat format;
446 size_t stride;
447 if (!view.ReadParam(&surfSize) || !view.ReadParam(&format) ||
448 !view.ReadParam(&stride)) {
449 return view.GetStatus();
451 auto& surf = out->dataSurf;
452 surf = gfx::Factory::CreateDataSourceSurfaceWithStride(surfSize, format,
453 stride, true);
454 if (!surf) {
455 return QueueStatus::kOOMError;
458 gfx::DataSourceSurface::ScopedMap map(surf,
459 gfx::DataSourceSurface::WRITE);
460 if (!map.IsMapped()) {
461 return QueueStatus::kOOMError;
463 const size_t dataSize = stride * surfSize.height;
464 const auto& begin = map.GetData();
465 if (!view.Read(begin, begin + dataSize)) {
466 return view.GetStatus();
469 return QueueStatus::kSuccess;
473 // ---------------------------------------------------------------
475 template <>
476 struct QueueParamTraits<nsACString> {
477 using ParamType = nsACString;
479 template <typename U>
480 static QueueStatus Write(ProducerView<U>& aProducerView,
481 const ParamType& aArg) {
482 if ((!aProducerView.WriteParam(aArg.IsVoid())) || aArg.IsVoid()) {
483 return aProducerView.GetStatus();
486 uint32_t len = aArg.Length();
487 if ((!aProducerView.WriteParam(len)) || (len == 0)) {
488 return aProducerView.GetStatus();
491 return aProducerView.Write(aArg.BeginReading(), len);
494 template <typename U>
495 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
496 bool isVoid = false;
497 if (!IsSuccess(aConsumerView.ReadParam(&isVoid))) {
498 return aConsumerView.GetStatus();
500 aArg->SetIsVoid(isVoid);
501 if (isVoid) {
502 return QueueStatus::kSuccess;
505 uint32_t len = 0;
506 if (!IsSuccess(aConsumerView.ReadParam(&len))) {
507 return aConsumerView.GetStatus();
510 if (len == 0) {
511 *aArg = "";
512 return QueueStatus::kSuccess;
515 char* buf = new char[len + 1];
516 if (!buf) {
517 return QueueStatus::kOOMError;
519 if (!IsSuccess(aConsumerView.Read(buf, len))) {
520 return aConsumerView.GetStatus();
522 buf[len] = '\0';
523 aArg->Adopt(buf, len);
524 return QueueStatus::kSuccess;
528 template <>
529 struct QueueParamTraits<nsAString> {
530 using ParamType = nsAString;
532 template <typename U>
533 static QueueStatus Write(ProducerView<U>& aProducerView,
534 const ParamType& aArg) {
535 if ((!aProducerView.WriteParam(aArg.IsVoid())) || (aArg.IsVoid())) {
536 return aProducerView.GetStatus();
538 // DLP: No idea if this includes null terminator
539 uint32_t len = aArg.Length();
540 if ((!aProducerView.WriteParam(len)) || (len == 0)) {
541 return aProducerView.GetStatus();
543 constexpr const uint32_t sizeofchar = sizeof(typename ParamType::char_type);
544 return aProducerView.Write(aArg.BeginReading(), len * sizeofchar);
547 template <typename U>
548 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
549 bool isVoid = false;
550 if (!aConsumerView.ReadParam(&isVoid)) {
551 return aConsumerView.GetStatus();
553 aArg->SetIsVoid(isVoid);
554 if (isVoid) {
555 return QueueStatus::kSuccess;
558 // DLP: No idea if this includes null terminator
559 uint32_t len = 0;
560 if (!aConsumerView.ReadParam(&len)) {
561 return aConsumerView.GetStatus();
564 if (len == 0) {
565 *aArg = nsString();
566 return QueueStatus::kSuccess;
569 uint32_t sizeofchar = sizeof(typename ParamType::char_type);
570 typename ParamType::char_type* buf = nullptr;
571 buf = static_cast<typename ParamType::char_type*>(
572 malloc((len + 1) * sizeofchar));
573 if (!buf) {
574 return QueueStatus::kOOMError;
577 if (!aConsumerView.Read(buf, len * sizeofchar)) {
578 return aConsumerView.GetStatus();
581 buf[len] = L'\0';
582 aArg->Adopt(buf, len);
583 return QueueStatus::kSuccess;
587 template <>
588 struct QueueParamTraits<nsCString> : public QueueParamTraits<nsACString> {
589 using ParamType = nsCString;
592 template <>
593 struct QueueParamTraits<nsString> : public QueueParamTraits<nsAString> {
594 using ParamType = nsString;
597 // ---------------------------------------------------------------
599 template <typename NSTArrayType,
600 bool =
601 IsTriviallySerializable<typename NSTArrayType::elem_type>::value>
602 struct NSArrayQueueParamTraits;
604 // For ElementTypes that are !IsTriviallySerializable
605 template <typename _ElementType>
606 struct NSArrayQueueParamTraits<nsTArray<_ElementType>, false> {
607 using ElementType = _ElementType;
608 using ParamType = nsTArray<ElementType>;
610 template <typename U>
611 static QueueStatus Write(ProducerView<U>& aProducerView,
612 const ParamType& aArg) {
613 aProducerView.WriteParam(aArg.Length());
614 for (auto& elt : aArg) {
615 aProducerView.WriteParam(elt);
617 return aProducerView.GetStatus();
620 template <typename U>
621 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
622 size_t arrayLen;
623 if (!aConsumerView.ReadParam(&arrayLen)) {
624 return aConsumerView.GetStatus();
627 if (!aArg->AppendElements(arrayLen, fallible)) {
628 return QueueStatus::kOOMError;
631 for (auto i : IntegerRange(arrayLen)) {
632 ElementType& elt = aArg->ElementAt(i);
633 aConsumerView.ReadParam(elt);
635 return aConsumerView.GetStatus();
639 // For ElementTypes that are IsTriviallySerializable
640 template <typename _ElementType>
641 struct NSArrayQueueParamTraits<nsTArray<_ElementType>, true> {
642 using ElementType = _ElementType;
643 using ParamType = nsTArray<ElementType>;
645 // TODO: Are there alignment issues?
646 template <typename U>
647 static QueueStatus Write(ProducerView<U>& aProducerView,
648 const ParamType& aArg) {
649 size_t arrayLen = aArg.Length();
650 aProducerView.WriteParam(arrayLen);
651 return aProducerView.Write(&aArg[0], aArg.Length() * sizeof(ElementType));
654 template <typename U>
655 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
656 size_t arrayLen;
657 if (!aConsumerView.ReadParam(&arrayLen)) {
658 return aConsumerView.GetStatus();
661 if (!aArg->AppendElements(arrayLen, fallible)) {
662 return QueueStatus::kOOMError;
665 return aConsumerView.Read(aArg->Elements(), arrayLen * sizeof(ElementType));
669 template <typename ElementType>
670 struct QueueParamTraits<nsTArray<ElementType>>
671 : public NSArrayQueueParamTraits<nsTArray<ElementType>> {
672 using ParamType = nsTArray<ElementType>;
675 // ---------------------------------------------------------------
677 template <typename ArrayType,
678 bool =
679 IsTriviallySerializable<typename ArrayType::ElementType>::value>
680 struct ArrayQueueParamTraits;
682 // For ElementTypes that are !IsTriviallySerializable
683 template <typename _ElementType, size_t Length>
684 struct ArrayQueueParamTraits<Array<_ElementType, Length>, false> {
685 using ElementType = _ElementType;
686 using ParamType = Array<ElementType, Length>;
688 template <typename U>
689 static QueueStatus Write(ProducerView<U>& aProducerView,
690 const ParamType& aArg) {
691 for (const auto& elt : aArg) {
692 aProducerView.WriteParam(elt);
694 return aProducerView.GetStatus();
697 template <typename U>
698 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
699 for (auto& elt : *aArg) {
700 aConsumerView.ReadParam(elt);
702 return aConsumerView.GetStatus();
706 // For ElementTypes that are IsTriviallySerializable
707 template <typename _ElementType, size_t Length>
708 struct ArrayQueueParamTraits<Array<_ElementType, Length>, true> {
709 using ElementType = _ElementType;
710 using ParamType = Array<ElementType, Length>;
712 template <typename U>
713 static QueueStatus Write(ProducerView<U>& aProducerView,
714 const ParamType& aArg) {
715 return aProducerView.Write(aArg.begin(), sizeof(ElementType[Length]));
718 template <typename U>
719 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
720 return aConsumerView.Read(aArg->begin(), sizeof(ElementType[Length]));
724 template <typename ElementType, size_t Length>
725 struct QueueParamTraits<Array<ElementType, Length>>
726 : public ArrayQueueParamTraits<Array<ElementType, Length>> {
727 using ParamType = Array<ElementType, Length>;
730 // ---------------------------------------------------------------
732 template <typename ElementType>
733 struct QueueParamTraits<Maybe<ElementType>> {
734 using ParamType = Maybe<ElementType>;
736 template <typename U>
737 static QueueStatus Write(ProducerView<U>& aProducerView,
738 const ParamType& aArg) {
739 aProducerView.WriteParam(static_cast<bool>(aArg));
740 return aArg ? aProducerView.WriteParam(aArg.ref())
741 : aProducerView.GetStatus();
744 template <typename U>
745 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
746 bool isSome;
747 if (!aConsumerView.ReadParam(&isSome)) {
748 return aConsumerView.GetStatus();
751 if (!isSome) {
752 aArg->reset();
753 return QueueStatus::kSuccess;
756 aArg->emplace();
757 return aConsumerView.ReadParam(aArg->ptr());
761 // ---------------------------------------------------------------
763 // Maybe<Variant> needs special behavior since Variant is not default
764 // constructable. The Variant's first type must be default constructible.
765 template <typename T, typename... Ts>
766 struct QueueParamTraits<Maybe<Variant<T, Ts...>>> {
767 using ParamType = Maybe<Variant<T, Ts...>>;
769 template <typename U>
770 static QueueStatus Write(ProducerView<U>& aProducerView,
771 const ParamType& aArg) {
772 aProducerView.WriteParam(aArg.mIsSome);
773 return (aArg.mIsSome) ? aProducerView.WriteParam(aArg.ref())
774 : aProducerView.GetStatus();
777 template <typename U>
778 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
779 bool isSome;
780 if (!aConsumerView.ReadParam(&isSome)) {
781 return aConsumerView.GetStatus();
784 if (!isSome) {
785 aArg->reset();
786 return QueueStatus::kSuccess;
789 aArg->emplace(VariantType<T>());
790 return aConsumerView.ReadParam(aArg->ptr());
794 // ---------------------------------------------------------------
796 template <typename TypeA, typename TypeB>
797 struct QueueParamTraits<std::pair<TypeA, TypeB>> {
798 using ParamType = std::pair<TypeA, TypeB>;
800 template <typename U>
801 static QueueStatus Write(ProducerView<U>& aProducerView,
802 const ParamType& aArg) {
803 aProducerView.WriteParam(aArg.first());
804 return aProducerView.WriteParam(aArg.second());
807 template <typename U>
808 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
809 aConsumerView.ReadParam(aArg->first());
810 return aConsumerView.ReadParam(aArg->second());
814 // ---------------------------------------------------------------
816 template <typename T>
817 struct QueueParamTraits<UniquePtr<T>> {
818 using ParamType = UniquePtr<T>;
820 template <typename U>
821 static QueueStatus Write(ProducerView<U>& aProducerView,
822 const ParamType& aArg) {
823 // TODO: Clean up move with PCQ
824 aProducerView.WriteParam(!static_cast<bool>(aArg));
825 if (aArg && aProducerView.WriteParam(*aArg.get())) {
826 const_cast<ParamType&>(aArg).reset();
828 return aProducerView.GetStatus();
831 template <typename U>
832 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
833 bool isNull;
834 if (!aConsumerView.ReadParam(&isNull)) {
835 return aConsumerView.GetStatus();
837 if (isNull) {
838 aArg->reset(nullptr);
839 return QueueStatus::kSuccess;
842 T* obj = new T();
843 aArg->reset(obj);
844 return aConsumerView.ReadParam(obj);
848 // ---------------------------------------------------------------
850 template <>
851 struct QueueParamTraits<mozilla::ipc::Shmem> {
852 using ParamType = mozilla::ipc::Shmem;
854 template <typename U>
855 static QueueStatus Write(ProducerView<U>& aProducerView, ParamType&& aParam) {
856 if (!aProducerView.WriteParam(
857 aParam.Id(mozilla::ipc::Shmem::PrivateIPDLCaller()))) {
858 return aProducerView.GetStatus();
861 aParam.RevokeRights(mozilla::ipc::Shmem::PrivateIPDLCaller());
862 aParam.forget(mozilla::ipc::Shmem::PrivateIPDLCaller());
865 template <typename U>
866 static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aResult) {
867 ParamType::id_t id;
868 if (!aConsumerView.ReadParam(&id)) {
869 return aConsumerView.GetStatus();
872 mozilla::ipc::Shmem::SharedMemory* rawmem =
873 aConsumerView.LookupSharedMemory(id);
874 if (!rawmem) {
875 return QueueStatus::kFatalError;
878 *aResult = mozilla::ipc::Shmem(mozilla::ipc::Shmem::PrivateIPDLCaller(),
879 rawmem, id);
880 return QueueStatus::kSuccess;
884 } // namespace webgl
885 } // namespace mozilla
887 #endif // _QUEUEPARAMTRAITS_H_