Sophie

Sophie

distrib > Mandriva > 2007.0 > x86_64 > media > main-release > by-pkgid > 926d2d1e3111287cee1b0a4fad4fb4f6 > files > 91

lib64dbus-1_3-devel-0.92-6mdv2007.0.x86_64.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>dbus-mainloop.c Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.2.15 -->
<center>
<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; <a class="qindex" href="annotated.html">Data Structures</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Data Fields</a> &nbsp; <a class="qindex" href="pages.html">Related Pages</a> &nbsp; </center>
<hr><h1>dbus-mainloop.c</h1><div class="fragment"><pre>00001 <font class="comment">/* -*- mode: C; c-file-style: "gnu" -*- */</font>
00002 <font class="comment">/* dbus-mainloop.c  Main loop utility</font>
00003 <font class="comment"> *</font>
00004 <font class="comment"> * Copyright (C) 2003  Red Hat, Inc.</font>
00005 <font class="comment"> *</font>
00006 <font class="comment"> * Licensed under the Academic Free License version 2.0</font>
00007 <font class="comment"> * </font>
00008 <font class="comment"> * This program is free software; you can redistribute it and/or modify</font>
00009 <font class="comment"> * it under the terms of the GNU General Public License as published by</font>
00010 <font class="comment"> * the Free Software Foundation; either version 2 of the License, or</font>
00011 <font class="comment"> * (at your option) any later version.</font>
00012 <font class="comment"> *</font>
00013 <font class="comment"> * This program is distributed in the hope that it will be useful,</font>
00014 <font class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</font>
00015 <font class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</font>
00016 <font class="comment"> * GNU General Public License for more details.</font>
00017 <font class="comment"> * </font>
00018 <font class="comment"> * You should have received a copy of the GNU General Public License</font>
00019 <font class="comment"> * along with this program; if not, write to the Free Software</font>
00020 <font class="comment"> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA</font>
00021 <font class="comment"> *</font>
00022 <font class="comment"> */</font>
00023 
00024 <font class="preprocessor">#include "dbus-mainloop.h"</font>
00025 
00026 <font class="preprocessor">#ifndef DOXYGEN_SHOULD_SKIP_THIS</font>
00027 <font class="preprocessor"></font>
00028 <font class="preprocessor">#include &lt;dbus/dbus-list.h&gt;</font>
00029 <font class="preprocessor">#include &lt;dbus/dbus-sysdeps.h&gt;</font>
00030 
00031 <font class="preprocessor">#define MAINLOOP_SPEW 0</font>
00032 <font class="preprocessor"></font>
00033 <font class="keyword">struct </font>DBusLoop
00034 {
00035   <font class="keywordtype">int</font> refcount;
00036   <a class="code" href="structDBusList.html">DBusList</a> *callbacks;
00037   <font class="keywordtype">int</font> callback_list_serial;
00038   <font class="keywordtype">int</font> watch_count;
00039   <font class="keywordtype">int</font> timeout_count;
00040   <font class="keywordtype">int</font> depth; 
00041   <a class="code" href="structDBusList.html">DBusList</a> *need_dispatch;
00042 };
00043 
00044 <font class="keyword">typedef</font> <font class="keyword">enum</font>
00045 {
00046   CALLBACK_WATCH,
00047   CALLBACK_TIMEOUT
00048 } CallbackType;
00049 
00050 <font class="keyword">typedef</font> <font class="keyword">struct</font>
00051 <font class="keyword"></font>{
00052   <font class="keywordtype">int</font> refcount;
00053   CallbackType type;
00054   <font class="keywordtype">void</font> *data;
00055   DBusFreeFunction free_data_func;
00056 } Callback;
00057 
00058 <font class="keyword">typedef</font> <font class="keyword">struct</font>
00059 <font class="keyword"></font>{
00060   Callback callback;
00061   DBusWatchFunction function;
00062   <a class="code" href="structDBusWatch.html">DBusWatch</a> *watch;
00063   <font class="comment">/* last watch handle failed due to OOM */</font>
00064   <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> last_iteration_oom : 1;
00065 } WatchCallback;
00066 
00067 <font class="keyword">typedef</font> <font class="keyword">struct</font>
00068 <font class="keyword"></font>{
00069   Callback callback;
00070   <a class="code" href="structDBusTimeout.html">DBusTimeout</a> *timeout;
00071   DBusTimeoutFunction function;
00072   <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> last_tv_sec;
00073   <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> last_tv_usec;
00074 } TimeoutCallback;
00075 
00076 <font class="preprocessor">#define WATCH_CALLBACK(callback)   ((WatchCallback*)callback)</font>
00077 <font class="preprocessor"></font><font class="preprocessor">#define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback)</font>
00078 <font class="preprocessor"></font>
00079 <font class="keyword">static</font> WatchCallback*
00080 watch_callback_new (<a class="code" href="structDBusWatch.html">DBusWatch</a>         *watch,
00081                     DBusWatchFunction  function,
00082                     <font class="keywordtype">void</font>              *data,
00083                     DBusFreeFunction   free_data_func)
00084 {
00085   WatchCallback *cb;
00086 
00087   cb = dbus_new (WatchCallback, 1);
00088   <font class="keywordflow">if</font> (cb == NULL)
00089     <font class="keywordflow">return</font> NULL;
00090 
00091   cb-&gt;watch = watch;
00092   cb-&gt;function = function;
00093   cb-&gt;last_iteration_oom = FALSE;
00094   cb-&gt;callback.refcount = 1;
00095   cb-&gt;callback.type = CALLBACK_WATCH;
00096   cb-&gt;callback.data = data;
00097   cb-&gt;callback.free_data_func = free_data_func;
00098   
00099   <font class="keywordflow">return</font> cb;
00100 }
00101 
00102 <font class="keyword">static</font> TimeoutCallback*
00103 timeout_callback_new (<a class="code" href="structDBusTimeout.html">DBusTimeout</a>         *timeout,
00104                       DBusTimeoutFunction  function,
00105                       <font class="keywordtype">void</font>                *data,
00106                       DBusFreeFunction     free_data_func)
00107 {
00108   TimeoutCallback *cb;
00109 
00110   cb = dbus_new (TimeoutCallback, 1);
00111   <font class="keywordflow">if</font> (cb == NULL)
00112     <font class="keywordflow">return</font> NULL;
00113 
00114   cb-&gt;timeout = timeout;
00115   cb-&gt;function = function;
00116   _dbus_get_current_time (&amp;cb-&gt;last_tv_sec,
00117                           &amp;cb-&gt;last_tv_usec);
00118   cb-&gt;callback.refcount = 1;    
00119   cb-&gt;callback.type = CALLBACK_TIMEOUT;
00120   cb-&gt;callback.data = data;
00121   cb-&gt;callback.free_data_func = free_data_func;
00122   
00123   <font class="keywordflow">return</font> cb;
00124 }
00125 
00126 <font class="keyword">static</font> Callback * 
00127 callback_ref (Callback *cb)
00128 {
00129   _dbus_assert (cb-&gt;refcount &gt; 0);
00130   
00131   cb-&gt;refcount += 1;
00132 
00133   <font class="keywordflow">return</font> cb;
00134 }
00135 
00136 <font class="keyword">static</font> <font class="keywordtype">void</font>
00137 callback_unref (Callback *cb)
00138 {
00139   _dbus_assert (cb-&gt;refcount &gt; 0);
00140 
00141   cb-&gt;refcount -= 1;
00142 
00143   <font class="keywordflow">if</font> (cb-&gt;refcount == 0)
00144     {
00145       <font class="keywordflow">if</font> (cb-&gt;free_data_func)
00146         (* cb-&gt;free_data_func) (cb-&gt;data);
00147       
00148       dbus_free (cb);
00149     }
00150 }
00151 
00152 <font class="keyword">static</font> dbus_bool_t
00153 add_callback (DBusLoop  *loop,
00154               Callback *cb)
00155 {
00156   <font class="keywordflow">if</font> (!_dbus_list_append (&amp;loop-&gt;callbacks, cb))
00157     <font class="keywordflow">return</font> FALSE;
00158 
00159   loop-&gt;callback_list_serial += 1;
00160 
00161   <font class="keywordflow">switch</font> (cb-&gt;type)
00162     {
00163     <font class="keywordflow">case</font> CALLBACK_WATCH:
00164       loop-&gt;watch_count += 1;
00165       <font class="keywordflow">break</font>;
00166     <font class="keywordflow">case</font> CALLBACK_TIMEOUT:
00167       loop-&gt;timeout_count += 1;
00168       <font class="keywordflow">break</font>;
00169     }
00170   
00171   <font class="keywordflow">return</font> TRUE;
00172 }
00173 
00174 <font class="keyword">static</font> <font class="keywordtype">void</font>
00175 remove_callback (DBusLoop  *loop,
00176                  <a class="code" href="structDBusList.html">DBusList</a> *link)
00177 {
00178   Callback *cb = link-&gt;<a class="code" href="structDBusList.html#m2">data</a>;
00179   
00180   <font class="keywordflow">switch</font> (cb-&gt;type)
00181     {
00182     <font class="keywordflow">case</font> CALLBACK_WATCH:
00183       loop-&gt;watch_count -= 1;
00184       <font class="keywordflow">break</font>;
00185     <font class="keywordflow">case</font> CALLBACK_TIMEOUT:
00186       loop-&gt;timeout_count -= 1;
00187       <font class="keywordflow">break</font>;
00188     }
00189   
00190   callback_unref (cb);
00191   _dbus_list_remove_link (&amp;loop-&gt;callbacks, link);
00192   loop-&gt;callback_list_serial += 1;
00193 }
00194 
00195 DBusLoop*
00196 _dbus_loop_new (<font class="keywordtype">void</font>)
00197 {
00198   DBusLoop *loop;
00199 
00200   loop = dbus_new0 (DBusLoop, 1);
00201   <font class="keywordflow">if</font> (loop == NULL)
00202     <font class="keywordflow">return</font> NULL;
00203 
00204   loop-&gt;refcount = 1;
00205   
00206   <font class="keywordflow">return</font> loop;
00207 }
00208 
00209 DBusLoop *
00210 _dbus_loop_ref (DBusLoop *loop)
00211 {
00212   _dbus_assert (loop != NULL);
00213   _dbus_assert (loop-&gt;refcount &gt; 0);
00214 
00215   loop-&gt;refcount += 1;
00216 
00217   <font class="keywordflow">return</font> loop;
00218 }
00219 
00220 <font class="keywordtype">void</font>
00221 _dbus_loop_unref (DBusLoop *loop)
00222 {
00223   _dbus_assert (loop != NULL);
00224   _dbus_assert (loop-&gt;refcount &gt; 0);
00225 
00226   loop-&gt;refcount -= 1;
00227   <font class="keywordflow">if</font> (loop-&gt;refcount == 0)
00228     {
00229       <font class="keywordflow">while</font> (loop-&gt;need_dispatch)
00230         {
00231           <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = _dbus_list_pop_first (&amp;loop-&gt;need_dispatch);
00232 
00233           dbus_connection_unref (connection);
00234         }
00235       
00236       dbus_free (loop);
00237     }
00238 }
00239 
00240 dbus_bool_t
00241 _dbus_loop_add_watch (DBusLoop          *loop,
00242                       <a class="code" href="structDBusWatch.html">DBusWatch</a>        *watch,
00243                       DBusWatchFunction  function,
00244                       <font class="keywordtype">void</font>             *data,
00245                       DBusFreeFunction  free_data_func)
00246 {
00247   WatchCallback *wcb;
00248 
00249   wcb = watch_callback_new (watch, function, data, free_data_func);
00250   <font class="keywordflow">if</font> (wcb == NULL)
00251     <font class="keywordflow">return</font> FALSE;
00252 
00253   <font class="keywordflow">if</font> (!add_callback (loop, (Callback*) wcb))
00254     {
00255       wcb-&gt;callback.free_data_func = NULL; <font class="comment">/* don't want to have this side effect */</font>
00256       callback_unref ((Callback*) wcb);
00257       <font class="keywordflow">return</font> FALSE;
00258     }
00259   
00260   <font class="keywordflow">return</font> TRUE;
00261 }
00262 
00263 <font class="keywordtype">void</font>
00264 _dbus_loop_remove_watch (DBusLoop          *loop,
00265                          <a class="code" href="structDBusWatch.html">DBusWatch</a>        *watch,
00266                          DBusWatchFunction  function,
00267                          <font class="keywordtype">void</font>             *data)
00268 {
00269   <a class="code" href="structDBusList.html">DBusList</a> *link;
00270   
00271   link = _dbus_list_get_first_link (&amp;loop-&gt;callbacks);
00272   <font class="keywordflow">while</font> (link != NULL)
00273     {
00274       <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&amp;loop-&gt;callbacks, link);
00275       Callback *<font class="keyword">this</font> = link-&gt;<a class="code" href="structDBusList.html#m2">data</a>;
00276 
00277       <font class="keywordflow">if</font> (this-&gt;type == CALLBACK_WATCH &amp;&amp;
00278           WATCH_CALLBACK (<font class="keyword">this</font>)-&gt;watch == watch &amp;&amp;
00279           this-&gt;data == data &amp;&amp;
00280           WATCH_CALLBACK (<font class="keyword">this</font>)-&gt;function == function)
00281         {
00282           remove_callback (loop, link);
00283           
00284           <font class="keywordflow">return</font>;
00285         }
00286       
00287       link = next;
00288     }
00289 
00290   _dbus_warn (<font class="stringliteral">"could not find watch %p function %p data %p to remove\n"</font>,
00291               watch, (<font class="keywordtype">void</font> *)function, data);
00292 }
00293 
00294 dbus_bool_t
00295 _dbus_loop_add_timeout (DBusLoop            *loop,
00296                         <a class="code" href="structDBusTimeout.html">DBusTimeout</a>        *timeout,
00297                         DBusTimeoutFunction  function,
00298                         <font class="keywordtype">void</font>               *data,
00299                         DBusFreeFunction    free_data_func)
00300 {
00301   TimeoutCallback *tcb;
00302 
00303   tcb = timeout_callback_new (timeout, function, data, free_data_func);
00304   <font class="keywordflow">if</font> (tcb == NULL)
00305     <font class="keywordflow">return</font> FALSE;
00306 
00307   <font class="keywordflow">if</font> (!add_callback (loop, (Callback*) tcb))
00308     {
00309       tcb-&gt;callback.free_data_func = NULL; <font class="comment">/* don't want to have this side effect */</font>
00310       callback_unref ((Callback*) tcb);
00311       <font class="keywordflow">return</font> FALSE;
00312     }
00313   
00314   <font class="keywordflow">return</font> TRUE;
00315 }
00316 
00317 <font class="keywordtype">void</font>
00318 _dbus_loop_remove_timeout (DBusLoop            *loop,
00319                            <a class="code" href="structDBusTimeout.html">DBusTimeout</a>        *timeout,
00320                            DBusTimeoutFunction  function,
00321                            <font class="keywordtype">void</font>               *data)
00322 {
00323   <a class="code" href="structDBusList.html">DBusList</a> *link;
00324   
00325   link = _dbus_list_get_first_link (&amp;loop-&gt;callbacks);
00326   <font class="keywordflow">while</font> (link != NULL)
00327     {
00328       <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&amp;loop-&gt;callbacks, link);
00329       Callback *<font class="keyword">this</font> = link-&gt;<a class="code" href="structDBusList.html#m2">data</a>;
00330 
00331       <font class="keywordflow">if</font> (this-&gt;type == CALLBACK_TIMEOUT &amp;&amp;
00332           TIMEOUT_CALLBACK (<font class="keyword">this</font>)-&gt;timeout == timeout &amp;&amp;
00333           this-&gt;data == data &amp;&amp;
00334           TIMEOUT_CALLBACK (<font class="keyword">this</font>)-&gt;function == function)
00335         {
00336           remove_callback (loop, link);
00337           
00338           <font class="keywordflow">return</font>;
00339         }
00340       
00341       link = next;
00342     }
00343 
00344   _dbus_warn (<font class="stringliteral">"could not find timeout %p function %p data %p to remove\n"</font>,
00345               timeout, (<font class="keywordtype">void</font> *)function, data);
00346 }
00347 
00348 <font class="comment">/* Convolutions from GLib, there really must be a better way</font>
00349 <font class="comment"> * to do this.</font>
00350 <font class="comment"> */</font>
00351 <font class="keyword">static</font> dbus_bool_t
00352 check_timeout (<font class="keywordtype">unsigned</font> <font class="keywordtype">long</font>    tv_sec,
00353                <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font>    tv_usec,
00354                TimeoutCallback *tcb,
00355                <font class="keywordtype">int</font>             *timeout)
00356 {
00357   <font class="keywordtype">long</font> sec_remaining;
00358   <font class="keywordtype">long</font> msec_remaining;
00359   <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> expiration_tv_sec;
00360   <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> expiration_tv_usec;
00361   <font class="keywordtype">long</font> interval_seconds;
00362   <font class="keywordtype">long</font> interval_milliseconds;
00363   <font class="keywordtype">int</font> interval;
00364 
00365   <font class="comment">/* I'm pretty sure this function could suck (a lot) less */</font>
00366   
00367   interval = dbus_timeout_get_interval (tcb-&gt;timeout);
00368   
00369   interval_seconds = interval / 1000L;
00370   interval_milliseconds = interval % 1000L;
00371   
00372   expiration_tv_sec = tcb-&gt;last_tv_sec + interval_seconds;
00373   expiration_tv_usec = tcb-&gt;last_tv_usec + interval_milliseconds * 1000;
00374   <font class="keywordflow">if</font> (expiration_tv_usec &gt;= 1000000)
00375     {
00376       expiration_tv_usec -= 1000000;
00377       expiration_tv_sec += 1;
00378     }
00379   
00380   sec_remaining = expiration_tv_sec - tv_sec;
00381   <font class="comment">/* need to force this to be signed, as it is intended to sometimes</font>
00382 <font class="comment">   * produce a negative result</font>
00383 <font class="comment">   */</font>
00384   msec_remaining = ((long) expiration_tv_usec - (long) tv_usec) / 1000L;
00385 
00386 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00387 <font class="preprocessor"></font>  _dbus_verbose (<font class="stringliteral">"Interval is %ld seconds %ld msecs\n"</font>,
00388                  interval_seconds,
00389                  interval_milliseconds);
00390   _dbus_verbose (<font class="stringliteral">"Now is  %lu seconds %lu usecs\n"</font>,
00391                  tv_sec, tv_usec);
00392   _dbus_verbose (<font class="stringliteral">"Last is %lu seconds %lu usecs\n"</font>,
00393                  tcb-&gt;last_tv_sec, tcb-&gt;last_tv_usec);
00394   _dbus_verbose (<font class="stringliteral">"Exp is  %lu seconds %lu usecs\n"</font>,
00395                  expiration_tv_sec, expiration_tv_usec);
00396   _dbus_verbose (<font class="stringliteral">"Pre-correction, sec_remaining %ld msec_remaining %ld\n"</font>,
00397                  sec_remaining, msec_remaining);
00398 <font class="preprocessor">#endif</font>
00399 <font class="preprocessor"></font>  
00400   <font class="comment">/* We do the following in a rather convoluted fashion to deal with</font>
00401 <font class="comment">   * the fact that we don't have an integral type big enough to hold</font>
00402 <font class="comment">   * the difference of two timevals in milliseconds.</font>
00403 <font class="comment">   */</font>
00404   <font class="keywordflow">if</font> (sec_remaining &lt; 0 || (sec_remaining == 0 &amp;&amp; msec_remaining &lt; 0))
00405     {
00406       *timeout = 0;
00407     }
00408   <font class="keywordflow">else</font>
00409     {
00410       <font class="keywordflow">if</font> (msec_remaining &lt; 0)
00411         {
00412           msec_remaining += 1000;
00413           sec_remaining -= 1;
00414         }
00415 
00416       <font class="keywordflow">if</font> (sec_remaining &gt; (_DBUS_INT_MAX / 1000) ||
00417           msec_remaining &gt; _DBUS_INT_MAX)
00418         *timeout = _DBUS_INT_MAX;
00419       <font class="keywordflow">else</font>
00420         *timeout = sec_remaining * 1000 + msec_remaining;        
00421     }
00422 
00423   <font class="keywordflow">if</font> (*timeout &gt; interval)
00424     {
00425       <font class="comment">/* This indicates that the system clock probably moved backward */</font>
00426       _dbus_verbose (<font class="stringliteral">"System clock set backward! Resetting timeout.\n"</font>);
00427       
00428       tcb-&gt;last_tv_sec = tv_sec;
00429       tcb-&gt;last_tv_usec = tv_usec;
00430 
00431       *timeout = interval;
00432     }
00433   
00434 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00435 <font class="preprocessor"></font>  _dbus_verbose (<font class="stringliteral">"  timeout expires in %d milliseconds\n"</font>, *timeout);
00436 <font class="preprocessor">#endif</font>
00437 <font class="preprocessor"></font>  
00438   <font class="keywordflow">return</font> *timeout == 0;
00439 }
00440 
00441 dbus_bool_t
00442 _dbus_loop_dispatch (DBusLoop *loop)
00443 {
00444 
00445 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00446 <font class="preprocessor"></font>  _dbus_verbose (<font class="stringliteral">"  %d connections to dispatch\n"</font>, _dbus_list_get_length (&amp;loop-&gt;need_dispatch));
00447 <font class="preprocessor">#endif</font>
00448 <font class="preprocessor"></font>  
00449   <font class="keywordflow">if</font> (loop-&gt;need_dispatch == NULL)
00450     <font class="keywordflow">return</font> FALSE;
00451   
00452  next:
00453   <font class="keywordflow">while</font> (loop-&gt;need_dispatch != NULL)
00454     {
00455       <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = _dbus_list_pop_first (&amp;loop-&gt;need_dispatch);
00456       
00457       <font class="keywordflow">while</font> (TRUE)
00458         {
00459           DBusDispatchStatus status;
00460           
00461           status = dbus_connection_dispatch (connection);
00462 
00463           <font class="keywordflow">if</font> (status == DBUS_DISPATCH_COMPLETE)
00464             {
00465               dbus_connection_unref (connection);
00466               <font class="keywordflow">goto</font> next;
00467             }
00468           <font class="keywordflow">else</font>
00469             {
00470               <font class="keywordflow">if</font> (status == DBUS_DISPATCH_NEED_MEMORY)
00471                 _dbus_wait_for_memory ();
00472             }
00473         }
00474     }
00475 
00476   <font class="keywordflow">return</font> TRUE;
00477 }
00478 
00479 dbus_bool_t
00480 _dbus_loop_queue_dispatch (DBusLoop       *loop,
00481                            <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection)
00482 {
00483   <font class="keywordflow">if</font> (_dbus_list_append (&amp;loop-&gt;need_dispatch, connection))
00484     {
00485       dbus_connection_ref (connection);
00486       <font class="keywordflow">return</font> TRUE;
00487     }
00488   <font class="keywordflow">else</font>
00489     <font class="keywordflow">return</font> FALSE;
00490 }
00491 
00492 <font class="comment">/* Returns TRUE if we invoked any timeouts or have ready file</font>
00493 <font class="comment"> * descriptors, which is just used in test code as a debug hack</font>
00494 <font class="comment"> */</font>
00495 
00496 dbus_bool_t
00497 _dbus_loop_iterate (DBusLoop     *loop,
00498                     dbus_bool_t   block)
00499 {  
00500 <font class="preprocessor">#define N_STACK_DESCRIPTORS 64</font>
00501 <font class="preprocessor"></font>  dbus_bool_t retval;
00502   <a class="code" href="structDBusPollFD.html">DBusPollFD</a> *fds;
00503   <a class="code" href="structDBusPollFD.html">DBusPollFD</a> stack_fds[N_STACK_DESCRIPTORS];
00504   <font class="keywordtype">int</font> n_fds;
00505   WatchCallback **watches_for_fds;
00506   WatchCallback *stack_watches_for_fds[N_STACK_DESCRIPTORS];
00507   <font class="keywordtype">int</font> i;
00508   <a class="code" href="structDBusList.html">DBusList</a> *link;
00509   <font class="keywordtype">int</font> n_ready;
00510   <font class="keywordtype">int</font> initial_serial;
00511   <font class="keywordtype">long</font> timeout;
00512   dbus_bool_t oom_watch_pending;
00513   <font class="keywordtype">int</font> orig_depth;
00514   
00515   retval = FALSE;      
00516 
00517   fds = NULL;
00518   watches_for_fds = NULL;
00519   n_fds = 0;
00520   oom_watch_pending = FALSE;
00521   orig_depth = loop-&gt;depth;
00522   
00523 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00524 <font class="preprocessor"></font>  _dbus_verbose (<font class="stringliteral">"Iteration block=%d depth=%d timeout_count=%d watch_count=%d\n"</font>,
00525                  block, loop-&gt;depth, loop-&gt;timeout_count, loop-&gt;watch_count);
00526 <font class="preprocessor">#endif</font>
00527 <font class="preprocessor"></font>  
00528   <font class="keywordflow">if</font> (loop-&gt;callbacks == NULL)
00529     <font class="keywordflow">goto</font> next_iteration;
00530 
00531   <font class="keywordflow">if</font> (loop-&gt;watch_count &gt; N_STACK_DESCRIPTORS)
00532     {
00533       fds = dbus_new0 (<a class="code" href="structDBusPollFD.html">DBusPollFD</a>, loop-&gt;watch_count);
00534       
00535       <font class="keywordflow">while</font> (fds == NULL)
00536         {
00537           _dbus_wait_for_memory ();
00538           fds = dbus_new0 (<a class="code" href="structDBusPollFD.html">DBusPollFD</a>, loop-&gt;watch_count);
00539         }
00540       
00541       watches_for_fds = dbus_new (WatchCallback*, loop-&gt;watch_count);
00542       <font class="keywordflow">while</font> (watches_for_fds == NULL)
00543         {
00544           _dbus_wait_for_memory ();
00545           watches_for_fds = dbus_new (WatchCallback*, loop-&gt;watch_count);
00546         }
00547     }
00548   <font class="keywordflow">else</font>
00549     {      
00550       fds = stack_fds;
00551       watches_for_fds = stack_watches_for_fds;
00552     }
00553 
00554   <font class="comment">/* fill our array of fds and watches */</font>
00555   n_fds = 0;
00556   link = _dbus_list_get_first_link (&amp;loop-&gt;callbacks);
00557   <font class="keywordflow">while</font> (link != NULL)
00558     {
00559       <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&amp;loop-&gt;callbacks, link);
00560       Callback *cb = link-&gt;<a class="code" href="structDBusList.html#m2">data</a>;
00561       <font class="keywordflow">if</font> (cb-&gt;type == CALLBACK_WATCH)
00562         {
00563           <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> flags;
00564           WatchCallback *wcb = WATCH_CALLBACK (cb);
00565 
00566           <font class="keywordflow">if</font> (wcb-&gt;last_iteration_oom)
00567             {
00568               <font class="comment">/* we skip this one this time, but reenable it next time,</font>
00569 <font class="comment">               * and have a timeout on this iteration</font>
00570 <font class="comment">               */</font>
00571               wcb-&gt;last_iteration_oom = FALSE;
00572               oom_watch_pending = TRUE;
00573               
00574               retval = TRUE; <font class="comment">/* return TRUE here to keep the loop going,</font>
00575 <font class="comment">                              * since we don't know the watch is inactive</font>
00576 <font class="comment">                              */</font>
00577 
00578 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00579 <font class="preprocessor"></font>              _dbus_verbose (<font class="stringliteral">"  skipping watch on fd %d as it was out of memory last time\n"</font>,
00580                              dbus_watch_get_fd (wcb-&gt;watch));
00581 <font class="preprocessor">#endif</font>
00582 <font class="preprocessor"></font>            }
00583           <font class="keywordflow">else</font> <font class="keywordflow">if</font> (dbus_watch_get_enabled (wcb-&gt;watch))
00584             {
00585               watches_for_fds[n_fds] = wcb;
00586 
00587               callback_ref (cb);
00588                   
00589               flags = dbus_watch_get_flags (wcb-&gt;watch);
00590                   
00591               fds[n_fds].<a class="code" href="structDBusPollFD.html#m0">fd</a> = dbus_watch_get_fd (wcb-&gt;watch);
00592               fds[n_fds].<a class="code" href="structDBusPollFD.html#m2">revents</a> = 0;
00593               fds[n_fds].<a class="code" href="structDBusPollFD.html#m1">events</a> = 0;
00594               <font class="keywordflow">if</font> (flags &amp; DBUS_WATCH_READABLE)
00595                 fds[n_fds].<a class="code" href="structDBusPollFD.html#m1">events</a> |= _DBUS_POLLIN;
00596               <font class="keywordflow">if</font> (flags &amp; DBUS_WATCH_WRITABLE)
00597                 fds[n_fds].<a class="code" href="structDBusPollFD.html#m1">events</a> |= _DBUS_POLLOUT;
00598 
00599 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00600 <font class="preprocessor"></font>              _dbus_verbose (<font class="stringliteral">"  polling watch on fd %d\n"</font>, fds[n_fds].fd);
00601 <font class="preprocessor">#endif</font>
00602 <font class="preprocessor"></font>
00603               n_fds += 1;
00604             }
00605           <font class="keywordflow">else</font>
00606             {
00607 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00608 <font class="preprocessor"></font>              _dbus_verbose (<font class="stringliteral">"  skipping disabled watch on fd %d\n"</font>,
00609                              dbus_watch_get_fd (wcb-&gt;watch));
00610 <font class="preprocessor">#endif</font>
00611 <font class="preprocessor"></font>            }
00612         }
00613               
00614       link = next;
00615     }
00616   
00617   timeout = -1;
00618   <font class="keywordflow">if</font> (loop-&gt;timeout_count &gt; 0)
00619     {
00620       <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> tv_sec;
00621       <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> tv_usec;
00622       
00623       _dbus_get_current_time (&amp;tv_sec, &amp;tv_usec);
00624           
00625       link = _dbus_list_get_first_link (&amp;loop-&gt;callbacks);
00626       <font class="keywordflow">while</font> (link != NULL)
00627         {
00628           <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&amp;loop-&gt;callbacks, link);
00629           Callback *cb = link-&gt;<a class="code" href="structDBusList.html#m2">data</a>;
00630 
00631           <font class="keywordflow">if</font> (cb-&gt;type == CALLBACK_TIMEOUT &amp;&amp;
00632               dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)-&gt;timeout))
00633             {
00634               TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
00635               <font class="keywordtype">int</font> msecs_remaining;
00636 
00637               check_timeout (tv_sec, tv_usec, tcb, &amp;msecs_remaining);
00638 
00639               <font class="keywordflow">if</font> (timeout &lt; 0)
00640                 timeout = msecs_remaining;
00641               <font class="keywordflow">else</font>
00642                 timeout = MIN (msecs_remaining, timeout);
00643 
00644 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00645 <font class="preprocessor"></font>              _dbus_verbose (<font class="stringliteral">"  timeout added, %d remaining, aggregate timeout %ld\n"</font>,
00646                              msecs_remaining, timeout);
00647 <font class="preprocessor">#endif</font>
00648 <font class="preprocessor"></font>              
00649               _dbus_assert (timeout &gt;= 0);
00650                   
00651               <font class="keywordflow">if</font> (timeout == 0)
00652                 <font class="keywordflow">break</font>; <font class="comment">/* it's not going to get shorter... */</font>
00653             }
00654 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00655 <font class="preprocessor"></font>          <font class="keywordflow">else</font> <font class="keywordflow">if</font> (cb-&gt;type == CALLBACK_TIMEOUT)
00656             {
00657               _dbus_verbose (<font class="stringliteral">"  skipping disabled timeout\n"</font>);
00658             }
00659 <font class="preprocessor">#endif</font>
00660 <font class="preprocessor"></font>          
00661           link = next;
00662         }
00663     }
00664 
00665   <font class="comment">/* Never block if we have stuff to dispatch */</font>
00666   <font class="keywordflow">if</font> (!block || loop-&gt;need_dispatch != NULL)
00667     {
00668       timeout = 0;
00669 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00670 <font class="preprocessor"></font>      _dbus_verbose (<font class="stringliteral">"  timeout is 0 as we aren't blocking\n"</font>);
00671 <font class="preprocessor">#endif</font>
00672 <font class="preprocessor"></font>    }
00673 
00674   <font class="comment">/* if a watch is OOM, don't wait longer than the OOM</font>
00675 <font class="comment">   * wait to re-enable it</font>
00676 <font class="comment">   */</font>
00677   <font class="keywordflow">if</font> (oom_watch_pending)
00678     timeout = MIN (timeout, _dbus_get_oom_wait ());
00679 
00680 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00681 <font class="preprocessor"></font>  _dbus_verbose (<font class="stringliteral">"  polling on %d descriptors timeout %ld\n"</font>, n_fds, timeout);
00682 <font class="preprocessor">#endif</font>
00683 <font class="preprocessor"></font>  
00684   n_ready = _dbus_poll (fds, n_fds, timeout);
00685 
00686   initial_serial = loop-&gt;callback_list_serial;
00687 
00688   <font class="keywordflow">if</font> (loop-&gt;timeout_count &gt; 0)
00689     {
00690       <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> tv_sec;
00691       <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> tv_usec;
00692 
00693       _dbus_get_current_time (&amp;tv_sec, &amp;tv_usec);
00694 
00695       <font class="comment">/* It'd be nice to avoid this O(n) thingy here */</font>
00696       link = _dbus_list_get_first_link (&amp;loop-&gt;callbacks);
00697       <font class="keywordflow">while</font> (link != NULL)
00698         {
00699           <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&amp;loop-&gt;callbacks, link);
00700           Callback *cb = link-&gt;<a class="code" href="structDBusList.html#m2">data</a>;
00701 
00702           <font class="keywordflow">if</font> (initial_serial != loop-&gt;callback_list_serial)
00703             <font class="keywordflow">goto</font> next_iteration;
00704 
00705           <font class="keywordflow">if</font> (loop-&gt;depth != orig_depth)
00706             <font class="keywordflow">goto</font> next_iteration;
00707               
00708           <font class="keywordflow">if</font> (cb-&gt;type == CALLBACK_TIMEOUT &amp;&amp;
00709               dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)-&gt;timeout))
00710             {
00711               TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
00712               <font class="keywordtype">int</font> msecs_remaining;
00713               
00714               <font class="keywordflow">if</font> (check_timeout (tv_sec, tv_usec,
00715                                  tcb, &amp;msecs_remaining))
00716                 {
00717                   <font class="comment">/* Save last callback time and fire this timeout */</font>
00718                   tcb-&gt;last_tv_sec = tv_sec;
00719                   tcb-&gt;last_tv_usec = tv_usec;
00720 
00721 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00722 <font class="preprocessor"></font>                  _dbus_verbose (<font class="stringliteral">"  invoking timeout\n"</font>);
00723 <font class="preprocessor">#endif</font>
00724 <font class="preprocessor"></font>                  
00725                   (* tcb-&gt;function) (tcb-&gt;timeout,
00726                                      cb-&gt;data);
00727 
00728                   retval = TRUE;
00729                 }
00730               <font class="keywordflow">else</font>
00731                 {
00732 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00733 <font class="preprocessor"></font>                  _dbus_verbose (<font class="stringliteral">"  timeout has not expired\n"</font>);
00734 <font class="preprocessor">#endif</font>
00735 <font class="preprocessor"></font>                }
00736             }
00737 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00738 <font class="preprocessor"></font>          <font class="keywordflow">else</font> <font class="keywordflow">if</font> (cb-&gt;type == CALLBACK_TIMEOUT)
00739             {
00740               _dbus_verbose (<font class="stringliteral">"  skipping invocation of disabled timeout\n"</font>);
00741             }
00742 <font class="preprocessor">#endif</font>
00743 <font class="preprocessor"></font>
00744           link = next;
00745         }
00746     }
00747       
00748   <font class="keywordflow">if</font> (n_ready &gt; 0)
00749     {
00750       i = 0;
00751       <font class="keywordflow">while</font> (i &lt; n_fds)
00752         {
00753           <font class="comment">/* FIXME I think this "restart if we change the watches"</font>
00754 <font class="comment">           * approach could result in starving watches</font>
00755 <font class="comment">           * toward the end of the list.</font>
00756 <font class="comment">           */</font>
00757           <font class="keywordflow">if</font> (initial_serial != loop-&gt;callback_list_serial)
00758             <font class="keywordflow">goto</font> next_iteration;
00759 
00760           <font class="keywordflow">if</font> (loop-&gt;depth != orig_depth)
00761             <font class="keywordflow">goto</font> next_iteration;
00762 
00763           <font class="keywordflow">if</font> (fds[i].<a class="code" href="structDBusPollFD.html#m2">revents</a> != 0)
00764             {
00765               WatchCallback *wcb;
00766               <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> condition;
00767                   
00768               wcb = watches_for_fds[i];
00769               
00770               condition = 0;
00771               <font class="keywordflow">if</font> (fds[i].<a class="code" href="structDBusPollFD.html#m2">revents</a> &amp; _DBUS_POLLIN)
00772                 condition |= DBUS_WATCH_READABLE;
00773               <font class="keywordflow">if</font> (fds[i].<a class="code" href="structDBusPollFD.html#m2">revents</a> &amp; _DBUS_POLLOUT)
00774                 condition |= DBUS_WATCH_WRITABLE;
00775               <font class="keywordflow">if</font> (fds[i].<a class="code" href="structDBusPollFD.html#m2">revents</a> &amp; _DBUS_POLLHUP)
00776                 condition |= DBUS_WATCH_HANGUP;
00777               <font class="keywordflow">if</font> (fds[i].<a class="code" href="structDBusPollFD.html#m2">revents</a> &amp; _DBUS_POLLERR)
00778                 condition |= DBUS_WATCH_ERROR;
00779 
00780               <font class="comment">/* condition may still be 0 if we got some</font>
00781 <font class="comment">               * weird POLLFOO thing like POLLWRBAND</font>
00782 <font class="comment">               */</font>
00783                   
00784               <font class="keywordflow">if</font> (condition != 0 &amp;&amp;
00785                   dbus_watch_get_enabled (wcb-&gt;watch))
00786                 {
00787                   <font class="keywordflow">if</font> (!(* wcb-&gt;function) (wcb-&gt;watch,
00788                                           condition,
00789                                           ((Callback*)wcb)-&gt;data))
00790                     wcb-&gt;last_iteration_oom = TRUE;
00791 
00792 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00793 <font class="preprocessor"></font>                  _dbus_verbose (<font class="stringliteral">"  Invoked watch, oom = %d\n"</font>,
00794                                  wcb-&gt;last_iteration_oom);
00795 <font class="preprocessor">#endif</font>
00796 <font class="preprocessor"></font>                  
00797                   retval = TRUE;
00798                 }
00799             }
00800               
00801           ++i;
00802         }
00803     }
00804       
00805  next_iteration:
00806 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00807 <font class="preprocessor"></font>  _dbus_verbose (<font class="stringliteral">"  moving to next iteration\n"</font>);
00808 <font class="preprocessor">#endif</font>
00809 <font class="preprocessor"></font>  
00810   <font class="keywordflow">if</font> (fds &amp;&amp; fds != stack_fds)
00811     dbus_free (fds);
00812   <font class="keywordflow">if</font> (watches_for_fds)
00813     {
00814       i = 0;
00815       <font class="keywordflow">while</font> (i &lt; n_fds)
00816         {
00817           callback_unref (&amp;watches_for_fds[i]-&gt;callback);
00818           ++i;
00819         }
00820       
00821       <font class="keywordflow">if</font> (watches_for_fds != stack_watches_for_fds)
00822         dbus_free (watches_for_fds);
00823     }
00824   
00825   <font class="keywordflow">if</font> (_dbus_loop_dispatch (loop))
00826     retval = TRUE;
00827   
00828 <font class="preprocessor">#if MAINLOOP_SPEW</font>
00829 <font class="preprocessor"></font>  _dbus_verbose (<font class="stringliteral">"Returning %d\n"</font>, retval);
00830 <font class="preprocessor">#endif</font>
00831 <font class="preprocessor"></font>  
00832   <font class="keywordflow">return</font> retval;
00833 }
00834 
00835 <font class="keywordtype">void</font>
00836 _dbus_loop_run (DBusLoop *loop)
00837 {
00838   <font class="keywordtype">int</font> our_exit_depth;
00839 
00840   _dbus_assert (loop-&gt;depth &gt;= 0);
00841   
00842   _dbus_loop_ref (loop);
00843   
00844   our_exit_depth = loop-&gt;depth;
00845   loop-&gt;depth += 1;
00846 
00847   _dbus_verbose (<font class="stringliteral">"Running main loop, depth %d -&gt; %d\n"</font>,
00848                  loop-&gt;depth - 1, loop-&gt;depth);
00849   
00850   <font class="keywordflow">while</font> (loop-&gt;depth != our_exit_depth)
00851     _dbus_loop_iterate (loop, TRUE);
00852 
00853   _dbus_loop_unref (loop);
00854 }
00855 
00856 <font class="keywordtype">void</font>
00857 _dbus_loop_quit (DBusLoop *loop)
00858 {
00859   _dbus_assert (loop-&gt;depth &gt; 0);  
00860   
00861   loop-&gt;depth -= 1;
00862 
00863   _dbus_verbose (<font class="stringliteral">"Quit main loop, depth %d -&gt; %d\n"</font>,
00864                  loop-&gt;depth + 1, loop-&gt;depth);
00865 }
00866 
00867 <font class="keywordtype">int</font>
00868 _dbus_get_oom_wait (<font class="keywordtype">void</font>)
00869 {
00870 <font class="preprocessor">#ifdef DBUS_BUILD_TESTS</font>
00871 <font class="preprocessor"></font>  <font class="comment">/* make tests go fast */</font>
00872   <font class="keywordflow">return</font> 0;
00873 <font class="preprocessor">#else</font>
00874 <font class="preprocessor"></font>  <font class="keywordflow">return</font> 500;
00875 <font class="preprocessor">#endif</font>
00876 <font class="preprocessor"></font>}
00877 
00878 <font class="keywordtype">void</font>
00879 _dbus_wait_for_memory (<font class="keywordtype">void</font>)
00880 {
00881   _dbus_verbose (<font class="stringliteral">"Waiting for more memory\n"</font>);
00882   _dbus_sleep_milliseconds (_dbus_get_oom_wait ());
00883 }
00884 
00885 <font class="preprocessor">#endif </font><font class="comment">/* DOXYGEN_SHOULD_SKIP_THIS */</font>
</pre></div><hr><address align="right"><small>Generated on Wed Jun 9 05:01:25 2004 for D-BUS by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 
width=110 height=53></a>1.2.15 </small></address>
</body>
</html>