Example #1
0
// actor_obj = start_actor(callable)
int ActorStart(lua_State *L) {
  // Get the global state
  lua_pushstring(L, RIDX_RUNTIMESTATE);
  lua_gettable(L, LUA_REGISTRYINDEX);
  TenshiRuntimeState s = (TenshiRuntimeState)lua_topointer(L, -1);
  lua_pop(L, 1);

  // Create an actor
  // TODO(rqou): Hope calling ActorCreate doesn't somehow introduce a subtle
  // bug of some sort.
  TenshiActorState a = ActorCreate(s);
  if (!a) {
    lua_pushstring(L, "could not create new actor object!");
    lua_error(L);
  }

  // Move our callable onto the new actor state.
  lua_xmove(L, a->L, 1);

  // Append the new callable to the run queue
  ActorSetRunnable(a, 0);

  // our stack is empty
  // The object we want can be looked up in the global taskset.
  // TODO(rqou): This is not the most efficient.
  lua_pushcfunction(L, ActorFindInTaskset);
  // TODO(rqou): Is there a better way than doing this and then transplanting
  // the data back?
  lua_pushthread(a->L);
  lua_xmove(a->L, L, 1);
  lua_call(L, 1, 1);

  // stack is new actor object
  return 1;
}
Example #2
0
int main(int argc, char **argv) {
  printf("Hello world!\n");

  TenshiRuntimeState s = TenshiRuntimeInit();

  printf("Allocated state: %p\n", s);

  TenshiRegisterCFunctions(s, testprogram_runtimeentries);

  const char studentcode[] =
    "sensor = get_device('stestsensor')\n"
    "actuator = get_device('atestactuator')\n"
    "sensor_sampled = triggers.sampled(sensor)\n"
    "\n"
    "while true do\n"
    "    local val = sensor_sampled:recv()\n"
    "    print('sensor is ' .. tostring(val))\n"
    "    actuator:send({val})\n"
    "end";

  TenshiActorState a;

  int ret = LoadStudentcode(s, studentcode, strlen(studentcode), &a);
  printf("LoadStudentcode: %d, TenshiActorState: %p\n", ret, a);

  ret = ActorSetRunnable(a, 1);
  printf("ActorSetRunnable: %d\n", ret);

  int i = 0;

  while (i < 100) {
    printf("-----> Sent into sensor: %d\n", i);
    global_sensor_data = i;
    ret = TenshiFlagSensor(s, hax_dev_sensor);
    printf("TenshiFlagSensor: %d\n", ret);

    ret = TenshiRunQuanta(s);
    printf("Ran quanta %d, ret = %d\n", i, ret);

    i++;
  }

  TenshiRuntimeDeinit(s);

  printf("Done!\n");

  return 0;
}
Example #3
0
int TenshiRunQuanta(TenshiRuntimeState s) {
  int ops_left = QUANTA_OPCODES;

  while (ops_left > 0) {
    TenshiActorState a;
    int ret = ActorDequeueHead(s, &a);
    if (ret != LUA_OK) return ret;

    if (!a) {
      printf("NOTHING TO RUN!\n");
      return LUA_OK;
    }

    ret = threading_run_ops(a->L, ops_left, &ops_left);
    if (ret == THREADING_ERROR) {
      printf("THERE WAS AN ERROR!\n");

      const char *msg = lua_tostring(a->L, -1);
      if (msg)  /* is error object a string? */
        luaL_traceback(a->L, a->L, msg, 0);  /* use standard traceback */
      else if (!lua_isnoneornil(a->L, -1)) {  /* non-string error object? */
        /* try its 'tostring' metamethod */
        if (!luaL_callmeta(a->L, -1, "__tostring"))
          lua_pushliteral(a->L, "(no error message)");
      }  /* else no error object, does nothing */

      const char *err_w_traceback = lua_tostring(a->L, -1);
      printf("%s\n", err_w_traceback);
      return LUA_ERRRUN;
    }

    if (ret == THREADING_EXITED) {
      printf("Thread exited!\n");
      ActorDestroy(a);
    } else if (ret == THREADING_YIELD) {
      printf("Thread yielded (blocked)!\n");
      ret = ActorSetBlocked(a);
      if (ret != LUA_OK) return ret;
    } else if (ret == THREADING_PREEMPT) {
      // Requeue it
      printf("Thread preempted!\n");
      ret = ActorSetRunnable(a, 0);
      if (ret != LUA_OK) return ret;
    }
  }

  return LUA_OK;
}
Example #4
0
int TenshiRunQuanta(TenshiRuntimeState s) {
  // Do timeouts
  ActorProcessTimeouts(s);

  // Run the sensor actor
  // Dup the function first, as it disappears when we exit
  // TODO(rqou): Will we have a problem with the hardcoded op limit?
  lua_pushvalue(s->sensor_actor->L, -1);
  int ret = threading_run_ops(s->sensor_actor->L, 1000, NULL);
  if (ret != THREADING_EXITED) {
    printf("There was an error running the sensor actor!\n");
    print_traceback(s->sensor_actor->L);
    return ret;
  }

  // Run the main code
  int ops_left = QUANTA_OPCODES;
  while (ops_left > 0) {
    TenshiActorState a;
    ret = ActorDequeueHead(s, &a);
    if (ret != LUA_OK) return ret;

    if (!a) {
      break;
    }

    ret = threading_run_ops(a->L, ops_left, &ops_left);
    if (ret == THREADING_ERROR) {
      printf("THERE WAS AN ERROR!\n");
      print_traceback(a->L);

      return LUA_ERRRUN;
    }

    if (ret == THREADING_EXITED) {
      printf("Thread exited!\n");
      ActorDestroy(a);
    } else if (ret == THREADING_YIELD) {
      printf("Thread yielded (blocked)!\n");
      ret = ActorSetBlocked(a);
      if (ret != LUA_OK) return ret;
    } else if (ret == THREADING_PREEMPT) {
      // Requeue it
      ret = ActorSetRunnable(a, 0);
      if (ret != LUA_OK) return ret;
    }
  }

  // Run the actuator actor
  // Dup the function first, as it disappears when we exit
  lua_pushvalue(s->actuator_actor->L, -1);
  ret = threading_run_ops(s->actuator_actor->L, 1000, NULL);
  if (ret != THREADING_EXITED) {
    printf("There was an error running the actuator actor!\n");
    print_traceback(s->actuator_actor->L);
    return ret;
  }

  lua_gc(s->L, LUA_GCCOLLECT, 0);

  return LUA_OK;
}