start some work on allowing ecore_extn to double-buffer. doesn't do
authorCarsten Haitzler <raster@rasterman.com>
Fri, 14 Dec 2012 11:19:09 +0000 (11:19 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Fri, 14 Dec 2012 11:19:09 +0000 (11:19 +0000)
anything atm about it.. just sets up infra for 2 buffers to exist and
be locked. :)

SVN revision: 80931

src/modules/ecore_evas/engines/buffer/ecore_evas_extn.c

index b21b34b..d78f6cb 100644 (file)
@@ -54,10 +54,10 @@ typedef struct _Shmfile Shmfile;
 
 struct _Shmfile
 {
-   int fd;
+   void *addr, *addr2;
+   const char *file, *file2;
+   int fd, fd2;
    int size;
-   void *addr;
-   const char *file;
 };
 
 static int blank = 0x00000000;
@@ -68,58 +68,81 @@ static Shmfile *
 shmfile_new(const char *base, int id, int size, Eina_Bool sys)
 {
    Shmfile *sf;
-   char file[PATH_MAX];
+   char file[PATH_MAX], file2[PATH_MAX];
 
    sf = calloc(1, sizeof(Shmfile));
+   if (!sf) return NULL;
+   sf->fd = -1;
+   sf->fd2 = -1;
+   sf->addr = MAP_FAILED;
+   sf->addr = MAP_FAILED;
    do
      {
         mode_t mode;
+        int v1, v2, v3;
 
-        snprintf(file, sizeof(file), "/%s-%i-%i.%i.%i",
-                 base, id, (int)time(NULL), (int)getpid(), (int)rand());
+        v1 = (int)time(NULL);
+        v2 = (int)getpid();
+        v3 = (int)rand();
         mode = S_IRUSR | S_IWUSR;
         if (sys) mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+        snprintf(file, sizeof(file), "/%s-%i-%i.%i.%i", base, id, v1, v2, v3);
         sf->fd = shm_open(file, O_RDWR | O_CREAT | O_EXCL, mode);
+        if (sf->fd >= 0)
+          {
+             snprintf(file2, sizeof(file2), "/%s-%i-%i.%i.%i-b", base, id, v1, v2, v3);
+             sf->fd2 = shm_open(file2, O_RDWR | O_CREAT | O_EXCL, mode);
+             if (sf->fd2 < 0)
+               {
+                  close(sf->fd);
+                  sf->fd = -1;
+               }
+          }
      }
    while (sf->fd < 0);
 
    sf->file = eina_stringshare_add(file);
-   if (!sf->file)
-     {
-        close(sf->fd);
-        shm_unlink(sf->file);
-        eina_stringshare_del(sf->file);
-        free(sf);
-        return NULL;
-     }
+   if (!sf->file) goto err;
+   sf->file2 = eina_stringshare_add(file2);
+   if (!sf->file2) goto err;
    sf->size = size;
-   if (ftruncate(sf->fd, size) < 0)
+   if (ftruncate(sf->fd, size) < 0) goto err;
+   if (ftruncate(sf->fd2, size) < 0) goto err;
+   sf->addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, sf->fd, 0);
+   if (sf->addr == MAP_FAILED) goto err;
+   sf->addr2 = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, sf->fd2, 0);
+   if (sf->addr2 == MAP_FAILED) goto err;
+   return sf;
+err:
+   if (sf->addr != MAP_FAILED) munmap(sf->addr, sf->size);
+   if (sf->addr2 != MAP_FAILED) munmap(sf->addr2, sf->size);
+   if (sf->fd >= 0)
      {
         close(sf->fd);
-        shm_unlink(sf->file);
-        eina_stringshare_del(sf->file);
-        free(sf);
-        return NULL;
+        shm_unlink(file);
      }
-   sf->addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, sf->fd, 0);
-   if (sf->addr == MAP_FAILED)
+   if (sf->fd2 >= 0)
      {
-        close(sf->fd);
-        shm_unlink(sf->file);
-        eina_stringshare_del(sf->file);
-        free(sf);
-        return NULL;
+        close(sf->fd2);
+        shm_unlink(file2);
      }
-   return sf;
+   if (sf->file) eina_stringshare_del(sf->file);
+   if (sf->file2) eina_stringshare_del(sf->file2);
+   free(sf);
+   return NULL;
 }
 
 void
 shmfile_free(Shmfile *sf)
 {
    munmap(sf->addr, sf->size);
+   munmap(sf->addr2, sf->size);
    close(sf->fd);
+   close(sf->fd2);
    shm_unlink(sf->file);
+   shm_unlink(sf->file2);
    eina_stringshare_del(sf->file);
+   eina_stringshare_del(sf->file2);
    free(sf);
 }
 
@@ -128,42 +151,57 @@ shmfile_open(const char *ref, int size, Eina_Bool sys)
 {
    Shmfile *sf;
    mode_t mode;
-
+   char *s;
+   int l;
+   
    sf = calloc(1, sizeof(Shmfile));
+   if (!sf) return NULL;
+   sf->fd = -1;
+   sf->fd2 = -1;
+   sf->addr = MAP_FAILED;
+   sf->addr = MAP_FAILED;
    mode = S_IRUSR | S_IWUSR;
    if (sys) mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-   sf->fd = shm_open(ref, O_RDWR, mode);
-   if (sf->fd < 0)
-     {
-        free(sf);
-        return NULL;
-     }
+   l = strlen(ref);
+   s = alloca(l + 3);
+   strcpy(s, ref);
+   s[l] = '-';
+   s[l + 1] = 'b';
+   s[l + 2] = 0;
    sf->file = eina_stringshare_add(ref);
-   if (!sf->file)
-     {
-        close(sf->fd);
-        eina_stringshare_del(sf->file);
-        free(sf);
-        return NULL;
-     }
+   if (!sf->file) goto err;
+   sf->file2 = eina_stringshare_add(s);
+   if (!sf->file2) goto err;
+   sf->fd = shm_open(sf->file, O_RDWR, mode);
+   if (sf->fd < 0) goto err;
+   sf->fd2 = shm_open(sf->file2, O_RDWR, mode);
+   if (sf->fd2 < 0) goto err;
    sf->size = size;
    sf->addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, sf->fd, 0);
-   if (sf->addr == MAP_FAILED)
-     {
-        close(sf->fd);
-        eina_stringshare_del(sf->file);
-        free(sf);
-        return NULL;
-     }
+   if (sf->addr == MAP_FAILED) goto err;
+   sf->addr2 = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, sf->fd2, 0);
+   if (sf->addr2 == MAP_FAILED) goto err;
    return sf;
+err:
+   if (sf->addr != MAP_FAILED) munmap(sf->addr, sf->size);
+   if (sf->addr2 != MAP_FAILED) munmap(sf->addr2, sf->size);
+   if (sf->fd >= 0) close(sf->fd);
+   if (sf->fd2 >= 0) close(sf->fd2);
+   if (sf->file) eina_stringshare_del(sf->file);
+   if (sf->file2) eina_stringshare_del(sf->file2);
+   free(sf);
+   return NULL;
 }
 
 void
 shmfile_close(Shmfile *sf)
 {
    munmap(sf->addr, sf->size);
+   munmap(sf->addr2, sf->size);
    close(sf->fd);
+   close(sf->fd2);
    eina_stringshare_del(sf->file);
+   eina_stringshare_del(sf->file2);
    free(sf);
 }
 
@@ -194,7 +232,8 @@ enum // opcodes
    OP_EV_MULTI_MOVE,
    OP_EV_KEY_UP,
    OP_EV_KEY_DOWN,
-   OP_EV_HOLD
+   OP_EV_HOLD,
+   OP_LOCK_FILE2
 };
 
 enum
@@ -359,14 +398,16 @@ struct _Extn
         Eina_Bool   sys : 1;
    } svc;
    struct {
-        const char *lock;
-        int         lockfd;
+        const char *lock, *lock2;
+        int         lockfd, lockfd2;
         const char *shm;
         int         w, h;
         Shmfile    *shmfile;
         Eina_List  *updates;
         Eina_Bool   have_lock : 1;
         Eina_Bool   have_real_lock : 1;
+        Eina_Bool   have_lock2 : 1;
+        Eina_Bool   have_real_lock2 : 1;
    } file;
    struct {
         Eina_Bool   done : 1; /* need to send change done event to the client(plug) */
@@ -419,7 +460,7 @@ _ecore_evas_extn_event(Ecore_Evas *ee, int event)
 }
 
 static Eina_Bool
-_ecore_evas_lock_other_have(Ecore_Evas *ee)
+_ecore_evas_lock_other_have(Ecore_Evas *ee, int buf)
 {
    Eina_List *l;
    Ecore_Evas *ee2;
@@ -437,57 +478,98 @@ _ecore_evas_lock_other_have(Ecore_Evas *ee)
        bdata2 = ee2->engine.data;
         extn2 = bdata2->data;
         if (!extn2) continue;
-        if ((extn->file.lock) && (extn2->file.lock) &&
-            (!strcmp(extn->file.lock, extn2->file.lock)) &&
-            (extn2->file.have_real_lock))
-          return EINA_TRUE;
+        if (buf == 0)
+          {
+             if ((extn->file.lock) && (extn2->file.lock) &&
+                 (!strcmp(extn->file.lock, extn2->file.lock)) &&
+                 (extn2->file.have_real_lock))
+               return EINA_TRUE;
+          }
+        else if (buf == 1)
+          {
+             if ((extn->file.lock2) && (extn2->file.lock2) &&
+                 (!strcmp(extn->file.lock2, extn2->file.lock2)) &&
+                 (extn2->file.have_real_lock2))
+               return EINA_TRUE;
+          }
      }
    return EINA_FALSE;
 }
 
 static void
-_ecore_evas_socket_lock(Ecore_Evas *ee)
+_ecore_evas_socket_lock(Ecore_Evas *ee, int buf)
 {
    Extn *extn;
    Ecore_Evas_Engine_Buffer_Data *bdata = ee->engine.data;
 
    extn = bdata->data;
    if (!extn) return;
-   if (extn->file.lockfd < 0) return;
-   if (extn->file.have_lock) return;
-   extn->file.have_lock = EINA_TRUE;
-   if (_ecore_evas_lock_other_have(ee)) return;
-   lockf(extn->file.lockfd, F_ULOCK, 0);
-   extn->file.have_real_lock = EINA_TRUE;
+   if (buf == 0)
+     {
+        if (extn->file.lockfd < 0) return;
+        if (extn->file.have_lock) return;
+        extn->file.have_lock = EINA_TRUE;
+        if (_ecore_evas_lock_other_have(ee, buf)) return;
+        if (lockf(extn->file.lockfd, F_ULOCK, 0) < 0)
+          {
+             extn->file.have_lock = EINA_FALSE;
+             return;
+          }
+        extn->file.have_real_lock = EINA_TRUE;
+     }
+   else if (buf == 1)
+     {
+        if (extn->file.lockfd2 < 0) return;
+        if (extn->file.have_lock2) return;
+        extn->file.have_lock2 = EINA_TRUE;
+        if (_ecore_evas_lock_other_have(ee, buf)) return;
+        if (lockf(extn->file.lockfd2, F_ULOCK, 0) < 0)
+          {
+             extn->file.have_lock2 = EINA_FALSE;
+             return;
+          }
+        extn->file.have_real_lock2 = EINA_TRUE;
+     }
 }
 
 static void
-_ecore_evas_socket_unlock(Ecore_Evas *ee)
+_ecore_evas_socket_unlock(Ecore_Evas *ee, int buf)
 {
    Extn *extn;
    Ecore_Evas_Engine_Buffer_Data *bdata = ee->engine.data;
 
    extn = bdata->data;
    if (!extn) return;
-   if (extn->file.lockfd < 0) return;
-   if (!extn->file.have_lock) return;
-   extn->file.have_lock = EINA_FALSE;
-   if (!extn->file.have_real_lock) return;
-   lockf(extn->file.lockfd, F_ULOCK, 0);
+   if (buf == 0)
+     {
+        if (extn->file.lockfd < 0) return;
+        if (!extn->file.have_lock) return;
+        extn->file.have_lock = EINA_FALSE;
+        if (!extn->file.have_real_lock) return;
+        if (lockf(extn->file.lockfd, F_ULOCK, 0) < 0) return;
+     }
+   else if (buf == 1)
+     {
+        if (extn->file.lockfd2 < 0) return;
+        if (!extn->file.have_lock2) return;
+        extn->file.have_lock2 = EINA_FALSE;
+        if (!extn->file.have_real_lock2) return;
+        if (lockf(extn->file.lockfd2, F_ULOCK, 0) < 0) return;
+     }
 }
 
 static void
 _ecore_evas_extn_plug_targer_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Ecore_Evas *ee = data;
-   if (ee) _ecore_evas_socket_lock(ee);
+   if (ee) _ecore_evas_socket_lock(ee, 0); // XXX choose right buffer to lock
 }
 
 static void
 _ecore_evas_extn_plug_targer_render_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Ecore_Evas *ee = data;
-   if (ee) _ecore_evas_socket_unlock(ee);
+   if (ee) _ecore_evas_socket_unlock(ee, 0); // XXX choose right buffer to lock
 }
 
 static void
@@ -548,9 +630,9 @@ _ecore_evas_extn_free(Ecore_Evas *ee)
      {
         Ecore_Event_Handler *hdl;
 
-        if (extn->file.have_lock)
-          _ecore_evas_socket_unlock(ee);
-        if (extn->file.lockfd)
+        if (extn->file.have_lock) _ecore_evas_socket_unlock(ee, 0);
+        if (extn->file.have_lock2) _ecore_evas_socket_unlock(ee, 1);
+        if (extn->file.lockfd >= 0)
           {
              close(extn->file.lockfd);
              if (extn->ipc.am_server)
@@ -558,6 +640,14 @@ _ecore_evas_extn_free(Ecore_Evas *ee)
                   if (extn->file.lock) unlink(extn->file.lock);
                }
           }
+        if (extn->file.lockfd2 >= 0)
+          {
+             close(extn->file.lockfd2);
+             if (extn->ipc.am_server)
+               {
+                  if (extn->file.lock2) unlink(extn->file.lock2);
+               }
+          }
         if (extn->svc.name) eina_stringshare_del(extn->svc.name);
         if (extn->ipc.clients)
           {
@@ -566,6 +656,7 @@ _ecore_evas_extn_free(Ecore_Evas *ee)
           }
         if (extn->ipc.server) ecore_ipc_server_del(extn->ipc.server);
         if (extn->file.lock) eina_stringshare_del(extn->file.lock);
+        if (extn->file.lock2) eina_stringshare_del(extn->file.lock2);
         if (extn->file.shm) eina_stringshare_del(extn->file.shm);
         if (extn->file.shmfile)
           {
@@ -1368,13 +1459,24 @@ _ipc_server_data(void *data, int type EINA_UNUSED, void *event)
          if ((e->data) && (e->size > 0) &&
              (((unsigned char *)e->data)[e->size - 1] == 0))
            {
-              if (extn->file.have_lock) _ecore_evas_socket_unlock(ee);
+              if (extn->file.have_lock) _ecore_evas_socket_unlock(ee, 0);
               if (extn->file.lockfd) close(extn->file.lockfd);
               if (extn->file.lock) eina_stringshare_del(extn->file.lock);
               extn->file.lock = eina_stringshare_add(e->data);
               extn->file.lockfd = open(extn->file.lock, O_RDONLY);
            }
          break;
+      case OP_LOCK_FILE2:
+         if ((e->data) && (e->size > 0) &&
+             (((unsigned char *)e->data)[e->size - 1] == 0))
+           {
+              if (extn->file.have_lock2) _ecore_evas_socket_unlock(ee, 1);
+              if (extn->file.lockfd2 >= 0) close(extn->file.lockfd2);
+              if (extn->file.lock2) eina_stringshare_del(extn->file.lock2);
+              extn->file.lock2 = eina_stringshare_add(e->data);
+              extn->file.lockfd2 = open(extn->file.lock2, O_RDONLY);
+           }
+         break;
       case OP_SHM_REF:
          // e->ref == w
          // e->ref_to == h
@@ -1638,14 +1740,14 @@ static void
 _ecore_evas_extn_plug_object_data_lock(Ecore_Evas *ee)
 {
    if (!ee) return;
-   _ecore_evas_socket_lock(ee);
+   _ecore_evas_socket_lock(ee, 0); // XXX lock correct buffer
 }
 
 static void
 _ecore_evas_extn_plug_object_data_unlock(Ecore_Evas *ee)
 {
    if (!ee) return;
-   _ecore_evas_socket_unlock(ee);
+   _ecore_evas_socket_unlock(ee, 0); // XXX lock correct buffer
 }
 
 static void
@@ -1783,9 +1885,9 @@ _ecore_evas_extn_socket_render(Ecore_Evas *ee)
 
    if (bdata->pixels)
      {
-        _ecore_evas_socket_lock(ee);
+        _ecore_evas_socket_lock(ee, 0); // XXX lock correct buffer
         updates = evas_render_updates(ee->evas);
-        _ecore_evas_socket_unlock(ee);
+        _ecore_evas_socket_unlock(ee, 0); // XXX lock correct buffer
      }
    EINA_LIST_FOREACH(updates, l, r)
      {
@@ -1833,6 +1935,7 @@ _ipc_client_add(void *data, int type EINA_UNUSED, void *event)
 
    extn->ipc.clients = eina_list_append(extn->ipc.clients, e->client);
    ecore_ipc_client_send(e->client, MAJOR, OP_LOCK_FILE, 0, 0, 0, extn->file.lock, strlen(extn->file.lock) + 1);
+   ecore_ipc_client_send(e->client, MAJOR, OP_LOCK_FILE2, 0, 0, 0, extn->file.lock2, strlen(extn->file.lock2) + 1);
 
    if (extn->file.shmfile)
      {
@@ -2395,7 +2498,7 @@ _ecore_evas_extn_socket_listen(Ecore_Evas *ee, const char *svcname, int svcnum,
           {
              if (extn->file.lockfd)
                {
-                  close(extn->file.lockfd);
+                  close(extn->file.lockfd >= 0);
                   unlink(buf);
                }
              eina_stringshare_del(extn->svc.name);
@@ -2405,6 +2508,30 @@ _ecore_evas_extn_socket_listen(Ecore_Evas *ee, const char *svcname, int svcnum,
              return EINA_FALSE;
           }
 
+        snprintf(buf, sizeof(buf), "/tmp/ee-lock-XXXXXX");
+        extn->file.lockfd2 = mkstemp(buf);
+        if (extn->file.lockfd2 >= 0)
+          extn->file.lock2 = eina_stringshare_add(buf);
+        if ((extn->file.lockfd2 < 0) || (!extn->file.lock2))
+          {
+             if (extn->file.lockfd >= 0)
+               {
+                  close(extn->file.lockfd);
+                  if (extn->file.lock) unlink(extn->file.lock);
+               }
+             if (extn->file.lockfd2 >= 0)
+               {
+                  close(extn->file.lockfd2);
+                  unlink(buf);
+               }
+             eina_stringshare_del(extn->svc.name);
+             if (extn->file.lock) eina_stringshare_del(extn->file.lock);
+             if (extn->file.lock2) eina_stringshare_del(extn->file.lock2);
+             free(extn);
+             ecore_ipc_shutdown();
+             return EINA_FALSE;
+          }
+        
         if (extn->svc.sys) ipctype = ECORE_IPC_LOCAL_SYSTEM;
         extn->ipc.am_server = EINA_TRUE;
         extn->ipc.server = ecore_ipc_server_add(ipctype,
@@ -2412,13 +2539,19 @@ _ecore_evas_extn_socket_listen(Ecore_Evas *ee, const char *svcname, int svcnum,
                                                 extn->svc.num, ee);
         if (!extn->ipc.server)
           {
-             if (extn->file.lockfd)
+             if (extn->file.lockfd >= 0)
                {
                   close(extn->file.lockfd);
                   if (extn->file.lock) unlink(extn->file.lock);
                }
+             if (extn->file.lockfd2 >= 0)
+               {
+                  close(extn->file.lockfd2);
+                  if (extn->file.lock2) unlink(extn->file.lock2);
+               }
              eina_stringshare_del(extn->svc.name);
              eina_stringshare_del(extn->file.lock);
+             eina_stringshare_del(extn->file.lock2);
              free(extn);
              ecore_ipc_shutdown();
              return EINA_FALSE;