diff options
author | Jose Bollo <jose.bollo@iot.bzh> | 2018-12-31 11:15:19 +0100 |
---|---|---|
committer | Jose Bollo <jose.bollo@iot.bzh> | 2019-01-02 09:46:01 +0100 |
commit | 75083317eb9a49eb9b65704c81a90c1cf44544d9 (patch) | |
tree | 646af8c50412179c5ca0d5a4f0fcc5154069b915 /bindings/samples/hello3.c | |
parent | 7916ea9258ce0a9d4951462836c5c06f2e227db3 (diff) |
hello3: Add verb 'after'
The verb 'after' launches a new thread
that after a delay will call a verb (like
call). The type of call can be set to 'call',
'callsync', 'subcall' or 'subcallsync'.
This allows to add test for asynchronous issues
in multithreaded environment.
Change-Id: Ic59a27b7b7fbd3716d34fdaa35c42aa9ecb7f201
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'bindings/samples/hello3.c')
-rw-r--r-- | bindings/samples/hello3.c | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/bindings/samples/hello3.c b/bindings/samples/hello3.c index b50ea46d..131e0e43 100644 --- a/bindings/samples/hello3.c +++ b/bindings/samples/hello3.c @@ -19,6 +19,8 @@ #include <string.h> #include <pthread.h> #include <fcntl.h> +#include <math.h> +#include <errno.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -29,7 +31,7 @@ #include <afb/afb-binding.h> #if !defined(APINAME) -#define APINAME "hello3" +#define APINAME "hello" #endif static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; @@ -618,6 +620,79 @@ static void locale (afb_req_t request) } } +static void in_after (afb_req_t request) +{ + int rc; + const char *ts, *ty; + char *te; + double td; + struct timespec t; + void (*calling)(afb_req_t); + + /* get the type */ + ty = afb_req_value(request, "type") ?: "call"; + if (strcmp(ty, "call") && strcmp(ty, "callsync") + && strcmp(ty, "subcall") && strcmp(ty, "subcallsync")) + return afb_req_reply(request, NULL, "invalid", "bad type"); + + /* get the delay */ + ts = afb_req_value(request, "delay"); + if (!ts) + return afb_req_reply(request, NULL, "invalid", "no delay"); + td = strtod(ts, &te); + if (*te || td < 0 || td > 3e6) /* a month is the biggest accepted */ + return afb_req_reply(request, NULL, "invalid", "bad delay"); + + /* wait for that time */ + if (td > 0) { + t.tv_nsec = (long)(1e6 * modf(td, &td)); + t.tv_sec = (time_t)td; + do { + rc = nanosleep(&t, &t); + } while (rc != 0 && errno == EINTR); + + if (rc) + return afb_req_reply(request, NULL, "error", "sleep failed"); + } + + /* do the call */ + if (!strcmp(ty, "subcallsync")) + subcall(request); + else if (!strcmp(ty, "subcall")) + subcallsync(request); + else if (!strcmp(ty, "callsync")) + callsync(request); + else + call(request); +} + +static void *thread_after (void *closure) +{ + afb_req_t request = closure; + in_after (request); + afb_req_unref(request); + return NULL; +} + +static void after (afb_req_t request) +{ + int rc; + pthread_t tid; + pthread_attr_t attr; + + afb_req_addref(request); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc =pthread_create(&tid, &attr, thread_after, request); + pthread_attr_destroy(&attr); + + if (rc != 0) { + afb_req_unref(request); + afb_req_reply(request, NULL, "cant-start", NULL); + } +} + static void api (afb_req_t request); /** @@ -735,6 +810,7 @@ static const struct afb_verb_v3 verbs[]= { { .verb="setctx", .callback=setctx, .vcbdata = (void*)(intptr_t)1 }, { .verb="setctxif", .callback=setctx, .vcbdata = (void*)(intptr_t)0 }, { .verb="getctx", .callback=getctx }, + { .verb="checktok", .callback=ok, .session=AFB_SESSION_CHECK }, { .verb="reftok", .callback=ok, .session=AFB_SESSION_CHECK | AFB_SESSION_REFRESH }, { .verb="info", .callback=info }, { .verb="eventloop", .callback=eventloop }, @@ -749,6 +825,7 @@ static const struct afb_verb_v3 verbs[]= { { .verb="mutebug", .callback=mutebug}, { .verb="queue", .callback=queue}, { .verb="settings", .callback=settings}, + { .verb="after", .callback=after}, { .verb=NULL} }; |