X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=AFBClient.cpp;h=9210eacbe89a2b9697f50338366b43216d47b84f;hb=715231c6093c54797d36c1e01667439d0a8741f3;hp=d3e3a5ec99146a501fb03fa5caf0f0346c86fcd3;hpb=49fe14f956c0bef44c047b7d6fc98412abaedace;p=staging%2Fwindowmanager.git diff --git a/AFBClient.cpp b/AFBClient.cpp index d3e3a5e..9210eac 100644 --- a/AFBClient.cpp +++ b/AFBClient.cpp @@ -7,6 +7,9 @@ #include #include +#include +#include + #include #include @@ -83,17 +86,21 @@ void onHangup(void *closure, afb_wsj1 *wsj1) { exit(0); } -static struct afb_wsj1_itf itf = { +constexpr static struct afb_wsj1_itf itf = { onHangup, onCall, onEvent, }; -void dispatch_internal(AFBClient *c, uint64_t timeout) { +// XXX: I am not sure this is the right thing to do though... +std::recursive_mutex dispatch_mutex; + +void dispatch_internal(struct sd_event *loop) { + std::lock_guard guard(dispatch_mutex); TRACE(); - c->dispatch(timeout); + sd_event_run(loop, -1); } /// object will be json_object_put -int api_call(AFBClient *c, struct afb_wsj1 *wsj1, const char *verb, +int api_call(struct sd_event *loop, struct afb_wsj1 *wsj1, const char *verb, json_object *object, std::function onReply) { TRACE(); @@ -104,7 +111,8 @@ int api_call(AFBClient *c, struct afb_wsj1 *wsj1, const char *verb, // Alternatively we could setup a local struct and use it as // closure, but I think it is cleaner this way. int call_rc = 0; - bool returned = false; + std::atomic returned; + returned.store(false, std::memory_order_relaxed); std::function wrappedOnReply = [&returned, &call_rc, &onReply](bool ok, json_object *j) { TRACEN(wrappedOnReply); @@ -115,7 +123,7 @@ int api_call(AFBClient *c, struct afb_wsj1 *wsj1, const char *verb, TRACEN(onReply); onReply(ok, j); } - returned = true; + returned.store(true, std::memory_order_release); }; // make the actual call, use wrappedOnReply as closure @@ -141,8 +149,8 @@ int api_call(AFBClient *c, struct afb_wsj1 *wsj1, const char *verb, // We need to dispatch until "returned" got set, this is necessary // if events get triggered by the call (and would be dispatched before // the actual call-reply). - while (!returned) { - dispatch_internal(c, -1); + while (!returned.load(std::memory_order_consume)) { + dispatch_internal(loop); } // return the actual API call result @@ -154,22 +162,45 @@ int api_call(AFBClient *c, struct afb_wsj1 *wsj1, const char *verb, } // namespace -AFBClient &AFBClient::instance() { - TRACE(); - static AFBClient obj; - return obj; -} +// _ ___ _ +// ___| | __ _ ___ ___ |_ _|_ __ ___ _ __ | | +// / __| |/ _` / __/ __| | || '_ ` _ \| '_ \| | +// | (__| | (_| \__ \__ \ | || | | | | | |_) | | +// \___|_|\__,_|___/___/ |___|_| |_| |_| .__/|_| +// |_| +class AFBClient::Impl { + friend class AFBClient; + + // This is the AFBClient interface impl + int init(int port, char const *token); + int dispatch(); + + // WM API + int requestSurface(const char *label); + int activateSurface(const char *label); + int deactivateSurface(const char *label); + int endDraw(const char *label); + + void set_event_handler(enum EventType et, + std::function f); + + Impl(); + ~Impl(); + + struct afb_wsj1 *wsj1; + struct sd_event *loop; +}; -AFBClient::AFBClient() : wsj1{}, loop{} { TRACE(); } +AFBClient::Impl::Impl() : wsj1{}, loop{} { TRACE(); } -AFBClient::~AFBClient() { +AFBClient::Impl::~Impl() { TRACE(); afb_wsj1_unref(wsj1); sd_event_unref(loop); loop = nullptr; } -int AFBClient::init(int port, char const *token) { +int AFBClient::Impl::init(int port, char const *token) { TRACE(); char *uribuf = nullptr; int rc = -1; @@ -205,7 +236,8 @@ int AFBClient::init(int port, char const *token) { asprintf(&uribuf, "ws://localhost:%d/api?token=%s", port, token); /* connect the websocket wsj1 to the uri given by the first argument */ - wsj1 = afb_ws_client_connect_wsj1(loop, uribuf, &itf, nullptr); + wsj1 = afb_ws_client_connect_wsj1( + loop, uribuf, const_cast(&itf), nullptr); if (wsj1 == nullptr) { sd_event_unref(loop); fprintf(stderr, "Connection to %s failed: %m\n", uribuf); @@ -219,18 +251,19 @@ fail: return rc; } -int AFBClient::dispatch(uint64_t timeout) { - return sd_event_run(loop, timeout); +int AFBClient::Impl::dispatch() { + std::lock_guard guard(dispatch_mutex); + return sd_event_run(loop, 1); } -int AFBClient::requestSurface(const char *label) { +int AFBClient::Impl::requestSurface(const char *label) { TRACE(); json_object *jp = json_object_new_object(); json_object_object_add(jp, "drawing_name", json_object_new_string(label)); int rc = -1; /* send the request */ int rc2 = api_call( - this, wsj1, "request_surface", jp, [&rc](bool ok, json_object *j) { + loop, wsj1, "request_surface", jp, [&rc](bool ok, json_object *j) { if (ok) { int id = json_object_get_int(json_object_object_get(j, "response")); @@ -255,11 +288,11 @@ int AFBClient::requestSurface(const char *label) { return rc2 < 0 ? rc2 : rc; } -int AFBClient::activateSurface(const char *label) { +int AFBClient::Impl::activateSurface(const char *label) { TRACE(); json_object *j = json_object_new_object(); json_object_object_add(j, "drawing_name", json_object_new_string(label)); - return api_call(this, wsj1, "activate_surface", j, [](bool ok, + return api_call(loop, wsj1, "activate_surface", j, [](bool ok, json_object *j) { if (!ok) { fprintf( @@ -270,11 +303,11 @@ int AFBClient::activateSurface(const char *label) { }); } -int AFBClient::deactivateSurface(const char *label) { +int AFBClient::Impl::deactivateSurface(const char *label) { TRACE(); json_object *j = json_object_new_object(); json_object_object_add(j, "drawing_name", json_object_new_string(label)); - return api_call(this, wsj1, "deactivate_surface", j, [](bool ok, + return api_call(loop, wsj1, "deactivate_surface", j, [](bool ok, json_object *j) { if (!ok) { fprintf( @@ -285,11 +318,11 @@ int AFBClient::deactivateSurface(const char *label) { }); } -int AFBClient::endDraw(const char *label) { +int AFBClient::Impl::endDraw(const char *label) { TRACE(); json_object *j = json_object_new_object(); json_object_object_add(j, "drawing_name", json_object_new_string(label)); - return api_call(this, wsj1, "enddraw", j, [](bool ok, json_object *j) { + return api_call(loop, wsj1, "enddraw", j, [](bool ok, json_object *j) { if (!ok) { fprintf( stderr, "API Call endDraw() failed: %s\n", @@ -299,10 +332,51 @@ int AFBClient::endDraw(const char *label) { }); } -void AFBClient::set_event_handler(enum EventType et, - std::function func) { +void AFBClient::Impl::set_event_handler( + enum EventType et, std::function func) { UNUSED(et); UNUSED(func); TRACE(); // XXX todo } + +// _ _ _____ ____ ____ _ _ _ +// ___| | __ _ ___ ___ / \ | ___| __ ) / ___| (_) ___ _ __ | |_ +// / __| |/ _` / __/ __| / _ \ | |_ | _ \| | | | |/ _ \ '_ \| __| +// | (__| | (_| \__ \__ \ / ___ \| _| | |_) | |___| | | __/ | | | |_ +// \___|_|\__,_|___/___/ /_/ \_\_| |____/ \____|_|_|\___|_| |_|\__| +// +int AFBClient::init(int port, char const *token) { + return this->d->init(port, token); +} + +int AFBClient::dispatch() { return this->d->dispatch(); } + +int AFBClient::requestSurface(const char *label) { + return this->d->requestSurface(label); +} + +int AFBClient::activateSurface(const char *label) { + return this->d->activateSurface(label); +} + +int AFBClient::deactivateSurface(const char *label) { + return this->d->deactivateSurface(label); +} + +int AFBClient::endDraw(const char *label) { return this->d->endDraw(label); } + +void AFBClient::set_event_handler(enum EventType et, + std::function f) { + return this->d->set_event_handler(et, std::move(f)); +} + +AFBClient &AFBClient::instance() { + TRACE(); + static AFBClient obj; + return obj; +} + +AFBClient::AFBClient() : d(new Impl) {} + +AFBClient::~AFBClient() { delete d; }