/* 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 UNUSED_VARIABLE 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)); }
void meta_prop_get_values (MetaDisplay *display, Window xwindow, MetaPropValue *values, int n_values) { int i; AgGetPropertyTask **tasks; meta_verbose ("Requesting %d properties of 0x%lx at once\n", n_values, xwindow); if (n_values == 0) return; tasks = g_new0 (AgGetPropertyTask*, n_values); /* Start up tasks. The "values" array can have values * with atom == None, which means to ignore that element. */ i = 0; while (i < n_values) { if (values[i].required_type == None) { switch (values[i].type) { case META_PROP_VALUE_INVALID: /* This means we don't really want a value, e.g. got * property notify on an atom we don't care about. */ if (values[i].atom != None) meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_STRFUNC); break; case META_PROP_VALUE_UTF8_LIST: case META_PROP_VALUE_UTF8: values[i].required_type = display->atom_UTF8_STRING; break; case META_PROP_VALUE_STRING: case META_PROP_VALUE_STRING_AS_UTF8: values[i].required_type = XA_STRING; break; case META_PROP_VALUE_MOTIF_HINTS: values[i].required_type = AnyPropertyType; break; case META_PROP_VALUE_CARDINAL_LIST: case META_PROP_VALUE_CARDINAL: values[i].required_type = XA_CARDINAL; break; case META_PROP_VALUE_WINDOW: values[i].required_type = XA_WINDOW; break; case META_PROP_VALUE_ATOM_LIST: values[i].required_type = XA_ATOM; break; case META_PROP_VALUE_TEXT_PROPERTY: values[i].required_type = AnyPropertyType; break; case META_PROP_VALUE_WM_HINTS: values[i].required_type = XA_WM_HINTS; break; case META_PROP_VALUE_CLASS_HINT: values[i].required_type = XA_STRING; break; case META_PROP_VALUE_SIZE_HINTS: values[i].required_type = XA_WM_SIZE_HINTS; break; case META_PROP_VALUE_SYNC_COUNTER: values[i].required_type = XA_CARDINAL; break; } } if (values[i].atom != None) tasks[i] = get_task (display, xwindow, values[i].atom, values[i].required_type); ++i; } /* Get replies for all our tasks */ meta_topic (META_DEBUG_SYNC, "Syncing to get %d GetProperty replies in %s\n", n_values, G_STRFUNC); XSync (display->xdisplay, False); /* Collect results, should arrive in order requested */ i = 0; while (i < n_values) { AgGetPropertyTask *task; GetPropertyResults results; if (tasks[i] == NULL) { /* Probably values[i].type was None, or ag_task_create() * returned NULL. */ values[i].type = META_PROP_VALUE_INVALID; goto next; } task = ag_get_next_completed_task (display->xdisplay); g_assert (task != NULL); g_assert (ag_task_have_reply (task)); results.display = display; results.xwindow = xwindow; results.xatom = values[i].atom; results.prop = NULL; results.n_items = 0; results.type = None; results.bytes_after = 0; results.format = 0; if (ag_task_get_reply_and_free (task, &results.type, &results.format, &results.n_items, &results.bytes_after, &results.prop) != Success || results.type == None) { values[i].type = META_PROP_VALUE_INVALID; if (results.prop) { XFree (results.prop); results.prop = NULL; } goto next; } switch (values[i].type) { case META_PROP_VALUE_INVALID: g_assert_not_reached (); break; case META_PROP_VALUE_UTF8_LIST: if (!utf8_list_from_results (&results, &values[i].v.string_list.strings, &values[i].v.string_list.n_strings)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_UTF8: if (!utf8_string_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_STRING: if (!latin1_string_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_STRING_AS_UTF8: if (!latin1_string_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; else { char *new_str; char *xmalloc_new_str; new_str = latin1_to_utf8 (values[i].v.str); xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1); if (xmalloc_new_str != NULL) { strcpy (xmalloc_new_str, new_str); meta_XFree (values[i].v.str); values[i].v.str = xmalloc_new_str; } g_free (new_str); } break; case META_PROP_VALUE_MOTIF_HINTS: if (!motif_hints_from_results (&results, &values[i].v.motif_hints)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_CARDINAL_LIST: if (!cardinal_list_from_results (&results, &values[i].v.cardinal_list.cardinals, &values[i].v.cardinal_list.n_cardinals)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_CARDINAL: if (!cardinal_with_atom_type_from_results (&results, values[i].required_type, &values[i].v.cardinal)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_WINDOW: if (!window_from_results (&results, &values[i].v.xwindow)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_ATOM_LIST: if (!atom_list_from_results (&results, &values[i].v.atom_list.atoms, &values[i].v.atom_list.n_atoms)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_TEXT_PROPERTY: if (!text_property_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_WM_HINTS: if (!wm_hints_from_results (&results, &values[i].v.wm_hints)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_CLASS_HINT: if (!class_hint_from_results (&results, &values[i].v.class_hint)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_SIZE_HINTS: if (!size_hints_from_results (&results, &values[i].v.size_hints.hints, &values[i].v.size_hints.flags)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_SYNC_COUNTER: #ifdef HAVE_XSYNC if (!counter_from_results (&results, &values[i].v.xcounter)) values[i].type = META_PROP_VALUE_INVALID; #else values[i].type = META_PROP_VALUE_INVALID; if (results.prop) { XFree (results.prop); results.prop = NULL; } #endif break; } next: ++i; } g_free (tasks); }
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 (¤t_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 (¤t_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 (¤t_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; }