1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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"
23 #include "WebGLTypes.h"
28 enum class QueueStatus
{
29 // Operation was successful
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.
35 // The operation required more room than the queue supports.
36 // It should not be retried -- it will always fail.
38 // The operation failed for some reason that is unrecoverable.
39 // All values below this value indicate a fata error.
41 // Fatal error: Internal processing ran out of memory. This is likely e.g.
42 // during de-serialization.
46 inline bool IsSuccess(QueueStatus status
) {
47 return status
== QueueStatus::kSuccess
;
50 inline bool operator!(const QueueStatus status
) { return !IsSuccess(status
); }
54 typedef typename
std::remove_reference
<typename
std::remove_cv
<T
>::type
>::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
);
69 struct IsTriviallySerializable
70 : public std::integral_constant
<bool, std::is_arithmetic
<T
>::value
&&
71 !std::is_same
<T
, bool>::value
> {};
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)
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) {...}
96 template <typename Arg
>
97 struct QueueParamTraits
; // Todo: s/QueueParamTraits/SizedParamTraits/
100 * The marshaller handles all data insertion into the queue.
104 static QueueStatus
WriteObject(uint8_t* aQueue
, size_t aQueueBufferSize
,
105 size_t aRead
, size_t* aWrite
, const void* aArg
,
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
);
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
,
126 if (UsedBytes(aQueueBufferSize
, *aRead
, aWrite
) < aArgLength
) {
127 return QueueStatus::kNotReady
;
131 uint8_t* buf
= reinterpret_cast<uint8_t*>(aArg
);
132 if (*aRead
+ aArgLength
<= aQueueBufferSize
) {
133 memcpy(buf
, aQueue
+ *aRead
, aArgLength
);
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
>
162 using Producer
= _Producer
;
164 ProducerView(Producer
* aProducer
, size_t aRead
, size_t* aWrite
)
165 : mProducer(aProducer
),
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
);
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
));
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
; }
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
>
220 using Consumer
= _Consumer
;
222 ConsumerView(Consumer
* aConsumer
, size_t* aRead
, size_t aWrite
)
223 : mConsumer(aConsumer
),
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
);
243 memcpy(dest
.begin().get(), view
->begin().get(), byteSize
);
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
);
254 mStatus
= QueueStatus::kTooSmall
;
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
) {
273 return mozilla::webgl::QueueParamTraits
<std::remove_cv_t
<Arg
>>::Read(*this,
277 QueueStatus
GetStatus() { return 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 // ---------------------------------------------------------------
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
) {
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
{
345 typedef typename
std::underlying_type
<E
>::type DataType
;
347 template <typename U
>
348 static QueueStatus
Write(ProducerView
<U
>& aProducerView
,
349 const ParamType
& aValue
) {
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
) {
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
384 ContiguousEnumValidatorInclusive
<E
, MinLegal
, MaxLegal
>> {
387 // ---------------------------------------------------------------
390 struct QueueParamTraits
<QueueStatus
>
391 : public ContiguousEnumSerializerInclusive
<
392 QueueStatus
, QueueStatus::kSuccess
, QueueStatus::kOOMError
> {};
394 // ---------------------------------------------------------------
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();
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
) {
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();
444 gfx::IntSize surfSize
;
445 gfx::SurfaceFormat format
;
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
,
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 // ---------------------------------------------------------------
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
) {
497 if (!IsSuccess(aConsumerView
.ReadParam(&isVoid
))) {
498 return aConsumerView
.GetStatus();
500 aArg
->SetIsVoid(isVoid
);
502 return QueueStatus::kSuccess
;
506 if (!IsSuccess(aConsumerView
.ReadParam(&len
))) {
507 return aConsumerView
.GetStatus();
512 return QueueStatus::kSuccess
;
515 char* buf
= new char[len
+ 1];
517 return QueueStatus::kOOMError
;
519 if (!IsSuccess(aConsumerView
.Read(buf
, len
))) {
520 return aConsumerView
.GetStatus();
523 aArg
->Adopt(buf
, len
);
524 return QueueStatus::kSuccess
;
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
) {
550 if (!aConsumerView
.ReadParam(&isVoid
)) {
551 return aConsumerView
.GetStatus();
553 aArg
->SetIsVoid(isVoid
);
555 return QueueStatus::kSuccess
;
558 // DLP: No idea if this includes null terminator
560 if (!aConsumerView
.ReadParam(&len
)) {
561 return aConsumerView
.GetStatus();
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
));
574 return QueueStatus::kOOMError
;
577 if (!aConsumerView
.Read(buf
, len
* sizeofchar
)) {
578 return aConsumerView
.GetStatus();
582 aArg
->Adopt(buf
, len
);
583 return QueueStatus::kSuccess
;
588 struct QueueParamTraits
<nsCString
> : public QueueParamTraits
<nsACString
> {
589 using ParamType
= nsCString
;
593 struct QueueParamTraits
<nsString
> : public QueueParamTraits
<nsAString
> {
594 using ParamType
= nsString
;
597 // ---------------------------------------------------------------
599 template <typename NSTArrayType
,
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
) {
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
) {
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
,
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
) {
747 if (!aConsumerView
.ReadParam(&isSome
)) {
748 return aConsumerView
.GetStatus();
753 return QueueStatus::kSuccess
;
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
) {
780 if (!aConsumerView
.ReadParam(&isSome
)) {
781 return aConsumerView
.GetStatus();
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
) {
834 if (!aConsumerView
.ReadParam(&isNull
)) {
835 return aConsumerView
.GetStatus();
838 aArg
->reset(nullptr);
839 return QueueStatus::kSuccess
;
844 return aConsumerView
.ReadParam(obj
);
848 // ---------------------------------------------------------------
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
) {
868 if (!aConsumerView
.ReadParam(&id
)) {
869 return aConsumerView
.GetStatus();
872 mozilla::ipc::Shmem::SharedMemory
* rawmem
=
873 aConsumerView
.LookupSharedMemory(id
);
875 return QueueStatus::kFatalError
;
878 *aResult
= mozilla::ipc::Shmem(mozilla::ipc::Shmem::PrivateIPDLCaller(),
880 return QueueStatus::kSuccess
;
885 } // namespace mozilla
887 #endif // _QUEUEPARAMTRAITS_H_