1 /* 2 * 3 * Copyright 2019 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #ifndef GRPCPP_IMPL_CODEGEN_MESSAGE_ALLOCATOR_H 20 #define GRPCPP_IMPL_CODEGEN_MESSAGE_ALLOCATOR_H 21 22 namespace grpc { 23 #ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL 24 namespace experimental { 25 #endif 26 27 // NOTE: This is an API for advanced users who need custom allocators. 28 // Per rpc struct for the allocator. This is the interface to return to user. 29 class RpcAllocatorState { 30 public: 31 virtual ~RpcAllocatorState() = default; 32 // Optionally deallocate request early to reduce the size of working set. 33 // A custom MessageAllocator needs to be registered to make use of this. 34 // This is not abstract because implementing it is optional. FreeRequest()35 virtual void FreeRequest() {} 36 }; 37 38 // This is the interface returned by the allocator. 39 // grpc library will call the methods to get request/response pointers and to 40 // release the object when it is done. 41 template <typename RequestT, typename ResponseT> 42 class MessageHolder : public RpcAllocatorState { 43 public: 44 // Release this object. For example, if the custom allocator's 45 // AllocateMessasge creates an instance of a subclass with new, the Release() 46 // should do a "delete this;". 47 virtual void Release() = 0; request()48 RequestT* request() { return request_; } response()49 ResponseT* response() { return response_; } 50 51 protected: set_request(RequestT * request)52 void set_request(RequestT* request) { request_ = request; } set_response(ResponseT * response)53 void set_response(ResponseT* response) { response_ = response; } 54 55 private: 56 // NOTE: subclasses should set these pointers. 57 RequestT* request_; 58 ResponseT* response_; 59 }; 60 61 // A custom allocator can be set via the generated code to a callback unary 62 // method, such as SetMessageAllocatorFor_Echo(custom_allocator). The allocator 63 // needs to be alive for the lifetime of the server. 64 // Implementations need to be thread-safe. 65 template <typename RequestT, typename ResponseT> 66 class MessageAllocator { 67 public: 68 virtual ~MessageAllocator() = default; 69 virtual MessageHolder<RequestT, ResponseT>* AllocateMessages() = 0; 70 }; 71 72 #ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL 73 } // namespace experimental 74 #endif 75 76 // TODO(vjpai): Remove namespace experimental when de-experimentalized fully. 77 #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL 78 namespace experimental { 79 80 using ::grpc::RpcAllocatorState; 81 82 template <typename RequestT, typename ResponseT> 83 using MessageHolder = ::grpc::MessageHolder<RequestT, ResponseT>; 84 85 template <typename RequestT, typename ResponseT> 86 using MessageAllocator = ::grpc::MessageAllocator<RequestT, ResponseT>; 87 88 } // namespace experimental 89 #endif 90 91 } // namespace grpc 92 93 #endif // GRPCPP_IMPL_CODEGEN_MESSAGE_ALLOCATOR_H 94