summaryrefslogtreecommitdiff
path: root/src/core/testasyncgetprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/testasyncgetprop.c')
-rw-r--r--src/core/testasyncgetprop.c497
1 files changed, 497 insertions, 0 deletions
diff --git a/src/core/testasyncgetprop.c b/src/core/testasyncgetprop.c
new file mode 100644
index 00000000..ed044009
--- /dev/null
+++ b/src/core/testasyncgetprop.c
@@ -0,0 +1,497 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2002 Havoc Pennington
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation.
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of The Open Group shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from The Open Group.
+ */
+
+#include "async-getprop.h"
+
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <assert.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+static void
+print_backtrace (void)
+{
+ void *bt[500];
+ int bt_size;
+ int i;
+ char **syms;
+
+ bt_size = backtrace (bt, 500);
+
+ syms = backtrace_symbols (bt, bt_size);
+
+ i = 0;
+ while (i < bt_size)
+ {
+ fprintf (stderr, " %s\n", syms[i]);
+ ++i;
+ }
+
+ free (syms);
+}
+#else
+static void
+print_backtrace (void)
+{
+ fprintf (stderr, "Not compiled with backtrace support\n");
+}
+#endif
+
+static int error_trap_depth = 0;
+
+static int
+x_error_handler (Display *xdisplay,
+ XErrorEvent *error)
+{
+ char buf[64];
+
+ XGetErrorText (xdisplay, error->error_code, buf, 63);
+
+ if (error_trap_depth == 0)
+ {
+ print_backtrace ();
+
+ fprintf (stderr, "Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
+ buf,
+ error->serial,
+ error->error_code,
+ error->request_code,
+ error->minor_code);
+
+ exit (1);
+ }
+
+ return 1; /* return value is meaningless */
+}
+
+static void
+error_trap_push (Display *xdisplay)
+{
+ ++error_trap_depth;
+}
+
+static void
+error_trap_pop (Display *xdisplay)
+{
+ if (error_trap_depth == 0)
+ {
+ fprintf (stderr, "Error trap underflow!\n");
+ exit (1);
+ }
+
+ XSync (xdisplay, False); /* get all errors out of the queue */
+ --error_trap_depth;
+}
+
+static char*
+my_strdup (const char *str)
+{
+ char *s;
+
+ s = malloc (strlen (str) + 1);
+ if (s == NULL)
+ {
+ fprintf (stderr, "malloc failed\n");
+ exit (1);
+ }
+ strcpy (s, str);
+
+ return s;
+}
+
+static char*
+atom_name (Display *display,
+ Atom atom)
+{
+ if (atom == None)
+ {
+ return my_strdup ("None");
+ }
+ else
+ {
+ char *xname;
+ char *ret;
+
+ error_trap_push (display);
+ xname = XGetAtomName (display, atom);
+ error_trap_pop (display);
+ if (xname == NULL)
+ return my_strdup ("[unknown atom]");
+
+ ret = my_strdup (xname);
+ XFree (xname);
+
+ return ret;
+ }
+}
+
+
+#define ELAPSED(start_time, current_time) \
+ (((((double)current_time.tv_sec - start_time.tv_sec) * 1000000 + \
+ (current_time.tv_usec - start_time.tv_usec))) / 1000.0)
+
+static struct timeval program_start_time;
+
+static Bool
+try_get_reply (Display *xdisplay,
+ AgGetPropertyTask *task)
+{
+ if (ag_task_have_reply (task))
+ {
+ int result;
+ Atom actual_type;
+ int actual_format;
+ unsigned long n_items;
+ unsigned long bytes_after;
+ unsigned char *data;
+ char *name;
+ struct timeval current_time;
+
+ gettimeofday (&current_time, NULL);
+
+ printf (" %gms (we have a reply for property %ld)\n",
+ ELAPSED (program_start_time, current_time),
+ ag_task_get_property (task));
+
+ data = NULL;
+
+ name = atom_name (xdisplay,
+ ag_task_get_property (task));
+ printf (" %s on 0x%lx:\n", name,
+ ag_task_get_window (task));
+ free (name);
+
+ result = ag_task_get_reply_and_free (task,
+ &actual_type,
+ &actual_format,
+ &n_items,
+ &bytes_after,
+ &data);
+ task = NULL;
+
+ if (result != Success)
+ {
+ fprintf (stderr, " error code %d getting reply\n", result);
+ }
+ else
+ {
+ name = atom_name (xdisplay, actual_type);
+ printf (" actual_type = %s\n", name);
+ free (name);
+
+ printf (" actual_format = %d\n", actual_format);
+
+ printf (" n_items = %lu\n", n_items);
+ printf (" bytes_after = %lu\n", bytes_after);
+
+ printf (" data = \"%s\"\n", data ? (char*) data : "NULL");
+ }
+
+ return True;
+ }
+
+ return False;
+}
+
+static void run_speed_comparison (Display *xdisplay,
+ Window window);
+
+int
+main (int argc, char **argv)
+{
+ Display *xdisplay;
+ int i;
+ int n_left;
+ int n_props;
+ Window window;
+ const char *window_str;
+ char *end;
+ Atom *props;
+ struct timeval current_time;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "specify window ID\n");
+ return 1;
+ }
+
+ window_str = argv[1];
+
+ end = NULL;
+ window = strtoul (window_str, &end, 0);
+ if (end == NULL || *end != '\0')
+ {
+ fprintf (stderr, "\"%s\" does not parse as a window ID\n", window_str);
+ return 1;
+ }
+
+ xdisplay = XOpenDisplay (NULL);
+ if (xdisplay == NULL)
+ {
+ fprintf (stderr, "Could not open display\n");
+ return 1;
+ }
+
+ if (getenv ("MARCO_SYNC") != NULL)
+ XSynchronize (xdisplay, True);
+
+ XSetErrorHandler (x_error_handler);
+
+ n_props = 0;
+ props = XListProperties (xdisplay, window, &n_props);
+ if (n_props == 0 || props == NULL)
+ {
+ fprintf (stderr, "Window has no properties\n");
+ return 1;
+ }
+
+ gettimeofday (&program_start_time, NULL);
+
+ i = 0;
+ while (i < n_props)
+ {
+ gettimeofday (&current_time, NULL);
+ printf (" %gms (sending request for property %ld)\n",
+ ELAPSED (program_start_time, current_time),
+ props[i]);
+ if (ag_task_create (xdisplay,
+ window, props[i],
+ 0, 0xffffffff,
+ False,
+ AnyPropertyType) == NULL)
+ {
+ fprintf (stderr, "Failed to send request\n");
+ return 1;
+ }
+
+ ++i;
+ }
+
+ XFree (props);
+ props = NULL;
+
+ n_left = n_props;
+
+ while (TRUE)
+ {
+ XEvent xevent;
+ int connection;
+ fd_set set;
+ AgGetPropertyTask *task;
+
+ /* Mop up event queue */
+ while (XPending (xdisplay) > 0)
+ {
+ XNextEvent (xdisplay, &xevent);
+ gettimeofday (&current_time, NULL);
+ printf (" %gms (processing event type %d)\n",
+ ELAPSED (program_start_time, current_time),
+ xevent.xany.type);
+ }
+
+ while ((task = ag_get_next_completed_task (xdisplay)))
+ {
+ try_get_reply (xdisplay, task);
+ n_left -= 1;
+ }
+
+ if (n_left == 0)
+ {
+ printf ("All %d replies received.\n", n_props);
+ break;
+ }
+
+ /* Wake up if we may have a reply */
+ connection = ConnectionNumber (xdisplay);
+
+ FD_ZERO (&set);
+ FD_SET (connection, &set);
+
+ gettimeofday (&current_time, NULL);
+ printf (" %gms (blocking for data %d left)\n",
+ ELAPSED (program_start_time, current_time), n_left);
+ select (connection + 1, &set, NULL, NULL, NULL);
+ }
+
+ run_speed_comparison (xdisplay, window);
+
+ return 0;
+}
+
+/* This function doesn't have all the printf's
+ * and other noise, it just compares async to sync
+ */
+static void
+run_speed_comparison (Display *xdisplay,
+ Window window)
+{
+ int i;
+ int n_props;
+ struct timeval start, end;
+ int n_left;
+
+ /* We just use atom values (0 to n_props) % 200, many are probably
+ * BadAtom, that's fine, but the %200 keeps most of them valid. The
+ * async case is about twice as advantageous when using valid atoms
+ * (or the issue may be that it's more advantageous when the
+ * properties are present and data is transmitted).
+ */
+ n_props = 4000;
+ printf ("Timing with %d property requests\n", n_props);
+
+ gettimeofday (&start, NULL);
+
+ i = 0;
+ while (i < n_props)
+ {
+ if (ag_task_create (xdisplay,
+ window, (Atom) i % 200,
+ 0, 0xffffffff,
+ False,
+ AnyPropertyType) == NULL)
+ {
+ fprintf (stderr, "Failed to send request\n");
+ exit (1);
+ }
+
+ ++i;
+ }
+
+ n_left = n_props;
+
+ while (TRUE)
+ {
+ int connection;
+ fd_set set;
+ XEvent xevent;
+ AgGetPropertyTask *task;
+
+ /* Mop up event queue */
+ while (XPending (xdisplay) > 0)
+ XNextEvent (xdisplay, &xevent);
+
+ while ((task = ag_get_next_completed_task (xdisplay)))
+ {
+ int result;
+ Atom actual_type;
+ int actual_format;
+ unsigned long n_items;
+ unsigned long bytes_after;
+ unsigned char *data;
+
+ assert (ag_task_have_reply (task));
+
+ data = NULL;
+ result = ag_task_get_reply_and_free (task,
+ &actual_type,
+ &actual_format,
+ &n_items,
+ &bytes_after,
+ &data);
+
+ if (data)
+ XFree (data);
+
+ n_left -= 1;
+ }
+
+ if (n_left == 0)
+ break;
+
+ /* Wake up if we may have a reply */
+ connection = ConnectionNumber (xdisplay);
+
+ FD_ZERO (&set);
+ FD_SET (connection, &set);
+
+ select (connection + 1, &set, NULL, NULL, NULL);
+ }
+
+ gettimeofday (&end, NULL);
+
+ printf ("Async time: %gms\n",
+ ELAPSED (start, end));
+
+ gettimeofday (&start, NULL);
+
+ error_trap_push (xdisplay);
+
+ i = 0;
+ while (i < n_props)
+ {
+ Atom actual_type;
+ int actual_format;
+ unsigned long n_items;
+ unsigned long bytes_after;
+ unsigned char *data;
+
+ data = NULL;
+ if (XGetWindowProperty (xdisplay, window,
+ (Atom) i % 200,
+ 0, 0xffffffff,
+ False,
+ AnyPropertyType,
+ &actual_type,
+ &actual_format,
+ &n_items,
+ &bytes_after,
+ &data) == Success)
+ {
+ if (data)
+ XFree (data);
+ }
+
+ ++i;
+ }
+
+ error_trap_pop (xdisplay);
+
+ gettimeofday (&end, NULL);
+
+ printf ("Sync time: %gms\n",
+ ELAPSED (start, end));
+}