D-Bus  1.6.8
dbus-timeout.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-timeout.c DBusTimeout implementation
00003  *
00004  * Copyright (C) 2003  CodeFactory AB
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-internals.h"
00026 #include "dbus-timeout.h"
00027 #include "dbus-list.h"
00028 
00040 struct DBusTimeout
00041 {
00042   int refcount;                                
00043   int interval;                                
00045   DBusTimeoutHandler handler;                  
00046   void *handler_data;                          
00047   DBusFreeFunction free_handler_data_function; 
00049   void *data;                                  
00050   DBusFreeFunction free_data_function;         
00051   unsigned int enabled : 1;                    
00052 };
00053 
00062 DBusTimeout*
00063 _dbus_timeout_new (int                 interval,
00064                    DBusTimeoutHandler  handler,
00065                    void               *data,
00066                    DBusFreeFunction    free_data_function)
00067 {
00068   DBusTimeout *timeout;
00069 
00070   timeout = dbus_new0 (DBusTimeout, 1);
00071   if (timeout == NULL)
00072     return NULL;
00073   
00074   timeout->refcount = 1;
00075   timeout->interval = interval;
00076 
00077   timeout->handler = handler;
00078   timeout->handler_data = data;
00079   timeout->free_handler_data_function = free_data_function;
00080 
00081   timeout->enabled = TRUE;
00082   
00083   return timeout;
00084 }
00085 
00092 DBusTimeout *
00093 _dbus_timeout_ref (DBusTimeout *timeout)
00094 {
00095   timeout->refcount += 1;
00096 
00097   return timeout;
00098 }
00099 
00106 void
00107 _dbus_timeout_unref (DBusTimeout *timeout)
00108 {
00109   _dbus_assert (timeout != NULL);
00110   _dbus_assert (timeout->refcount > 0);
00111   
00112   timeout->refcount -= 1;
00113   if (timeout->refcount == 0)
00114     {
00115       dbus_timeout_set_data (timeout, NULL, NULL); /* call free_data_function */
00116 
00117       if (timeout->free_handler_data_function)
00118         (* timeout->free_handler_data_function) (timeout->handler_data);
00119       
00120       dbus_free (timeout);
00121     }
00122 }
00123 
00133 void
00134 _dbus_timeout_set_interval (DBusTimeout *timeout,
00135                             int          interval)
00136 {
00137   _dbus_assert (interval >= 0);
00138   
00139   timeout->interval = interval;
00140 }
00141 
00152 void
00153 _dbus_timeout_set_enabled (DBusTimeout  *timeout,
00154                            dbus_bool_t   enabled)
00155 {
00156   timeout->enabled = enabled != FALSE;
00157 }
00158 
00159 
00176 struct DBusTimeoutList
00177 {
00178   DBusList *timeouts; 
00180   DBusAddTimeoutFunction add_timeout_function;       
00181   DBusRemoveTimeoutFunction remove_timeout_function; 
00182   DBusTimeoutToggledFunction timeout_toggled_function; 
00183   void *timeout_data;                                
00184   DBusFreeFunction timeout_free_data_function;       
00185 };
00186 
00193 DBusTimeoutList*
00194 _dbus_timeout_list_new (void)
00195 {
00196   DBusTimeoutList *timeout_list;
00197 
00198   timeout_list = dbus_new0 (DBusTimeoutList, 1);
00199   if (timeout_list == NULL)
00200     return NULL;
00201 
00202   return timeout_list;
00203 }
00204 
00210 void
00211 _dbus_timeout_list_free (DBusTimeoutList *timeout_list)
00212 {
00213   /* free timeout_data and remove timeouts as a side effect */
00214   _dbus_timeout_list_set_functions (timeout_list,
00215                                     NULL, NULL, NULL, NULL, NULL);
00216 
00217   _dbus_list_foreach (&timeout_list->timeouts,
00218                       (DBusForeachFunction) _dbus_timeout_unref,
00219                       NULL);
00220   _dbus_list_clear (&timeout_list->timeouts);
00221 
00222   dbus_free (timeout_list);
00223 }
00224 
00238 dbus_bool_t
00239 _dbus_timeout_list_set_functions (DBusTimeoutList           *timeout_list,
00240                                   DBusAddTimeoutFunction     add_function,
00241                                   DBusRemoveTimeoutFunction  remove_function,
00242                                   DBusTimeoutToggledFunction toggled_function,
00243                                   void                      *data,
00244                                   DBusFreeFunction           free_data_function)
00245 {
00246   /* Add timeouts with the new function, failing on OOM */
00247   if (add_function != NULL)
00248     {
00249       DBusList *link;
00250       
00251       link = _dbus_list_get_first_link (&timeout_list->timeouts);
00252       while (link != NULL)
00253         {
00254           DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
00255                                                      link);
00256       
00257           if (!(* add_function) (link->data, data))
00258             {
00259               /* remove it all again and return FALSE */
00260               DBusList *link2;
00261               
00262               link2 = _dbus_list_get_first_link (&timeout_list->timeouts);
00263               while (link2 != link)
00264                 {
00265                   DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
00266                                                              link2);
00267 
00268                   (* remove_function) (link2->data, data);
00269                   
00270                   link2 = next;
00271                 }
00272 
00273               return FALSE;
00274             }
00275       
00276           link = next;
00277         }
00278     }
00279   
00280   /* Remove all current timeouts from previous timeout handlers */
00281 
00282   if (timeout_list->remove_timeout_function != NULL)
00283     {
00284       _dbus_list_foreach (&timeout_list->timeouts,
00285                           (DBusForeachFunction) timeout_list->remove_timeout_function,
00286                           timeout_list->timeout_data);
00287     }
00288 
00289   if (timeout_list->timeout_free_data_function != NULL)
00290     (* timeout_list->timeout_free_data_function) (timeout_list->timeout_data);
00291 
00292   timeout_list->add_timeout_function = add_function;
00293   timeout_list->remove_timeout_function = remove_function;
00294   timeout_list->timeout_toggled_function = toggled_function;
00295   timeout_list->timeout_data = data;
00296   timeout_list->timeout_free_data_function = free_data_function;
00297 
00298   return TRUE;
00299 }
00300 
00309 dbus_bool_t
00310 _dbus_timeout_list_add_timeout (DBusTimeoutList *timeout_list,
00311                                 DBusTimeout     *timeout)
00312 {
00313   if (!_dbus_list_append (&timeout_list->timeouts, timeout))
00314     return FALSE;
00315 
00316   _dbus_timeout_ref (timeout);
00317 
00318   if (timeout_list->add_timeout_function != NULL)
00319     {
00320       if (!(* timeout_list->add_timeout_function) (timeout,
00321                                                    timeout_list->timeout_data))
00322         {
00323           _dbus_list_remove_last (&timeout_list->timeouts, timeout);
00324           _dbus_timeout_unref (timeout);
00325           return FALSE;
00326         }
00327     }
00328 
00329   return TRUE;
00330 }
00331 
00339 void
00340 _dbus_timeout_list_remove_timeout (DBusTimeoutList *timeout_list,
00341                                    DBusTimeout     *timeout)
00342 {
00343   if (!_dbus_list_remove (&timeout_list->timeouts, timeout))
00344     _dbus_assert_not_reached ("Nonexistent timeout was removed");
00345 
00346   if (timeout_list->remove_timeout_function != NULL)
00347     (* timeout_list->remove_timeout_function) (timeout,
00348                                                timeout_list->timeout_data);
00349 
00350   _dbus_timeout_unref (timeout);
00351 }
00352 
00361 void
00362 _dbus_timeout_list_toggle_timeout (DBusTimeoutList           *timeout_list,
00363                                    DBusTimeout               *timeout,
00364                                    dbus_bool_t                enabled)
00365 {
00366   enabled = !!enabled;
00367   
00368   if (enabled == timeout->enabled)
00369     return;
00370 
00371   timeout->enabled = enabled;
00372   
00373   if (timeout_list->timeout_toggled_function != NULL)
00374     (* timeout_list->timeout_toggled_function) (timeout,
00375                                                 timeout_list->timeout_data);
00376 }
00377 
00415 int
00416 dbus_timeout_get_interval (DBusTimeout *timeout)
00417 {
00418   return timeout->interval;
00419 }
00420 
00428 void*
00429 dbus_timeout_get_data (DBusTimeout *timeout)
00430 {
00431   return timeout->data;
00432 }
00433 
00445 void
00446 dbus_timeout_set_data (DBusTimeout      *timeout,
00447                        void             *data,
00448                        DBusFreeFunction  free_data_function)
00449 {
00450   if (timeout->free_data_function != NULL)
00451     (* timeout->free_data_function) (timeout->data);
00452 
00453   timeout->data = data;
00454   timeout->free_data_function = free_data_function;
00455 }
00456 
00471 dbus_bool_t
00472 dbus_timeout_handle (DBusTimeout *timeout)
00473 {
00474   return (* timeout->handler) (timeout->handler_data);
00475 }
00476 
00477 
00485 dbus_bool_t
00486 dbus_timeout_get_enabled (DBusTimeout *timeout)
00487 {
00488   return timeout->enabled;
00489 }
00490