shada: Use pre-populated set of buffers on removable media

Should be faster then constantly running shada_removable for each buffer many
times.
This commit is contained in:
ZyX 2015-07-04 17:55:58 +03:00
parent 75c9a7e65b
commit 4eeafe7f72

View File

@ -200,6 +200,27 @@ typedef struct {
RINGBUF_INIT(HM, hm, ShadaEntry, shada_free_shada_entry) RINGBUF_INIT(HM, hm, ShadaEntry, shada_free_shada_entry)
/// Check whether buffer is in the given set
///
/// @param[in] set Set to check within.
/// @param[in] buf Buffer to find.
///
/// @return true or false.
static inline bool in_bufset(const khash_t(bufset) *const set, const buf_T *buf)
FUNC_ATTR_PURE
{
return kh_get(bufset, set, (uintptr_t) buf) != kh_end(set);
}
/// Check whether buffer is on removable media
///
/// Uses pre-populated set with buffers on removable media named removable_bufs.
///
/// @param[in] buf Buffer to check.
///
/// @return true or false.
#define SHADA_REMOVABLE(buf) in_bufset(removable_bufs, buf)
/// Msgpack callback for writing to FILE* /// Msgpack callback for writing to FILE*
static int msgpack_fbuffer_write(void *data, const char *buf, size_t len) static int msgpack_fbuffer_write(void *data, const char *buf, size_t len)
{ {
@ -720,7 +741,7 @@ static void shada_read(FILE *const fp, const int flags)
} }
FOR_ALL_TAB_WINDOWS(tp, wp) { FOR_ALL_TAB_WINDOWS(tp, wp) {
(void) tp; (void) tp;
if (kh_get(bufset, cl_bufs, (uintptr_t) wp->w_buffer) != kh_end(cl_bufs)) { if (in_bufset(cl_bufs, wp->w_buffer)) {
wp->w_changelistidx = wp->w_buffer->b_changelistlen; wp->w_changelistidx = wp->w_buffer->b_changelistlen;
} }
} }
@ -1031,6 +1052,7 @@ static void shada_pack_entry(msgpack_packer *const packer,
static void shada_write(FILE *const newfp, FILE *const oldfp) static void shada_write(FILE *const newfp, FILE *const oldfp)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(1)
{ {
khash_t(bufset) *const removable_bufs = kh_init(bufset);
int max_kbyte_i = get_viminfo_parameter('s'); int max_kbyte_i = get_viminfo_parameter('s');
if (max_kbyte_i < 0) { if (max_kbyte_i < 0) {
max_kbyte_i = 10; max_kbyte_i = 10;
@ -1042,6 +1064,13 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
msgpack_packer *packer = msgpack_packer_new(newfp, &msgpack_fbuffer_write); msgpack_packer *packer = msgpack_packer_new(newfp, &msgpack_fbuffer_write);
FOR_ALL_BUFFERS(buf) {
if (buf->b_ffname != NULL && shada_removable((char *) buf->b_ffname)) {
int kh_ret;
(void) kh_put(bufset, removable_bufs, (uintptr_t) buf, &kh_ret);
}
}
// First write values that do not require merging // First write values that do not require merging
// 1. Header // 1. Header
shada_pack_entry(packer, (ShadaEntry) { shada_pack_entry(packer, (ShadaEntry) {
@ -1074,13 +1103,13 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
size_t buf_count = 0; size_t buf_count = 0;
FOR_ALL_BUFFERS(buf) { FOR_ALL_BUFFERS(buf) {
if (buf->b_ffname != NULL && !shada_removable(buf->b_ffname)) { if (buf->b_ffname != NULL && !SHADA_REMOVABLE(buf)) {
buf_count++; buf_count++;
} }
} }
msgpack_pack_array(packer, buf_count); msgpack_pack_array(packer, buf_count);
FOR_ALL_BUFFERS(buf) { FOR_ALL_BUFFERS(buf) {
if (buf->b_ffname == NULL || shada_removable(buf->b_ffname)) { if (buf->b_ffname == NULL || SHADA_REMOVABLE(buf)) {
continue; continue;
} }
msgpack_pack_map(packer, 3); msgpack_pack_map(packer, 3);
@ -1107,7 +1136,7 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
? NULL ? NULL
: buflist_findnr(fm.fmark.fnum)); : buflist_findnr(fm.fmark.fnum));
if (buf != NULL if (buf != NULL
? shada_removable(buf->b_ffname) ? SHADA_REMOVABLE(buf)
: fm.fmark.fnum != 0) { : fm.fmark.fnum != 0) {
continue; continue;
} }
@ -1219,8 +1248,9 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
// 7. Global marks // 7. Global marks
if (get_viminfo_parameter('f') != 0) { if (get_viminfo_parameter('f') != 0) {
ShadaEntry *const global_marks = list_global_marks(); ShadaEntry *const global_marks = list_global_marks(removable_bufs);
for (ShadaEntry *mark = global_marks; mark->type != kSDItemMissing; mark++) { for (ShadaEntry *mark = global_marks; mark->type != kSDItemMissing;
mark++) {
shada_pack_entry(packer, *mark, max_kbyte); shada_pack_entry(packer, *mark, max_kbyte);
} }
xfree(global_marks); xfree(global_marks);
@ -1228,7 +1258,7 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
// 8. Buffer marks and buffer change list // 8. Buffer marks and buffer change list
FOR_ALL_BUFFERS(buf) { FOR_ALL_BUFFERS(buf) {
if (buf->b_ffname == NULL || shada_removable(buf->b_ffname)) { if (buf->b_ffname == NULL || SHADA_REMOVABLE(buf)) {
continue; continue;
} }
ShadaEntry *const buffer_marks = list_buffer_marks(buf); ShadaEntry *const buffer_marks = list_buffer_marks(buf);
@ -1300,6 +1330,7 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
} while (var_iter != NULL); } while (var_iter != NULL);
} }
kh_destroy(bufset, removable_bufs);
msgpack_packer_free(packer); msgpack_packer_free(packer);
} }
@ -2280,11 +2311,14 @@ shada_read_next_item_end:
/// @warning Listed marks must be used before any buffer- or mark-editing /// @warning Listed marks must be used before any buffer- or mark-editing
/// function is run. /// function is run.
/// ///
/// @param[in] removable_bufs Set of buffers on removable media.
///
/// @return Array of ShadaEntry values, last one has type kSDItemMissing. /// @return Array of ShadaEntry values, last one has type kSDItemMissing.
/// ///
/// @warning Resulting ShadaEntry values must not be freed. Returned /// @warning Resulting ShadaEntry values must not be freed. Returned
/// array must be freed with `xfree()`. /// array must be freed with `xfree()`.
static ShadaEntry *list_global_marks(void) static ShadaEntry *list_global_marks(
const khash_t(bufset) *const removable_bufs)
{ {
const void *iter = NULL; const void *iter = NULL;
const size_t nummarks = mark_global_amount(); const size_t nummarks = mark_global_amount();
@ -2299,24 +2333,19 @@ static ShadaEntry *list_global_marks(void)
cur->data.filemark.additional_data = cur_fm.fmark.additional_data; cur->data.filemark.additional_data = cur_fm.fmark.additional_data;
cur->timestamp = cur_fm.fmark.timestamp; cur->timestamp = cur_fm.fmark.timestamp;
if (cur_fm.fmark.fnum == 0) { if (cur_fm.fmark.fnum == 0) {
cur->data.filemark.fname = (char *) (cur_fm.fname == NULL if (cur_fm.fname == NULL) {
? NULL continue;
: cur_fm.fname); }
cur->data.filemark.fname = (char *) cur_fm.fname;
} else { } else {
const buf_T *const buf = buflist_findnr(cur_fm.fmark.fnum); const buf_T *const buf = buflist_findnr(cur_fm.fmark.fnum);
if (buf == NULL) { if (buf == NULL || buf->b_ffname == NULL || SHADA_REMOVABLE(buf)) {
continue; continue;
} else { } else {
cur->data.filemark.fname = (char *) buf->b_ffname; cur->data.filemark.fname = (char *) buf->b_ffname;
} }
} }
if (cur->data.filemark.fname != NULL) { cur++;
if (shada_removable(cur->data.filemark.fname)) {
continue;
} else {
cur++;
}
}
} while(iter != NULL); } while(iter != NULL);
} }
cur->type = kSDItemMissing; cur->type = kSDItemMissing;