Make generated APIs thread-safe 24/168724/2
authorJunghoon Park <jh9216.park@samsung.com>
Tue, 30 Jan 2018 09:44:39 +0000 (18:44 +0900)
committerJunghoon Park <jh9216.park@samsung.com>
Tue, 30 Jan 2018 10:06:50 +0000 (19:06 +0900)
Change-Id: I63c7998e99ec90ffc24cd52a77c946590b0a7391
Signed-off-by: Junghoon Park <jh9216.park@samsung.com>
idlc/cs_gen/cs_proxy_gen.cc

index aa621d4..482ee1d 100644 (file)
@@ -72,6 +72,7 @@ void CsProxyGen::GenInterface(std::ofstream& stream, const Interface& iface) {
       "private IntPtr _port;\n" \
       "private bool _online = false;\n" \
       "private string _appId;\n" \
+      "private Object _lock = new Object();\n" \
       "private List<CallbackBase> _delegateList = new List<CallbackBase>();\n" \
       "private Interop.LibRPCPort.Proxy.ConnectedEventCallback _connectedEventCallback;\n" \
       "private Interop.LibRPCPort.Proxy.DisconnectedEventCallback _disconnectedEventCallback;\n" \
@@ -113,8 +114,12 @@ void CsProxyGen::GenInterface(std::ofstream& stream, const Interface& iface) {
       "\n" \
       "private void OnReceivedEvent(string endPoint, string port_name, IntPtr data)\n" \
       "{\n" \
-      "    if (Interop.LibRPCPort.Parcel.CreateFromPort(out IntPtr parcel_received, _port) != 0)\n" \
-      "        return;\n" \
+      "    IntPtr parcel_received;\n" \
+      "    lock (_lock)\n" \
+      "    {\n" \
+      "        if (Interop.LibRPCPort.Parcel.CreateFromPort(out parcel_received, _port) != 0)\n" \
+      "            return;\n" \
+      "    }\n" \
       "\n" \
       "    Interop.LibRPCPort.Parcel.ReadInt32(parcel_received, out int cmd);\n" \
       "    if (cmd != (int)MethodId.Callback)\n" \
@@ -228,8 +233,7 @@ void CsProxyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
 
   const char* mid =
       "// Send\n" \
-      "Interop.LibRPCPort.Parcel.Send(p, _port);\n" \
-      "Interop.LibRPCPort.Parcel.Destroy(p);\n";
+      "Interop.LibRPCPort.Parcel.Send(p, _port);\n";
 
   stream << AddIndent(TAB_SIZE * 4, pre);
 
@@ -238,25 +242,40 @@ void CsProxyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
          << "Interop.LibRPCPort.Parcel.WriteInt32(p, (int)MethodId."
          << decl.GetID() << ");" << NLine(1);
   std::string m;
+  std::string l;
   for (auto& i : decl.GetParameters().GetParams()) {
     auto& pt = i->GetParameterType();
     if (pt.GetDirection() == ParameterType::Direction::OUT)
       continue;
     m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p");
     if (IsDelegateType(pt.GetBaseType().ToString()))
-      m += "_delegateList.Add(" + i->GetID() + ");\n";
+      l += "_delegateList.Add(" + i->GetID() + ");\n";
   }
-
   stream << AddIndent(TAB_SIZE * 4, m) << NLine(1);
-  stream << AddIndent(TAB_SIZE * 4, mid) << NLine(1);
+
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC)
+    stream << Tab(4) << "IntPtr parcel_received;" << NLine(1);
+  stream << Tab(4) << "lock (_lock)" << NLine(1);
+  GenBrace(stream, TAB_SIZE * 4, [&]() {
+    if (!l.empty())
+      stream << AddIndent(TAB_SIZE * 5, l) << NLine(1);
+    stream << AddIndent(TAB_SIZE * 5, mid) << NLine(1);
+    if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
+      stream << Tab(5) << "// Receive" << NLine(1);
+      stream << Tab(5)
+             << "ConsumeCommand(out parcel_received, _port);" << NLine(1);
+    }
+  });
+  stream << NLine(1);
 
   // Deserialize
-  if (decl.GetMethodType() == Declaration::MethodType::ASYNC)
+  if (decl.GetMethodType() == Declaration::MethodType::ASYNC) {
+    stream << Tab(4) << "Interop.LibRPCPort.Parcel.Destroy(p);"
+         << NLine(1);
     return;
+  }
 
   const char* receive_block =
-      "// Receive\n" \
-      "ConsumeCommand(out IntPtr parcel_received, _port);\n" \
       "if (parcel_received == IntPtr.Zero)\n" \
       "{\n" \
       "    throw new InvalidOperationException(\"Can't receive data\");\n" \
@@ -281,6 +300,8 @@ void CsProxyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
                                                 "ret", "parcel_received"));
   }
 
+  stream << Tab(4) << "Interop.LibRPCPort.Parcel.Destroy(p);"
+         << NLine(1);
   stream << Tab(4) << "Interop.LibRPCPort.Parcel.Destroy(parcel_received);"
          << NLine(1);