Add threading support.

This commit is contained in:
Dave Davenport 2015-11-12 00:18:43 +01:00
parent 086449b433
commit 0fe524d0cd
4 changed files with 134 additions and 80 deletions

View File

@ -148,4 +148,5 @@ Settings config = {
.fullscreen = FALSE,
.fake_transparency = FALSE,
.dpi = -1,
.threads = 1,
};

View File

@ -252,6 +252,8 @@ typedef struct _Settings
unsigned int fake_transparency;
/** dpi */
int dpi;
/** Number threads (1 to disable) */
unsigned int threads;
} Settings;
/** Global Settings structure. */

View File

@ -705,25 +705,75 @@ static void menu_mouse_navigation ( MenuState *state, XButtonEvent *xbe )
}
}
typedef struct
{
MenuState *state;
char **tokens;
unsigned int start;
unsigned int stop;
unsigned int count;
}thread_state;
static gpointer filter_elements ( gpointer data )
{
thread_state *t = (thread_state *) data;
// input changed
for ( unsigned int i = t->start; i < t->stop; i++ ) {
int match = t->state->sw->token_match ( t->tokens,
t->state->lines[i],
t->state->lines_not_ascii[i],
config.case_sensitive,
i,
t->state->sw );
// If each token was matched, add it to list.
if ( match ) {
t->state->line_map[t->start + t->count] = i;
if ( config.levenshtein_sort ) {
t->state->distance[i] = levenshtein ( t->state->text->text, t->state->lines[i] );
}
t->count++;
}
}
return 0;
}
static void menu_refilter ( MenuState *state )
{
if ( strlen ( state->text->text ) > 0 ) {
unsigned int j = 0;
char **tokens = tokenize ( state->text->text, config.case_sensitive );
// input changed
for ( unsigned int i = 0; i < state->num_lines; i++ ) {
int match = state->sw->token_match ( tokens, state->lines[i], state->lines_not_ascii[i], config.case_sensitive, i, state->sw );
// If each token was matched, add it to list.
if ( match ) {
state->line_map[j] = i;
if ( config.levenshtein_sort ) {
state->distance[i] = levenshtein ( state->text->text, state->lines[i] );
}
j++;
/**
* On long lists it can be beneficial to parallelize.
* If number of threads is 1, no thread is spawn.
* If number of threads > 1 and there are enough (> 20000) items, spawn threads.
* For large lists with 8 threads I see a factor three speedup of the whole function.
*/
unsigned int nt = MIN ( state->num_lines / 1000, config.threads );
thread_state states[nt];
GThread *threads[nt];
unsigned int steps = ( state->num_lines + nt ) / nt;
for ( unsigned int i = 0; i < nt; i++ ) {
states[i].state = state;
states[i].tokens = tokens;
states[i].start = i * steps;
states[i].stop = MIN ( state->num_lines, ( i + 1 ) * steps );
states[i].count = 0;
if ( i > 0 ) {
threads[i] = g_thread_new ( NULL, filter_elements, &( states[i] ) );
}
}
// Run one in this thread.
filter_elements ( &states[0] );
for ( unsigned int i = 1; i < nt; i++ ) {
g_thread_join ( threads[i] );
}
for ( unsigned int i = 0; i < nt; i++ ) {
if ( j != states[i].start ) {
memcpy ( &( state->line_map[j] ), &( state->line_map[states[i].start] ), sizeof ( unsigned int ) * ( states[i].count ) );
}
j += states[i].count;
}
if ( config.levenshtein_sort ) {
g_qsort_with_data ( state->line_map, j, sizeof ( int ), lev_sort, state->distance );
}

View File

@ -55,88 +55,89 @@ typedef struct
* Currently supports string, boolean and number (signed and unsigned).
*/
static XrmOption xrmOptions[] = {
{ xrm_String, "switchers", { .str = &config.switchers }, NULL, "" },
{ xrm_String, "modi", { .str = &config.switchers }, NULL, "Enabled modi" },
{ xrm_Number, "opacity", { .num = &config.window_opacity }, NULL, "Window opacity" },
{ xrm_SNumber, "width", { .snum = &config.menu_width }, NULL, "Window width" },
{ xrm_Number, "lines", { .num = &config.menu_lines }, NULL, "Number of lines" },
{ xrm_Number, "columns", { .num = &config.menu_columns }, NULL, "Number of columns" },
{ xrm_String, "switchers", { .str = &config.switchers }, NULL, "" },
{ xrm_String, "modi", { .str = &config.switchers }, NULL, "Enabled modi" },
{ xrm_Number, "opacity", { .num = &config.window_opacity }, NULL, "Window opacity" },
{ xrm_SNumber, "width", { .snum = &config.menu_width }, NULL, "Window width" },
{ xrm_Number, "lines", { .num = &config.menu_lines }, NULL, "Number of lines" },
{ xrm_Number, "columns", { .num = &config.menu_columns }, NULL, "Number of columns" },
{ xrm_String, "font", { .str = &config.menu_font }, NULL, "Font to use" },
{ xrm_String, "font", { .str = &config.menu_font }, NULL, "Font to use" },
/* Foreground color */
{ xrm_String, "foreground", { .str = &config.menu_fg }, NULL, "" },
{ xrm_String, "fg", { .str = &config.menu_fg }, NULL, "Foreground color" },
{ xrm_String, "background", { .str = &config.menu_bg }, NULL, "" },
{ xrm_String, "bg", { .str = &config.menu_bg }, NULL, "Background color" },
{ xrm_String, "foreground", { .str = &config.menu_fg }, NULL, "" },
{ xrm_String, "fg", { .str = &config.menu_fg }, NULL, "Foreground color" },
{ xrm_String, "background", { .str = &config.menu_bg }, NULL, "" },
{ xrm_String, "bg", { .str = &config.menu_bg }, NULL, "Background color" },
{ xrm_String, "fg-active", { .str = &config.menu_fg_active }, NULL, "Foreground color for active row" },
{ xrm_String, "fg-urgent", { .str = &config.menu_fg_urgent }, NULL, "Foreground color for urgent row" },
{ xrm_String, "hlfg-active", { .str = &config.menu_hlfg_active }, NULL, "Foreground color for highlighted active row" },
{ xrm_String, "hlfg-urgent", { .str = &config.menu_hlfg_urgent }, NULL, "Foreground color for highlighted urgent row" },
{ xrm_String, "fg-active", { .str = &config.menu_fg_active }, NULL, "Foreground color for active row" },
{ xrm_String, "fg-urgent", { .str = &config.menu_fg_urgent }, NULL, "Foreground color for urgent row" },
{ xrm_String, "hlfg-active", { .str = &config.menu_hlfg_active }, NULL, "Foreground color for highlighted active row" },
{ xrm_String, "hlfg-urgent", { .str = &config.menu_hlfg_urgent }, NULL, "Foreground color for highlighted urgent row" },
{ xrm_String, "bg-active", { .str = &config.menu_bg_active }, NULL, "Background color for active row" },
{ xrm_String, "bg-urgent", { .str = &config.menu_bg_urgent }, NULL, "Background color for urgent row" },
{ xrm_String, "hlbg-active", { .str = &config.menu_hlbg_active }, NULL, "Background color for highlighted active row" },
{ xrm_String, "hlbg-urgent", { .str = &config.menu_hlbg_urgent }, NULL, "Background color for highlighted urgent row" },
{ xrm_String, "bg-active", { .str = &config.menu_bg_active }, NULL, "Background color for active row" },
{ xrm_String, "bg-urgent", { .str = &config.menu_bg_urgent }, NULL, "Background color for urgent row" },
{ xrm_String, "hlbg-active", { .str = &config.menu_hlbg_active }, NULL, "Background color for highlighted active row" },
{ xrm_String, "hlbg-urgent", { .str = &config.menu_hlbg_urgent }, NULL, "Background color for highlighted urgent row" },
{ xrm_String, "background-alternate", { .str = &config.menu_bg_alt }, NULL, "" },
{ xrm_String, "bgalt", { .str = &config.menu_bg_alt }, NULL, "Background color for alternating row" },
{ xrm_String, "background-alternate", { .str = &config.menu_bg_alt }, NULL, "" },
{ xrm_String, "bgalt", { .str = &config.menu_bg_alt }, NULL, "Background color for alternating row" },
{ xrm_String, "highlightfg", { .str = &config.menu_hlfg }, NULL, "" },
{ xrm_String, "hlfg", { .str = &config.menu_hlfg }, NULL, "Foreground color for highlighted row" },
{ xrm_String, "highlightfg", { .str = &config.menu_hlfg }, NULL, "" },
{ xrm_String, "hlfg", { .str = &config.menu_hlfg }, NULL, "Foreground color for highlighted row" },
{ xrm_String, "highlightbg", { .str = &config.menu_hlbg }, NULL, "" },
{ xrm_String, "hlbg", { .str = &config.menu_hlbg }, NULL, "Background color for highlighted row" },
{ xrm_String, "highlightbg", { .str = &config.menu_hlbg }, NULL, "" },
{ xrm_String, "hlbg", { .str = &config.menu_hlbg }, NULL, "Background color for highlighted row" },
{ xrm_String, "bordercolor", { .str = &config.menu_bc }, NULL, "" },
{ xrm_String, "bc", { .str = &config.menu_bc }, NULL, "Border color" },
{ xrm_Boolean, "color-enabled", { .num = &config.color_enabled }, NULL, "Use extended color scheme" },
{ xrm_String, "color-normal", { .str = &config.color_normal }, NULL, "Color scheme for normal row" },
{ xrm_String, "color-urgent", { .str = &config.color_urgent }, NULL, "Color scheme for urgent row" },
{ xrm_String, "color-active", { .str = &config.color_active }, NULL, "Color scheme for active row" },
{ xrm_String, "color-window", { .str = &config.color_window }, NULL, "Color scheme window" },
{ xrm_String, "bordercolor", { .str = &config.menu_bc }, NULL, "" },
{ xrm_String, "bc", { .str = &config.menu_bc }, NULL, "Border color" },
{ xrm_Boolean, "color-enabled", { .num = &config.color_enabled }, NULL, "Use extended color scheme" },
{ xrm_String, "color-normal", { .str = &config.color_normal }, NULL, "Color scheme for normal row" },
{ xrm_String, "color-urgent", { .str = &config.color_urgent }, NULL, "Color scheme for urgent row" },
{ xrm_String, "color-active", { .str = &config.color_active }, NULL, "Color scheme for active row" },
{ xrm_String, "color-window", { .str = &config.color_window }, NULL, "Color scheme window" },
{ xrm_Number, "borderwidth", { .num = &config.menu_bw }, NULL, "" },
{ xrm_Number, "bw", { .num = &config.menu_bw }, NULL, "Border width" },
{ xrm_Number, "borderwidth", { .num = &config.menu_bw }, NULL, "" },
{ xrm_Number, "bw", { .num = &config.menu_bw }, NULL, "Border width" },
{ xrm_Number, "location", { .num = &config.location }, NULL, "Location on screen" },
{ xrm_Number, "location", { .num = &config.location }, NULL, "Location on screen" },
{ xrm_Number, "padding", { .num = &config.padding }, NULL, "Padding" },
{ xrm_SNumber, "yoffset", { .snum = &config.y_offset }, NULL, "Y-offset relative to location" },
{ xrm_SNumber, "xoffset", { .snum = &config.x_offset }, NULL, "X-offset relative to location" },
{ xrm_Boolean, "fixed-num-lines", { .num = &config.fixed_num_lines }, NULL, "Always show number of lines" },
{ xrm_Number, "padding", { .num = &config.padding }, NULL, "Padding" },
{ xrm_SNumber, "yoffset", { .snum = &config.y_offset }, NULL, "Y-offset relative to location" },
{ xrm_SNumber, "xoffset", { .snum = &config.x_offset }, NULL, "X-offset relative to location" },
{ xrm_Boolean, "fixed-num-lines", { .num = &config.fixed_num_lines }, NULL, "Always show number of lines" },
{ xrm_String, "terminal", { .str = &config.terminal_emulator }, NULL, "Terminal to use" },
{ xrm_String, "ssh-client", { .str = &config.ssh_client }, NULL, "Ssh client to use" },
{ xrm_String, "ssh-command", { .str = &config.ssh_command }, NULL, "Ssh command to execute" },
{ xrm_String, "run-command", { .str = &config.run_command }, NULL, "Run command to execute" },
{ xrm_String, "run-list-command", { .str = &config.run_list_command }, NULL, "Command to get extra run targets" },
{ xrm_String, "run-shell-command", { .str = &config.run_shell_command }, NULL, "Run command to execute that runs in shell" },
{ xrm_String, "terminal", { .str = &config.terminal_emulator }, NULL, "Terminal to use" },
{ xrm_String, "ssh-client", { .str = &config.ssh_client }, NULL, "Ssh client to use" },
{ xrm_String, "ssh-command", { .str = &config.ssh_command }, NULL, "Ssh command to execute" },
{ xrm_String, "run-command", { .str = &config.run_command }, NULL, "Run command to execute" },
{ xrm_String, "run-list-command", { .str = &config.run_list_command }, NULL, "Command to get extra run targets" },
{ xrm_String, "run-shell-command", { .str = &config.run_shell_command }, NULL, "Run command to execute that runs in shell" },
{ xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL, "Disable history in run/ssh" },
{ xrm_Boolean, "levenshtein-sort", { .num = &config.levenshtein_sort }, NULL, "Use levenshtein sorting" },
{ xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL, "Set case-sensitivity" },
{ xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL, "Enable sidebar-mode" },
{ xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL, "Set lazy filter limit" },
{ xrm_SNumber, "eh", { .snum = &config.element_height }, NULL, "Row height (in chars)" },
{ xrm_Boolean, "auto-select", { .num = &config.auto_select }, NULL, "Enable auto select mode" },
{ xrm_Boolean, "parse-hosts", { .num = &config.parse_hosts }, NULL, "Parse hosts file for ssh mode" },
{ xrm_Boolean, "parse-known-hosts", { .num = &config.parse_known_hosts }, NULL, "Parse known_hosts file for ssh mode" },
{ xrm_String, "combi-modi", { .str = &config.combi_modi }, NULL, "Set the modi to combine in combi mode" },
{ xrm_Boolean, "fuzzy", { .num = &config.fuzzy }, NULL, "Do a more fuzzy matching" },
{ xrm_Boolean, "glob", { .num = &config.glob }, NULL, "Use glob matching" },
{ xrm_Boolean, "tokenize", { .num = &config.tokenize }, NULL, "Tokenize input string" },
{ xrm_Number, "monitor", { .snum = &config.monitor }, NULL, "" },
{ xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL, "Disable history in run/ssh" },
{ xrm_Boolean, "levenshtein-sort", { .num = &config.levenshtein_sort }, NULL, "Use levenshtein sorting" },
{ xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL, "Set case-sensitivity" },
{ xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL, "Enable sidebar-mode" },
{ xrm_Number, "lazy-filter-limit", { .num = &config.lazy_filter_limit }, NULL, "Set lazy filter limit" },
{ xrm_SNumber, "eh", { .snum = &config.element_height }, NULL, "Row height (in chars)" },
{ xrm_Boolean, "auto-select", { .num = &config.auto_select }, NULL, "Enable auto select mode" },
{ xrm_Boolean, "parse-hosts", { .num = &config.parse_hosts }, NULL, "Parse hosts file for ssh mode" },
{ xrm_Boolean, "parse-known-hosts", { .num = &config.parse_known_hosts }, NULL, "Parse known_hosts file for ssh mode" },
{ xrm_String, "combi-modi", { .str = &config.combi_modi }, NULL, "Set the modi to combine in combi mode" },
{ xrm_Boolean, "fuzzy", { .num = &config.fuzzy }, NULL, "Do a more fuzzy matching" },
{ xrm_Boolean, "glob", { .num = &config.glob }, NULL, "Use glob matching" },
{ xrm_Boolean, "tokenize", { .num = &config.tokenize }, NULL, "Tokenize input string" },
{ xrm_Number, "monitor", { .snum = &config.monitor }, NULL, "" },
/* Alias for dmenu compatibility. */
{ xrm_SNumber, "m", { .snum = &config.monitor }, NULL, "Monitor id to show on" },
{ xrm_Number, "line-margin", { .num = &config.line_margin }, NULL, "Margin between rows" },
{ xrm_String, "filter", { .str = &config.filter }, NULL, "Pre-set filter" },
{ xrm_String, "separator-style", { .str = &config.separator_style }, NULL, "Separator style (none, dash, solid)" },
{ xrm_Boolean, "hide-scrollbar", { .num = &config.hide_scrollbar }, NULL, "Hide scroll-bar" },
{ xrm_Boolean, "markup-rows", { .num = &config.markup_rows }, NULL, "Show markup" },
{ xrm_Boolean, "fullscreen", { .num = &config.fullscreen }, NULL, "Fullscreen" },
{ xrm_Boolean, "fake-transparency", { .num = &config.fake_transparency }, NULL, "Fake transparency" },
{ xrm_SNumber, "dpi", { .snum = &config.dpi }, NULL, "DPI" }
{ xrm_SNumber, "m", { .snum = &config.monitor }, NULL, "Monitor id to show on" },
{ xrm_Number, "line-margin", { .num = &config.line_margin }, NULL, "Margin between rows" },
{ xrm_String, "filter", { .str = &config.filter }, NULL, "Pre-set filter" },
{ xrm_String, "separator-style", { .str = &config.separator_style }, NULL, "Separator style (none, dash, solid)" },
{ xrm_Boolean, "hide-scrollbar", { .num = &config.hide_scrollbar }, NULL, "Hide scroll-bar" },
{ xrm_Boolean, "markup-rows", { .num = &config.markup_rows }, NULL, "Show markup" },
{ xrm_Boolean, "fullscreen", { .num = &config.fullscreen }, NULL, "Fullscreen" },
{ xrm_Boolean, "fake-transparency", { .num = &config.fake_transparency }, NULL, "Fake transparency" },
{ xrm_SNumber, "dpi", { .snum = &config.dpi }, NULL, "DPI" },
{ xrm_Number, "threads", { .num = &config.threads }, NULL, "Threads to use for string matching" }
};
// Dynamic options.