Server::OldAPI::CallResult Server::OldAPI::callMethod(BredyHttpSrv::IHttpRequestInfo* httpRequest, ConstStrA methodName, const JSON::Value& args, const JSON::Value& context, const JSON::Value& id) { class FakePeer: public IPeer { public: virtual BredyHttpSrv::IHttpRequestInfo *getHttpRequest() const {return req;} virtual ConstStrA getName() const { return req->getIfc<BredyHttpSrv::IHttpPeerInfo>().getPeerRealAddr(); } virtual natural getPortIndex() const { return req->getIfc<BredyHttpSrv::IHttpPeerInfo>().getSourceId(); } virtual IRpcNotify *getNotifySvc() const { return 0; } virtual void setContext(Context *ctx) { this->ctx = ctx; } virtual Context *getContext() const { return ctx; } virtual IClient *getClient() const { return 0; } virtual natural getVersion() const { return version; } ContextVar ctx; BredyHttpSrv::IHttpRequestInfo *req; natural version; FakePeer(BredyHttpSrv::IHttpRequestInfo *req,natural version):req(req),version(version) {} }; FakePeer fakePeer(httpRequest, this->version); WeakRefTarget<IPeer> peer(&fakePeer); JSON::Builder json; Request req; req.context = context; req.params = args; req.id = id; req.methodName = json(methodName); req.isNotification = false; req.dispatcher = owner.getDispatcherWeakRef(); req.peer = peer; req.json = json.factory; CallResult cres; Future<Response> resp = owner.callMethod(req); cres.id = id; try { const Response &result = resp.getValue(); cres.error = JSON::getConstant(JSON::constNull); cres.result = static_cast<const JSON::Value &>(result.result); cres.newContext = static_cast<const JSON::Value &>(result.context); cres.logOutput = result.logOutput; return cres; } catch (jsonsrv::RpcError &e) { cres.error = e.getError(); cres.result = JSON::getConstant(JSON::constNull); cres.logOutput = cres.error; return cres; } catch (RpcException &e) { cres.error = const_cast<JSON::INode *>(e.getJSON(json).get()); cres.result = JSON::getConstant(JSON::constNull); cres.logOutput = cres.error; return cres; } }
// The primary thread function, which issues calls through the secondary thread void rundemos() { // Create an event for which our second thread will wait hExternalEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Create the secondary thread DWORD dwThreadId; HANDLE hThread = CreateThread(NULL, 0, demoThread, NULL, 0, &dwThreadId); // Obtain a scheduler instance, through which we can make cross thread calls CallScheduler<APCPickupPolicy>* scheduler = CallScheduler<APCPickupPolicy>::getInstance(); // Do a first cross thread call, to a function returning a string try { string dataString = scheduler->syncCall<string, ExceptionTypes<std::exception>>(dwThreadId, boost::bind(demoFunction, 'a'), INFINITE); cout << "demoFunction returned: " << dataString << endl; } catch(CallTimeoutException&) { cout << "Call timeout." << endl; } catch(CallSchedulingFailedException&) { cout << "Call scheduling failed -- Probably a broken pickup policy." << endl; } catch(std::exception& e) { cout << "The scheduled call threw a std exception: " << e.what() << endl; } // Do a second cross thread call, to a function returning nothing try { // Expect a std::exception or DemoException scheduler->syncCall<void, ExceptionTypes<std::exception, DemoException>>(dwThreadId, boost::bind(demoVoidFunction, 'a'), 500); } catch(CallTimeoutException&) { cout << "Call timeout" << endl; } catch(CallSchedulingFailedException&) { cout << "Call scheduling failed -- Probably a broken pickup policy." << endl; } catch(std::exception& e) { cout << "demoVoidFunction threw a std exception: " << e.what() << endl; } catch(DemoException&) { cout << "demoVoidFunction threw a DemoException" << endl; } // Do a third cross thread call, to a function returning an int try { // Expect a std::exception or DemoException int demoInt = scheduler->syncCall<int, ExceptionTypes<std::exception, DemoException>>(dwThreadId, boost::bind(demoIntFunction, '!'), 500); cout << "demoIntFunction returned: " << demoInt << endl; } catch(CallTimeoutException&) { cout << "Call timeout" << endl; } catch(CallSchedulingFailedException&) { cout << "Call scheduling failed -- Probably a broken pickup policy." << endl; } catch(std::exception& e) { cout << "demoIntFunction threw a std exception: " << e.what() << endl; } catch(DemoException&) { cout << "demoIntFunction threw a DemoException" << endl; } // Do a fourth cross thread call, to a function returning an int try { boost::function<int()> f = boost::bind(demoIntFunctionDelayed, '!'); Future<int> futureDemoInt = scheduler->asyncCall<ExceptionTypes<DemoException, std::exception>>(dwThreadId, f); //Future<int> futureDemoInt2 = scheduler->asyncCall<ExceptionTypes<DemoException, std::exception>>(dwThreadId, boost::bind(demoIntFunctionDelayed, '!')); Future<void> futureDemoInt3 = scheduler->asyncCall<void>(dwThreadId, boost::bind(demoIntFunctionDelayed, '?')); Future<int> futureDemoInt4 = scheduler->asyncCall<int>(dwThreadId, boost::bind(demoIntFunctionDelayed, '!')); Future<int> futureDemoInt5 = scheduler->asyncCall<int, ExceptionTypes<DemoException>>(dwThreadId, boost::bind(demoIntFunctionDelayed, '!')); Future<void> futureDemoInt6 = scheduler->asyncCall<void, ExceptionTypes<DemoException>>(dwThreadId, boost::bind(demoIntFunctionDelayed, '!')); Future<void> futureDemoInt7 = scheduler->asyncCall<ExceptionTypes<DemoException>, void>(dwThreadId, boost::bind(demoIntFunctionDelayed, '!')); Future<int> futureDemoInt8 = scheduler->asyncCall<ExceptionTypes<DemoException>, int>(dwThreadId, boost::bind(demoIntFunctionDelayed, '!')); while(futureDemoInt.wait(10) == ASYNCH_CALL_PENDING) { cout << "Still waiting ..." << endl; } cout << "demoIntFunctionDelayed returned: " << futureDemoInt.getValue() << endl; } catch(CallSchedulingFailedException&) { cout << "Call scheduling failed -- Probably a broken pickup policy." << endl; } // Cleanup SetEvent(hExternalEvent); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hExternalEvent); }