1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <Ice/IncomingAsync.h>
6 #include <Ice/ServantLocator.h>
7 #include <Ice/Object.h>
8 #include <Ice/ConnectionI.h>
9 #include <Ice/LocalException.h>
10 #include <Ice/Protocol.h>
11 #include <Ice/Instance.h>
12 #include <Ice/Properties.h>
13 #include <Ice/ReplyStatus.h>
14 #include <IceUtil/Mutex.h>
15 #include <IceUtil/MutexPtrLock.h>
16
17 using namespace std;
18 using namespace Ice;
19 using namespace IceInternal;
20
21 #ifndef ICE_CPP11_MAPPING
upCast(IncomingAsync * p)22 IceUtil::Shared* IceInternal::upCast(IncomingAsync* p) { return p; }
upCast(AMD_Object_ice_invoke * p)23 IceUtil::Shared* Ice::upCast(AMD_Object_ice_invoke* p) { return p; }
24
~AMDCallback()25 Ice::AMDCallback::~AMDCallback()
26 {
27 // Out of line to avoid weak vtable
28 }
29
~AMD_Object_ice_invoke()30 Ice::AMD_Object_ice_invoke::~AMD_Object_ice_invoke()
31 {
32 // Out of line to avoid weak vtable
33 }
34 #endif
35
36 namespace
37 {
38
39 IceUtil::Mutex* globalMutex = 0;
40
41 class Init
42 {
43 public:
44
Init()45 Init()
46 {
47 globalMutex = new IceUtil::Mutex;
48 }
49
~Init()50 ~Init()
51 {
52 delete globalMutex;
53 globalMutex = 0;
54 }
55 };
56
57 Init init;
58
59 }
60
IncomingAsync(Incoming & in)61 IceInternal::IncomingAsync::IncomingAsync(Incoming& in) :
62 IncomingBase(in),
63 _responseSent(false),
64 _responseHandlerCopy(ICE_GET_SHARED_FROM_THIS(_responseHandler))
65 {
66 #ifndef ICE_CPP11_MAPPING
67 in.setAsync(this);
68 #endif
69 }
70
71 #ifdef ICE_CPP11_MAPPING
72 shared_ptr<IncomingAsync>
create(Incoming & in)73 IceInternal::IncomingAsync::create(Incoming& in)
74 {
75 auto async = make_shared<IncomingAsync>(in);
76 in.setAsync(async);
77 return async;
78 }
79 #endif
80
81 #ifndef ICE_CPP11_MAPPING
82 void
ice_exception(const::std::exception & exc)83 IceInternal::IncomingAsync::ice_exception(const ::std::exception& exc)
84 {
85 try
86 {
87 for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
88 {
89 if(!(*p)->exception(exc))
90 {
91 return;
92 }
93 }
94 }
95 catch(...)
96 {
97 return;
98 }
99
100 checkResponseSent();
101 IncomingBase::exception(exc, true); // User thread
102 }
103
104 void
ice_exception()105 IceInternal::IncomingAsync::ice_exception()
106 {
107 try
108 {
109 for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
110 {
111 if(!(*p)->exception())
112 {
113 return;
114 }
115 }
116 }
117 catch(...)
118 {
119 return;
120 }
121
122 checkResponseSent();
123 IncomingBase::exception("unknown c++ exception", true); // User thread
124 }
125
126 #endif
127
128 void
kill(Incoming & in)129 IceInternal::IncomingAsync::kill(Incoming& in)
130 {
131 checkResponseSent();
132 in._observer.adopt(_observer); // Give back the observer to incoming.
133 }
134
135 void
completed()136 IceInternal::IncomingAsync::completed()
137 {
138 for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
139 {
140 try
141 {
142 #ifdef ICE_CPP11_MAPPING
143 if(p->first && !p->first())
144 #else
145 if(!(*p)->response())
146 #endif
147 {
148 return;
149 }
150 }
151 catch(...)
152 {
153 }
154 }
155
156 checkResponseSent();
157 IncomingBase::response(true); // User thread
158 }
159
160 #ifdef ICE_CPP11_MAPPING
161 void
completed(exception_ptr ex)162 IceInternal::IncomingAsync::completed(exception_ptr ex)
163 {
164 for(DispatchInterceptorCallbacks::iterator p = _interceptorCBs.begin(); p != _interceptorCBs.end(); ++p)
165 {
166 try
167 {
168 if(p->second && !p->second(ex))
169 {
170 return;
171 }
172 }
173 catch(...)
174 {
175 }
176 }
177
178 checkResponseSent();
179 try
180 {
181 rethrow_exception(ex);
182 }
183 catch(const std::exception& exc)
184 {
185 IncomingBase::exception(exc, true); // User thread
186 }
187 catch(...)
188 {
189 IncomingBase::exception("unknown c++ exception", true); // User thread
190 }
191 }
192 #endif
193
194 void
checkResponseSent()195 IceInternal::IncomingAsync::checkResponseSent()
196 {
197 IceUtil::Mutex::Lock sync(*globalMutex);
198 if(_responseSent)
199 {
200 throw ResponseSentException(__FILE__, __LINE__);
201 }
202 _responseSent = true;
203 }
204
205 #ifndef ICE_CPP11_MAPPING
AMD_Object_ice_invoke(Incoming & in)206 IceAsync::Ice::AMD_Object_ice_invoke::AMD_Object_ice_invoke(Incoming& in) : IncomingAsync(in)
207 {
208 }
209
210 void
ice_response(bool ok,const vector<Byte> & outEncaps)211 IceAsync::Ice::AMD_Object_ice_invoke::ice_response(bool ok, const vector<Byte>& outEncaps)
212 {
213 if(outEncaps.empty())
214 {
215 writeParamEncaps(0, 0, ok);
216 }
217 else
218 {
219 writeParamEncaps(&outEncaps[0], static_cast<Int>(outEncaps.size()), ok);
220 }
221 completed();
222 }
223
224 void
ice_response(bool ok,const pair<const Byte *,const Byte * > & outEncaps)225 IceAsync::Ice::AMD_Object_ice_invoke::ice_response(bool ok, const pair<const Byte*, const Byte*>& outEncaps)
226 {
227 writeParamEncaps(outEncaps.first, static_cast<Int>(outEncaps.second - outEncaps.first), ok);
228 completed();
229 }
230 #endif
231