示例#1
0
void
Mutex_Lock(Mutex mutex, const char *reason)
{
    if (WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0) {       /* Got mutex */
        multi_debug("%s: lock acquired", reason);
    } else {
        multi_debug("%s: waiting on lock", reason);
        WaitForSingleObject(mutex, INFINITE);
        multi_debug("lock relinquished");
    }
}
示例#2
0
static void
ResetManualEvent(ManualEvent ME)
{
    multi_debug("reset manual event locks");
#if GLIB_CHECK_VERSION (2,32,0)
    g_mutex_lock(&condMutex);
    ME->signalled = FALSE;
    g_mutex_unlock(&condMutex);
#else
    g_mutex_lock(condMutex);
    ME->signalled = FALSE;
    g_mutex_unlock(condMutex);
#endif
    multi_debug("reset manual event unlocks");
}
示例#3
0
static void
MT_CreateThreads(void)
{
    unsigned int i;
    multi_debug("CreateThreads()");
    td.result = 0;
    td.closingThreads = FALSE;
    for (i = 0; i < td.numThreads; i++) {
        int *pID = (int *) malloc(sizeof(int));
        *pID = i;
#ifdef GLIB_THREADS
#if GLIB_CHECK_VERSION (2,32,0)
        if (!g_thread_try_new("Worker", MT_WorkerThreadFunction, pID, NULL))
#else
        if (!g_thread_create(MT_WorkerThreadFunction, pID, FALSE, NULL))
#endif
#else
        if (_beginthread(MT_WorkerThreadFunction, 0, pID) == 0)
#endif
            printf("Failed to create thread\n");
    }
    td.addedTasks = td.numThreads;
    /* Wait for all the threads to be created (timeout after 1 second) */
    if (MT_WaitForTasks(WaitingForThreads, 1000, FALSE) != (int) td.numThreads)
        g_print("Error creating threads!\n");
}
// Special loop that runs even if the watch is not on
// We can't rely on pulse_register_timer etc since they aren't running if
// the screen isn't on.
// pulse_get_millis doesn't update, and the clock runs so slow that per min is
// about as good as it gets.
// Screen cannot be used.
void mode_btlostphone_apploop(void) {
  multi_debug("mode_btlostphone_apploop\n");
  // multi_debug("%i > %i\n", pulse_get_millis(), mode_btlostphone_millis);
  // ALARM if we have passed our timeout
  if (multiTimeNow.tm_min != mode_btlostphone_min) {
    multi_debug("vibe!\n");

    // schedule next "alarm"
    mode_btlostphone_min = multiTimeNow.tm_min;

    // Buzz
    pulse_vibe_on();
    pulse_mdelay(1000); // should notice this...
    pulse_vibe_off();
  }
}
示例#5
0
static void
SetManualEvent(ManualEvent ME)
{
    multi_debug("reset manual event locks");
#if GLIB_CHECK_VERSION (2,32,0)
    g_mutex_lock(&condMutex);
    ME->signalled = TRUE;
    g_cond_broadcast(&ME->cond);
    g_mutex_unlock(&condMutex);
#else
    g_mutex_lock(condMutex);
    ME->signalled = TRUE;
    g_cond_broadcast(ME->cond);
    g_mutex_unlock(condMutex);
#endif
    multi_debug("reset manual event unlocks");
}
示例#6
0
void mode_demo_init() {
  multi_debug("init\n");
  multiMyWatchFaceName = "mode_demo";
  multiLoopTimeMS = 1000; // 1 second, since 200ms is too spammy in the demo
  multiButtonDownLongPressTimeMS = 400; // just under half a second
  printf("MODEINIT\nThe display is not really available...\n");
  // Would normally not pause here!
  pulse_mdelay(2000);
}
void mode_displaysleep_draw_digit(int iPosition, int iDigit) {
  multi_debug("digit %i %i\n", iPosition, iDigit);

  if(modeDisplaysleepCurrentlyDisplayed[iPosition] != iDigit) {
    modeDisplaysleepCurrentlyDisplayed[iPosition] = iDigit;
    pulse_draw_image(modeDisplaySleepWatchDigits[iDigit], 
      SCREEN_WIDTH - 12, 50 + (7 * iPosition));
  }
}
示例#8
0
static void
Mutex_Release(Mutex mutex)
{
#ifdef DEBUG_MULTITHREADED
    multi_debug("Releasing lock");
#endif
#if GLIB_CHECK_VERSION (2,32,0)
    g_mutex_unlock(&mutex);
#else
    g_mutex_unlock(mutex);
#endif
}
示例#9
0
int
MT_WaitForTasks(gboolean(*pCallback) (gpointer), int callbackTime, int autosave)
{
    int callbackLoops = callbackTime / UI_UPDATETIME;
    int waits = 0;
    int polltime = callbackLoops ? UI_UPDATETIME : callbackTime;
    guint as_source = 0;

    /* Set total tasks to wait for */
    td.totalTasks = td.addedTasks;
#if USE_GTK
    GTKSuspendInput();
#endif

    if (autosave)
        as_source = g_timeout_add(nAutoSaveTime * 60000, save_autosave, NULL);
    multi_debug("Waiting for all tasks");
    while (!WaitForAllTasks(polltime)) {
        waits++;
        if (pCallback && waits >= callbackLoops) {
            waits = 0;
            pCallback(NULL);
        }
        ProcessEvents();
    }
    if (autosave) {
        g_source_remove(as_source);
        save_autosave(NULL);
    }
    multi_debug("Done waiting for all tasks");

    td.doneTasks = td.addedTasks = 0;
    td.totalTasks = -1;

#if USE_GTK
    GTKResumeInput();
#endif
    return td.result;
}
// This is called regularly to stop the watch "going to sleep"; all we
// want to do here is cancel our existing timer and create a new one
void mode_displaysleep_update_power_down(int iPowerDownMS) {
  multi_debug("mode_displaysleep_update_power_down %i\n", iPowerDownMS);

  // Ensure our own personal "active" loop is cancelled
  pulse_cancel_timer(&modeDisplaysleepingTimerID); 
  assert(modeDisplaysleepingTimerID == -1);

  pulse_cancel_timer(&modeDisplaysleepPowerDownTimerID); // pulse
  assert(modeDisplaysleepPowerDownTimerID == -1);

  modeDisplaysleepPowerDownTimerID = pulse_register_timer(iPowerDownMS,
                   &mode_displaysleep_power_down, 0); // pulse
  assert(modeDisplaysleepPowerDownTimerID != -1);
}
示例#11
0
static void
Mutex_Lock(Mutex mutex, const char *reason)
{
#ifdef DEBUG_MULTITHREADED
    multi_debug(reason);
#else
    (void) reason;
#endif
#if GLIB_CHECK_VERSION (2,32,0)
    g_mutex_lock(&mutex);
#else
    g_mutex_lock(mutex);
#endif
}
示例#12
0
static void
WaitForManualEvent(ManualEvent ME)
{
#if GLIB_CHECK_VERSION (2,32,0)
    gint64 end_time;
#else
    GTimeVal tv;
#endif
    multi_debug("wait for manual event locks");
#if GLIB_CHECK_VERSION (2,32,0)
    g_mutex_lock(&condMutex);
    end_time = g_get_monotonic_time() + 10 * G_TIME_SPAN_SECOND;
#else
    g_mutex_lock(condMutex);
#endif
    while (!ME->signalled) {
        multi_debug("waiting for manual event");
#if GLIB_CHECK_VERSION (2,32,0)
        if (!g_cond_wait_until(&ME->cond, &condMutex, end_time))
#else
        g_get_current_time(&tv);
        g_time_val_add(&tv, 10 * 1000 * 1000);
        if (g_cond_timed_wait(ME->cond, condMutex, &tv))
#endif
            break;
        else {
            multi_debug("still waiting for manual event");
        }
    }

#if GLIB_CHECK_VERSION (2,32,0)
    g_mutex_unlock(&condMutex);
#else
    g_mutex_unlock(condMutex);
#endif
    multi_debug("wait for manual event unlocks");
}
void mode_displaysleep_tick_tock() {
  multi_debug("mode_displaysleep_tick_tock\n");

  pulse_cancel_timer(&modeDisplaysleepingTimerID); 
  assert(modeDisplaysleepingTimerID == -1);

  modeDisplaysleepingTimerID = pulse_register_timer(10000, // slow
                   &mode_displaysleep_tick_tock, 0); // pulse
  assert(modeDisplaysleepingTimerID != -1);

  mode_displaysleep_draw_digit(0, multiTimeNow.tm_hour / 10); // Digit *?:??
  mode_displaysleep_draw_digit(1, multiTimeNow.tm_hour % 10); // Digit ?*:??
  // position 2 has the colon!
  mode_displaysleep_draw_digit(3, multiTimeNow.tm_min / 10);  // Digit ??:*?
  mode_displaysleep_draw_digit(4, multiTimeNow.tm_min % 10);  // Digit ??:?*
}
示例#14
0
void
MT_AddTask(Task * pt, gboolean lock)
{
    if (lock) {
        Mutex_Lock(td.queueLock, "add task");
    }
    if (td.addedTasks == 0)
        td.result = 0;          /* Reset result for new tasks */
    td.addedTasks++;
    td.tasks = g_list_append(td.tasks, pt);
    if (g_list_length(td.tasks) == 1) { /* New tasks */
        SetManualEvent(td.activity);
    }
    if (lock) {
        multi_debug("add task: release");
        Mutex_Release(td.queueLock);
    }
}
示例#15
0
static Task *
MT_GetTask(void)
{
    Task *task = NULL;

    Mutex_Lock(td.queueLock, "get task");

    if (g_list_length(td.tasks) > 0) {
        task = (Task *) g_list_first(td.tasks)->data;
        td.tasks = g_list_delete_link(td.tasks, g_list_first(td.tasks));
        if (g_list_length(td.tasks) == 0) {
            ResetManualEvent(td.activity);
        }
    }

    multi_debug("get task: release");
    Mutex_Release(td.queueLock);

    return task;
}
void mode_btlostphone_watch_functions(const enum multi_function_table iFunc) {
  //multi_debug("enum %i\n", iFunc);
  switch (iFunc) {
    case COLDBOOT:
      mode_btlostphone_alarm_ignore = false;
      break;
    // No MODEINIT since all vars are globally used when the face is not visible
    case BUTTONWAKE:
      mode_btlostphone_update_screen = true;
      break;
    case MAINLOOP:
      if (mode_btlostphone_update_screen) {
        mode_btlostphone_draw_watch_face();
        mode_btlostphone_update_screen = false;
      }
      break;
    case BUTTONUP:
      mode_btlostphone_alarm_ignore = !mode_btlostphone_alarm_ignore;
      //break; // fall through to hardware change to reset timer etc
    case HARDWARECHANGE:
      multi_debug("HARDWARECHANGE\n");
      // BUTTONUP falls through here...
      // IMPORTANT: may not be active watch face so no screen output
      mode_btlostphone_update_screen = true; // if active it will update
      // Reset our "timer"
      mode_btlostphone_min = -1;
      //break; // Falls through to APPLOOP to buzz immediately
    case APPLOOP:
      // HARDWARECHANGE falls through here
      // Hence no screen output allowed
      if (!multiBluetoothIsConnected && !mode_btlostphone_alarm_ignore) {
        mode_btlostphone_apploop();
      }
      break;
    default: // ignore features we do not use
      break;
  }
}
示例#17
0
void
mt_add_tasks(unsigned int num_tasks, AsyncFun pFun, void *taskData, gpointer linked)
{
    unsigned int i;
    {
#ifdef DEBUG_MULTITHREADED
        char buf[20];
        sprintf(buf, "add %u tasks", num_tasks);
        Mutex_Lock(td.queueLock, buf);
#else
        Mutex_Lock(td.queueLock, NULL);
#endif
    }
    for (i = 0; i < num_tasks; i++) {
        Task *pt = (Task *) malloc(sizeof(Task));
        pt->fun = pFun;
        pt->data = taskData;
        pt->pLinkedTask = linked;
        MT_AddTask(pt, FALSE);
    }
    multi_debug("add many release: lock");
    Mutex_Release(td.queueLock);
}
// It's time to sleep!
void mode_displaysleep_power_down() {
  multi_debug("mode_displaysleep_power_down - time to sleep\n");
  // Immediately stop the watch doing anything else
  multi_external_sleep_init();

  pulse_cancel_timer(&modeDisplaysleepPowerDownTimerID); // pulse

  // Clear the display
  pulse_blank_canvas();

  pulse_oled_set_brightness(0); // dark

  // Clear our positions
  for (int i=0; i<MODE_DISPLAYSLEEP_DIGIT_POS_SIZE; i++) {
    modeDisplaysleepCurrentlyDisplayed[i] = MODE_DISPLAYSLEEP_NO_DIGIT;
  }

  // Display the colon
  mode_displaysleep_draw_digit(2, 10); // Digit ??*?? <-- colon

  // Now start the proper loop
  mode_displaysleep_tick_tock(); 
}
示例#19
0
int
MT_WaitForTasks(gboolean(*pCallback) (gpointer), int callbackTime, int autosave)
{
    GList *member;
    guint cb_source = 0;
    guint as_source = 0;
    td.doneTasks = 0;

#if USE_GTK
    GTKSuspendInput();
#endif

    multi_debug("Waiting for all tasks");

    pCallback(NULL);
    cb_source = g_timeout_add(1000, pCallback, NULL);
    if (autosave)
        as_source = g_timeout_add(nAutoSaveTime * 60000, save_autosave, NULL);
    for (member = g_list_first(td.tasks); member; member = member->next, td.doneTasks++) {
        Task *task = member->data;
        task->fun(task->data);
        free(task->pLinkedTask);
        free(task);
        ProcessEvents();
    }
    g_list_free(td.tasks);
    if (autosave) {
        g_source_remove(as_source);
        save_autosave(NULL);
    }
    td.tasks = NULL;

#if USE_GTK
    GTKResumeInput();
#endif
    return td.result;
}
示例#20
0
void mode_demo_main_loop() {
  multi_debug("main loop\n");
  printf("MAINLOOP\n");
}
示例#21
0
void mode_demo_bluetooth_received() {
  multi_debug("mode_demo_bluetooth_received\n");
  printf("BLUETOOTHREC\nFirst byte was %i\n", multiBluetoothRecBuffer[0]);
}
示例#22
0
void mode_demo_button_up() {
  multi_debug("mode_demo_button_up\n");
  printf("BUTTONUP\n");
}
示例#23
0
void mode_demo_button_down_long_press() {
  multi_debug("mode_demo_button_down_long_press\n");
  printf("BUTTONDOWNLONGPRESS\n");
}
示例#24
0
static gboolean
WaitingForThreads(gpointer UNUSED(unused))
{                               /* Unlikely to be called */
    multi_debug("Waiting for threads to be created!");
    return FALSE;
}
示例#25
0
void mode_demo_button_down() {
  multi_debug("mode_demo_button_down\n");
  printf("BUTTONDOWN\n");
}
示例#26
0
void mode_demo_woken_by_button() {
  multi_debug("mode_demo_woken_by_button\n");
  printf("BUTTONWAKE\n");
  printf("My face name %s\n", multiMyWatchFaceName);
}
示例#27
0
void
Mutex_Release(Mutex mutex)
{
    multi_debug("Releasing lock");
    ReleaseMutex(mutex);
}
示例#28
0
void mode_demo_cold_boot() {
  multi_debug("cold boot\n");
  printf("COLDBOOT\nThe display is not really available...\n");
  pulse_mdelay(1000);
}