#include <emscripten/emscripten.h>
#include <emscripten/eventloop.h>
#include <emscripten/console.h>

#include <assert.h>
#include <pthread.h>
#include <stdio.h>

_Atomic int ready;

void markReady(void* arg) {
  ready = 1;
}

void* thread_main(void* arg) {
  int keepalive = (intptr_t)arg;
  emscripten_outf("in thread_main: %d", keepalive);
  if (keepalive) {
    // Exit with live runtime.  Once we are in the event loop call markReady.
    emscripten_async_call(markReady, NULL, 0);
    emscripten_exit_with_live_runtime();
  }
  return NULL;
}

void checkThreadPool() {
  int running = EM_ASM_INT(return Object.keys(PThread.pthreads).length);
  int unused = EM_ASM_INT(return PThread.unusedWorkers.length);
  printf("running=%d unused=%d\n", running, unused);
  assert(running == 0);
  assert(unused == 1);
}

int main() {
  printf("in main\n");
  checkThreadPool();
  pthread_t t, t2;

  for (int i = 0; i < 3; i++) {
    ready = 0;

    // Create a thread that exit's with a non-zero keepalive counter
    pthread_create(&t, NULL, thread_main, (void*)1);
    while (!ready) {}
    pthread_cancel(t);
    pthread_join(t, NULL);
    checkThreadPool();

    // Create a second thread that should re-use the same worker.
    // This thread should reset its keepalive counter on startup and
    // be able to exit normally.
    pthread_create(&t2, NULL, thread_main, NULL);
    pthread_join(t2, NULL);
    checkThreadPool();
  }
  printf("done\n");
}
