1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2024-11-18 13:54:36 -05:00

Add threadpool support, add optional timings compile flag

This commit is contained in:
Dave Davenport 2015-11-14 13:47:45 +01:00
parent 45c8de9387
commit 80e873c8a3
7 changed files with 188 additions and 72 deletions

View file

@ -34,6 +34,7 @@ rofi_SOURCES=\
config/config.c\ config/config.c\
source/helper.c\ source/helper.c\
source/textbox.c\ source/textbox.c\
source/timings.c\
source/history.c\ source/history.c\
source/scrollbar.c\ source/scrollbar.c\
source/i3-support.c\ source/i3-support.c\
@ -49,6 +50,7 @@ rofi_SOURCES=\
include/rofi.h\ include/rofi.h\
include/keyb.h\ include/keyb.h\
include/helper.h\ include/helper.h\
include/timings.h\
include/history.h\ include/history.h\
include/textbox.h\ include/textbox.h\
include/scrollbar.h\ include/scrollbar.h\

View file

@ -3,15 +3,15 @@ AC_INIT([rofi], [0.15.12-devel], [https://github.com/DaveDavenport/rofi/])
AC_CONFIG_SRCDIR([source/rofi.c]) AC_CONFIG_SRCDIR([source/rofi.c])
AC_CONFIG_HEADER([config.h]) AC_CONFIG_HEADER([config.h])
## dnl ---------------------------------------------------------------------
# Setup automake to be silent and in foreign mode. dnl Setup automake to be silent and in foreign mode.
## dnl ---------------------------------------------------------------------
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects dist-xz]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects dist-xz])
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
## dnl ---------------------------------------------------------------------
# Check for compiler dnl Check for compiler
## dnl ---------------------------------------------------------------------
AC_PROG_CC([clang gcc cc]) AC_PROG_CC([clang gcc cc])
AC_PROG_CC_C99 AC_PROG_CC_C99
AM_PROG_CC_C_O AM_PROG_CC_C_O
@ -21,27 +21,31 @@ AC_USE_SYSTEM_EXTENSIONS
dnl --------------------------------------------------------------------- dnl ---------------------------------------------------------------------
dnl Disable window mode dnl Disable window mode
dnl --------------------------------------------------------------------- dnl ---------------------------------------------------------------------
AC_ARG_ENABLE([windowmode], AC_HELP_STRING([--disable-windowmode],[Disable window mode])) AC_ARG_ENABLE([windowmode], AC_HELP_STRING([--disable-windowmode],[Disable window mode]))
AS_IF([ test "x$enable_windowmode" != "xno"], [AC_DEFINE([WINDOW_MODE],[1],[Enable the window mode])]) AS_IF([ test "x$enable_windowmode" != "xno"], [AC_DEFINE([WINDOW_MODE],[1],[Enable the window mode])])
## dnl ---------------------------------------------------------------------
# I3 check dnl Output timing information
## dnl ---------------------------------------------------------------------
AC_ARG_ENABLE([timings], AC_HELP_STRING([--enable-timings],[Enable timing output]))
AS_IF( [ test "x$enable_timings" = "xyes"], [AC_DEFINE([TIMINGS],[1], [Enable timings output])])
dnl ---------------------------------------------------------------------
dnl I3 check
dnl ---------------------------------------------------------------------
AC_ARG_ENABLE(i3support, [AS_HELP_STRING([--disable-i3support], [Disable check for i3 support])]) AC_ARG_ENABLE(i3support, [AS_HELP_STRING([--disable-i3support], [Disable check for i3 support])])
AS_IF([test "x$enable_i3support" != xno && test "x$enable_windowmode" != "xno"],[AC_CHECK_HEADERS([i3/ipc.h], [i3_header=yes; break;])]) AS_IF([test "x$enable_i3support" != xno && test "x$enable_windowmode" != "xno"],[AC_CHECK_HEADERS([i3/ipc.h], [i3_header=yes; break;])])
## dnl ---------------------------------------------------------------------
# Check for C functions. dnl Check for C functions.
## dnl ---------------------------------------------------------------------
AC_CHECK_FUNC([getdelim],, AC_MSG_ERROR("Could not find getdelim in c library")) AC_CHECK_FUNC([getdelim],, AC_MSG_ERROR("Could not find getdelim in c library"))
AC_CHECK_FUNC([sysconf],, AC_MSG_ERROR("Could not find sysconf")) AC_CHECK_FUNC([sysconf],, AC_MSG_ERROR("Could not find sysconf"))
##
# Check dependencies dnl ---------------------------------------------------------------------
## dnl Check dependencies
dnl ---------------------------------------------------------------------
PKG_PROG_PKG_CONFIG PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES([x11], [x11]) PKG_CHECK_MODULES([x11], [x11])
@ -66,6 +70,11 @@ echo "I3 support: Enabled"
else else
echo "I3 support: Disabled" echo "I3 support: Disabled"
fi fi
if test x$enable_timings = xyes; then
echo "Timing output: Enabled"
else
echo "Timing output: Disabled"
fi
echo "-------------------------------------" echo "-------------------------------------"
echo "Now type 'make' to build" echo "Now type 'make' to build"
echo "" echo ""

View file

@ -7,6 +7,7 @@
#include <textbox.h> #include <textbox.h>
#include <cairo.h> #include <cairo.h>
#include <cairo-xlib.h> #include <cairo-xlib.h>
#include "timings.h"
#include "keyb.h" #include "keyb.h"
/** /**

View file

@ -33,14 +33,14 @@ typedef struct
typedef enum typedef enum
{ {
TB_AUTOHEIGHT = 1 << 0, TB_AUTOHEIGHT = 1 << 0,
TB_AUTOWIDTH = 1 << 1, TB_AUTOWIDTH = 1 << 1,
TB_LEFT = 1 << 16, TB_LEFT = 1 << 16,
TB_RIGHT = 1 << 17, TB_RIGHT = 1 << 17,
TB_CENTER = 1 << 18, TB_CENTER = 1 << 18,
TB_EDITABLE = 1 << 19, TB_EDITABLE = 1 << 19,
TB_MARKUP = 1 << 20, TB_MARKUP = 1 << 20,
TB_WRAP = 1 << 21, TB_WRAP = 1 << 21,
} TextboxFlags; } TextboxFlags;
typedef enum typedef enum

View file

@ -37,6 +37,9 @@
#include "dialogs/dmenu.h" #include "dialogs/dmenu.h"
#include "helper.h" #include "helper.h"
// We limit at 1000000 rows for now.
#define DMENU_MAX_ROWS 1000000
struct range_pair struct range_pair
{ {
unsigned int start; unsigned int start;
@ -59,7 +62,8 @@ typedef struct _DmenuModePrivateData
static char **get_dmenu ( unsigned int *length ) static char **get_dmenu ( unsigned int *length )
{ {
char **retv = NULL; TICK_N ( "Read stdin START" )
char **retv = NULL;
unsigned int rvlength = 1; unsigned int rvlength = 1;
*length = 0; *length = 0;
@ -75,18 +79,19 @@ static char **get_dmenu ( unsigned int *length )
data[l - 1] = '\0'; data[l - 1] = '\0';
} }
retv[( *length )] = data; //copy; retv[( *length )] = data; //copy;
retv[( *length ) + 1] = NULL; data = NULL;
data = NULL; data_l = 0;
data_l = 0;
( *length )++; ( *length )++;
// Stop when we hit 2³¹ entries. // Stop when we hit 2³¹ entries.
if ( ( *length ) == INT_MAX ) { if ( ( *length ) >= DMENU_MAX_ROWS ) {
return retv; break;
} }
} }
retv = g_realloc ( retv, ( *length + 1 ) * sizeof ( char* ) ); retv[( *length ) + 1] = NULL;
retv = g_realloc ( retv, ( *length + 1 ) * sizeof ( char* ) );
TICK_N ( "Read stdin STOP" )
return retv; return retv;
} }

View file

@ -517,7 +517,7 @@ void config_sanity_check ( Display *display )
config.threads = 1; config.threads = 1;
long procs = sysconf ( _SC_NPROCESSORS_CONF ); long procs = sysconf ( _SC_NPROCESSORS_CONF );
if ( procs > 0 ) { if ( procs > 0 ) {
config.threads = MIN(procs,UINT_MAX); config.threads = MIN ( procs, UINT_MAX );
} }
} }
// If alternative row is not set, copy the normal background color. // If alternative row is not set, copy the normal background color.

View file

@ -23,8 +23,8 @@
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/ */
#include <config.h> #include <config.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -94,6 +94,8 @@ cairo_t *draw = NULL;
XIM xim; XIM xim;
XIC xic; XIC xic;
GThreadPool *tpool = NULL;
/** /**
* @param name Name of the switcher to lookup. * @param name Name of the switcher to lookup.
* *
@ -705,18 +707,21 @@ static void menu_mouse_navigation ( MenuState *state, XButtonEvent *xbe )
} }
} }
typedef struct typedef struct _thread_state
{ {
MenuState *state; MenuState *state;
char **tokens; char **tokens;
unsigned int start; unsigned int start;
unsigned int stop; unsigned int stop;
unsigned int count; unsigned int count;
GCond *cond;
GMutex *mutex;
unsigned int *acount;
void ( *callback )( struct _thread_state *t, gpointer data );
}thread_state; }thread_state;
static gpointer filter_elements ( gpointer data ) static void filter_elements ( thread_state *t, G_GNUC_UNUSED gpointer user_data )
{ {
thread_state *t = (thread_state *) data;
// input changed // input changed
for ( unsigned int i = t->start; i < t->stop; i++ ) { for ( unsigned int i = t->start; i < t->stop; i++ ) {
int match = t->state->sw->token_match ( t->tokens, int match = t->state->sw->token_match ( t->tokens,
@ -735,39 +740,76 @@ static gpointer filter_elements ( gpointer data )
t->count++; t->count++;
} }
} }
return 0; g_mutex_lock ( t->mutex );
( *( t->acount ) )--;
g_cond_signal ( t->cond );
g_mutex_unlock ( t->mutex );
}
static void check_is_ascii ( thread_state *t, G_GNUC_UNUSED gpointer user_data )
{
for ( unsigned int i = t->start; i < t->stop; i++ ) {
t->state->lines_not_ascii[i] = is_not_ascii ( t->state->lines[i] );
}
g_mutex_lock ( t->mutex );
( *( t->acount ) )--;
g_cond_signal ( t->cond );
g_mutex_unlock ( t->mutex );
}
/**
* Small wrapper function to create easy workers.
*/
static void call_thread ( gpointer data, gpointer user_data )
{
thread_state *t = (thread_state *) data;
t->callback ( t, user_data );
} }
static void menu_refilter ( MenuState *state ) static void menu_refilter ( MenuState *state )
{ {
TICK_N ( "Filter start" )
if ( strlen ( state->text->text ) > 0 ) { if ( strlen ( state->text->text ) > 0 ) {
unsigned int j = 0; unsigned int j = 0;
char **tokens = tokenize ( state->text->text, config.case_sensitive ); char **tokens = tokenize ( state->text->text, config.case_sensitive );
/** /**
* On long lists it can be beneficial to parallelize. * On long lists it can be beneficial to parallelize.
* If number of threads is 1, no thread is spawn. * If number of threads is 1, no thread is spawn.
* If number of threads > 1 and there are enough (> 20000) items, spawn threads. * If number of threads > 1 and there are enough (> 1000) items, spawn jobs for the thread pool.
* For large lists with 8 threads I see a factor three speedup of the whole function. * For large lists with 8 threads I see a factor three speedup of the whole function.
*/ */
unsigned int nt = MAX ( 1, MIN ( state->num_lines / 1000, config.threads ) ); unsigned int nt = MAX ( 1, state->num_lines / 500 );
thread_state states[nt]; thread_state states[nt];
GThread *threads[nt]; GCond cond;
GMutex mutex;
g_mutex_init ( &mutex );
g_cond_init ( &cond );
unsigned int count = nt;
unsigned int steps = ( state->num_lines + nt ) / nt; unsigned int steps = ( state->num_lines + nt ) / nt;
for ( unsigned int i = 0; i < nt; i++ ) { for ( unsigned int i = 0; i < nt; i++ ) {
states[i].state = state; states[i].state = state;
states[i].tokens = tokens; states[i].tokens = tokens;
states[i].start = i * steps; states[i].start = i * steps;
states[i].stop = MIN ( state->num_lines, ( i + 1 ) * steps ); states[i].stop = MIN ( state->num_lines, ( i + 1 ) * steps );
states[i].count = 0; states[i].count = 0;
states[i].cond = &cond;
states[i].mutex = &mutex;
states[i].acount = &count;
states[i].callback = filter_elements;
if ( i > 0 ) { if ( i > 0 ) {
threads[i] = g_thread_new ( NULL, filter_elements, &( states[i] ) ); g_thread_pool_push ( tpool, &states[i], NULL );
} }
} }
// Run one in this thread. // Run one in this thread.
filter_elements ( &states[0] ); filter_elements ( &states[0], NULL );
for ( unsigned int i = 1; i < nt; i++ ) { // No need to do this with only one thread.
g_thread_join ( threads[i] ); if ( nt > 1 ) {
g_mutex_lock ( &mutex );
while ( count > 0 ) {
g_cond_wait ( &cond, &mutex );
}
g_mutex_unlock ( &mutex );
} }
g_cond_clear ( &cond );
g_mutex_clear ( &mutex );
for ( unsigned int i = 0; i < nt; i++ ) { for ( unsigned int i = 0; i < nt; i++ ) {
if ( j != states[i].start ) { if ( j != states[i].start ) {
memcpy ( &( state->line_map[j] ), &( state->line_map[states[i].start] ), sizeof ( unsigned int ) * ( states[i].count ) ); memcpy ( &( state->line_map[j] ), &( state->line_map[states[i].start] ), sizeof ( unsigned int ) * ( states[i].count ) );
@ -800,6 +842,7 @@ static void menu_refilter ( MenuState *state )
scrollbar_set_max_value ( state->scrollbar, state->filtered_lines ); scrollbar_set_max_value ( state->scrollbar, state->filtered_lines );
state->refilter = FALSE; state->refilter = FALSE;
state->rchanged = TRUE; state->rchanged = TRUE;
TICK_N ( "Filter done" )
} }
static void menu_draw ( MenuState *state, cairo_t *d ) static void menu_draw ( MenuState *state, cairo_t *d )
@ -882,8 +925,9 @@ static void menu_draw ( MenuState *state, cairo_t *d )
static void menu_update ( MenuState *state ) static void menu_update ( MenuState *state )
{ {
cairo_surface_t *surf = cairo_image_surface_create ( get_format (), state->w, state->h ); TICK ()
cairo_t *d = cairo_create ( surf ); cairo_surface_t * surf = cairo_image_surface_create ( get_format (), state->w, state->h );
cairo_t *d = cairo_create ( surf );
cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE ); cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE );
if ( config.fake_transparency ) { if ( config.fake_transparency ) {
if ( state->bg != NULL ) { if ( state->bg != NULL ) {
@ -901,6 +945,7 @@ static void menu_update ( MenuState *state )
color_background ( display, d ); color_background ( display, d );
cairo_paint ( d ); cairo_paint ( d );
} }
TICK_N ( "Background" )
color_border ( display, d ); color_border ( display, d );
if ( config.menu_bw > 0 ) { if ( config.menu_bw > 0 ) {
@ -972,6 +1017,7 @@ static void menu_update ( MenuState *state )
// Flush the surface. // Flush the surface.
cairo_surface_flush ( surface ); cairo_surface_flush ( surface );
TICK ()
} }
/** /**
@ -1066,7 +1112,8 @@ static void menu_resize ( MenuState *state )
MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *selected_line, unsigned int *next_pos, const char *message ) MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *selected_line, unsigned int *next_pos, const char *message )
{ {
int shift = FALSE; TICK ()
int shift = FALSE;
MenuState state = { MenuState state = {
.sw = sw, .sw = sw,
.selected_line = selected_line, .selected_line = selected_line,
@ -1093,9 +1140,40 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select
// find out which lines contain non-ascii codepoints, so we can be faster in some cases. // find out which lines contain non-ascii codepoints, so we can be faster in some cases.
if ( state.lines != NULL ) { if ( state.lines != NULL ) {
for ( unsigned int line = 0; state.lines[line]; line++ ) { TICK_N ( "Is ASCII start" )
state.lines_not_ascii[line] = is_not_ascii ( state.lines[line] ); unsigned int nt = MAX ( 1, state.num_lines / 5000 );
thread_state states[nt];
unsigned int steps = ( state.num_lines + nt ) / nt;
unsigned int count = nt;
GCond cond;
GMutex mutex;
g_mutex_init ( &mutex );
g_cond_init ( &cond );
for ( unsigned int i = 0; i < nt; i++ ) {
states[i].state = &state;
states[i].start = i * steps;
states[i].stop = MIN ( ( i + 1 ) * steps, state.num_lines );
states[i].acount = &count;
states[i].mutex = &mutex;
states[i].cond = &cond;
states[i].callback = check_is_ascii;
if ( i > 0 ) {
g_thread_pool_push ( tpool, &( states[i] ), NULL );
}
} }
// Run one in this thread.
check_is_ascii ( &( states[0] ), NULL );
// No need to do this with only one thread.
if ( nt > 1 ) {
g_mutex_lock ( &mutex );
while ( count > 0 ) {
g_cond_wait ( &cond, &mutex );
}
g_mutex_unlock ( &mutex );
}
g_cond_clear ( &cond );
g_mutex_clear ( &mutex );
TICK_N ( "Is ASCII stop" )
} }
if ( next_pos ) { if ( next_pos ) {
@ -1111,6 +1189,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select
// Break off. // Break off.
return MENU_CANCEL; return MENU_CANCEL;
} }
TICK_N ( "Grab keyboard" )
// main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker // main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker
XWindowAttributes attr; XWindowAttributes attr;
if ( main_window == None || XGetWindowAttributes ( display, main_window, &attr ) == 0 ) { if ( main_window == None || XGetWindowAttributes ( display, main_window, &attr ) == 0 ) {
@ -1119,8 +1198,10 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select
sn_launchee_context_setup_window ( sncontext, main_window ); sn_launchee_context_setup_window ( sncontext, main_window );
} }
} }
TICK_N ( "Startup notification" )
// Get active monitor size. // Get active monitor size.
monitor_active ( display, &( state.mon ) ); monitor_active ( display, &( state.mon ) );
TICK_N ( "Get active monitor" )
if ( config.fake_transparency ) { if ( config.fake_transparency ) {
Window root = DefaultRootWindow ( display ); Window root = DefaultRootWindow ( display );
int screen = DefaultScreen ( display ); int screen = DefaultScreen ( display );
@ -1136,6 +1217,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select
cairo_paint ( dr ); cairo_paint ( dr );
cairo_destroy ( dr ); cairo_destroy ( dr );
cairo_surface_destroy ( s ); cairo_surface_destroy ( s );
TICK_N ( "Fake transparency" )
} }
// we need this at this point so we can get height. // we need this at this point so we can get height.
@ -1299,6 +1381,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select
} }
// Get next event. (might block) // Get next event. (might block)
XNextEvent ( display, &ev ); XNextEvent ( display, &ev );
TICK_N ( "X Event" )
if ( sndisplay != NULL ) { if ( sndisplay != NULL ) {
sn_display_process_event ( sndisplay, &ev ); sn_display_process_event ( sndisplay, &ev );
} }
@ -1759,19 +1842,15 @@ static void print_main_application_options ( void )
printf ( "\t"color_bold "-display [string]"color_reset " X server to contact.\n" ); printf ( "\t"color_bold "-display [string]"color_reset " X server to contact.\n" );
printf ( "\t\t"color_italic "${DISPLAY}"color_reset "\n" ); printf ( "\t\t"color_italic "${DISPLAY}"color_reset "\n" );
printf ( "\t"color_bold "-h,-help"color_reset " This help message.\n" ); printf ( "\t"color_bold "-h,-help"color_reset " This help message.\n" );
printf ( printf ( "\t"color_bold "-dump-xresources"color_reset
"\t"color_bold "-dump-xresources"color_reset " Dump the current configuration in Xresources format and exit.\n" );
" Dump the current configuration in Xresources format and exit.\n" ); printf ( "\t"color_bold "-e [string]"color_reset
printf ( " Show a dialog displaying the passed message and exit.\n" );
"\t"color_bold "-e [string]"color_reset
" Show a dialog displaying the passed message and exit.\n" );
printf ( "\t"color_bold "-markup"color_reset " Enable pango markup where possible.\n" ); printf ( "\t"color_bold "-markup"color_reset " Enable pango markup where possible.\n" );
printf ( printf ( "\t"color_bold "-normal-window"color_reset
"\t"color_bold "-normal-window"color_reset " In dmenu mode, behave as a normal window. (experimental)\n" );
" In dmenu mode, behave as a normal window. (experimental)\n" ); printf ( "\t"color_bold "-show [mode]"color_reset
printf ( " Show the mode 'mode' and exit. The mode has to be enabled.\n" );
"\t"color_bold "-show [mode]"color_reset
" Show the mode 'mode' and exit. The mode has to be enabled.\n" );
} }
else { else {
printf ( "\t-no-config Do not load configuration, use default values.\n" ); printf ( "\t-no-config Do not load configuration, use default values.\n" );
@ -1810,6 +1889,10 @@ static void help ( G_GNUC_UNUSED int argc, char **argv )
*/ */
static void cleanup () static void cleanup ()
{ {
if ( tpool ) {
g_thread_pool_free ( tpool, TRUE, FALSE );
tpool = NULL;
}
// Cleanup // Cleanup
if ( display != NULL ) { if ( display != NULL ) {
if ( main_window != None ) { if ( main_window != None ) {
@ -1850,6 +1933,8 @@ static void cleanup ()
// Cleanup the custom keybinding // Cleanup the custom keybinding
cleanup_abe (); cleanup_abe ();
TIMINGS_STOP ()
} }
/** /**
@ -2171,6 +2256,8 @@ static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, Display *xdispl
int main ( int argc, char *argv[] ) int main ( int argc, char *argv[] )
{ {
TIMINGS_START ()
cmd_set_arguments ( argc, argv ); cmd_set_arguments ( argc, argv );
// Quiet flag // Quiet flag
int quiet = ( find_arg ( "-quiet" ) >= 0 ); int quiet = ( find_arg ( "-quiet" ) >= 0 );
@ -2195,7 +2282,7 @@ int main ( int argc, char *argv[] )
// Free the basename for dmenu detection. // Free the basename for dmenu detection.
g_free ( base_name ); g_free ( base_name );
} }
TICK ()
// Get the path to the cache dir. // Get the path to the cache dir.
cache_dir = g_get_user_cache_dir (); cache_dir = g_get_user_cache_dir ();
@ -2206,9 +2293,11 @@ int main ( int argc, char *argv[] )
} }
config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" ); config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" );
TICK ()
// Register cleanup function. // Register cleanup function.
atexit ( cleanup ); atexit ( cleanup );
TICK ()
// Get DISPLAY, first env, then argument. // Get DISPLAY, first env, then argument.
display_str = getenv ( "DISPLAY" ); display_str = getenv ( "DISPLAY" );
find_arg_str ( "-display", &display_str ); find_arg_str ( "-display", &display_str );
@ -2225,15 +2314,17 @@ int main ( int argc, char *argv[] )
fprintf ( stderr, "cannot open display!\n" ); fprintf ( stderr, "cannot open display!\n" );
return EXIT_FAILURE; return EXIT_FAILURE;
} }
TICK_N ( "Open Display" )
// startup not. // startup not.
sndisplay = sn_display_new ( display, error_trap_push, error_trap_pop ); sndisplay = sn_display_new ( display, error_trap_push, error_trap_pop );
if ( sndisplay != NULL ) { if ( sndisplay != NULL ) {
sncontext = sn_launchee_context_new_from_environment ( sndisplay, DefaultScreen ( display ) ); sncontext = sn_launchee_context_new_from_environment ( sndisplay, DefaultScreen ( display ) );
} }
TICK_N ( "Startup Notification" )
// Setup keybinding // Setup keybinding
setup_abe (); setup_abe ();
TICK_N ( "Setup abe" )
if ( find_arg ( "-no-config" ) < 0 ) { if ( find_arg ( "-no-config" ) < 0 ) {
load_configuration ( display ); load_configuration ( display );
@ -2254,8 +2345,10 @@ int main ( int argc, char *argv[] )
x11_setup ( display ); x11_setup ( display );
TICK_N ( "X11 Setup " )
// Sanity check // Sanity check
config_sanity_check ( display ); config_sanity_check ( display );
TICK_N ( "Config sanity check" )
// Dump. // Dump.
// catch help request // catch help request
if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) { if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) {
@ -2268,7 +2361,7 @@ int main ( int argc, char *argv[] )
} }
// Parse the keybindings. // Parse the keybindings.
parse_keys_abe (); parse_keys_abe ();
TICK_N ( "Parse ABE" )
char *msg = NULL; char *msg = NULL;
if ( find_arg_str ( "-e", &( msg ) ) ) { if ( find_arg_str ( "-e", &( msg ) ) ) {
int markup = FALSE; int markup = FALSE;
@ -2278,6 +2371,12 @@ int main ( int argc, char *argv[] )
return show_error_message ( msg, markup ); return show_error_message ( msg, markup );
} }
// Create thread pool
tpool = g_thread_pool_new ( call_thread, NULL, config.threads, FALSE, NULL );
g_thread_pool_set_max_idle_time ( 60000 );
g_thread_pool_set_max_unused_threads ( config.threads );
TICK_N ( "Setup Threadpool" )
// Dmenu mode. // Dmenu mode.
if ( dmenu_mode == TRUE ) { if ( dmenu_mode == TRUE ) {
normal_window_mode = find_arg ( "-normal-window" ) >= 0; normal_window_mode = find_arg ( "-normal-window" ) >= 0;