Austin Eng fd4688e8d0 Separate WireServer.cpp into multiple files.
This patch copies methods and classes from WireServer.cpp and
distributes them over multiple files. Headers and forward declarations
are added as necessary, but no functional changes are made.

Bug: dawn:88
Change-Id: I471b8c27804916257eff266a51d087ba1ddbfeb6
Reviewed-on: https://dawn-review.googlesource.com/c/4000
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
2019-01-30 02:20:58 +00:00

189 lines
7.7 KiB
C++

//* Copyright 2019 The Dawn Authors
//*
//* Licensed under the Apache License, Version 2.0 (the "License");
//* you may not use this file except in compliance with the License.
//* You may obtain a copy of the License at
//*
//* http://www.apache.org/licenses/LICENSE-2.0
//*
//* Unless required by applicable law or agreed to in writing, software
//* distributed under the License is distributed on an "AS IS" BASIS,
//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//* See the License for the specific language governing permissions and
//* limitations under the License.
#include "common/Assert.h"
#include "dawn_wire/server/Server.h"
namespace dawn_wire { namespace server {
{% for type in by_category["object"] %}
{% for method in type.methods %}
{% set Suffix = as_MethodSuffix(type.name, method.name) %}
{% if Suffix not in client_side_commands %}
//* The generic command handlers
bool Server::Handle{{Suffix}}(const char** commands, size_t* size) {
{{Suffix}}Cmd cmd;
DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator, *this);
if (deserializeResult == DeserializeResult::FatalError) {
return false;
}
{% if Suffix in server_custom_pre_handler_commands %}
if (!PreHandle{{Suffix}}(cmd)) {
return false;
}
{% endif %}
//* Unpack 'self'
auto* selfData = mKnown{{type.name.CamelCase()}}.Get(cmd.selfId);
ASSERT(selfData != nullptr);
//* In all cases allocate the object data as it will be refered-to by the client.
{% set return_type = method.return_type %}
{% set returns = return_type.name.canonical_case() != "void" %}
{% if returns %}
{% set Type = method.return_type.name.CamelCase() %}
auto* resultData = mKnown{{Type}}.Allocate(cmd.result.id);
if (resultData == nullptr) {
return false;
}
resultData->serial = cmd.result.serial;
{% if type.is_builder %}
selfData->builtObject = cmd.result;
{% endif %}
{% endif %}
//* After the data is allocated, apply the argument error propagation mechanism
if (deserializeResult == DeserializeResult::ErrorObject) {
{% if type.is_builder %}
selfData->valid = false;
//* If we are in GetResult, fake an error callback
{% if returns %}
On{{type.name.CamelCase()}}Error(DAWN_BUILDER_ERROR_STATUS_ERROR, "Maybe monad", cmd.selfId, selfData->serial);
{% endif %}
{% endif %}
return true;
}
{% if returns %}
auto result ={{" "}}
{%- endif %}
mProcs.{{as_varName(type.name, method.name)}}(cmd.self
{%- for arg in method.arguments -%}
, cmd.{{as_varName(arg.name)}}
{%- endfor -%}
);
{% if Suffix in server_custom_post_handler_commands %}
if (!PostHandle{{Suffix}}(cmd)) {
return false;
}
{% endif %}
{% if returns %}
resultData->handle = result;
resultData->valid = result != nullptr;
{% if return_type.name.CamelCase() in server_reverse_lookup_objects %}
//* For created objects, store a mapping from them back to their client IDs
if (result) {
m{{return_type.name.CamelCase()}}IdTable.Store(result, cmd.result.id);
}
{% endif %}
//* builders remember the ID of the object they built so that they can send it
//* in the callback to the client.
{% if return_type.is_builder %}
if (result != nullptr) {
uint64_t userdata1 = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this));
uint64_t userdata2 = (uint64_t(resultData->serial) << uint64_t(32)) + cmd.result.id;
mProcs.{{as_varName(return_type.name, Name("set error callback"))}}(result, Forward{{return_type.name.CamelCase()}}ToClient, userdata1, userdata2);
}
{% endif %}
{% endif %}
return true;
}
{% endif %}
{% endfor %}
{% endfor %}
bool Server::HandleDestroyObject(const char** commands, size_t* size) {
DestroyObjectCmd cmd;
DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator);
if (deserializeResult == DeserializeResult::FatalError) {
return false;
}
ObjectId objectId = cmd.objectId;
//* ID 0 are reserved for nullptr and cannot be destroyed.
if (objectId == 0) {
return false;
}
switch (cmd.objectType) {
{% for type in by_category["object"] %}
{% set ObjectType = type.name.CamelCase() %}
case ObjectType::{{ObjectType}}: {
{% if ObjectType == "Device" %}
//* Freeing the device has to be done out of band.
return false;
{% else %}
auto* data = mKnown{{type.name.CamelCase()}}.Get(objectId);
if (data == nullptr) {
return false;
}
{% if type.name.CamelCase() in server_reverse_lookup_objects %}
m{{type.name.CamelCase()}}IdTable.Remove(data->handle);
{% endif %}
if (data->handle != nullptr) {
mProcs.{{as_varName(type.name, Name("release"))}}(data->handle);
}
mKnown{{type.name.CamelCase()}}.Free(objectId);
return true;
{% endif %}
}
{% endfor %}
default:
UNREACHABLE();
}
}
const char* Server::HandleCommands(const char* commands, size_t size) {
mProcs.deviceTick(mKnownDevice.Get(1)->handle);
while (size >= sizeof(WireCmd)) {
WireCmd cmdId = *reinterpret_cast<const WireCmd*>(commands);
bool success = false;
switch (cmdId) {
{% for command in cmd_records["command"] %}
case WireCmd::{{command.name.CamelCase()}}:
success = Handle{{command.name.CamelCase()}}(&commands, &size);
break;
{% endfor %}
default:
success = false;
}
if (!success) {
return nullptr;
}
mAllocator.Reset();
}
if (size != 0) {
return nullptr;
}
return commands;
}
}} // namespace dawn_wire::server