LCOV - code coverage report
Current view: top level - pulse - glib-mainloop.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 225 300 75.0 %
Date: 2012-07-17 Functions: 17 23 73.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 153 406 37.7 %

           Branch data     Line data    Source code
       1                 :            : /***
       2                 :            :   This file is part of PulseAudio.
       3                 :            : 
       4                 :            :   Copyright 2004-2006 Lennart Poettering
       5                 :            : 
       6                 :            :   PulseAudio is free software; you can redistribute it and/or modify
       7                 :            :   it under the terms of the GNU Lesser General Public License as published
       8                 :            :   by the Free Software Foundation; either version 2.1 of the License,
       9                 :            :   or (at your option) any later version.
      10                 :            : 
      11                 :            :   PulseAudio is distributed in the hope that it will be useful, but
      12                 :            :   WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      14                 :            :   General Public License for more details.
      15                 :            : 
      16                 :            :   You should have received a copy of the GNU Lesser General Public License
      17                 :            :   along with PulseAudio; if not, write to the Free Software
      18                 :            :   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      19                 :            :   USA.
      20                 :            : ***/
      21                 :            : 
      22                 :            : #ifdef HAVE_CONFIG_H
      23                 :            : #include <config.h>
      24                 :            : #endif
      25                 :            : 
      26                 :            : #include <pulse/xmalloc.h>
      27                 :            : #include <pulse/timeval.h>
      28                 :            : 
      29                 :            : #include <pulsecore/core-util.h>
      30                 :            : #include <pulsecore/log.h>
      31                 :            : #include <pulsecore/llist.h>
      32                 :            : 
      33                 :            : #include <glib.h>
      34                 :            : #include "glib-mainloop.h"
      35                 :            : 
      36                 :            : struct pa_io_event {
      37                 :            :     pa_glib_mainloop *mainloop;
      38                 :            :     int dead;
      39                 :            : 
      40                 :            :     GPollFD poll_fd;
      41                 :            :     int poll_fd_added;
      42                 :            : 
      43                 :            :     pa_io_event_cb_t callback;
      44                 :            :     void *userdata;
      45                 :            :     pa_io_event_destroy_cb_t destroy_callback;
      46                 :            : 
      47                 :            :     PA_LLIST_FIELDS(pa_io_event);
      48                 :            : };
      49                 :            : 
      50                 :            : struct pa_time_event {
      51                 :            :     pa_glib_mainloop *mainloop;
      52                 :            :     int dead;
      53                 :            : 
      54                 :            :     int enabled;
      55                 :            :     struct timeval timeval;
      56                 :            : 
      57                 :            :     pa_time_event_cb_t callback;
      58                 :            :     void *userdata;
      59                 :            :     pa_time_event_destroy_cb_t destroy_callback;
      60                 :            : 
      61                 :            :     PA_LLIST_FIELDS(pa_time_event);
      62                 :            : };
      63                 :            : 
      64                 :            : struct pa_defer_event {
      65                 :            :     pa_glib_mainloop *mainloop;
      66                 :            :     int dead;
      67                 :            : 
      68                 :            :     int enabled;
      69                 :            : 
      70                 :            :     pa_defer_event_cb_t callback;
      71                 :            :     void *userdata;
      72                 :            :     pa_defer_event_destroy_cb_t destroy_callback;
      73                 :            : 
      74                 :            :     PA_LLIST_FIELDS(pa_defer_event);
      75                 :            : };
      76                 :            : 
      77                 :            : struct pa_glib_mainloop {
      78                 :            :     GSource source;
      79                 :            : 
      80                 :            :     pa_mainloop_api api;
      81                 :            :     GMainContext *context;
      82                 :            : 
      83                 :            :     PA_LLIST_HEAD(pa_io_event, io_events);
      84                 :            :     PA_LLIST_HEAD(pa_time_event, time_events);
      85                 :            :     PA_LLIST_HEAD(pa_defer_event, defer_events);
      86                 :            : 
      87                 :            :     int n_enabled_defer_events, n_enabled_time_events;
      88                 :            :     int io_events_please_scan, time_events_please_scan, defer_events_please_scan;
      89                 :            : 
      90                 :            :     pa_time_event *cached_next_time_event;
      91                 :            : };
      92                 :            : 
      93                 :          1 : static void cleanup_io_events(pa_glib_mainloop *g, int force) {
      94                 :            :     pa_io_event *e;
      95                 :            : 
      96                 :          1 :     e = g->io_events;
      97         [ +  + ]:          2 :     while (e) {
      98                 :          1 :         pa_io_event *n = e->next;
      99                 :            : 
     100 [ -  + ][ #  # ]:          1 :         if (!force && g->io_events_please_scan <= 0)
     101                 :            :             break;
     102                 :            : 
     103 [ -  + ][ #  # ]:          1 :         if (force || e->dead) {
     104 [ -  + ][ -  + ]:          1 :             PA_LLIST_REMOVE(pa_io_event, g->io_events, e);
         [ -  + ][ -  + ]
     105                 :            : 
     106         [ +  - ]:          1 :             if (e->dead) {
     107 [ -  + ][ -  + ]:          1 :                 g_assert(g->io_events_please_scan > 0);
     108                 :          1 :                 g->io_events_please_scan--;
     109                 :            :             }
     110                 :            : 
     111         [ -  + ]:          1 :             if (e->poll_fd_added)
     112                 :          0 :                 g_source_remove_poll(&g->source, &e->poll_fd);
     113                 :            : 
     114         [ -  + ]:          1 :             if (e->destroy_callback)
     115                 :          0 :                 e->destroy_callback(&g->api, e, e->userdata);
     116                 :            : 
     117                 :          1 :             pa_xfree(e);
     118                 :            :         }
     119                 :            : 
     120                 :          1 :         e = n;
     121                 :            :     }
     122                 :            : 
     123 [ -  + ][ -  + ]:          1 :     g_assert(g->io_events_please_scan == 0);
     124                 :          1 : }
     125                 :            : 
     126                 :          1 : static void cleanup_time_events(pa_glib_mainloop *g, int force) {
     127                 :            :     pa_time_event *e;
     128                 :            : 
     129                 :          1 :     e = g->time_events;
     130         [ +  + ]:          2 :     while (e) {
     131                 :          1 :         pa_time_event *n = e->next;
     132                 :            : 
     133 [ -  + ][ #  # ]:          1 :         if (!force && g->time_events_please_scan <= 0)
     134                 :            :             break;
     135                 :            : 
     136 [ -  + ][ #  # ]:          1 :         if (force || e->dead) {
     137 [ -  + ][ -  + ]:          1 :             PA_LLIST_REMOVE(pa_time_event, g->time_events, e);
         [ -  + ][ -  + ]
     138                 :            : 
     139         [ +  - ]:          1 :             if (e->dead) {
     140 [ -  + ][ -  + ]:          1 :                 g_assert(g->time_events_please_scan > 0);
     141                 :          1 :                 g->time_events_please_scan--;
     142                 :            :             }
     143                 :            : 
     144 [ -  + ][ #  # ]:          1 :             if (!e->dead && e->enabled) {
     145 [ #  # ][ #  # ]:          0 :                 g_assert(g->n_enabled_time_events > 0);
     146                 :          0 :                 g->n_enabled_time_events--;
     147                 :            :             }
     148                 :            : 
     149         [ -  + ]:          1 :             if (e->destroy_callback)
     150                 :          0 :                 e->destroy_callback(&g->api, e, e->userdata);
     151                 :            : 
     152                 :          1 :             pa_xfree(e);
     153                 :            :         }
     154                 :            : 
     155                 :          1 :         e = n;
     156                 :            :     }
     157                 :            : 
     158 [ -  + ][ -  + ]:          1 :     g_assert(g->time_events_please_scan == 0);
     159                 :          1 : }
     160                 :            : 
     161                 :          1 : static void cleanup_defer_events(pa_glib_mainloop *g, int force) {
     162                 :            :     pa_defer_event *e;
     163                 :            : 
     164                 :          1 :     e = g->defer_events;
     165         [ +  + ]:          2 :     while (e) {
     166                 :          1 :         pa_defer_event *n = e->next;
     167                 :            : 
     168 [ -  + ][ #  # ]:          1 :         if (!force && g->defer_events_please_scan <= 0)
     169                 :            :             break;
     170                 :            : 
     171 [ -  + ][ #  # ]:          1 :         if (force || e->dead) {
     172 [ -  + ][ -  + ]:          1 :             PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e);
         [ -  + ][ -  + ]
     173                 :            : 
     174         [ +  - ]:          1 :             if (e->dead) {
     175 [ -  + ][ -  + ]:          1 :                 g_assert(g->defer_events_please_scan > 0);
     176                 :          1 :                 g->defer_events_please_scan--;
     177                 :            :             }
     178                 :            : 
     179 [ -  + ][ #  # ]:          1 :             if (!e->dead && e->enabled) {
     180 [ #  # ][ #  # ]:          0 :                 g_assert(g->n_enabled_defer_events > 0);
     181                 :          0 :                 g->n_enabled_defer_events--;
     182                 :            :             }
     183                 :            : 
     184         [ -  + ]:          1 :             if (e->destroy_callback)
     185                 :          0 :                 e->destroy_callback(&g->api, e, e->userdata);
     186                 :            : 
     187                 :          1 :             pa_xfree(e);
     188                 :            :         }
     189                 :            : 
     190                 :          1 :         e = n;
     191                 :            :     }
     192                 :            : 
     193 [ -  + ][ -  + ]:          1 :     g_assert(g->defer_events_please_scan == 0);
     194                 :          1 : }
     195                 :            : 
     196                 :            : static gushort map_flags_to_glib(pa_io_event_flags_t flags) {
     197 [ #  # ][ #  # ]:          1 :     return (gushort)
         [ #  # ][ -  + ]
         [ +  - ][ +  - ]
     198                 :          1 :         ((flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) |
     199                 :          1 :          (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) |
     200                 :            :          (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) |
     201                 :          1 :          (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0));
     202                 :            : }
     203                 :            : 
     204                 :            : static pa_io_event_flags_t map_flags_from_glib(gushort flags) {
     205                 :          0 :     return
     206                 :          0 :         (flags & G_IO_IN ? PA_IO_EVENT_INPUT : 0) |
     207         [ #  # ]:          0 :         (flags & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) |
     208                 :          0 :         (flags & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) |
     209         [ #  # ]:          0 :         (flags & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0);
     210                 :            : }
     211                 :            : 
     212                 :          1 : static pa_io_event* glib_io_new(
     213                 :            :         pa_mainloop_api*m,
     214                 :            :         int fd,
     215                 :            :         pa_io_event_flags_t f,
     216                 :            :         pa_io_event_cb_t cb,
     217                 :            :         void *userdata) {
     218                 :            : 
     219                 :            :     pa_io_event *e;
     220                 :            :     pa_glib_mainloop *g;
     221                 :            : 
     222 [ -  + ][ -  + ]:          1 :     g_assert(m);
     223 [ -  + ][ -  + ]:          1 :     g_assert(m->userdata);
     224 [ -  + ][ -  + ]:          1 :     g_assert(fd >= 0);
     225 [ -  + ][ -  + ]:          1 :     g_assert(cb);
     226                 :            : 
     227                 :          1 :     g = m->userdata;
     228                 :            : 
     229                 :          1 :     e = pa_xnew(pa_io_event, 1);
     230                 :          1 :     e->mainloop = g;
     231                 :          1 :     e->dead = 0;
     232                 :            : 
     233                 :          1 :     e->poll_fd.fd = fd;
     234                 :          1 :     e->poll_fd.events = map_flags_to_glib(f);
     235                 :          1 :     e->poll_fd.revents = 0;
     236                 :            : 
     237                 :          1 :     e->callback = cb;
     238                 :          1 :     e->userdata = userdata;
     239                 :          1 :     e->destroy_callback = NULL;
     240                 :            : 
     241 [ -  + ][ -  + ]:          1 :     PA_LLIST_PREPEND(pa_io_event, g->io_events, e);
     242                 :            : 
     243                 :          1 :     g_source_add_poll(&g->source, &e->poll_fd);
     244                 :          1 :     e->poll_fd_added = 1;
     245                 :            : 
     246                 :          1 :     return e;
     247                 :            : }
     248                 :            : 
     249                 :          0 : static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) {
     250 [ #  # ][ #  # ]:          0 :     g_assert(e);
     251 [ #  # ][ #  # ]:          0 :     g_assert(!e->dead);
     252                 :            : 
     253                 :          0 :     e->poll_fd.events = map_flags_to_glib(f);
     254                 :          0 : }
     255                 :            : 
     256                 :          1 : static void glib_io_free(pa_io_event*e) {
     257 [ -  + ][ -  + ]:          1 :     g_assert(e);
     258 [ -  + ][ -  + ]:          1 :     g_assert(!e->dead);
     259                 :            : 
     260                 :          1 :     e->dead = 1;
     261                 :          1 :     e->mainloop->io_events_please_scan++;
     262                 :            : 
     263         [ +  - ]:          1 :     if (e->poll_fd_added) {
     264                 :          1 :         g_source_remove_poll(&e->mainloop->source, &e->poll_fd);
     265                 :          1 :         e->poll_fd_added = 0;
     266                 :            :     }
     267                 :          1 : }
     268                 :            : 
     269                 :          0 : static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) {
     270 [ #  # ][ #  # ]:          0 :     g_assert(e);
     271 [ #  # ][ #  # ]:          0 :     g_assert(!e->dead);
     272                 :            : 
     273                 :          0 :     e->destroy_callback = cb;
     274                 :          0 : }
     275                 :            : 
     276                 :            : /* Time sources */
     277                 :            : 
     278                 :          1 : static pa_time_event* glib_time_new(
     279                 :            :         pa_mainloop_api*m,
     280                 :            :         const struct timeval *tv,
     281                 :            :         pa_time_event_cb_t cb,
     282                 :            :         void *userdata) {
     283                 :            : 
     284                 :            :     pa_glib_mainloop *g;
     285                 :            :     pa_time_event *e;
     286                 :            : 
     287 [ -  + ][ -  + ]:          1 :     g_assert(m);
     288 [ -  + ][ -  + ]:          1 :     g_assert(m->userdata);
     289 [ -  + ][ -  + ]:          1 :     g_assert(cb);
     290                 :            : 
     291                 :          1 :     g = m->userdata;
     292                 :            : 
     293                 :          1 :     e = pa_xnew(pa_time_event, 1);
     294                 :          1 :     e->mainloop = g;
     295                 :          1 :     e->dead = 0;
     296                 :            : 
     297         [ +  - ]:          1 :     if ((e->enabled = !!tv)) {
     298                 :          1 :         e->timeval = *tv;
     299                 :          1 :         g->n_enabled_time_events++;
     300                 :            : 
     301         [ -  + ]:          1 :         if (g->cached_next_time_event) {
     302 [ #  # ][ #  # ]:          0 :             g_assert(g->cached_next_time_event->enabled);
     303                 :            : 
     304         [ #  # ]:          0 :             if (pa_timeval_cmp(tv, &g->cached_next_time_event->timeval) < 0)
     305                 :          0 :                 g->cached_next_time_event = e;
     306                 :            :         }
     307                 :            :     }
     308                 :            : 
     309                 :          1 :     e->callback = cb;
     310                 :          1 :     e->userdata = userdata;
     311                 :          1 :     e->destroy_callback = NULL;
     312                 :            : 
     313 [ -  + ][ -  + ]:          1 :     PA_LLIST_PREPEND(pa_time_event, g->time_events, e);
     314                 :            : 
     315                 :          1 :     return e;
     316                 :            : }
     317                 :            : 
     318                 :          1 : static void glib_time_restart(pa_time_event*e, const struct timeval *tv) {
     319 [ -  + ][ -  + ]:          1 :     g_assert(e);
     320 [ -  + ][ -  + ]:          1 :     g_assert(!e->dead);
     321                 :            : 
     322         [ +  - ]:          1 :     if (e->enabled && !tv) {
     323 [ -  + ][ -  + ]:          1 :         g_assert(e->mainloop->n_enabled_time_events > 0);
     324                 :          1 :         e->mainloop->n_enabled_time_events--;
     325         [ #  # ]:          0 :     } else if (!e->enabled && tv)
     326                 :          0 :         e->mainloop->n_enabled_time_events++;
     327                 :            : 
     328         [ -  + ]:          1 :     if ((e->enabled = !!tv))
     329                 :          0 :         e->timeval = *tv;
     330                 :            : 
     331 [ +  - ][ -  + ]:          1 :     if (e->mainloop->cached_next_time_event && e->enabled) {
     332 [ #  # ][ #  # ]:          0 :         g_assert(e->mainloop->cached_next_time_event->enabled);
     333                 :            : 
     334         [ #  # ]:          0 :         if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
     335                 :          0 :             e->mainloop->cached_next_time_event = e;
     336         [ +  - ]:          1 :     } else if (e->mainloop->cached_next_time_event == e)
     337                 :          1 :         e->mainloop->cached_next_time_event = NULL;
     338                 :          1 : }
     339                 :            : 
     340                 :          1 : static void glib_time_free(pa_time_event *e) {
     341 [ -  + ][ -  + ]:          1 :     g_assert(e);
     342 [ -  + ][ -  + ]:          1 :     g_assert(!e->dead);
     343                 :            : 
     344                 :          1 :     e->dead = 1;
     345                 :          1 :     e->mainloop->time_events_please_scan++;
     346                 :            : 
     347         [ -  + ]:          1 :     if (e->enabled)
     348                 :          0 :         e->mainloop->n_enabled_time_events--;
     349                 :            : 
     350         [ -  + ]:          1 :     if (e->mainloop->cached_next_time_event == e)
     351                 :          0 :         e->mainloop->cached_next_time_event = NULL;
     352                 :          1 : }
     353                 :            : 
     354                 :          0 : static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) {
     355 [ #  # ][ #  # ]:          0 :     g_assert(e);
     356 [ #  # ][ #  # ]:          0 :     g_assert(!e->dead);
     357                 :            : 
     358                 :          0 :     e->destroy_callback = cb;
     359                 :          0 : }
     360                 :            : 
     361                 :            : /* Deferred sources */
     362                 :            : 
     363                 :          1 : static pa_defer_event* glib_defer_new(
     364                 :            :         pa_mainloop_api*m,
     365                 :            :         pa_defer_event_cb_t cb,
     366                 :            :         void *userdata) {
     367                 :            : 
     368                 :            :     pa_defer_event *e;
     369                 :            :     pa_glib_mainloop *g;
     370                 :            : 
     371 [ -  + ][ -  + ]:          1 :     g_assert(m);
     372 [ -  + ][ -  + ]:          1 :     g_assert(m->userdata);
     373 [ -  + ][ -  + ]:          1 :     g_assert(cb);
     374                 :            : 
     375                 :          1 :     g = m->userdata;
     376                 :            : 
     377                 :          1 :     e = pa_xnew(pa_defer_event, 1);
     378                 :          1 :     e->mainloop = g;
     379                 :          1 :     e->dead = 0;
     380                 :            : 
     381                 :          1 :     e->enabled = 1;
     382                 :          1 :     g->n_enabled_defer_events++;
     383                 :            : 
     384                 :          1 :     e->callback = cb;
     385                 :          1 :     e->userdata = userdata;
     386                 :          1 :     e->destroy_callback = NULL;
     387                 :            : 
     388 [ -  + ][ -  + ]:          1 :     PA_LLIST_PREPEND(pa_defer_event, g->defer_events, e);
     389                 :          1 :     return e;
     390                 :            : }
     391                 :            : 
     392                 :          1 : static void glib_defer_enable(pa_defer_event *e, int b) {
     393 [ -  + ][ -  + ]:          1 :     g_assert(e);
     394 [ -  + ][ -  + ]:          1 :     g_assert(!e->dead);
     395                 :            : 
     396         [ +  - ]:          1 :     if (e->enabled && !b) {
     397 [ -  + ][ -  + ]:          1 :         g_assert(e->mainloop->n_enabled_defer_events > 0);
     398                 :          1 :         e->mainloop->n_enabled_defer_events--;
     399         [ #  # ]:          0 :     } else if (!e->enabled && b)
     400                 :          0 :         e->mainloop->n_enabled_defer_events++;
     401                 :            : 
     402                 :          1 :     e->enabled = b;
     403                 :          1 : }
     404                 :            : 
     405                 :          1 : static void glib_defer_free(pa_defer_event *e) {
     406 [ -  + ][ -  + ]:          1 :     g_assert(e);
     407 [ -  + ][ -  + ]:          1 :     g_assert(!e->dead);
     408                 :            : 
     409                 :          1 :     e->dead = 1;
     410                 :          1 :     e->mainloop->defer_events_please_scan++;
     411                 :            : 
     412         [ -  + ]:          1 :     if (e->enabled) {
     413 [ #  # ][ #  # ]:          0 :         g_assert(e->mainloop->n_enabled_defer_events > 0);
     414                 :          0 :         e->mainloop->n_enabled_defer_events--;
     415                 :            :     }
     416                 :          1 : }
     417                 :            : 
     418                 :          0 : static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb) {
     419 [ #  # ][ #  # ]:          0 :     g_assert(e);
     420 [ #  # ][ #  # ]:          0 :     g_assert(!e->dead);
     421                 :            : 
     422                 :          0 :     e->destroy_callback = cb;
     423                 :          0 : }
     424                 :            : 
     425                 :            : /* quit() */
     426                 :            : 
     427                 :          0 : static void glib_quit(pa_mainloop_api*a, int retval) {
     428                 :            : 
     429                 :          0 :     g_warning("quit() ignored");
     430                 :            : 
     431                 :            :     /* NOOP */
     432                 :          0 : }
     433                 :            : 
     434                 :          2 : static pa_time_event* find_next_time_event(pa_glib_mainloop *g) {
     435                 :          2 :     pa_time_event *t, *n = NULL;
     436 [ -  + ][ -  + ]:          2 :     g_assert(g);
     437                 :            : 
     438         [ +  + ]:          2 :     if (g->cached_next_time_event)
     439                 :          1 :         return g->cached_next_time_event;
     440                 :            : 
     441         [ +  + ]:          2 :     for (t = g->time_events; t; t = t->next) {
     442                 :            : 
     443 [ +  - ][ -  + ]:          1 :         if (t->dead || !t->enabled)
     444                 :          0 :             continue;
     445                 :            : 
     446 [ -  + ][ #  # ]:          1 :         if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) {
     447                 :          1 :             n = t;
     448                 :            : 
     449                 :            :             /* Shortcut for tv = { 0, 0 } */
     450         [ +  - ]:          1 :             if (n->timeval.tv_sec <= 0)
     451                 :            :                 break;
     452                 :            :         }
     453                 :            :     }
     454                 :            : 
     455                 :          1 :     g->cached_next_time_event = n;
     456                 :          2 :     return n;
     457                 :            : }
     458                 :            : 
     459                 :            : static void scan_dead(pa_glib_mainloop *g) {
     460 [ -  + ][ -  + ]:          2 :     g_assert(g);
     461                 :            : 
     462         [ -  + ]:          2 :     if (g->io_events_please_scan)
     463                 :          0 :         cleanup_io_events(g, 0);
     464                 :            : 
     465         [ -  + ]:          2 :     if (g->time_events_please_scan)
     466                 :          0 :         cleanup_time_events(g, 0);
     467                 :            : 
     468         [ -  + ]:          2 :     if (g->defer_events_please_scan)
     469                 :          0 :         cleanup_defer_events(g, 0);
     470                 :            : }
     471                 :            : 
     472                 :          2 : static gboolean prepare_func(GSource *source, gint *timeout) {
     473                 :          2 :     pa_glib_mainloop *g = (pa_glib_mainloop*) source;
     474                 :            : 
     475 [ -  + ][ -  + ]:          2 :     g_assert(g);
     476 [ -  + ][ -  + ]:          2 :     g_assert(timeout);
     477                 :            : 
     478                 :            :     scan_dead(g);
     479                 :            : 
     480         [ +  + ]:          2 :     if (g->n_enabled_defer_events) {
     481                 :          1 :         *timeout = 0;
     482                 :          1 :         return TRUE;
     483         [ +  - ]:          1 :     } else if (g->n_enabled_time_events) {
     484                 :            :         pa_time_event *t;
     485                 :            :         GTimeVal now;
     486                 :            :         struct timeval tvnow;
     487                 :            :         pa_usec_t usec;
     488                 :            : 
     489                 :          1 :         t = find_next_time_event(g);
     490 [ -  + ][ -  + ]:          1 :         g_assert(t);
     491                 :            : 
     492                 :          1 :         g_get_current_time(&now);
     493                 :          1 :         tvnow.tv_sec = now.tv_sec;
     494                 :          1 :         tvnow.tv_usec = now.tv_usec;
     495                 :            : 
     496         [ +  - ]:          1 :         if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
     497                 :          1 :             *timeout = 0;
     498                 :          1 :             return TRUE;
     499                 :            :         }
     500                 :          0 :         usec = pa_timeval_diff(&t->timeval, &tvnow);
     501                 :          0 :         *timeout = (gint) (usec / 1000);
     502                 :            :     } else
     503                 :          2 :         *timeout = -1;
     504                 :            : 
     505                 :            :     return FALSE;
     506                 :            : }
     507                 :          0 : static gboolean check_func(GSource *source) {
     508                 :          0 :     pa_glib_mainloop *g = (pa_glib_mainloop*) source;
     509                 :            :     pa_io_event *e;
     510                 :            : 
     511 [ #  # ][ #  # ]:          0 :     g_assert(g);
     512                 :            : 
     513         [ #  # ]:          0 :     if (g->n_enabled_defer_events)
     514                 :            :         return TRUE;
     515         [ #  # ]:          0 :     else if (g->n_enabled_time_events) {
     516                 :            :         pa_time_event *t;
     517                 :            :         GTimeVal now;
     518                 :            :         struct timeval tvnow;
     519                 :            : 
     520                 :          0 :         t = find_next_time_event(g);
     521 [ #  # ][ #  # ]:          0 :         g_assert(t);
     522                 :            : 
     523                 :          0 :         g_get_current_time(&now);
     524                 :          0 :         tvnow.tv_sec = now.tv_sec;
     525                 :          0 :         tvnow.tv_usec = now.tv_usec;
     526                 :            : 
     527         [ #  # ]:          0 :         if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0)
     528                 :            :             return TRUE;
     529                 :            :     }
     530                 :            : 
     531         [ #  # ]:          0 :     for (e = g->io_events; e; e = e->next)
     532 [ #  # ][ #  # ]:          0 :         if (!e->dead && e->poll_fd.revents != 0)
     533                 :            :             return TRUE;
     534                 :            : 
     535                 :            :     return FALSE;
     536                 :            : }
     537                 :            : 
     538                 :          2 : static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) {
     539                 :          2 :     pa_glib_mainloop *g = (pa_glib_mainloop*) source;
     540                 :            :     pa_io_event *e;
     541                 :            : 
     542 [ -  + ][ -  + ]:          2 :     g_assert(g);
     543                 :            : 
     544         [ +  + ]:          2 :     if (g->n_enabled_defer_events) {
     545                 :            :         pa_defer_event *d;
     546                 :            : 
     547         [ +  - ]:          1 :         for (d = g->defer_events; d; d = d->next) {
     548 [ +  - ][ -  + ]:          1 :             if (d->dead || !d->enabled)
     549                 :          0 :                 continue;
     550                 :            : 
     551                 :            :             break;
     552                 :            :         }
     553                 :            : 
     554 [ -  + ][ -  + ]:          1 :         g_assert(d);
     555                 :            : 
     556                 :          1 :         d->callback(&g->api, d, d->userdata);
     557                 :          1 :         return TRUE;
     558                 :            :     }
     559                 :            : 
     560         [ +  - ]:          1 :     if (g->n_enabled_time_events) {
     561                 :            :         GTimeVal now;
     562                 :            :         struct timeval tvnow;
     563                 :            :         pa_time_event *t;
     564                 :            : 
     565                 :          1 :         t = find_next_time_event(g);
     566 [ -  + ][ -  + ]:          1 :         g_assert(t);
     567                 :            : 
     568                 :          1 :         g_get_current_time(&now);
     569                 :          1 :         tvnow.tv_sec = now.tv_sec;
     570                 :          1 :         tvnow.tv_usec = now.tv_usec;
     571                 :            : 
     572         [ +  - ]:          1 :         if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
     573                 :            : 
     574                 :            :             /* Disable time event */
     575                 :          1 :             glib_time_restart(t, NULL);
     576                 :            : 
     577                 :          1 :             t->callback(&g->api, t, &t->timeval, t->userdata);
     578                 :          1 :             return TRUE;
     579                 :            :         }
     580                 :            :     }
     581                 :            : 
     582         [ #  # ]:          2 :     for (e = g->io_events; e; e = e->next)
     583 [ #  # ][ #  # ]:          0 :         if (!e->dead && e->poll_fd.revents != 0) {
     584                 :          0 :             e->callback(&g->api, e, e->poll_fd.fd, map_flags_from_glib(e->poll_fd.revents), e->userdata);
     585                 :          0 :             e->poll_fd.revents = 0;
     586                 :          0 :             return TRUE;
     587                 :            :         }
     588                 :            : 
     589                 :            :     return FALSE;
     590                 :            : }
     591                 :            : 
     592                 :            : static const pa_mainloop_api vtable = {
     593                 :            :     .userdata = NULL,
     594                 :            : 
     595                 :            :     .io_new = glib_io_new,
     596                 :            :     .io_enable = glib_io_enable,
     597                 :            :     .io_free = glib_io_free,
     598                 :            :     .io_set_destroy= glib_io_set_destroy,
     599                 :            : 
     600                 :            :     .time_new = glib_time_new,
     601                 :            :     .time_restart = glib_time_restart,
     602                 :            :     .time_free = glib_time_free,
     603                 :            :     .time_set_destroy = glib_time_set_destroy,
     604                 :            : 
     605                 :            :     .defer_new = glib_defer_new,
     606                 :            :     .defer_enable = glib_defer_enable,
     607                 :            :     .defer_free = glib_defer_free,
     608                 :            :     .defer_set_destroy = glib_defer_set_destroy,
     609                 :            : 
     610                 :            :     .quit = glib_quit,
     611                 :            : };
     612                 :            : 
     613                 :          1 : pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) {
     614                 :            :     pa_glib_mainloop *g;
     615                 :            : 
     616                 :            :     static GSourceFuncs source_funcs = {
     617                 :            :         prepare_func,
     618                 :            :         check_func,
     619                 :            :         dispatch_func,
     620                 :            :         NULL,
     621                 :            :         NULL,
     622                 :            :         NULL
     623                 :            :     };
     624                 :            : 
     625                 :          1 :     g = (pa_glib_mainloop*) g_source_new(&source_funcs, sizeof(pa_glib_mainloop));
     626         [ +  - ]:          1 :     g_main_context_ref(g->context = c ? c : g_main_context_default());
     627                 :            : 
     628                 :          1 :     g->api = vtable;
     629                 :          1 :     g->api.userdata = g;
     630                 :            : 
     631                 :          1 :     PA_LLIST_HEAD_INIT(pa_io_event, g->io_events);
     632                 :          1 :     PA_LLIST_HEAD_INIT(pa_time_event, g->time_events);
     633                 :          1 :     PA_LLIST_HEAD_INIT(pa_defer_event, g->defer_events);
     634                 :            : 
     635                 :          1 :     g->n_enabled_defer_events = g->n_enabled_time_events = 0;
     636                 :          1 :     g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0;
     637                 :            : 
     638                 :          1 :     g->cached_next_time_event = NULL;
     639                 :            : 
     640                 :          1 :     g_source_attach(&g->source, g->context);
     641                 :          1 :     g_source_set_can_recurse(&g->source, FALSE);
     642                 :            : 
     643                 :          1 :     return g;
     644                 :            : }
     645                 :            : 
     646                 :          1 : void pa_glib_mainloop_free(pa_glib_mainloop* g) {
     647 [ -  + ][ -  + ]:          1 :     g_assert(g);
     648                 :            : 
     649                 :          1 :     cleanup_io_events(g, 1);
     650                 :          1 :     cleanup_defer_events(g, 1);
     651                 :          1 :     cleanup_time_events(g, 1);
     652                 :            : 
     653                 :          1 :     g_main_context_unref(g->context);
     654                 :          1 :     g_source_destroy(&g->source);
     655                 :          1 :     g_source_unref(&g->source);
     656                 :          1 : }
     657                 :            : 
     658                 :          1 : pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) {
     659 [ -  + ][ -  + ]:          1 :     g_assert(g);
     660                 :            : 
     661                 :          1 :     return &g->api;
     662                 :            : }

Generated by: LCOV version 1.9