1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
// Copyright 2019 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License. Both these licenses can be
// found in the LICENSE file.
#include <iostream>
#include <ctime>
#include <cassert>
#include <condition_variable>
#include <pthread.h>
#include <emscripten.h>
static long now() {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return time.tv_sec * 1000 + time.tv_nsec / 1000 / 1000;
}
static long ping, pong;
static std::mutex mutex;
static std::condition_variable cond_var;
static bool pong_requested = false;
void *thread_main(void *arg) {
std::cout << "running thread ..." << std::endl;
std::unique_lock<std::mutex> lock(mutex);
while (!pong_requested)
cond_var.wait(lock);
pong = now(); // Measure time in the pthread
std::cout << "pong - ping: " << (pong - ping) << std::endl;
pong_requested = false;
cond_var.notify_one();
return NULL;
}
EMSCRIPTEN_KEEPALIVE
extern "C" int notify() {
{
std::unique_lock<std::mutex> lock(mutex);
std::cout << "notifying ..." << std::endl;
ping = now();
pong_requested = true;
cond_var.notify_one();
}
{
std::unique_lock<std::mutex> lock(mutex);
while (pong_requested)
cond_var.wait(lock);
long last = now();
std::cout << "last - pong: " << (last - ping) << std::endl;
// Time measured on a worker should be relative to the main thread,
// so that things are basically monotonic.
assert((int(pong >= ping) + 2 * int(last >= pong)) == 3);
emscripten_force_exit(0);
}
return 0;
}
int main() {
std::cout << "running main ..." << std::endl;
EM_ASM(setTimeout(() => Module._notify()));
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_t thread;
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int error = pthread_create(&thread, &attr, thread_main, NULL);
assert(!error);
emscripten_exit_with_live_runtime();
__builtin_trap();
}
|