testasyncgetprop.c

Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 
00003 /*
00004  * Copyright (C) 2002 Havoc Pennington
00005  *
00006  * Permission to use, copy, modify, distribute, and sell this software
00007  * and its documentation for any purpose is hereby granted without
00008  * fee, provided that the above copyright notice appear in all copies
00009  * and that both that copyright notice and this permission notice
00010  * appear in supporting documentation.
00011  *
00012  * The above copyright notice and this permission notice shall be
00013  * included in all copies or substantial portions of the Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00016  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00018  * NONINFRINGEMENT.  IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
00019  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00021  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022  *
00023  * Except as contained in this notice, the name of The Open Group shall not be
00024  * used in advertising or otherwise to promote the sale, use or other dealings
00025  * in this Software without prior written authorization from The Open Group.
00026  */
00027 
00028 #include "async-getprop.h"
00029 
00030 #include <time.h>
00031 #include <sys/time.h>
00032 #include <sys/types.h>
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <unistd.h>
00036 #include <string.h>
00037 #include <errno.h>
00038 #include <signal.h>
00039 #include <assert.h>
00040 
00041 #ifndef TRUE
00042 #define TRUE 1
00043 #endif
00044 
00045 #ifndef FALSE
00046 #define FALSE 0
00047 #endif
00048 
00049 #ifndef NULL
00050 #define NULL ((void*) 0)
00051 #endif
00052 
00053 #ifdef HAVE_BACKTRACE
00054 #include <execinfo.h>
00055 static void
00056 print_backtrace (void)
00057 {
00058   void *bt[500];
00059   int bt_size;
00060   int i;
00061   char **syms;
00062 
00063   bt_size = backtrace (bt, 500);
00064 
00065   syms = backtrace_symbols (bt, bt_size);
00066 
00067   i = 0;
00068   while (i < bt_size)
00069     {
00070       fprintf (stderr, "  %s\n", syms[i]);
00071       ++i;
00072     }
00073 
00074   free (syms);
00075 }
00076 #else
00077 static void
00078 print_backtrace (void)
00079 {
00080   fprintf (stderr, "Not compiled with backtrace support\n");
00081 }
00082 #endif
00083 
00084 static int error_trap_depth = 0;
00085 
00086 static int
00087 x_error_handler (Display     *xdisplay,
00088                  XErrorEvent *error)
00089 {
00090   char buf[64];
00091 
00092   XGetErrorText (xdisplay, error->error_code, buf, 63);
00093 
00094   if (error_trap_depth == 0)
00095     {
00096       print_backtrace ();
00097       
00098       fprintf (stderr, "Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
00099                buf,
00100                error->serial,
00101                error->error_code,
00102                error->request_code,
00103                error->minor_code);
00104       
00105       exit (1);
00106     }
00107 
00108   return 1; /* return value is meaningless */
00109 }
00110 
00111 static void
00112 error_trap_push (Display   *xdisplay)
00113 {
00114   ++error_trap_depth;
00115 }
00116 
00117 static void
00118 error_trap_pop (Display   *xdisplay)
00119 {
00120   if (error_trap_depth == 0)
00121     {
00122       fprintf (stderr, "Error trap underflow!\n");
00123       exit (1);
00124     }
00125   
00126   XSync (xdisplay, False); /* get all errors out of the queue */
00127   --error_trap_depth;
00128 }
00129 
00130 static char*
00131 my_strdup (const char *str)
00132 {
00133   char *s;
00134 
00135   s = malloc (strlen (str) + 1);
00136   if (s == NULL)
00137     {
00138       fprintf (stderr, "malloc failed\n");
00139       exit (1);
00140     }
00141   strcpy (s, str);
00142 
00143   return s;
00144 }
00145 
00146 static char*
00147 atom_name (Display *display,
00148            Atom     atom)
00149 {
00150   if (atom == None)
00151     {
00152       return my_strdup ("None");
00153     }
00154   else
00155     {
00156       char *xname;
00157       char *ret;
00158 
00159       error_trap_push (display);
00160       xname = XGetAtomName (display, atom);
00161       error_trap_pop (display);
00162       if (xname == NULL)
00163         return my_strdup ("[unknown atom]");
00164 
00165       ret = my_strdup (xname);
00166       XFree (xname);
00167 
00168       return ret;
00169     }
00170 }
00171 
00172 
00173 #define ELAPSED(start_time, current_time) \
00174     (((((double)current_time.tv_sec - start_time.tv_sec) * 1000000 + \
00175        (current_time.tv_usec - start_time.tv_usec))) / 1000.0)
00176 
00177 static struct timeval program_start_time;
00178 
00179 static Bool
00180 try_get_reply (Display           *xdisplay,
00181                AgGetPropertyTask *task)
00182 {
00183   if (ag_task_have_reply (task))
00184     {
00185       int result;
00186       Atom actual_type;
00187       int actual_format;
00188       unsigned long n_items;
00189       unsigned long bytes_after;
00190       char *data;
00191       char *name;
00192       struct timeval current_time;
00193 
00194       gettimeofday (&current_time, NULL);
00195       
00196       printf (" %gms (we have a reply for property %ld)\n",
00197               ELAPSED (program_start_time, current_time),
00198               ag_task_get_property (task));
00199       
00200       data = NULL;
00201 
00202       name = atom_name (xdisplay,
00203                         ag_task_get_property (task));
00204       printf (" %s on 0x%lx:\n", name,
00205               ag_task_get_window (task));
00206       free (name);
00207       
00208       result = ag_task_get_reply_and_free (task,
00209                                            &actual_type,
00210                                            &actual_format,
00211                                            &n_items,
00212                                            &bytes_after,
00213                                            &data);
00214       task = NULL;
00215 
00216       if (result != Success)
00217         {
00218           fprintf (stderr, "  error code %d getting reply\n", result);
00219         }
00220       else
00221         {
00222           name = atom_name (xdisplay, actual_type);
00223           printf ("  actual_type = %s\n", name);
00224           free (name);
00225           
00226           printf ("  actual_format = %d\n", actual_format);
00227           
00228           printf ("  n_items = %lu\n", n_items);
00229           printf ("  bytes_after = %lu\n", bytes_after);
00230           
00231           printf ("  data = \"%s\"\n", data ? (char*) data : "NULL");
00232         }
00233 
00234       return True;
00235     }
00236 
00237   return False;
00238 }
00239 
00240 static void run_speed_comparison (Display *xdisplay,
00241                                   Window   window);
00242 
00243 int
00244 main (int argc, char **argv)
00245 {
00246   Display *xdisplay;
00247   int i;
00248   int n_left;
00249   int n_props;
00250   Window window;
00251   const char *window_str;
00252   char *end;
00253   Atom *props;
00254   struct timeval current_time;
00255   
00256   if (argc < 2)
00257     {
00258       fprintf (stderr, "specify window ID\n");
00259       return 1;
00260     }
00261   
00262   window_str = argv[1];
00263 
00264   end = NULL;
00265   window = strtoul (window_str, &end, 0);
00266   if (end == NULL || *end != '\0')
00267     {
00268       fprintf (stderr, "\"%s\" does not parse as a window ID\n", window_str);
00269       return 1;
00270     }
00271 
00272   xdisplay = XOpenDisplay (NULL);
00273   if (xdisplay == NULL)
00274     {
00275       fprintf (stderr, "Could not open display\n");
00276       return 1;
00277     }
00278 
00279   if (getenv ("METACITY_SYNC") != NULL)
00280     XSynchronize (xdisplay, True);
00281 
00282   XSetErrorHandler (x_error_handler);
00283   
00284   n_props = 0;
00285   props = XListProperties (xdisplay, window, &n_props);
00286   if (n_props == 0 || props == NULL)
00287     {
00288       fprintf (stderr, "Window has no properties\n");
00289       return 1;
00290     }
00291 
00292   gettimeofday (&program_start_time, NULL);
00293   
00294   i = 0;
00295   while (i < n_props)
00296     {
00297       gettimeofday (&current_time, NULL);
00298       printf (" %gms (sending request for property %ld)\n",
00299               ELAPSED (program_start_time, current_time),
00300               props[i]);
00301       if (ag_task_create (xdisplay,
00302                           window, props[i],
00303                           0, 0xffffffff,
00304                           False,
00305                           AnyPropertyType) == NULL)
00306         {
00307           fprintf (stderr, "Failed to send request\n");
00308           return 1;
00309         }
00310       
00311       ++i;
00312     }
00313 
00314   XFree (props);
00315   props = NULL;
00316 
00317   n_left = n_props;
00318   
00319   while (TRUE)
00320     {
00321       XEvent xevent;
00322       int connection;
00323       fd_set set;
00324       AgGetPropertyTask *task;
00325       
00326       /* Mop up event queue */
00327       while (XPending (xdisplay) > 0)
00328         {                  
00329           XNextEvent (xdisplay, &xevent);
00330           gettimeofday (&current_time, NULL);
00331           printf (" %gms (processing event type %d)\n",
00332                   ELAPSED (program_start_time, current_time),
00333                   xevent.xany.type);
00334         }
00335       
00336       while ((task = ag_get_next_completed_task (xdisplay)))
00337         {
00338           try_get_reply (xdisplay, task);
00339           n_left -= 1;
00340         }
00341 
00342       if (n_left == 0)
00343         {
00344           printf ("All %d replies received.\n", n_props);
00345           break;
00346         }
00347 
00348       /* Wake up if we may have a reply */
00349       connection = ConnectionNumber (xdisplay);
00350 
00351       FD_ZERO (&set);
00352       FD_SET (connection, &set);
00353 
00354       gettimeofday (&current_time, NULL);
00355       printf (" %gms (blocking for data %d left)\n",
00356               ELAPSED (program_start_time, current_time), n_left);
00357       select (connection + 1, &set, NULL, NULL, NULL);
00358     }
00359 
00360   run_speed_comparison (xdisplay, window);
00361   
00362   return 0;
00363 }
00364 
00365 /* This function doesn't have all the printf's
00366  * and other noise, it just compares async to sync
00367  */
00368 static void
00369 run_speed_comparison (Display *xdisplay,
00370                       Window   window)
00371 {
00372   int i;
00373   int n_props;
00374   struct timeval start, end;
00375   int n_left;
00376   
00377   /* We just use atom values (0 to n_props) % 200, many are probably
00378    * BadAtom, that's fine, but the %200 keeps most of them valid. The
00379    * async case is about twice as advantageous when using valid atoms
00380    * (or the issue may be that it's more advantageous when the
00381    * properties are present and data is transmitted).
00382    */
00383   n_props = 4000;
00384   printf ("Timing with %d property requests\n", n_props);
00385   
00386   gettimeofday (&start, NULL);
00387   
00388   i = 0;
00389   while (i < n_props)
00390     {
00391       if (ag_task_create (xdisplay,
00392                           window, (Atom) i % 200,
00393                           0, 0xffffffff,
00394                           False,
00395                           AnyPropertyType) == NULL)
00396         {
00397           fprintf (stderr, "Failed to send request\n");
00398           exit (1);
00399         }
00400       
00401       ++i;
00402     }
00403 
00404   n_left = n_props;
00405   
00406   while (TRUE)
00407     {
00408       int connection;
00409       fd_set set;
00410       XEvent xevent;
00411       AgGetPropertyTask *task;
00412       
00413       /* Mop up event queue */
00414       while (XPending (xdisplay) > 0)
00415         XNextEvent (xdisplay, &xevent);
00416       
00417       while ((task = ag_get_next_completed_task (xdisplay)))
00418         {
00419           int result;
00420           Atom actual_type;
00421           int actual_format;
00422           unsigned long n_items;
00423           unsigned long bytes_after;
00424           char *data;
00425 
00426           assert (ag_task_have_reply (task));
00427           
00428           data = NULL;
00429           result = ag_task_get_reply_and_free (task,
00430                                                &actual_type,
00431                                                &actual_format,
00432                                                &n_items,
00433                                                &bytes_after,
00434                                                &data);
00435           
00436           if (data)
00437             XFree (data);
00438           
00439           n_left -= 1;
00440         }
00441       
00442       if (n_left == 0)
00443         break;
00444 
00445       /* Wake up if we may have a reply */
00446       connection = ConnectionNumber (xdisplay);
00447 
00448       FD_ZERO (&set);
00449       FD_SET (connection, &set);
00450 
00451       select (connection + 1, &set, NULL, NULL, NULL);
00452     }
00453   
00454   gettimeofday (&end, NULL);
00455   
00456   printf ("Async time: %gms\n",
00457           ELAPSED (start, end));
00458   
00459   gettimeofday (&start, NULL);
00460 
00461   error_trap_push (xdisplay);
00462   
00463   i = 0;
00464   while (i < n_props)
00465     {
00466       Atom actual_type;
00467       int actual_format;
00468       unsigned long n_items;
00469       unsigned long bytes_after;
00470       unsigned char *data;
00471       
00472       data = NULL;
00473       if (XGetWindowProperty (xdisplay, window,
00474                               (Atom) i % 200,
00475                               0, 0xffffffff,
00476                               False,
00477                               AnyPropertyType,
00478                               &actual_type,
00479                               &actual_format,
00480                               &n_items,
00481                               &bytes_after,
00482                               &data) == Success)
00483         {
00484           if (data)
00485             XFree (data);
00486         }
00487       
00488       ++i;
00489     }
00490 
00491   error_trap_pop (xdisplay);
00492   
00493   gettimeofday (&end, NULL);
00494   
00495   printf ("Sync time:  %gms\n",
00496           ELAPSED (start, end));
00497 }

Generated on Sat Aug 23 22:04:17 2008 for metacity by  doxygen 1.5.5