Here's an example using QueueUserAPC and SleepEx to implement
a JobQueue (only NT/W2000). Updated 7-Feb-2002
Cheers
Florent
[This message has been edited by Florent Heyworth (edited February 07, 2002).]
a JobQueue (only NT/W2000). Updated 7-Feb-2002
Code:
#IF 0 ******************************************************* * ' Illustrates a Job Queue using QueueUserAPC * ' An easy way to implement a serialized Job Queue * ' running on a single thread * ' * ' Written : Florent Heyworth * ' Date : 22-Apr-2001 * ' Updated : 07-Feb-2002 * ' * ' Notes of course you could use an array() in a * ' function for the same functionality in this example * ' However in a multi-threaded application this * ' becomes *very* useful since any thread can queue * ' a job to the job queue using the JobQueue's thread * ' handle (just make it global or pass it on the * ' stack) - You could use messages but I find this * ' useful... * ' * ' Updates: changed example to FIFO and LIFO queues * ' changed SleepEx parameter * ' ******************************************************* #ENDIF #INCLUDE "win32api.inc" TYPE T_JOB szChars AS ASCIIZ * 41 lJobNum AS LONG END TYPE %APC_EXIT = -1 %APC_DO_NOTHING = 0 FUNCTION JobQueue_Lifo( BYVAL lArg AS LONG ) AS LONG 'last in first out queue LOCAL lAlert AS LONG LOCAL dwWait AS DWORD LOCAL t AS T_JOB PTR lAlert = 1 'alertable dwWait = %INFINITE 'forever [img]http://www.powerbasic.com/support/forums/smile.gif[/img] IF lArg = %APC_EXIT THEN dwWait = 0 'no wait lAlert = 0 'non-alertable END IF 'Changed passing of lAlert parameter CALL SleepEx( dwWait, lAlert ) 'wait until another APC is queued IF lArg <> %APC_DO_NOTHING AND lArg <> %APC_EXIT THEN SLEEP 1000 ' simulate some real processing t = lArg PRINT "Chars: " @t.szChars PRINT "Jobnr: " + FORMAT$( @t.lJobNum ) CALL HeapFree( GetProcessHeap(), 0, BYVAL t ) 'free dynamically allocated structure END IF END FUNCTION FUNCTION JobQueue_Fifo( BYVAL lArg AS LONG ) AS LONG 'First in first out queue LOCAL lAlert AS LONG LOCAL dwWait AS DWORD LOCAL t AS T_JOB PTR lAlert = 1 'alertable dwWait = %INFINITE 'forever [img]http://www.powerbasic.com/support/forums/smile.gif[/img] IF lArg = %APC_EXIT THEN dwWait = 0 'no wait lAlert = 0 'non-alertable END IF IF lArg <> %APC_DO_NOTHING AND lArg <> %APC_EXIT THEN SLEEP 1000 ' simulate some real processing t = lArg PRINT "Chars: " @t.szChars PRINT "Jobnr: " + FORMAT$( @t.lJobNum ) CALL HeapFree( GetProcessHeap(), 0, BYVAL t ) 'free dynamically allocated structure END IF 'changed passing of lAlert parameter CALL SleepEx( dwWait, lAlert ) 'wait until another APC is queued END FUNCTION FUNCTION PBMAIN() AS LONG LOCAL hThread AS LONG LOCAL hResult AS LONG LOCAL lArg AS LONG LOCAL lDummy AS LONG LOCAL i AS LONG LOCAL t AS T_JOB PTR '/////////////////////////////////////////////////////////// ' FIFO queue DEMO '/////////////////////////////////////////////////////////// THREAD CREATE Jobqueue_Fifo( %APC_DO_NOTHING ) TO hThread SLEEP 200 'give the thread a chance STDOUT "Fifo Queue" FOR i = 0 TO 100 t = HeapAlloc( GetProcessHeap(), %HEAP_ZERO_MEMORY, SIZEOF(@t) ) @t.szChars = STRING$( SIZEOF(@t.szChars)-1, CHR$(i + 33) ) @t.lJobNum = i IF QueueUserAPC( CODEPTR(JobQueue_Fifo), hThread, t ) = %FALSE THEN STDOUT "QueueUserAPC() failed exiting loop" EXIT FOR END IF NEXT SLEEP 5000 'simulate items queued and a pause FOR i = 100 TO 200 t = HeapAlloc( GetProcessHeap(), %HEAP_ZERO_MEMORY, SIZEOF(@t) ) @t.szChars = STRING$( SIZEOF(@t.szChars)-1, CHR$(i - 33) ) @t.lJobNum = i IF QueueUserAPC( CODEPTR(JobQueue_Fifo), hThread, t ) = %FALSE THEN STDOUT "QueueUserAPC() failed exiting loop" EXIT FOR END IF NEXT IF QueueUserAPC( CODEPTR(JobQueue_Fifo), hThread, %APC_EXIT ) THEN PRINT "Called exit APC" ELSE PRINT "Called exit APC failed" END IF CALL WaitForSingleObject( hThread, %INFINITE ) 'wait until all jobs are finished THREAD CLOSE hThread TO hResult '/////////////////////////////////////////////////////////// ' LIFO queue DEMO '/////////////////////////////////////////////////////////// THREAD CREATE Jobqueue_Lifo( %APC_DO_NOTHING ) TO hThread SLEEP 200 'give the thread a chance STDOUT "Lifo Queue" FOR i = 0 TO 100 t = HeapAlloc( GetProcessHeap(), %HEAP_ZERO_MEMORY, SIZEOF(@t) ) @t.szChars = STRING$( SIZEOF(@t.szChars)-1, CHR$(i + 33) ) @t.lJobNum = i IF QueueUserAPC( CODEPTR(JobQueue_Lifo), hThread, t ) = %FALSE THEN STDOUT "QueueUserAPC() failed exiting loop" EXIT FOR END IF NEXT SLEEP 5000 'simulate items queued and a pause FOR i = 100 TO 200 t = HeapAlloc( GetProcessHeap(), %HEAP_ZERO_MEMORY, SIZEOF(@t) ) @t.szChars = STRING$( SIZEOF(@t.szChars)-1, CHR$(i - 33) ) @t.lJobNum = i IF QueueUserAPC( CODEPTR(JobQueue_Lifo), hThread, t ) = %FALSE THEN STDOUT "QueueUserAPC() failed exiting loop" EXIT FOR END IF NEXT IF QueueUserAPC( CODEPTR(JobQueue_Lifo), hThread, %APC_EXIT ) THEN PRINT "Called exit APC" ELSE PRINT "Called exit APC failed" END IF CALL WaitForSingleObject( hThread, %INFINITE ) 'wait until all jobs are finished THREAD CLOSE hThread TO hResult PRINT "Job well done" WAITKEY$ END FUNCTION
Florent
[This message has been edited by Florent Heyworth (edited February 07, 2002).]
Comment