• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef DAWNWIRE_CHUNKEDCOMMANDSERIALIZER_H_
16 #define DAWNWIRE_CHUNKEDCOMMANDSERIALIZER_H_
17 
18 #include "common/Alloc.h"
19 #include "common/Compiler.h"
20 #include "dawn_wire/Wire.h"
21 #include "dawn_wire/WireCmd_autogen.h"
22 
23 #include <algorithm>
24 #include <cstring>
25 #include <memory>
26 
27 namespace dawn_wire {
28 
29     class ChunkedCommandSerializer {
30       public:
31         ChunkedCommandSerializer(CommandSerializer* serializer);
32 
33         template <typename Cmd>
SerializeCommand(const Cmd & cmd)34         void SerializeCommand(const Cmd& cmd) {
35             SerializeCommand(cmd, 0, [](SerializeBuffer*) { return WireResult::Success; });
36         }
37 
38         template <typename Cmd, typename ExtraSizeSerializeFn>
SerializeCommand(const Cmd & cmd,size_t extraSize,ExtraSizeSerializeFn && SerializeExtraSize)39         void SerializeCommand(const Cmd& cmd,
40                               size_t extraSize,
41                               ExtraSizeSerializeFn&& SerializeExtraSize) {
42             SerializeCommandImpl(
43                 cmd,
44                 [](const Cmd& cmd, size_t requiredSize, SerializeBuffer* serializeBuffer) {
45                     return cmd.Serialize(requiredSize, serializeBuffer);
46                 },
47                 extraSize, std::forward<ExtraSizeSerializeFn>(SerializeExtraSize));
48         }
49 
50         template <typename Cmd>
SerializeCommand(const Cmd & cmd,const ObjectIdProvider & objectIdProvider)51         void SerializeCommand(const Cmd& cmd, const ObjectIdProvider& objectIdProvider) {
52             SerializeCommand(cmd, objectIdProvider, 0,
53                              [](SerializeBuffer*) { return WireResult::Success; });
54         }
55 
56         template <typename Cmd, typename ExtraSizeSerializeFn>
SerializeCommand(const Cmd & cmd,const ObjectIdProvider & objectIdProvider,size_t extraSize,ExtraSizeSerializeFn && SerializeExtraSize)57         void SerializeCommand(const Cmd& cmd,
58                               const ObjectIdProvider& objectIdProvider,
59                               size_t extraSize,
60                               ExtraSizeSerializeFn&& SerializeExtraSize) {
61             SerializeCommandImpl(
62                 cmd,
63                 [&objectIdProvider](const Cmd& cmd, size_t requiredSize,
64                                     SerializeBuffer* serializeBuffer) {
65                     return cmd.Serialize(requiredSize, serializeBuffer, objectIdProvider);
66                 },
67                 extraSize, std::forward<ExtraSizeSerializeFn>(SerializeExtraSize));
68         }
69 
70       private:
71         template <typename Cmd, typename SerializeCmdFn, typename ExtraSizeSerializeFn>
SerializeCommandImpl(const Cmd & cmd,SerializeCmdFn && SerializeCmd,size_t extraSize,ExtraSizeSerializeFn && SerializeExtraSize)72         void SerializeCommandImpl(const Cmd& cmd,
73                                   SerializeCmdFn&& SerializeCmd,
74                                   size_t extraSize,
75                                   ExtraSizeSerializeFn&& SerializeExtraSize) {
76             size_t commandSize = cmd.GetRequiredSize();
77             size_t requiredSize = commandSize + extraSize;
78 
79             if (requiredSize <= mMaxAllocationSize) {
80                 char* allocatedBuffer = static_cast<char*>(mSerializer->GetCmdSpace(requiredSize));
81                 if (allocatedBuffer != nullptr) {
82                     SerializeBuffer serializeBuffer(allocatedBuffer, requiredSize);
83                     WireResult r1 = SerializeCmd(cmd, requiredSize, &serializeBuffer);
84                     WireResult r2 = SerializeExtraSize(&serializeBuffer);
85                     if (DAWN_UNLIKELY(r1 != WireResult::Success || r2 != WireResult::Success)) {
86                         mSerializer->OnSerializeError();
87                     }
88                 }
89                 return;
90             }
91 
92             auto cmdSpace = std::unique_ptr<char[]>(AllocNoThrow<char>(requiredSize));
93             if (!cmdSpace) {
94                 return;
95             }
96             SerializeBuffer serializeBuffer(cmdSpace.get(), requiredSize);
97             WireResult r1 = SerializeCmd(cmd, requiredSize, &serializeBuffer);
98             WireResult r2 = SerializeExtraSize(&serializeBuffer);
99             if (DAWN_UNLIKELY(r1 != WireResult::Success || r2 != WireResult::Success)) {
100                 mSerializer->OnSerializeError();
101                 return;
102             }
103             SerializeChunkedCommand(cmdSpace.get(), requiredSize);
104         }
105 
106         void SerializeChunkedCommand(const char* allocatedBuffer, size_t remainingSize);
107 
108         CommandSerializer* mSerializer;
109         size_t mMaxAllocationSize;
110     };
111 
112 }  // namespace dawn_wire
113 
114 #endif  // DAWNWIRE_CHUNKEDCOMMANDSERIALIZER_H_
115