Turi Create  4.0
ipc_deserializer.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef CPPIPC_IPC_DESERIALIZER_HPP
7 #define CPPIPC_IPC_DESERIALIZER_HPP
8 
9 #ifdef DISABLE_TURI_CPPIPC_PROXY_GENERATION
10 #include <core/system/cppipc/common/ipc_deserializer_minimal.hpp>
11 
12 #else
13 
14 #include <type_traits>
15 #include <core/storage/serialization/iarchive.hpp>
16 #include <core/system/cppipc/ipc_object_base.hpp>
17 namespace cppipc {
18 
19 class comm_server;
20 class comm_client;
21 
22 namespace detail {
23 extern void set_deserializer_to_server(comm_server* server);
24 extern void set_deserializer_to_client(comm_client* client);
25 extern void get_deserialization_type(comm_server** server, comm_client** client);
26 extern std::shared_ptr<void> get_server_object_ptr(comm_server* server, size_t object_id);
27 
28 } // detail
29 } // cppipc
30 
31 
32 // This is using an undocumented feature of the serializer to overwrite the
33 // deserializer for when attempting to deserialize T where T inherits from
34 // ipc_object_base. This will allow me to transport proxied objects
35 // across the network, even if the proxied object is stored inside another
36 // object.
37 namespace turi {
38 namespace archive_detail {
39 
40 // by templating over Server, we detach the cyclic dependency between
41 // this file and comm_server
42 // Tries to find an object on the server, and registers it if it is not found.
43 // Returns objectID
44 template <typename Server, typename T>
45 size_t get_server_object_id(Server* server, std::shared_ptr<T> objectptr) {
46  return server->register_object(objectptr);
47 }
48 
49 
50 
51 template <typename OutArcType, typename T>
52 struct serialize_impl<OutArcType, std::shared_ptr<T>, false,
53  typename std::enable_if<std::is_convertible<T*, cppipc::ipc_object_base*>::value>::type
54  > {
55  inline static
56  void
57  exec(OutArcType& oarc, const std::shared_ptr<T> value) {
58  // check that the object has been registered on the server size
59  cppipc::comm_server* server;
60  cppipc::comm_client* client;
61  cppipc::detail::get_deserialization_type(&server, &client);
62  if (server) {
63  // server to client message is an "object ID"
64  oarc << get_server_object_id(server, value);
65  } else {
66  oarc << (*value);
67  }
68  }
69 };
70 
71 
72 template <typename InArcType, typename T>
73 struct deserialize_impl<InArcType, std::shared_ptr<T>, false,
74  typename std::enable_if<std::is_convertible<T*, cppipc::ipc_object_base*>::value>::type
75  > {
76  inline static
77  void exec(InArcType& iarc, std::shared_ptr<T>& value) {
78  cppipc::comm_server* server;
79  cppipc::comm_client* client;
80  cppipc::detail::get_deserialization_type(&server, &client);
81  if (server) {
82  size_t object_id;
83  iarc >> object_id;
84  std::shared_ptr<void> obj = cppipc::detail::get_server_object_ptr(server, object_id);
85  if (obj == NULL) {
86  throw std::to_string(object_id) + " Object not found";
87  }
88  value = std::static_pointer_cast<T>(obj);
89  } else if (client) {
90  size_t object_id;
91  iarc >> object_id;
92  value.reset(new typename T::proxy_object_type(*client, false, object_id));
93  }
94  }
95 };
96 } // archive_detail
97 } // turicreate
98 #endif
99 #endif
STL namespace.