Hello, here are:
1)
patch (against CVS) for adding shaped window support for colokeyed windows,
seems to work :-)
2)
patch (against CVS) to avoid additional threads, i used it for some time and
it looks stable.
The master works the old way.
I fixed also the master and slave code in order to be (almost) safe against
"pthread_cancel" during WaitForEvent(WithTimeout).
I say "almost" because it is not safe when a thread is pthread_cancel'ed at
the very beginning of WaitForEvent(WithTimeout), but you have to be quite
unlucky :-)
I have also seen the addition in cvs of the WakeUp method in EventBuffer, and
i implemented it for the thread that is "selecting" /dev/fusion with a
SIGCONT signal that terminates the "select".
I did not know wich signal to use, i decided SIGCONT because it is very little
used. If you don't like it, just change the SIG_AWAKE macro
3)
a couple of programs to test shaped windows, pthread_cancels and
WakeUps
Please test and let me know if it works for you :-)
Ciao
Maurizio
Index: DirectFB/src/core/windows.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/windows.c,v
retrieving revision 1.160
diff -u -r1.160 windows.c
--- DirectFB/src/core/windows.c 28 Jul 2003 14:21:52 -0000 1.160
+++ DirectFB/src/core/windows.c 3 Aug 2003 12:38:07 -0000
@@ -1671,63 +1671,125 @@
int wx = x - w->x;
int wy = y - w->y;
- if (((w->options & (DWOP_ALPHACHANNEL|DWOP_SHAPED)) !=
- (DWOP_ALPHACHANNEL|DWOP_SHAPED)) || !w->surface ||
- ((w->options & DWOP_OPAQUE_REGION) &&
- (wx >= w->opaque.x1 && wx <= w->opaque.x2 &&
- wy >= w->opaque.y1 && wy <= w->opaque.y2)))
+ if ( !(w->options & DWOP_SHAPED) ||
+ !(w->options &(DWOP_ALPHACHANNEL|DWOP_COLORKEYING))
+ || !w->surface ||
+ ((w->options & DWOP_OPAQUE_REGION) &&
+ (wx >= w->opaque.x1 && wx <= w->opaque.x2 &&
+ wy >= w->opaque.y1 && wy <= w->opaque.y2)))
{
return w;
}
- else {
+ else
+ {
void *data;
int pitch;
CoreSurface *surface = w->surface;
- if (DFB_PIXELFORMAT_HAS_ALPHA( surface->format ) &&
- dfb_surface_soft_lock( surface, DSLF_READ,
- &data, &pitch, true ) == DFB_OK)
+ if( dfb_surface_soft_lock( surface, DSLF_READ,
+ &data, &pitch, true ) == DFB_OK )
{
- int alpha = -1;
+ if(w->options & DWOP_ALPHACHANNEL)
+ {
+ int alpha = -1;
+
+ DFB_ASSERT( DFB_PIXELFORMAT_HAS_ALPHA( surface->format ) );
+
+ switch (surface->format)
+ {
+ case DSPF_ARGB:
+ alpha = *(__u32*)(data +
+ 4 * wx + pitch * wy) >> 24;
+ break;
+ case DSPF_ARGB1555:
+ alpha = *(__u16*)(data + 2 * wx +
+ pitch * wy) & 0x8000;
+ alpha = alpha ? 0xff : 0x00;
+ break;
+ case DSPF_ALUT44:
+ alpha = *(__u8*)(data +
+ wx + pitch * wy) & 0xf0;
+ alpha |= alpha >> 4;
+ break;
+ case DSPF_LUT8: {
+ CorePalette *palette = surface->palette;
+ __u8 pix = *((__u8*) data + wx +
+ pitch * wy);
+
+ if (palette && pix < palette->num_entries) {
+ alpha = palette->entries[pix].a;
+ break;
+ }
+
+ /* fall through */
+ }
+
+ default:
+ break;
+ }
- switch (surface->format) {
- case DSPF_ARGB:
- alpha = *(__u32*)(data +
- 4 * wx + pitch * wy) >> 24;
- break;
- case DSPF_ARGB1555:
- alpha = *(__u16*)(data + 2 * wx +
- pitch * wy) & 0x8000;
- alpha = alpha ? 0xff : 0x00;
- break;
- case DSPF_ALUT44:
- alpha = *(__u8*)(data +
- wx + pitch * wy) & 0xf0;
- alpha |= alpha >> 4;
- break;
- case DSPF_LUT8: {
- CorePalette *palette = surface->palette;
- __u8 pix = *((__u8*) data + wx +
- pitch * wy);
-
- if (palette && pix < palette->num_entries) {
- alpha = palette->entries[pix].a;
- break;
- }
-
- /* fall through */
- }
-
- default:
- break;
- }
-
- if (alpha) { /* alpha == -1 on error */
- dfb_surface_unlock( surface, true );
- return w;
- }
+ if (alpha) /* alpha == -1 on error */
+ {
+ dfb_surface_unlock( surface, true );
+ return w;
+ }
- dfb_surface_unlock( surface, true );
+ }
+ if(w->options & DWOP_COLORKEYING)
+ {
+ int pixel = 0;
+
+ switch (surface->format)
+ {
+ case DSPF_ARGB:
+ case DSPF_RGB32:
+ pixel = *(__u32*)(data +
+ 4 * wx + pitch * wy)
+ & 0x00ffffff;
+ break;
+
+ case DSPF_RGB24: //endianess? boh...
+ pixel = (*(__u32*)(data +
+ 3 * wx + pitch * wy))
+ & 0x00ffffff;
+ break;
+
+ case DSPF_RGB16:
+ pixel = *(__u16*)(data + 2 * wx +
+ pitch * wy);
+ break;
+
+ case DSPF_ARGB1555:
+ pixel = *(__u16*)(data + 2 * wx +
+ pitch * wy)
+ & 0x7fff;
+ break;
+
+ case DSPF_RGB332:
+ case DSPF_LUT8:
+ pixel = *(__u8*)(data +
+ wx + pitch * wy);
+ break;
+
+ case DSPF_ALUT44:
+ pixel = *(__u8*)(data +
+ wx + pitch * wy)
+ & 0x0f;
+ break;
+
+ default:
+ break;
+ }
+
+ if ( pixel != w->color_key )
+ {
+ dfb_surface_unlock( surface, true );
+ return w;
+ }
+
+ }
+
+ dfb_surface_unlock( surface, true );
}
}
}
Index: DirectFB/include/directfb.h
===================================================================
RCS file: /cvs/directfb/DirectFB/include/directfb.h,v
retrieving revision 1.186
diff -u -r1.186 directfb.h
--- DirectFB/include/directfb.h 2 Aug 2003 19:35:40 -0000 1.186
+++ DirectFB/include/directfb.h 3 Aug 2003 12:38:21 -0000
@@ -2989,8 +2989,9 @@
window's alpha channel */
DWOP_OPAQUE_REGION = 0x00000004, /* overrides DWOP_ALPHACHANNEL for the
region set by SetOpaqueRegion() */
- DWOP_SHAPED = 0x00000008, /* Do not send events if alpha==0, can
- be used with DWOP_ALPHACHANNEL */
+ DWOP_SHAPED = 0x00000008, /* window doesn't receive mouse events for
+ invisible regions, must be used with
+ DWOP_ALPHACHANNEL or DWOP_COLORKEYING */
DWOP_KEEP_POSITION = 0x00000010, /* window can't be moved
with the mouse */
DWOP_KEEP_SIZE = 0x00000020, /* window can't be resized
Index: DirectFB/src/core/fusion/fusion.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/fusion/fusion.c,v
retrieving revision 1.41
diff -u -r1.41 fusion.c
--- DirectFB/src/core/fusion/fusion.c 9 Jul 2003 15:43:08 -0000 1.41
+++ DirectFB/src/core/fusion/fusion.c 3 Aug 2003 13:15:16 -0000
@@ -67,13 +67,14 @@
int _fusion_fd = -1;
FusionShared *_fusion_shared = NULL;
-static CoreThread *read_loop;
+static CoreThread *read_loop = NULL;
/****************
* Public API *
****************/
int _fusion_id = 0; /* non-zero if Fusion is initialized */
+int dfb_is_master = 0;
int
fusion_init( int world, int *world_ret )
@@ -148,12 +149,13 @@
fusion_skirmish_init( &_fusion_shared->arenas_lock );
gettimeofday( &_fusion_shared->start_time, NULL );
+
+ dfb_is_master = 1;
+ read_loop = dfb_thread_create( CTT_MESSAGING, fusion_read_loop, NULL );
}
else
_fusion_shared = __shmalloc_get_root();
- read_loop = dfb_thread_create( CTT_MESSAGING, fusion_read_loop, NULL );
-
if (world_ret)
*world_ret = world;
@@ -186,8 +188,11 @@
}
/* Wait for its termination. */
+ if(dfb_is_master && read_loop)
+ {
dfb_thread_join( read_loop );
dfb_thread_destroy( read_loop );
+ }
/* Master has to deinitialize shared data. */
if (_fusion_id == 1) {
@@ -252,9 +257,9 @@
(tv.tv_usec - _fusion_shared->start_time.tv_usec) / 1000;
}
-/*****************************
- * File internal functions *
- *****************************/
+/*
+ * File internal functions (keep this for master use only)
+ */
static void *
fusion_read_loop( CoreThread *thread, void *arg )
@@ -288,7 +293,7 @@
switch (header->msg_type) {
case FMT_SEND:
if (!fusion_refs)
- return NULL;
+ return NULL;;
break;
case FMT_CALL:
_fusion_call_process( header->msg_id, data );
@@ -309,6 +314,97 @@
FPERROR( "reading from fusion device failed\n" );
return NULL;
+}
+
+/*
+ * functions to implement slave polling
+ */
+
+void
+fusion_read_pending( )
+{
+ int len = 0;
+ char buf[1024];
+ char *buf_p = buf;
+
+ len = read (_fusion_fd, buf, 1024);
+
+ buf_p = buf;
+ while (buf_p < buf + len)
+ {
+ FusionReadMessage *header = (FusionReadMessage*) buf_p;
+ void *data = buf_p + sizeof(FusionReadMessage);
+
+ switch (header->msg_type) {
+ case FMT_SEND:
+ if (!fusion_refs)
+ return;
+ break;
+ case FMT_CALL:
+ _fusion_call_process( header->msg_id, data );
+ break;
+ case FMT_REACTOR:
+ _fusion_reactor_process_message( header->msg_id, data );
+ break;
+ default:
+ FDEBUG( "discarding message of unknown type '%d'\n",
+ header->msg_type );
+ break;
+ }
+
+ buf_p = data + header->msg_size;
+ }
+ return;
+}
+
+
+void
+fusion_read_iteration( )
+{
+ int result;
+ fd_set set;
+
+ FD_ZERO(&set);
+ FD_SET(_fusion_fd,&set);
+
+ result = select (_fusion_fd+1, &set, NULL, NULL, NULL);
+
+ if (result <= 0)
+ FPERROR( "reading from fusion device failed\n" );
+}
+
+//return 1 on timeout reached
+int
+fusion_read_iteration_timeout( struct timeval tv )
+{
+ int result;
+ fd_set set;
+ struct timeval now;
+
+ FD_ZERO(&set);
+ FD_SET(_fusion_fd,&set);
+
+ gettimeofday( &now, NULL );
+ tv.tv_sec -= now.tv_sec;
+ tv.tv_usec -= now.tv_usec;
+
+ if(tv.tv_usec<0)
+ {
+ tv.tv_usec += 1000000;
+ tv.tv_sec -= 1;
+ }
+
+ if(tv.tv_sec<0)
+ return 1;
+
+ result = select (_fusion_fd+1, &set, NULL, NULL, &tv);
+
+ if (result < 0)
+ FPERROR( "reading from fusion device failed\n" ); //error
+ else if(result == 0)
+ return 1;
+
+ return 0;
}
#else
Index: DirectFB/src/core/fusion/fusion.h
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/fusion/fusion.h,v
retrieving revision 1.8
diff -u -r1.8 fusion.h
--- DirectFB/src/core/fusion/fusion.h 7 Jul 2003 17:25:36 -0000 1.8
+++ DirectFB/src/core/fusion/fusion.h 3 Aug 2003 13:15:17 -0000
@@ -60,6 +60,13 @@
*/
long long fusion_get_millis();
+/*
+ to implement slave polling
+*/
+void fusion_read_pending( );
+void fusion_read_iteration( );
+int fusion_read_iteration_timeout( struct timeval );
+
#ifdef __cplusplus
}
Index: DirectFB/src/input/idirectfbinputbuffer.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/input/idirectfbinputbuffer.c,v
retrieving revision 1.38
diff -u -r1.38 idirectfbinputbuffer.c
--- DirectFB/src/input/idirectfbinputbuffer.c 2 Aug 2003 19:35:40 -0000 1.38
+++ DirectFB/src/input/idirectfbinputbuffer.c 3 Aug 2003 13:15:21 -0000
@@ -37,6 +37,7 @@
#include <core/fusion/reactor.h>
#include <core/fusion/list.h>
+#include <core/fusion/fusion.h>
#include <directfb.h>
#include <directfb_internals.h>
@@ -93,9 +94,105 @@
pthread_cond_t wait_condition;/* condition used for idle
wait in WaitForEvent() */
+
+ int interrupted; /* signal interruption */
} IDirectFBEventBuffer_data;
/*
+ * Structures and functions to know about
+ * thread that are in pthread_cond_wait
+ * and could be awaken to select /dev/fusion
+ */
+
+typedef struct _waiting_thread
+{
+ struct _waiting_thread *next;
+ pthread_cond_t *cond; //to awake the thread...
+ pthread_mutex_t *mutex;
+}waiting_thread;
+
+static waiting_thread *waiting_threads_list = NULL;
+static pthread_mutex_t fusion_lock;
+static pthread_mutex_t wtlist_lock;
+static int mutexes_init = 0;
+static pid_t fusion_pid = 0;
+static IDirectFBEventBuffer_data *fusion_data = NULL;
+extern int dfb_is_master;
+
+/*
+ * function to handle the list of waiting threads
+ */
+
+static waiting_thread *
+put_in_waiting_thread_list( pthread_cond_t *cond, pthread_mutex_t *mtx)
+{
+ waiting_thread *newitem = (waiting_thread*)malloc(sizeof(waiting_thread));
+ pthread_mutex_lock( &wtlist_lock );
+ newitem->cond = cond;
+ newitem->mutex = mtx;
+ newitem->next = waiting_threads_list;
+ waiting_threads_list = newitem;
+ pthread_mutex_unlock( &wtlist_lock );
+
+ return newitem;
+}
+
+static void
+take_from_waiting_thread_list(waiting_thread *item)
+{
+ waiting_thread **tmp;
+ pthread_mutex_lock( &wtlist_lock );
+ tmp = &waiting_threads_list;
+ while(*tmp)
+ {
+ if(*tmp == item)
+ {
+ *tmp = (*tmp)->next;
+ break;
+ }
+ tmp = &((*tmp)->next);
+ }
+ free(item);
+ pthread_mutex_unlock( &wtlist_lock );
+}
+
+//check if waiting_thread points to something died...
+static void
+waiting_thread_wake()
+{
+ pthread_mutex_lock( &wtlist_lock );
+ if(waiting_threads_list)
+ pthread_cond_broadcast( waiting_threads_list->cond );
+ pthread_mutex_unlock( &wtlist_lock );
+}
+
+/*
+ cleanups for thread if pthread_cancel'ed
+*/
+static void
+selector_cleanup(void* ign)
+{
+ pthread_mutex_unlock( &fusion_lock );
+ fusion_pid = 0;
+ waiting_thread_wake();
+}
+
+static void waiter_cleanup(void* it)
+{
+ waiting_thread *item = it;
+ pthread_mutex_unlock( item->mutex );
+ take_from_waiting_thread_list(item);
+}
+
+/*
+ sighandler to enable wakeup of who is selecting /dev/fusion
+*/
+#define SIG_AWAKE SIGCONT
+static void dummy(int g)
+{
+}
+
+/*
* adds an event to the event queue
*/
static void IDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data,
@@ -108,7 +205,6 @@
void *ctx );
-
static void
IDirectFBEventBuffer_Destruct( IDirectFBEventBuffer *thiz )
{
@@ -190,13 +286,264 @@
return DFB_OK;
}
+/*
+ * this functions are implemented separatley for master and slave
+ */
+
static DFBResult
-IDirectFBEventBuffer_WaitForEvent( IDirectFBEventBuffer *thiz )
+IDirectFBEventBuffer_WaitForEvent_slave(
+ IDirectFBEventBuffer *thiz )
+{
+ INTERFACE_GET_DATA(IDirectFBEventBuffer)
+
+ if(data->events)
+ return DFB_OK;
+ data->interrupted = 0;
+
+ //someone else is selecting
+ if(pthread_mutex_trylock( &fusion_lock )!=0)
+ {
+ waiting_thread *me;
+
+ //please let me know if you go away...
+ me = put_in_waiting_thread_list(&(data->wait_condition),
+ &(data->events_mutex));
+
+ do
+ {
+ //let me know if you go away *OR* there is something for me.
+ pthread_cleanup_push(waiter_cleanup,me);
+ pthread_mutex_lock( &data->events_mutex );
+
+ pthread_cond_wait( &data->wait_condition,
+ &data->events_mutex );
+
+ pthread_mutex_unlock( &data->events_mutex );
+ pthread_cleanup_pop(0);
+
+ //there is really something for me!
+ if(data->events||data->interrupted)
+ {
+ //clenup signal condition
+ take_from_waiting_thread_list(me);
+
+ //before going away, it may happen that
+ //i (b) was awaken by (a) to select **AND**
+ //there are messages for me, so if i
+ //return immediatly (c) could fuck up...
+ if(waiting_threads_list &&
+ pthread_mutex_trylock( &fusion_lock )==0)
+ {
+ //so lets awake (c) :-)
+ pthread_mutex_unlock( &fusion_lock );
+ waiting_thread_wake();
+ }
+
+ return (data->interrupted) ? DFB_INTERRUPTED : DFB_OK;
+ }
+ else
+ {
+ if(pthread_mutex_trylock( &fusion_lock )==0)
+ break;
+
+ //d'oh, i was awaken and a brother quicker then me
+ //got the mutex ... -> continue waiting,
+ //or congrats to the selector thread for being so fast
+ //to process events and select before i could react!
+ }
+
+ }
+ while(1);
+
+ //cleanup signal condition
+ take_from_waiting_thread_list(me);
+ }
+
+ //if i die someone will remember me :-)
+ pthread_cleanup_push(selector_cleanup,NULL);
+ fusion_data = data;
+
+ //select main loop
+ do
+ {
+ fusion_read_pending( );
+
+ if(data->events || data->interrupted)
+ break;
+
+ signal(SIG_AWAKE,dummy);
+ fusion_pid = getpid( );
+ fusion_read_iteration( );
+ fusion_pid = 0;
+ signal(SIG_AWAKE,SIG_DFL);
+ }
+ while (1);
+
+ pthread_mutex_unlock( &fusion_lock );
+ pthread_cleanup_pop(0);
+
+ //i go away, someone else has to be awaken, maybe...
+ waiting_thread_wake();
+
+ return (data->interrupted) ? DFB_INTERRUPTED : DFB_OK;
+}
+
+static DFBResult
+IDirectFBEventBuffer_WaitForEventWithTimeout_slave(
+ IDirectFBEventBuffer *thiz,
+ unsigned int seconds,
+ unsigned int milli_seconds )
+{
+ DFBResult retval = DFB_OK;
+ struct timeval tv;
+ struct timespec ts;
+ INTERFACE_GET_DATA(IDirectFBEventBuffer)
+
+ if(data->events)
+ return DFB_OK;
+ data->interrupted = 0;
+
+ gettimeofday(&tv,NULL);
+ tv.tv_sec += seconds;
+ tv.tv_usec += milli_seconds * 1000;
+ if(tv.tv_usec>=1000)
+ {
+ tv.tv_sec += 1;
+ tv.tv_sec -= 1000;
+ }
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+
+ //someone else is selecting
+ if(pthread_mutex_trylock( &fusion_lock )!=0)
+ {
+ waiting_thread *me;
+
+ //please let me know if you go away...
+ me = put_in_waiting_thread_list(&(data->wait_condition),
+ &(data->events_mutex));
+
+ do
+ {
+ //let me know if you go away *OR* there is something for me.
+ pthread_cleanup_push(waiter_cleanup,me);
+ pthread_mutex_lock( &data->events_mutex );
+
+ if(pthread_cond_timedwait( &data->wait_condition,
+ &data->events_mutex, &ts ))
+ retval = DFB_TIMEOUT;
+
+ pthread_mutex_unlock( &data->events_mutex );
+ pthread_cleanup_pop(0);
+
+ //there is really something for me! (or just a timeout)
+ if( data->events || data->interrupted || retval == DFB_TIMEOUT)
+ {
+ //clenup signal condition
+ take_from_waiting_thread_list(me);
+
+ //before going away, it may happen that
+ //i (b) was awaken by (a) to select **AND**
+ //there are messages for me, so if i
+ //return immediatly (c) could fuck up...
+ if(waiting_threads_list &&
+ pthread_mutex_trylock( &fusion_lock )==0)
+ {
+ //so lets awake (c) :-)
+ pthread_mutex_unlock( &fusion_lock );
+ waiting_thread_wake();
+ }
+
+
+ return (data->interrupted) ? DFB_INTERRUPTED : retval;
+ }
+ else
+ {
+ if(pthread_mutex_trylock( &fusion_lock )==0)
+ break;
+
+ //d'oh, i was awaken and a brother quicker then me
+ //got the 35/*mutex 35/*... -> continue waiting
+ //or congrats to the selector for being so fast
+ //to process events!
+ }
+
+ }
+ while(1);
+
+ //cleanup signal condition
+ take_from_waiting_thread_list(me);
+ }
+
+ //if i die someone will remember me :-)
+ pthread_cleanup_push(selector_cleanup,NULL);
+ fusion_data = data;
+
+ //select mainfusion_pid loop
+ do
+ {
+ fusion_read_pending();
+
+ if(data->events || data->interrupted)
+ break;
+
+ signal(SIG_AWAKE,dummy);
+ fusion_pid = getpid( );
+ if(fusion_read_iteration_timeout( tv ));
+ {
+ fusion_pid = 0;
+ signal(SIG_AWAKE,SIG_DFL);
+ retval = DFB_TIMEOUT;
+ break;
+ }
+ fusion_pid = 0;
+ signal(SIG_AWAKE,SIG_DFL);
+ }
+ while (1);
+
+ pthread_mutex_unlock( &fusion_lock );
+ pthread_cleanup_pop(0);
+
+ //i go away, someone else has to be awaken, maybe...
+ waiting_thread_wake();
+
+ return DFB_OK;
+}
+
+static DFBResult
+IDirectFBEventBuffer_HasEvent_slave( IDirectFBEventBuffer *thiz )
+{
+ INTERFACE_GET_DATA(IDirectFBEventBuffer)
+
+ //noone else is reading for us...
+ pthread_cleanup_push( (void(*)(void*))pthread_mutex_unlock ,
+ (void*)&fusion_lock );
+
+ if(pthread_mutex_trylock( &fusion_lock )==0)
+ {
+ fusion_read_pending();
+ pthread_mutex_unlock( &fusion_lock );
+ }
+
+ pthread_cleanup_pop(0);
+
+ return (data->events ? DFB_OK : DFB_BUFFEREMPTY);
+}
+
+/*
+ * keep the old functions to make work the master
+ */
+
+ static DFBResult
+IDirectFBEventBuffer_WaitForEvent_master(
+ IDirectFBEventBuffer *thiz )
{
DFBResult ret = DFB_OK;
INTERFACE_GET_DATA(IDirectFBEventBuffer)
+ pthread_cleanup_push( (void(*)(void*))pthread_mutex_unlock,
+ (void*)&(data->events_mutex) );
pthread_mutex_lock( &data->events_mutex );
if (!data->events)
@@ -204,13 +551,15 @@
if (!data->events)
ret = DFB_INTERRUPTED;
- pthread_mutex_unlock( &data->events_mutex );
+ pthread_mutex_unlock( &data->events_mutex );
+ pthread_cleanup_pop(0);
return ret;
}
static DFBResult
-IDirectFBEventBuffer_WaitForEventWithTimeout( IDirectFBEventBuffer *thiz,
+IDirectFBEventBuffer_WaitForEventWithTimeout_master(
+ IDirectFBEventBuffer *thiz,
unsigned int seconds,
unsigned int milli_seconds )
{
@@ -218,48 +567,70 @@
struct timespec timeout;
DFBResult ret = DFB_OK;
int locked = 0;
+ int hasevents = 0;
long int nano_seconds = milli_seconds * 1000000;
INTERFACE_GET_DATA(IDirectFBEventBuffer)
+ pthread_cleanup_push( (void(*)(void*))pthread_mutex_unlock,
+ (void*)&(data->events_mutex));
+
if (pthread_mutex_trylock( &data->events_mutex ) == 0) {
- if (data->events) {
- pthread_mutex_unlock ( &data->events_mutex );
- return ret;
- }
+ if (data->events)
+ hasevents = 1;
locked = 1;
}
- gettimeofday( &now, NULL );
-
- timeout.tv_sec = now.tv_sec + seconds;
- timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds;
-
- timeout.tv_sec += timeout.tv_nsec / 1000000000;
- timeout.tv_nsec %= 1000000000;
-
- if (!locked)
- pthread_mutex_lock( &data->events_mutex );
-
- if (!data->events) {
- if (pthread_cond_timedwait( &data->wait_condition,
- &data->events_mutex,
- &timeout ) == ETIMEDOUT)
- ret = DFB_TIMEOUT;
- else if (!data->events)
- ret = DFB_INTERRUPTED;
+ if(!hasevents)
+ {
+ gettimeofday( &now, NULL );
+
+ timeout.tv_sec = now.tv_sec + seconds;
+ timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds;
+
+ timeout.tv_sec += timeout.tv_nsec / 1000000000;
+ timeout.tv_nsec %= 1000000000;
+
+ if (!locked)
+ pthread_mutex_lock( &data->events_mutex );
+
+ if (!data->events) {
+ if (pthread_cond_timedwait( &data->wait_condition,
+ &data->events_mutex,
+ &timeout ) == ETIMEDOUT)
+ ret = DFB_TIMEOUT;
+ else if (!data->events)
+ ret = DFB_INTERRUPTED;
+ }
}
-
- pthread_mutex_unlock( &data->events_mutex );
+
+ pthread_mutex_unlock( &data->events_mutex );
+ pthread_cleanup_pop(0);
return ret;
}
static DFBResult
+IDirectFBEventBuffer_HasEvent_master(
+ IDirectFBEventBuffer *thiz )
+{
+ INTERFACE_GET_DATA(IDirectFBEventBuffer)
+
+ return (data->events ? DFB_OK : DFB_BUFFEREMPTY);
+}
+
+/*
+ * end master functions
+ */
+
+static DFBResult
IDirectFBEventBuffer_WakeUp( IDirectFBEventBuffer *thiz )
{
INTERFACE_GET_DATA(IDirectFBEventBuffer)
+ data->interrupted = 1; //has no meaning for the master :-)
+ if(fusion_pid && fusion_data == data)
+ kill(fusion_pid,SIG_AWAKE);
pthread_cond_broadcast( &data->wait_condition );
return DFB_OK;
@@ -343,14 +714,6 @@
}
static DFBResult
-IDirectFBEventBuffer_HasEvent( IDirectFBEventBuffer *thiz )
-{
- INTERFACE_GET_DATA(IDirectFBEventBuffer)
-
- return (data->events ? DFB_OK : DFB_BUFFEREMPTY);
-}
-
-static DFBResult
IDirectFBEventBuffer_PostEvent( IDirectFBEventBuffer *thiz,
DFBEvent *event )
{
@@ -382,19 +745,44 @@
data->filter = filter;
data->filter_ctx = filter_ctx;
+ if(dfb_is_master && mutexes_init==0) //if master skip mutex
+ mutexes_init++;
+ if(mutexes_init==0)
+ {
+ pthread_mutex_init( &fusion_lock, NULL );
+ pthread_mutex_init( &wtlist_lock, NULL );
+ }
+ mutexes_init++;
+
pthread_mutex_init( &data->events_mutex, NULL );
pthread_cond_init( &data->wait_condition, NULL );
-
- thiz->AddRef = IDirectFBEventBuffer_AddRef;
- thiz->Release = IDirectFBEventBuffer_Release;
- thiz->Reset = IDirectFBEventBuffer_Reset;
- thiz->WaitForEvent = IDirectFBEventBuffer_WaitForEvent;
- thiz->WaitForEventWithTimeout = IDirectFBEventBuffer_WaitForEventWithTimeout;
- thiz->GetEvent = IDirectFBEventBuffer_GetEvent;
- thiz->PeekEvent = IDirectFBEventBuffer_PeekEvent;
- thiz->HasEvent = IDirectFBEventBuffer_HasEvent;
- thiz->PostEvent = IDirectFBEventBuffer_PostEvent;
- thiz->WakeUp = IDirectFBEventBuffer_WakeUp;
+
+ if(dfb_is_master)
+ {
+ thiz->WaitForEvent =
+ IDirectFBEventBuffer_WaitForEvent_master;
+ thiz->WaitForEventWithTimeout =
+ IDirectFBEventBuffer_WaitForEventWithTimeout_master;
+ thiz->HasEvent =
+ IDirectFBEventBuffer_HasEvent_master;
+ }
+ else
+ {
+ thiz->WaitForEvent =
+ IDirectFBEventBuffer_WaitForEvent_slave;
+ thiz->WaitForEventWithTimeout =
+ IDirectFBEventBuffer_WaitForEventWithTimeout_slave;
+ thiz->HasEvent =
+ IDirectFBEventBuffer_HasEvent_slave;
+ }
+
+ thiz->AddRef = IDirectFBEventBuffer_AddRef;
+ thiz->Release = IDirectFBEventBuffer_Release;
+ thiz->Reset = IDirectFBEventBuffer_Reset;
+ thiz->GetEvent = IDirectFBEventBuffer_GetEvent;
+ thiz->PeekEvent = IDirectFBEventBuffer_PeekEvent;
+ thiz->PostEvent = IDirectFBEventBuffer_PostEvent;
+ thiz->WakeUp = IDirectFBEventBuffer_WakeUp;
return DFB_OK;
}
#include <directfb.h>
#include <pthread.h>
#include <signal.h>
IDirectFB *d;
IDirectFBDisplayLayer *l;
IDirectFBWindow *w1;
IDirectFBWindow *w2;
IDirectFBWindow *w3;
IDirectFBSurface *s1;
IDirectFBSurface *s2;
IDirectFBSurface *s3;
IDirectFBEventBuffer *e1;
IDirectFBEventBuffer *e2;
IDirectFBEventBuffer *e3;
pthread_t dummy;
void * illkillyou(void *a)
{
while(1)
{
char k;
scanf("%c",&k);
if(k=='k')
{
printf("killing brother :-)\n");
printf("i wish you a bloody continue, ha ha ha...\n");
pthread_cancel(dummy);
}
}
}
void * async_shit(void *a)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
printf("child pid %d\n",getpid());
while(2)
{
DFBWindowEvent ev;
e2->WaitForEvent( e2 );
e2->GetEvent( e2, DFB_EVENT(&ev) );
if(ev.type == DWET_MOTION)
{
DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
s2->FillRectangle(s2,ev.x-5,ev.y-5,10,10);
s2->Flip(s2,&r,0);
}
}
};
void * async_shit3(void *a)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
printf("child pid %d\n",getpid());
while(3)
{
DFBWindowEvent ev;
e3->WaitForEvent( e3 );
e3->GetEvent( e3, DFB_EVENT(&ev) );
if(ev.type == DWET_MOTION)
{
DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
s3->FillRectangle(s3,ev.x-5,ev.y-5,10,10);
s3->Flip(s3,&r,0);
}
}
};
#define TRE
int main(int argc,char *argv[])
{
int i;
DirectFBInit(&argc,&argv);
DirectFBCreate(&d);
d->GetDisplayLayer(d, DLID_PRIMARY, &l );
{
DFBWindowDescription desc;
desc.flags= (DFBWindowDescriptionFlags)
(DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|
DWDESC_POSX|DWDESC_POSY|DWDESC_PIXELFORMAT);
desc.caps = DWCAPS_ALPHACHANNEL;
desc.pixelformat = DSPF_ARGB;
desc.posx = 40;
desc.posy = 40;
desc.height = 300;
desc.width = 300;
l->CreateWindow( l, &desc, &w1 );
desc.posx = 100;
desc.posy = 300;
l->CreateWindow( l, &desc, &w2 );
#ifdef TRE
desc.posx = 300;
desc.posy = 100;
l->CreateWindow( l, &desc, &w3 );
#endif
}
w1->SetOpacity( w1, 0xff );
w1->GetSurface( w1, &s1 );
w1->SetOptions(w1,DWOP_ALPHACHANNEL|DWOP_SHAPED);
w1->CreateEventBuffer( w1, &e1 );
s1->Clear(s1,0xff,0xff,0xff,0xff);
s1->SetColor(s1,0,0,0,0);
s1->FillRectangle(s1,100,0,150,250);
s1->SetColor(s1,0,0,0,0xff);
s1->Flip(s1,0,0);
w2->SetOpacity( w2, 0xff );
w2->GetSurface( w2, &s2 );
w2->SetOptions(w2,DWOP_NONE);
w2->CreateEventBuffer( w2, &e2 );
s2->Clear(s2,0,0xff,0xff,0);
s2->SetColor(s2,0xff,0,0,0);
s2->Flip(s2,0,0);
#ifdef TRE
w3->SetOpacity( w3, 0xff );
w3->GetSurface( w3, &s3 );
w3->SetOptions(w3,DWOP_COLORKEYING|DWOP_SHAPED);
w3->SetColorKey(w3,6,6,6);
w3->CreateEventBuffer( w3, &e3 );
s3->Clear(s3,6,6,6,7);
s3->SetColor(s3,0xff,0xff,0,0xff);
s3->FillTriangle(s3,300,0,0,150,300,300);
s3->SetColor(s3,0xff,0,0xff,0);
s3->Flip(s3,0,0);
#endif
pthread_create(&dummy,NULL,illkillyou,NULL);
#ifdef TRE
pthread_create(&dummy,NULL,async_shit3,NULL);
#endif
pthread_create(&dummy,NULL,async_shit,NULL);
printf("write k<enter> to murder a thread\n");
while(1)
{
DFBWindowEvent ev;
e1->WaitForEvent( e1 );
e1->GetEvent( e1, DFB_EVENT(&ev) );
if(ev.type == DWET_MOTION)
{
DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
s1->FillRectangle(s1,ev.x-5,ev.y-5,10,10);
s1->Flip(s1,&r,0);
}
}
return 0;
}
#include <directfb.h>
#include <pthread.h>
#include <signal.h>
IDirectFB *d;
IDirectFBDisplayLayer *l;
IDirectFBWindow *w1;
IDirectFBWindow *w2;
IDirectFBWindow *w3;
IDirectFBSurface *s1;
IDirectFBSurface *s2;
IDirectFBSurface *s3;
IDirectFBEventBuffer *e1;
IDirectFBEventBuffer *e2;
IDirectFBEventBuffer *e3;
pthread_t dummy;
void * illkillyou(void *a)
{
while(1)
{
char k;
scanf("%c",&k);
if(k=='k')
{
printf("awaking brother :-)\n");
printf("it is so sleepy, d'oh...\n");
e1->WakeUp(e1);
}
}
}
int main(int argc,char *argv[])
{
int i;
DirectFBInit(&argc,&argv);
DirectFBCreate(&d);
d->GetDisplayLayer(d, DLID_PRIMARY, &l );
{
DFBWindowDescription desc;
desc.flags= (DFBWindowDescriptionFlags)
(DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|
DWDESC_POSX|DWDESC_POSY|DWDESC_PIXELFORMAT);
desc.pixelformat = DSPF_ARGB;
desc.caps = DWCAPS_ALPHACHANNEL;
desc.posx = 40;
desc.posy = 40;
desc.height = 300;
desc.width = 300;
l->CreateWindow( l, &desc, &w1 );
}
w1->SetOpacity( w1, 0xff);
w1->CreateEventBuffer( w1, &e1 );
w1->SetOptions(w1,DWOP_ALPHACHANNEL|DWOP_SHAPED);
w1->GetSurface( w1, &s1 );
s1->Clear(s1,0xff,0xff,0xff,0xff);
s1->SetColor(s1,0,0,0,0);
s1->FillRectangle(s1,100,0,100,250);
s1->SetColor(s1,0xff,0x80,0,0xff);
s1->Flip(s1,0,0);
pthread_create(&dummy,NULL,illkillyou,NULL);
printf("write k<enter> to wakeup the buffer\n");
while(1)
{
DFBWindowEvent ev;
DFBResult e;
e = e1->WaitForEvent( e1 );
if(e==DFB_INTERRUPTED)
printf("awaken :-)\n");
else
{
e1->GetEvent( e1, DFB_EVENT(&ev) );
if(ev.type == DWET_MOTION)
{
DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
s1->FillRectangle(s1,ev.x-5,ev.y-5,10,10);
s1->Flip(s1,&r,0);
}
}
}
return 0;
}