00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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;
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);
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 (¤t_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 (¤t_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
00327 while (XPending (xdisplay) > 0)
00328 {
00329 XNextEvent (xdisplay, &xevent);
00330 gettimeofday (¤t_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
00349 connection = ConnectionNumber (xdisplay);
00350
00351 FD_ZERO (&set);
00352 FD_SET (connection, &set);
00353
00354 gettimeofday (¤t_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
00366
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
00378
00379
00380
00381
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
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
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 }