Threads, User events and DC_CLEAREVENTS()

This forum is for eXpress++ general support.
Post Reply
Message
Author
mzipkin
Posts: 15
Joined: Thu May 13, 2010 8:27 pm

Threads, User events and DC_CLEAREVENTS()

#1 Post by mzipkin »

Roger,

In a multi-threaded app, DC_CLEAREVENTS can clear events which are not intended to be cleared.

My background thread sends events to the foreground (GUI) thread. But the foreground thread calls DC_CLEAREVENTS explicitly as well as indirectly through other objects created by Express. DC_CLEAREVENTS does not distinguish between user events and GUI events, so the user events are swallowed along with all other events. Because the enqueuing and clearing of events happens in separate threads, the event queue itself becomes a shared resource which is impossible to synchronize.

The following workaround makes a distinction between "USER" events and all other events:

1) By default, DC_CLEAREVENTS() should remove only GUI events which are < xbeP_User. (or < xbeP_User+1000)

2) When new parameter lClearAll is true, the fcn would clear all events from the queue without restriction. (i.e. as it operates in the current release)

This would enable existing applications to clear only the Standard XBASE-defined events for GUI without touching xbeP_user+1000 or beyond. It would also prevent the need for modifying any calls to DC_CLEAREVENTS which already exist within Express since they apply only to GUI events.

Any new applications requiring *all* events to be cleared could specify lClearAll. Express seems to care only about events below xbeP_User+1000 with 2 exceptions: 1342 and 3497.

I've appended a revised DC_CLEAREVENTS() for your review. (the BB complains about attaching files)

Do you forsee any problems with this strategy?


Best regards,

Mark

// DC_ClearEvents with added parameter: lClearAll 5/13/10 MFZ001

#include "appevent.ch"
FUNCTION DC_ClearEvents ( nClearEvent, oClearXbp, aKeyboardQueue, aKeepEvents, lClearAll )

LOCAL nEvent := 1, aNewQueue := {}, mp1, mp2, oXbp, lAddToQueue,i
lClearAll := IIF(Valtype(lClearAll) = 'L', lClearAll, .F.)

DO WHILE nEvent <> 0
nEvent := AppEvent( @mp1, @mp2, @oXbp, .01 )
IF Valtype(aKeyboardQueue) = 'A' .AND. nEvent == xbeP_Keyboard
AAdd(aKeyboardQueue,mp1)
ENDIF

IF Valtype(nClearEvent) = 'N' .AND. Valtype(oClearXbp) = 'O' .AND. ;
!( nEvent == nClearEvent .AND. oXbp == oClearXbp )
lAddToQueue := .t.
ELSEIF Valtype(nClearEvent) = 'N' .AND. !( nEvent == nClearEvent )
lAddToQueue := .t.
ELSEIF Valtype(oClearXbp) = 'O' .AND. !( oXbp == oClearXbp )
lAddToQueue := .t.
ELSEIF Valtype(aKeepEvents) == 'A' .AND. nEvent $ aKeepEvents
lAddToQueue := .t.
ELSEIF !lClearAll .AND. nEvent >= (xbeP_User+1000) // MFZ001
lAddToQueue := .t. // MFZ001
ELSE
lAddToQueue := .f.
ENDIF
IF lAddToQueue
AADD( aNewQueue, { nEvent, mp1, mp2, oXbp } )
ENDIF
ENDDO

FOR i := 1 TO LEN(aNewQueue)
PostAppEvent( aNewQueue[i,1], aNewQueue[i,2], aNewQueue[i,3], aNewQueue[i,4] )
NEXT

RETURN nil

Post Reply