Browse Source

More GOS module changes

GQUEUE as a seperate module
GOS changes including basic Win32 O/S support
remotes/origin_old/ugfx_release_2.6
inmarket 9 years ago
parent
commit
8fcbf4e5d5
  1. 55
      drivers/multiple/Win32/gdisp_lld.c
  2. 1
      gfx.mk
  3. 8
      gfxconf.example.h
  4. 10
      include/gfx.h
  5. 12
      include/gfx_rules.h
  6. 37
      include/gos/chibios.h
  7. 227
      include/gos/gos.h
  8. 74
      include/gos/win32.h
  9. 229
      include/gqueue/gqueue.h
  10. 66
      include/gqueue/options.h
  11. 29
      include/gwin/console.h
  12. 18
      include/gwin/options.h
  13. 114
      src/gos/chibios.c
  14. 81
      src/gos/win32.c
  15. 255
      src/gqueue/gqueue.c
  16. 1
      src/gqueue/gqueue.mk
  17. 4
      src/gwin/button.c
  18. 201
      src/gwin/console.c

55
drivers/multiple/Win32/gdisp_lld.c

@ -24,6 +24,15 @@
#include <wingdi.h>
#include <assert.h>
/* Our threading model - ChibiOS or Win32 */
#ifndef GDISP_THREAD_CHIBIOS
#if GFX_USE_OS_WIN32
#define GDISP_THREAD_CHIBIOS FALSE
#else
#define GDISP_THREAD_CHIBIOS TRUE
#endif
#endif
#ifndef GDISP_SCREEN_WIDTH
#define GDISP_SCREEN_WIDTH 640
#endif
@ -230,10 +239,7 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
return 0;
}
static DWORD WINAPI WindowThread(LPVOID lpParameter) {
(void)lpParameter;
MSG msg;
static void InitWindow(void) {
HANDLE hInstance;
WNDCLASS wc;
RECT rect;
@ -274,14 +280,39 @@ static DWORD WINAPI WindowThread(LPVOID lpParameter) {
ShowWindow(winRootWindow, SW_SHOW);
UpdateWindow(winRootWindow);
isReady = TRUE;
}
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
#if GDISP_THREAD_CHIBIOS
static DECLARESTACK(waWindowThread, 1024);
static threadreturn_t WindowThread(void *param) {
(void)param;
MSG msg;
InitWindow();
do {
gfxSleepMilliseconds(1);
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while (msg.message != WM_QUIT);
ExitProcess(0);
return msg.wParam;
}
ExitProcess(0);
return msg.wParam;
}
#else
static DWORD WINAPI WindowThread(LPVOID param) {
(void)param;
MSG msg;
InitWindow();
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ExitProcess(0);
return msg.wParam;
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
@ -312,7 +343,11 @@ bool_t gdisp_lld_init(void) {
wHeight = GDISP_SCREEN_HEIGHT;
/* Initialise the window */
#if GDISP_THREAD_CHIBIOS
gfxCreateThread(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0);
#else
CreateThread(0, 0, WindowThread, 0, 0, 0);
#endif
while (!isReady)
Sleep(1);

1
gfx.mk

@ -7,6 +7,7 @@ GFXINC += $(GFXLIB)/include
GFXSRC += $(GFXLIB)/src/gfx.c
include $(GFXLIB)/src/gos/gos.mk
include $(GFXLIB)/src/gqueue/gqueue.mk
include $(GFXLIB)/src/gdisp/gdisp.mk
include $(GFXLIB)/src/tdisp/tdisp.mk
include $(GFXLIB)/src/gevent/gevent.mk

8
gfxconf.example.h

@ -25,6 +25,7 @@
#define GFX_USE_GWIN FALSE
#define GFX_USE_GEVENT FALSE
#define GFX_USE_GTIMER FALSE
#define GFX_USE_GQUEUE FALSE
#define GFX_USE_GINPUT FALSE
#define GFX_USE_GADC FALSE
#define GFX_USE_GAUDIN FALSE
@ -90,6 +91,11 @@
/* Features for the GTIMER subsystem. */
/* NONE */
/* Features for the GQUEUE subsystem. */
#define GQUEUE_NEED_ASYNC FALSE
#define GQUEUE_NEED_GSYNC FALSE
#define GQUEUE_NEED_FSYNC FALSE
/* Features for the GINPUT subsystem. */
#define GINPUT_NEED_MOUSE FALSE
#define GINPUT_NEED_KEYBOARD FALSE
@ -118,6 +124,8 @@
#define GTIMER_THREAD_WORKAREA_SIZE 512
#define GADC_MAX_LOWSPEED_DEVICES 4
#define GWIN_BUTTON_LAZY_RELEASE FALSE
#define GWIN_CONSOLE_USE_BASESTREAM FALSE
#define GWIN_CONSOLE_USE_FLOAT FALSE
*/
/* Optional Low Level Driver Definitions */

10
include/gfx.h

@ -86,6 +86,14 @@
#ifndef GFX_USE_GTIMER
#define GFX_USE_GTIMER FALSE
#endif
/**
* @brief GFX Queue API
* @details Defaults to FALSE
* @details Provides queue management.
*/
#ifndef GFX_USE_GQUEUE
#define GFX_USE_GQUEUE FALSE
#endif
/**
* @brief GFX Input Device API
* @details Defaults to FALSE
@ -143,6 +151,7 @@
*/
#include "gos/options.h"
#include "gmisc/options.h"
#include "gqueue/options.h"
#include "gevent/options.h"
#include "gtimer/options.h"
#include "gdisp/options.h"
@ -164,6 +173,7 @@
*/
#include "gos/gos.h"
#include "gmisc/gmisc.h"
#include "gqueue/gqueue.h"
#include "gevent/gevent.h"
#include "gtimer/gtimer.h"
#include "gdisp/gdisp.h"

12
include/gfx_rules.h

@ -101,6 +101,15 @@
#if GDISP_NEED_MULTITHREAD && GDISP_NEED_ASYNC
#error "GDISP: Only one of GDISP_NEED_MULTITHREAD and GDISP_NEED_ASYNC should be defined."
#endif
#if GDISP_NEED_ASYNC && !(GFX_USE_GQUEUE && GQUEUE_NEED_GSYNC)
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GDISP: GFX_USE_GQUEUE or GQUEUE_NEED_GSYNC is not TRUE. It has been turned on for you."
#endif
#undef GFX_USE_GQUEUE
#define GFX_USE_GQUEUE TRUE
#undef GQUEUE_NEED_GSYNC
#define GQUEUE_NEED_GSYNC TRUE
#endif
#endif
#if GFX_USE_TDISP
@ -141,6 +150,9 @@
#if GFX_USE_GAUDOUT
#endif
#if GFX_USE_GQUEUE
#endif
#if GFX_USE_GMISC
#endif

37
include/gos/chibios.h

@ -67,17 +67,6 @@ typedef struct {
#define gfxMutex Mutex
typedef struct gfxQueue {
struct gfxQueueItem *head;
struct gfxQueueItem *tail;
Semaphore sem;
} gfxQueue;
typedef struct gfxQueueItem {
struct gfxQueueItem *next;
Semaphore sem;
} gfxQueueItem;
/*===========================================================================*/
/* Function declarations. */
/*===========================================================================*/
@ -90,30 +79,24 @@ extern "C" {
#define gfxExit() chSysHalt()
#define gfxAlloc(sz) chHeapAlloc(NULL, sz)
#define gfxFree(ptr) chHeapFree(ptr)
#define gfxYield() chThdYield()
#define gfxSystemTicks() chTimeNow()
#define gfxMillisecondsToTicks(ms) MS2ST(ms)
#define gfxSystemLock() chSysLock()
#define gfxSystemUnlock() chSysUnlock()
#define gfxMutexInit(pmutex) chMtxInit(pmutex)
#define gfxMutexDestroy(pmutex) ;
#define gfxMutexEnter(pmutex) chMtxLock(pmutex)
#define gfxMutexExit(pmutex) chMtxUnlock()
void gfxSleepMilliseconds(delaytime_t ms);
void gfxSleepMicroseconds(delaytime_t ms);
void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit);
void gfxSemDestroy(gfxSem *psem);
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms);
void gfxSemSignal(gfxSem *psem);
void gfxSemSignalI(gfxSem *psem);
#define gfxSemCounterI(psem) ((psem)->sem.s_cnt)
#define gfxSemCounter(psem) ((psem)->sem.s_cnt)
#define gfxSystemTicks() chTimeNow()
#define gfxMillisecondsToTicks(ms) MS2ST(ms)
#define gfxYield() chThdYield()
#define gfxSystemLock() chSysLock()
#define gfxSystemUnlock() chSysUnlock()
#define gfxMutexInit(pmutex) chMtxInit(pmutex)
#define gfxMutexEnter(pmutex) chMtxLock(pmutex)
#define gfxMutexExit(pmutex) chMtxUnlock()
void gfxQueueInit(gfxQueue *pqueue);
gfxQueueItem * gfxQueueGet(gfxQueue *pqueue, delaytime_t ms);
bool_t gfxQueuePut(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms);
#define gfxQueuePop(q) gfxQueueGet(q)
bool_t gfxQueuePush(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms);
void gfxQueueRemove(gfxQueue *pqueue, gfxQueueItem *pitem);
bool_t gfxQueueIsEmpty(gfxQueue *pqueue);
bool_t gfxQueueIsIn(gfxQueue *pqueue, gfxQueueItem *pitem);
bool_t gfxCreateThread(void *stackarea, size_t stacksz, threadpriority_t prio, gfxThreadFunction fn, void *param);
#ifdef __cplusplus

227
include/gos/gos.h

@ -36,11 +36,6 @@
/* Type definitions */
/*===========================================================================*/
/**
* @brief A function for a new thread to execute.
*/
typedef threadreturn_t (*gfxThreadFunction)(void *param);
/**
* @brief Various integer sizes
* @note Your platform may use slightly different definitions to these
@ -66,6 +61,10 @@
typedef short semcount_t;
typedef int threadreturn_t;
typedef int threadpriority_t;
/**
* @brief A function for a new thread to execute.
*/
typedef threadreturn_t (*gfxThreadFunction)(void *param);
/**
* @}
*
@ -77,7 +76,7 @@
#define TRUE 1
#define TIME_IMMEDIATE 0
#define TIME_INFINITE ((delaytime_t)-1)
#define MAX_SEMAPHORE_COUNT ((semcount_t)-1)
#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1))
#define LOW_PRIORITY 0
#define NORMAL_PRIORITY 1
#define HIGH_PRIORITY 2
@ -96,18 +95,6 @@
*/
typedef struct {} gfxMutex;
/**
* @brief A queue
* @note Your operating system will have a proper definition for this structure
*/
typedef struct {} gfxQueue;
/**
* @brief A queue item
* @note Your operating system will have a proper definition for this structure
*/
typedef struct {} gfxQueueItem;
/*===========================================================================*/
/* Function declarations. */
/*===========================================================================*/
@ -151,6 +138,15 @@
*/
void gfxFree(void *ptr);
/**
* @brief Yield the current thread
* @details Give up the rest of the current time slice for this thread in order to give other threads
* a chance to run.
*
* @api
*/
void gfxYield(void);
/**
* @brief Put the current thread to sleep for the specified period in milliseconds
*
@ -176,83 +172,6 @@
*/
void gfxSleepMicroseconds(delaytime_t ms);
/**
* @brief Initialise a Counted Semaphore
*
* @param[in] psem A pointer to the semaphore
* @param[in] val The initial value of the semaphore
* @param[in] limit The maxmimum value of the semaphore
*
* @note Operations defined for counted semaphores:
* Signal: The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
* Wait: The semaphore counter is decreased and if the result becomes negative the thread is queued
* in the semaphore and suspended.
*
* @api
*/
void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit);
/**
* @brief Wait on a semaphore
* @details The semaphore counter is decreased and if the result becomes negative the thread waits for it to become
* non-negative again
* @return FALSE if the wait timeout occurred otherwise TRUE
*
* @param[in] psem A pointer to the semaphore
* @param[in] ms The maxmimum time to wait for the semaphore
*
* @api
*/
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms);
/**
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @param[in] psem A pointer to the semaphore
*
* @api
*/
void gfxSemSignal(gfxSem *psem);
/**
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
void gfxSemSignalI(gfxSem *psem);
/**
* @brief Get the current semaphore count
* @return The current semaphore count
*
* @param[in] psem A pointer to the semaphore
*
* @api
*/
semcount_t gfxSemCounter(gfxSem *pSem);
/**
* @brief Get the current semaphore count
* @return The current semaphore count
*
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
semcount_t gfxSemCounterI(gfxSem *pSem);
/**
* @brief Get the current operating system tick time
* @return The current tick time
@ -282,15 +201,6 @@
*/
systemticks_t gfxMillisecondsToTicks(delaytime_t ms);
/**
* @brief Yield the current thread
* @details Give up the rest of the current time slice for this thread in order to give other threads
* a chance to run.
*
* @api
*/
void gfxYield(void);
/**
* @brief Lock the operating system to protect a sequence of code
*
@ -326,6 +236,15 @@
*/
void gfxMutexInit(gfxMutex *pmutex);
/**
* @brief Destroy a Mutex.
*
* @param[in] pmutex A pointer to the mutex
*
* @api
*/
void gfxMutexDestroy(gfxMutex *pmutex);
/**
* @brief Enter the critical code region protected by the mutex.
* @details Blocks until there is no other thread in the critical region.
@ -347,104 +266,92 @@
void gfxMutexExit(gfxMutex *pmutex);
/**
* @brief Initialise a queue.
*
* @param[in] pqueue A pointer to the queue
*
* @note Whilst queues are normally FIFO, a GFX queue also supports push and pop operations.
* A pop operation is the same as normal get from the queue but a push places the item
* at the head of the queue instead of the tail (as a put would).
* @brief Initialise a Counted Semaphore
*
* @api
*/
void gfxQueueInit(gfxQueue *pqueue);
/**
* @brief Get an item from the head of the queue.
* @return NULL if the timeout expires before an item is available
* @param[in] psem A pointer to the semaphore
* @param[in] val The initial value of the semaphore
* @param[in] limit The maxmimum value of the semaphore
*
* @param[in] pqueue A pointer to the queue
* @param[in] ms The maxmimum time to wait for an item
* @note Operations defined for counted semaphores:
* Signal: The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
* Wait: The semaphore counter is decreased and if the result becomes negative the thread is queued
* in the semaphore and suspended.
*
* @api
*/
gfxQueueItem * gfxQueueGet(gfxQueue *pqueue, delaytime_t ms);
void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit);
/**
* @brief Put an item on the end of the queue.
* @return FALSE on timeout, otherwise TRUE
* @brief Destroy a Counted Semaphore
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
* @param[in] ms The maxmimum time to wait for an item to be removed from the queue
* @param[in] psem A pointer to the semaphore
*
* @note Use a delay time of TIME_IMMEDIATE if you don't want to wait until the
* item is removed from the queue
* @note Any threads waiting on the semaphore will be released
*
* @api
*/
bool_t gfxQueuePut(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms);
void gfxSemDestroy(gfxSem *psem);
/**
* @brief Pop an item from the head of the queue.
* @return NULL if there are no more items on the queue
* @brief Wait on a semaphore
* @details The semaphore counter is decreased and if the result becomes negative the thread waits for it to become
* non-negative again
* @return FALSE if the wait timeout occurred otherwise TRUE
*
* @param[in] pqueue A pointer to the queue
* @param[in] psem A pointer to the semaphore
* @param[in] ms The maxmimum time to wait for the semaphore
*
* @api
*/
#define gfxQueuePop(pqueue, ms) gfxQueueGet(pqueue, ms)
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms);
/**
* @brief Push an item into the start of the queue.
* @return FALSE on timeout, otherwise TRUE
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
* @param[in] ms The maxmimum time to wait for an item to be popped
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @note Use a delay time of TIME_IMMEDIATE if you don't want to wait until the
* item is removed from the queue
* @param[in] psem A pointer to the semaphore
*
* @api
*/
bool_t gfxQueuePush(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms);
void gfxSemSignal(gfxSem *psem);
/**
* @brief Remove an item from the queue.
* @note Removes the specified item from the queue whereever it is in the queue
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @note If the item isn't in the queue the routine just returns.
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
void gfxQueueRemove(gfxQueue *pqueue, gfxQueueItem *pitem);
void gfxSemSignalI(gfxSem *psem);
/**
* @brief Is the queue empty?
* @return TRUE if the queue is empty
* @brief Get the current semaphore count
* @return The current semaphore count
*
* @param[in] pqueue A pointer to the queue
* @param[in] psem A pointer to the semaphore
*
* @api
*/
bool_t gfxQueueIsEmpty(gfxQueue *pqueue);
semcount_t gfxSemCounter(gfxSem *pSem);
/**
* @brief Is an item in the queue?
* @return TRUE if the item is in the queue?
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
* @brief Get the current semaphore count
* @return The current semaphore count
*
* @note This operation may be expensive.
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
bool_t gfxQueueIsIn(gfxQueue *pqueue, gfxQueueItem *pitem);
semcount_t gfxSemCounterI(gfxSem *pSem);
/**
* @brief Start a new thread.

74
include/gos/win32.h

@ -26,6 +26,80 @@
#define _GOS_WIN32_H
#if GFX_USE_OS_WIN32
//#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/**
* size_t
* TRUE, FALSE
* are already defined by Win32
*/
typedef __int8 bool_t;
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef DWORD delaytime_t;
typedef DWORD systemticks_t;
typedef LONG semcount_t;
#define threadreturn_t DWORD WINAPI
typedef int threadpriority_t;
typedef threadreturn_t (*gfxThreadFunction)(void *param);
#define TIME_IMMEDIATE 0
#define TIME_INFINITE INFINITE
#define MAX_SEMAPHORE_COUNT ((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1))
#define LOW_PRIORITY THREAD_PRIORITY_BELOW_NORMAL
#define NORMAL_PRIORITY THREAD_PRIORITY_NORMAL
#define HIGH_PRIORITY THREAD_PRIORITY_ABOVE_NORMAL
#define DECLARESTACK(name, sz) uint8_t name[0];
typedef HANDLE gfxSem;
typedef HANDLE gfxMutex;
#define gfxExit() ExitProcess(0)
#define gfxAlloc(sz) malloc(sz)
#define gfxFree(ptr) free(ptr)
#define gfxSleepMilliseconds(ms) Sleep(ms)
#define gfxYield() Sleep(0)
#define gfxSystemTicks() GetTickCount()
#define gfxMillisecondsToTicks(ms) (ms)
#define gfxMutexInit(pmutex) *(pmutex) = CreateMutex(NULL, FALSE, NULL)
#define gfxMutexDestory(pmutex) CloseHandle(*(pmutex))
#define gfxMutexEnter(pmutex) WaitForSingleObject(*(pmutex), INFINITE)
#define gfxMutexExit(pmutex) ReleaseMutex(*(pmutex))
#define gfxSemInit(psem, val, limit) *(psem) = CreateSemaphore(NULL, val, limit, NULL)
#define gfxSemDestory(psem) CloseHandle(*(psem))
#define gfxSemSignal(psem) ReleaseSemaphore(*(psem), 1, NULL)
#define gfxSemSignalI(psem) ReleaseSemaphore(*(psem), 1, NULL)
#define gfxSemCounterI(psem) gfxSemCounter(psem)
/*===========================================================================*/
/* Function declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void gfxHalt(const char *msg);
void gfxSleepMicroseconds(delaytime_t ms);
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms);
semcount_t gfxSemCounter(gfxSem *pSem);
void gfxSystemLock(void);
void gfxSystemUnlock(void);
bool_t gfxCreateThread(void *stackarea, size_t stacksz, threadpriority_t prio, gfxThreadFunction fn, void *param);
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_OS_WIN32 */
#endif /* _GOS_WIN32_H */

229
include/gqueue/gqueue.h

@ -0,0 +1,229 @@
/*
ChibiOS/GFX - Copyright (C) 2012, 2013
Joel Bodenmann aka Tectu <joel@unormal.org>
This file is part of ChibiOS/GFX.
ChibiOS/GFX is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/GFX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file include/gqueue/gqueue.h
* @brief GQUEUE header file.
*
* @addtogroup GQUEUE
* @brief GQUEUE provides queue management. There are 3 types of queues:
* <ul><li><b>Asynchronous Queues (ASync) </b> - Queue operations never block</li>
* <li><b>Get Synchronous Queues (GSync) </b> - Queue Get operations block until something is placed in the Queue</li>
* <li><b>Put Synchronous Queues (PSync)</b> - Queue Put operations block until the element is removed from the Queue</li>
* <li><b>Fully Synchronous Queues (FSync)</b> - Queue GET and Put operations block</li>
* </ul>
* We need 4 types of queues even though fully synchronous queues support all operations including asynchronous
* operations because fully synchronous queues have the highest storage requirements. The other queue types are
* optimizations. Efficiency IS important to use (particularly RAM efficiency).
* In practice we only implement ASync, GSync and FSync queues as PSync queues are of dubious value.
* @{
*/
#ifndef _GQUEUE_H
#define _GQUEUE_H
#if GFX_USE_GQUEUE || defined(__DOXYGEN__)
/**
* @brief A queue
* @{
*/
typedef struct gfxQueueASync {
struct gfxQueueASyncItem *head;
struct gfxQueueASyncItem *tail;
} gfxQueueAsync;
typedef struct gfxQueueGSync {
struct gfxQueueGSyncItem *head;
struct gfxQueueGSyncItem *tail;
gfxSem sem;
} gfxQueueGSync;
typedef struct gfxQueueFSync {
struct gfxQueueFSyncItem *head;
struct gfxQueueFSyncItem *tail;
gfxSem sem;
} gfxQueueGSync;
/* @} */
/**
* @brief A queue item
* @{
*/
typedef struct gfxQueueASyncItem {
struct gfxQueueASyncItem *next;
} gfxQueueASyncItem;
typedef struct gfxQueueGSyncItem {
struct gfxQueueGSyncItem *next;
} gfxQueueGSyncItem;
typedef struct gfxQueueFSyncItem {
struct gfxQueueFSyncItem *next;
gfxSem sem;
} gfxQueueFSyncItem;
/* @} */
/*===========================================================================*/
/* Function declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialise a queue.
*
* @param[in] pqueue A pointer to the queue
*
* @note Whilst queues are normally FIFO, a GFX queue also supports push and pop operations.
* A pop operation is the same as normal get from the queue but a push places the item
* at the head of the queue instead of the tail (as a put would).
*
* @api
* @{
*/
void gfxQueueASyncInit(gfxQueueASync *pqueue);
void gfxQueueGSyncInit(gfxQueueGSync *pqueue);
void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
/* @} */
/**
* @brief Get an item from the head of the queue.
* @return NULL if the timeout expires before an item is available
*
* @param[in] pqueue A pointer to the queue
* @param[in] ms The maxmimum time to wait for an item. For ASync queues this parameter is
* not specified as TIME_IMMEDIATE is assumed.
*
* @api
* @{
*/
gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue);
gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms);
gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms);
/* @} */
/**
* @brief Put an item on the end of the queue.
* @return none for ASync and GSync queues; For FSync queues - FALSE on timeout, otherwise TRUE
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
* @param[in] ms The maxmimum time to wait for an item to be removed from the queue (only for FSync queues)
*
* @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the
* item is removed from the queue. Note that even if the timeout occurs - the item
* remains in the queue.
*
* @api
* @{
*/
void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms);
/* @} */
/**
* @brief Pop an item from the head of the queue.
* @detail This is exactly the same as the Get operation above.
*
* @api
* @{
*/
#define gfxQueueASyncPop(pqueue) gfxQueueASyncGet(pqueue)
#define gfxQueueGSyncPop(pqueue, ms) gfxQueueGSyncGet(pqueue, ms)
#define gfxQueueFSyncPop(pqueue, ms) gfxQueueFSyncGet(pqueue, ms)
/* @} */
/**
* @brief Push an item into the start of the queue.
* @return none for ASync and GSync queues; For FSync queues - FALSE on timeout, otherwise TRUE
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
* @param[in] ms The maxmimum time to wait for an item to be popped (only for FSync queues)
*
* @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the
* item is removed from the queue. Note that even if the timeout occurs - the item
* remains in the queue.
*
* @api
* @{
*/
void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms);
/* @} */
/**
* @brief Remove an item from the queue.
* @note Removes the specified item from the queue where-ever it is in the queue
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
*
* @note If the item isn't in the queue the routine just returns.
* @note If a process is waiting on the Put/Push operation for the item, that process
* will be signaled.
*
* @api
* @{
*/
void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem);
/* @} */
/**
* @brief Is the queue empty?
* @return TRUE if the queue is empty
*
* @param[in] pqueue A pointer to the queue
*
* @api
* @{
*/
bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue);
bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue);
bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue);
/* @} */
/**
* @brief Is an item in the queue?
* @return TRUE if the item is in the queue?
*
* @param[in] pqueue A pointer to the queue
* @param[in] pitem A pointer to the queue item
*
* @note This operation may be expensive.
*
* @api
* @{
*/
bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem);
/* @} */
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GQUEUE */
#endif /* _GQUEUE_H */
/** @} */

66
include/gqueue/options.h

@ -0,0 +1,66 @@
/*
ChibiOS/GFX - Copyright (C) 2012, 2013
Joel Bodenmann aka Tectu <joel@unormal.org>
This file is part of ChibiOS/GFX.
ChibiOS/GFX is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/GFX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file include/gqueue/options.h
* @brief GQUEUE - Queue options header file.
*
* @addtogroup GQUEUE
* @{
*/
#ifndef _GQUEUE_OPTIONS_H
#define _GQUEUE_OPTIONS_H
/**
* @name GQUEUE Functions to include.
* @{
*/
/**
* @brief Enable Asynchronous Queues
* @details Defaults to FALSE
*/
#ifndef GQUEUE_NEED_ASYNC
#define GQUEUE_NEED_ASYNC FALSE
#endif
/**
* @brief Enable Get-Synchronous Queues
* @details Defaults to FALSE
*/
#ifndef GQUEUE_NEED_GSYNC
#define GQUEUE_NEED_GSYNC FALSE
#endif
/**
* @brief Enable Fully Synchronous Queues
* @details Defaults to FALSE
*/
#ifndef GQUEUE_NEED_FSYNC
#define GQUEUE_NEED_FSYNC FALSE
#endif
/**
* @}
*
* @name GQUEUE Optional Sizing Parameters
* @{
*/
/** @} */
#endif /* _GQUEUE_OPTIONS_H */
/** @} */

29
include/gwin/console.h

@ -40,7 +40,7 @@
typedef struct GConsoleObject_t {
GWindowObject gwin;
#if GFX_USE_OS_CHIBIOS
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
struct GConsoleWindowStream_t {
const struct GConsoleWindowVMT_t *vmt;
_base_asynchronous_channel_data
@ -80,7 +80,7 @@ extern "C" {
*/
GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font);
#if GFX_USE_OS_CHIBIOS
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
/**
* @brief Get a stream from a console window suitable for use with chprintf().
* @return The stream handle or NULL if this is not a console window.
@ -128,6 +128,31 @@ void gwinPutString(GHandle gh, const char *str);
*/
void gwinPutCharArray(GHandle gh, const char *str, size_t n);
/**
* @brief Print a formatted string at the cursor position in the window. It will wrap lines as required.
* @details This function implements a minimal printf() like functionality
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* @note Uses the current foreground color to draw the string and fills the background using the background drawing color
*
* @param[in] gh The window handle (must be a console window)
* @param[in] fmt The format string (as per printf)
* @param[in] ... The format string arguments.
*
* @api
*/
void gwinPrintf(GHandle gh, const char *fmt, ...);
#ifdef __cplusplus
}
#endif

18
include/gwin/options.h

@ -59,9 +59,27 @@
* @name GWIN Optional Parameters
* @{
*/
/**
* @brief Buttons should not insist the mouse is over the button on mouse release
* @details Defaults to FALSE
*/
#ifndef GWIN_BUTTON_LAZY_RELEASE
#define GWIN_BUTTON_LAZY_RELEASE FALSE
#endif
/**
* @brief Console Windows need floating point support in @p gwinPrintf
* @details Defaults to FALSE
*/
#ifndef GWIN_CONSOLE_USE_FLOAT
#define GWIN_CONSOLE_USE_FLOAT FALSE
#endif
/**
* @brief Console Windows need BaseStreamSequential support (ChibiOS only)
* @details Defaults to FALSE
*/
#ifndef GWIN_CONSOLE_USE_BASESTREAM
#define GWIN_CONSOLE_USE_BASESTREAM FALSE
#endif
/** @} */
#endif /* _GWIN_OPTIONS_H */

114
src/gos/chibios.c

@ -57,13 +57,14 @@ void gfxSleepMicroseconds(delaytime_t ms) {
default: chThdSleepMicroseconds(ms); return;
}
}
void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) {
if (val > limit) val = limit;
psem->limit = limit;
chSemInit(&psem->sem, val);
}
void gfxSemDestroy(gfxSem *psem) {
chSemReset(&psem->sem, 1);
}
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) {
if (ms == TIME_INFINITE) {
chSemWait(&psem->sem);
@ -85,115 +86,6 @@ void gfxSemSignalI(gfxSem *psem) {
chSemSignalI(&psem->sem);
}
void gfxQueueInit(gfxQueue *pqueue) {
pqueue->head = pqueue->tail = 0;
chSemInit(&pqueue->sem, 0);
}
gfxQueueItem * gfxQueueGet(gfxQueue *pqueue, delaytime_t ms) {
gfxQueueItem *pi;
chSysLock();
/* If someone else is waiting or if the queue is empty - wait ourselves */
if (pqueue->sem.s_cnt < 0 || !pqueue->head) {
if (chSemWaitTimeoutS(&pqueue->sem, ms == TIME_INFINITE ? TIME_INFINITE : MS2ST(ms)) == RDY_TIMEOUT) {
chSysUnlock();
return NULL;
}
}
/* We can now get the head element */
pi = pqueue->head;
pqueue->head = pi;
chSemSignalI(&pi->sem);
chSysUnlock();
return pi;
}
bool_t gfxQueuePut(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms) {
chSemInit(&pitem->sem, 0);
chSysLock();
pitem->next = 0;
if (!pqueue->head) {
pqueue->head = pqueue->tail = pitem;
} else {
pqueue->tail->next = pitem;
pqueue->tail = pitem;
}
/* Wake up someone who is waiting */
if (chSemGetCounterI(&pqueue->sem) < 0)
chSemSignalI(&pqueue->sem);
chSysUnlock();
return chSemWaitTimeout(&pitem->sem, ms == TIME_INFINITE ? TIME_INFINITE : MS2ST(ms)) != RDY_TIMEOUT;
}
bool_t gfxQueuePush(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms) {
chSemInit(&pitem->sem, 0);
chSysLock();
pitem->next = pqueue->head;
pqueue->head = pitem;
if (!pitem->next)
pqueue->tail = pitem;
/* Wake up someone who is waiting */
if (chSemGetCounterI(&pqueue->sem) < 0)
chSemSignalI(&pqueue->sem);
chSysUnlock();
return chSemWaitTimeout(&pitem->sem, ms == TIME_INFINITE ? TIME_INFINITE : MS2ST(ms)) != RDY_TIMEOUT;
}
void gfxQueueRemove(gfxQueue *pqueue, gfxQueueItem *pitem) {
gfxQueueItem *pi;
chSysLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
chSemSignalI(&pitem->sem);
} else {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
chSemSignalI(&pitem->sem);
break;
}
}
}
}
chSysUnlock();
}
bool_t gfxQueueIsEmpty(gfxQueue *pqueue) {
return pqueue->head == NULL;
}
bool_t gfxQueueIsIn(gfxQueue *pqueue, gfxQueueItem *pitem) {
gfxQueueItem *pi;
chSysLock();
for(pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
chSysUnlock();
return TRUE;
}
}
chSysUnlock();
return FALSE;
}
/**
* @brief Start a new thread.
* @return Return TRUE if the thread was started, FALSE on an error
*
* @param[in] stackarea A pointer to the area for the new threads stack or NULL to dynamically allocate it
* @param[in] stacksz The size of the thread stack. 0 means the default operating system size although this
* is only valid when stackarea is dynamically allocated.
* @param[in] prio The priority of the new thread
* @param[in] fn The function the new thread will run
* @param[in] param A parameter to pass the thread function.
*
* @api
*/
bool_t gfxCreateThread(void *stackarea, size_t stacksz, threadpriority_t prio, gfxThreadFunction fn, void *param) {
if (!stackarea) {
if (!stacksz) stacksz = 256;

81
src/gos/win32.c

@ -26,7 +26,86 @@
#if GFX_USE_OS_WIN32
#error "GOS: WIN32 not supported yet"
#include <stdio.h>
static HANDLE SystemMutex;
void _gosInit(void) {
}
void gfxHalt(const char *msg) {
fprintf(stderr, "%s\n", msg);
ExitProcess(1);
}
void gfxSleepMicroseconds(delaytime_t ms) {
static LARGE_INTEGER pcfreq;
static int initflag;
LARGE_INTEGER t1, t2, tdiff;
switch(ms) {
case TIME_IMMEDIATE: return;
case TIME_INFINITE: while(1) Sleep(1000); return;
}
if (!initflag) {
QueryPerformanceFrequency(&pcfreq);
initflag++;
}
tdiff.QuadPart = pcfreq.QuadPart * ms / 1000000;
QueryPerformanceCounter(&t1);
do {
QueryPerformanceCounter(&t2);
} while (t2.QuadPart - t1.QuadPart < tdiff.QuadPart);
}
void gfxSystemLock(void) {
if (!SystemMutex)
SystemMutex = CreateMutex(NULL, FALSE, NULL);
WaitForSingleObject(SystemMutex, INFINITE);
}
void gfxSystemUnlock(void) {
ReleaseMutex(SystemMutex);
}
bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) {
return WaitForSingleObject(*psem, ms) == WAIT_OBJECT_0;
}
typedef LONG __stdcall (*_NtQuerySemaphore)(
HANDLE SemaphoreHandle,
DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */
PVOID SemaphoreInformation, /* but this is to much to dump here */
ULONG SemaphoreInformationLength,
PULONG ReturnLength OPTIONAL
);
semcount_t gfxSemCounter(gfxSem *pSem) {
static _NtQuerySemaphore NtQuerySemaphore;
struct _SEMAPHORE_BASIC_INFORMATION {
ULONG CurrentCount;
ULONG MaximumCount;
} BasicInfo;
if (!NtQuerySemaphore)
NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySemaphore");
NtQuerySemaphore(*pSem, 0, &BasicInfo, sizeof(BasicInfo), NULL);
return BasicInfo.CurrentCount;
}
bool_t gfxCreateThread(void *stackarea, size_t stacksz, threadpriority_t prio, gfxThreadFunction fn, void *param) {
(void) stackarea;
HANDLE thd;
if (!(thd = CreateThread(NULL, stacksz, fn, param, CREATE_SUSPENDED, NULL)))
return FALSE;
SetThreadPriority(thd, prio);
ResumeThread(thd);
return TRUE;
}
#endif /* GFX_USE_OS_WIN32 */
/** @} */

255
src/gqueue/gqueue.c

@ -0,0 +1,255 @@
/*
ChibiOS/GFX - Copyright (C) 2012, 2013
Joel Bodenmann aka Tectu <joel@unormal.org>
This file is part of ChibiOS/GFX.
ChibiOS/GFX is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/GFX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file src/gqueue/gqueue.c
* @brief GQUEUE source file.
*/
#if GFX_USE_GQUEUE
#if GQUEUE_NEED_ASYNC
void gfxQueueASyncInit(gfxQueueASync *pqueue) {
pqueue->head = pqueue->tail = 0;
}
gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue) {
gfxQueueASyncItem *pi;
if (!pqueue->head) return 0;
gfxSystemLock();
if ((pi = pqueue->head))
pqueue->head = pi->next;
gfxSytemUnlock();
return pi;
}
void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
pitem->next = 0;
gfxSystemLock();
if (!pqueue->head) {
pqueue->head = pqueue->tail = pitem;
} else {
pqueue->tail->next = pitem;
pqueue->tail = pitem;
}
gfxSystemUnlock();
}
void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
gfxSystemLock();
pitem->next = pqueue->head;
pqueue->head = pitem;
if (!pitem->next)
pqueue->tail = pitem;
gfxSystemUnlock();
}
void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
} else {
for(gfxQueueASyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
break;
}
}
}
}
gfxSystemUnlock();
}
bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue) {
return pqueue->head == NULL;
}
bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
gfxSystemLock();
for(gfxQueueASyncItem *pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;
}
}
gfxSystemUnlock();
return FALSE;
}
#endif
#if GQUEUE_NEED_GSYNC
void gfxQueueGSyncInit(gfxQueueGSync *pqueue) {
pqueue->head = pqueue->tail = 0;
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT);
}
gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms) {
gfxQueueGSyncItem *pi;
if (!gfxSemWait(&pqueue->sem, ms)) return 0;
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
gfxSytemUnlock();
return pi;
}
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 gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
gfxSystemLock();
pitem->next = pqueue->head;
pqueue->head = pitem;
if (!pitem->next)
pqueue->tail = pitem;
gfxSystemUnlock();
gfxSemSignal(&pqueue->sem);
}
void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
} else {
for(gfxQueueGSyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
break;
}
}
}
}
gfxSystemUnlock();
}
bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue) {
return pqueue->head == NULL;
}
bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
gfxSystemLock();
for(gfxQueueGSyncItem *pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;
}
}
gfxSystemUnlock();
return FALSE;
}
#endif
#if GQUEUE_NEED_FSYNC
void gfxQueueFSyncInit(gfxQueueFSync *pqueue) {
pqueue->head = pqueue->tail = 0;
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT);
}
gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) {
gfxQueueFSyncItem *pi;
if (!gfxSemWait(&pqueue->sem, ms)) return 0;
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
gfxSytemUnlock();
gfxSemSignalI(&pi->sem);
gfxSemDestroy(&pi->sem);
return pi;
}
bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) {
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 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;