void geventDetachSource(GListener *pl, GSourceHandle gsh) { if (pl) { gfxMutexEnter(&geventMutex); deleteAssignments(pl, gsh); if (!gsh && gfxSemCounter(&pl->waitqueue) < 0) { gfxSemWait(&pl->eventlock, TIME_INFINITE); // Obtain the buffer lock pl->event.type = GEVENT_EXIT; // Set up the EXIT event gfxSemSignal(&pl->waitqueue); // Wake up the listener gfxSemSignal(&pl->eventlock); // Release the buffer lock } gfxMutexExit(&geventMutex); } }
void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param) { if (pl) { gfxMutexEnter(&geventMutex); gfxSemWait(&pl->eventlock, TIME_INFINITE); // Obtain the buffer lock pl->param = param; // Set the param pl->callback = fn; // Set the callback function if (gfxSemCounter(&pl->waitqueue) < 0) { pl->event.type = GEVENT_EXIT; // Set up the EXIT event gfxSemSignal(&pl->waitqueue); // Wake up the listener } gfxSemSignal(&pl->eventlock); // Release the buffer lock gfxMutexExit(&geventMutex); } }
/* Null is treated as a wildcard. */ static void deleteAssignments(GListener *pl, GSourceHandle gsh) { GSourceListener *psl; for(psl = Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) { if ((!pl || psl->pListener == pl) && (!gsh || psl->pSource == gsh)) { if (gfxSemCounter(&psl->pListener->waitqueue) < 0) { gfxSemWait(&psl->pListener->eventlock, TIME_INFINITE); // Obtain the buffer lock psl->pListener->event.type = GEVENT_EXIT; // Set up the EXIT event gfxSemSignal(&psl->pListener->waitqueue); // Wake up the listener gfxSemSignal(&psl->pListener->eventlock); // Release the buffer lock } psl->pListener = 0; } } }
void geventSendEvent(GSourceListener *psl) { gfxMutexEnter(&geventMutex); if (psl->pListener->callback) { // Mark it back as free and as sent. This is early to be marking as free but it protects // if the callback alters the listener in any way psl->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY|GLISTENER_PENDING); gfxMutexExit(&geventMutex); // Do the callback psl->pListener->callback(psl->pListener->param, &psl->pListener->event); } else { // Wake up the listener psl->pListener->flags &= ~GLISTENER_WITHSOURCE; if ((psl->pListener->flags & GLISTENER_WAITING)) { psl->pListener->flags &= ~(GLISTENER_WAITING|GLISTENER_PENDING); gfxSemSignal(&psl->pListener->waitqueue); } else psl->pListener->flags |= GLISTENER_PENDING; // The listener thread will free the event buffer when ready gfxMutexExit(&geventMutex); } }
void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) { gfxQueueFSyncItem *pi; if (!pitem) return; // Safety gfxSystemLock(); if (pqueue->head) { if (pqueue->head == pitem) { pqueue->head = pitem->next; found: pitem->next = 0; gfxSystemUnlock(); gfxSemSignal(&pitem->sem); gfxSemDestroy(&pitem->sem); return; } for(pi = pqueue->head; pi->next; pi = pi->next) { if (pi->next == pitem) { pi->next = pitem->next; if (pqueue->tail == pitem) pqueue->tail = pi; goto found; } } } gfxSystemUnlock(); }
bool_t gfxQueueFSyncInsert(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gfxQueueASyncItem *pafter, delaytime_t ms) { if (!pitem) return; // Safety gfxSemInit(&pitem->sem, 0, 1); gfxSystemLock(); if (pafter && gfxQueueGSyncIsInI(pqueue, pafter)) { pitem->next = pafter->next; pafter->next = pitem; if (pqueue->tail == pafter) pqueue->tail = pitem; } else { pitem->next = 0; if (!pqueue->head) { pqueue->head = pqueue->tail = pitem; } else { pqueue->tail->next = pitem; pqueue->tail = pitem; } } gfxSystemUnlock(); gfxSemSignal(&pqueue->sem); return gfxSemWait(&pitem->sem, ms); }
/* We already have the geventMutex */ static void doExitEvent(GListener *pl) { // Don't do the exit if someone else currently has the event lock if ((pl->flags & (GLISTENER_WAITING|GLISTENER_EVENTBUSY)) == GLISTENER_WAITING) { pl->flags |= GLISTENER_EVENTBUSY; // Event buffer is in use pl->event.type = GEVENT_EXIT; // Set up the EXIT event pl->flags &= ~GLISTENER_WAITING; // Wake up the listener (with data) gfxSemSignal(&pl->waitqueue); } }
void gtimerJab(GTimer *pt) { gfxMutexEnter(&mutex); // Jab it! pt->flags |= GTIMER_FLG_JABBED; // Bump the thread gfxSemSignal(&waitsem); gfxMutexExit(&mutex); }
void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { gfxSystemLock(); pitem->next = pqueue->head; pqueue->head = pitem; if (!pitem->next) pqueue->tail = pitem; gfxSystemUnlock(); gfxSemSignal(&pqueue->sem); }
void _gwinDrawEnd(GHandle gh) { // Ensure there is no clip set #if GDISP_NEED_CLIP gdispGUnsetClip(gh->display); #endif // Look for something to redraw _gwinFlushRedraws(REDRAW_INSESSION); // Release the lock gfxSemSignal(&gwinsem); }
bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) { gfxSemInit(&pitem->sem, 0, 1); gfxSystemLock(); pitem->next = pqueue->head; pqueue->head = pitem; if (!pitem->next) pqueue->tail = pitem; gfxSystemUnlock(); gfxSemSignal(&pqueue->sem); return gfxSemWait(&pitem->sem, ms); }
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, delaytime_t millisec) { gfxMutexEnter(&mutex); // Start our thread if not already going if (!hThread) { hThread = gfxThreadCreate(waTimerThread, GTIMER_THREAD_WORKAREA_SIZE, GTIMER_THREAD_PRIORITY, GTimerThreadHandler, 0); if (hThread) {gfxThreadClose(hThread);} // We never really need the handle again } // Is this already scheduled? if (pt->flags & GTIMER_FLG_SCHEDULED) { // Cancel it! if (pt->next == pt) pTimerHead = 0; else { pt->next->prev = pt->prev; pt->prev->next = pt->next; if (pTimerHead == pt) pTimerHead = pt->next; } } // Set up the timer structure pt->fn = fn; pt->param = param; pt->flags = GTIMER_FLG_SCHEDULED; if (periodic) pt->flags |= GTIMER_FLG_PERIODIC; if (millisec == TIME_INFINITE) { pt->flags |= GTIMER_FLG_INFINITE; pt->period = TIME_INFINITE; } else { pt->period = gfxMillisecondsToTicks(millisec); pt->when = gfxSystemTicks() + pt->period; } // Just pop it on the end of the queue if (pTimerHead) { pt->next = pTimerHead; pt->prev = pTimerHead->prev; pt->prev->next = pt; pt->next->prev = pt; } else pt->next = pt->prev = pTimerHead = pt; // Bump the thread if (!(pt->flags & GTIMER_FLG_INFINITE)) gfxSemSignal(&waitsem); gfxMutexExit(&mutex); }
void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { pitem->next = 0; gfxSystemLock(); if (!pqueue->head) { pqueue->head = pqueue->tail = pitem; } else { pqueue->tail->next = pitem; pqueue->tail = pitem; } gfxSystemUnlock(); gfxSemSignal(&pqueue->sem); }
void geventSendEvent(GSourceListener *psl) { gfxMutexEnter(&geventMutex); if (psl->pListener->callback) { // This test needs to be taken inside the mutex gfxMutexExit(&geventMutex); // We already know we have the event lock psl->pListener->callback(psl->pListener->param, &psl->pListener->event); } else { // Wake up the listener if (gfxSemCounter(&psl->pListener->waitqueue) <= 0) gfxSemSignal(&psl->pListener->waitqueue); gfxMutexExit(&geventMutex); } }
gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) { gfxQueueFSyncItem *pi; if (!gfxSemWait(&pqueue->sem, ms)) return 0; gfxSystemLock(); pi = pqueue->head; pqueue->head = pi->next; pi->next = 0; gfxSystemUnlock(); gfxSemSignal(&pi->sem); gfxSemDestroy(&pi->sem); return pi; }
bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) { if (!pitem) return; // Safety gfxSemInit(&pitem->sem, 0, 1); pitem->next = 0; gfxSystemLock(); if (!pqueue->head) { pqueue->head = pqueue->tail = pitem; } else { pqueue->tail->next = pitem; pqueue->tail = pitem; } gfxSystemUnlock(); gfxSemSignal(&pqueue->sem); return gfxSemWait(&pitem->sem, ms); }
bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, unsigned flags) { GSourceListener *psl, *pslfree; // Safety first if (!pl || !gsh) { GEVENT_ASSERT(FALSE); return FALSE; } gfxMutexEnter(&geventMutex); // Check if this pair is already in the table (scan for a free slot at the same time) pslfree = 0; for(psl = Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) { if (pl == psl->pListener && gsh == psl->pSource) { // Just update the flags gfxSemWait(&pl->eventlock, TIME_INFINITE); // Safety first - just in case a source is using it psl->listenflags = flags; gfxSemSignal(&pl->eventlock); // Release this lock gfxMutexExit(&geventMutex); return TRUE; } if (!pslfree && !psl->pListener) pslfree = psl; } // A free slot was found - allocate it if (pslfree) { pslfree->pListener = pl; pslfree->pSource = gsh; pslfree->listenflags = flags; pslfree->srcflags = 0; } gfxMutexExit(&geventMutex); GEVENT_ASSERT(pslfree != 0); return pslfree != 0; }
GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr) { GSourceListener *psl; // Safety first if (!gsh) return 0; gfxMutexEnter(&geventMutex); // Unlock the last listener event buffer if (lastlr) gfxSemSignal(&lastlr->pListener->eventlock); // Loop through the table looking for attachments to this source for(psl = lastlr ? (lastlr+1) : Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) { if (gsh == psl->pSource) { gfxSemWait(&psl->pListener->eventlock, TIME_INFINITE); // Obtain a lock on the listener event buffer gfxMutexExit(&geventMutex); return psl; } } gfxMutexExit(&geventMutex); return 0; }
void _gwinFlushRedraws(GRedrawMethod how) { GHandle gh; // Do we really need to do anything? if (!RedrawPending) return; // Obtain the drawing lock if (how == REDRAW_WAIT) gfxSemWait(&gwinsem, TIME_INFINITE); else if (how == REDRAW_NOWAIT && !gfxSemWait(&gwinsem, TIME_IMMEDIATE)) // Someone is drawing - They will do the redraw when they are finished return; // Do loss of visibility first while ((RedrawPending & DOREDRAW_INVISIBLES)) { RedrawPending &= ~DOREDRAW_INVISIBLES; // Catch new requests for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != GWIN_FLG_NEEDREDRAW) continue; // Do the redraw #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); _GWINwm->vmt->Redraw(gh); gdispGUnsetClip(gh->display); #else _GWINwm->vmt->Redraw(gh); #endif // Postpone further redraws #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP if (how == REDRAW_NOWAIT) { RedrawPending |= DOREDRAW_INVISIBLES; TriggerRedraw(); goto releaselock; } #endif } } // Do the visible windows next while ((RedrawPending & DOREDRAW_VISIBLES)) { RedrawPending &= ~DOREDRAW_VISIBLES; // Catch new requests for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) continue; // Do the redraw #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); _GWINwm->vmt->Redraw(gh); gdispGUnsetClip(gh->display); #else _GWINwm->vmt->Redraw(gh); #endif // Postpone further redraws (if there are any and the options are set right) #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP if (how == REDRAW_NOWAIT) { while((gh = gwinGetNextWindow(gh))) { if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) { RedrawPending |= DOREDRAW_VISIBLES; TriggerRedraw(); break; } } goto releaselock; } #endif } } #if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP releaselock: #endif // Release the lock if (how == REDRAW_WAIT || how == REDRAW_NOWAIT) gfxSemSignal(&gwinsem); }