mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
file_stream: solidify retry mechanism; df: multiline controls for text_cache-based info, begin porting over txti-based systems
This commit is contained in:
@@ -168,6 +168,7 @@
|
||||
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
|
||||
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
|
||||
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c)
|
||||
# define ins_atomic_u32_eval(x,c) InterlockedAdd((volatile LONG *)(x), 0)
|
||||
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
|
||||
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c))
|
||||
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile __int64 *)(x), (__int64)(c))
|
||||
|
||||
@@ -10570,6 +10570,183 @@ df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF
|
||||
return sig;
|
||||
}
|
||||
|
||||
internal B32
|
||||
df_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
B32 change = 0;
|
||||
UI_NavActionList *nav_actions = ui_nav_actions();
|
||||
for(UI_NavActionNode *n = nav_actions->first, *next = 0; n != 0; n = next)
|
||||
{
|
||||
next = n->next;
|
||||
B32 taken = 0;
|
||||
|
||||
String8 line = txt_string_from_info_data_line_num(info, data, cursor->line);
|
||||
UI_NavTxtOp single_line_op = ui_nav_single_line_txt_op_from_action(scratch.arena, n->v, line, *cursor, *mark);
|
||||
|
||||
//- rjf: invalid single-line op or endpoint units => try multiline
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_EndPoint || single_line_op.flags & UI_NavTxtOpFlag_Invalid)
|
||||
{
|
||||
U64 line_count = info->lines_count;
|
||||
String8 prev_line = txt_string_from_info_data_line_num(info, data, cursor->line-1);
|
||||
String8 next_line = txt_string_from_info_data_line_num(info, data, cursor->line+1);
|
||||
Vec2S32 delta = n->v.delta;
|
||||
|
||||
//- rjf: wrap lines right
|
||||
if(n->v.delta_unit != UI_NavDeltaUnit_EndPoint && delta.x > 0 && cursor->column == line.size+1 && cursor->line+1 <= line_count)
|
||||
{
|
||||
cursor->line += 1;
|
||||
cursor->column = 1;
|
||||
*preferred_column = 1;
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: wrap lines left
|
||||
if(n->v.delta_unit != UI_NavDeltaUnit_EndPoint && delta.x < 0 && cursor->column == 1 && cursor->line-1 >= 1)
|
||||
{
|
||||
cursor->line -= 1;
|
||||
cursor->column = prev_line.size+1;
|
||||
*preferred_column = prev_line.size+1;
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement down (plain)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_Element && delta.y > 0 && cursor->line+1 <= line_count)
|
||||
{
|
||||
cursor->line += 1;
|
||||
cursor->column = Min(*preferred_column, next_line.size+1);
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement up (plain)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_Element && delta.y < 0 && cursor->line-1 >= 1)
|
||||
{
|
||||
cursor->line -= 1;
|
||||
cursor->column = Min(*preferred_column, prev_line.size+1);
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement down (chunk)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_Chunk && delta.y > 0 && cursor->line+1 <= line_count)
|
||||
{
|
||||
for(S64 line_num = cursor->line+1; line_num <= line_count; line_num += 1)
|
||||
{
|
||||
String8 line = txt_string_from_info_data_line_num(info, data, line_num);
|
||||
U64 line_size = line.size;
|
||||
if(line_size == 0)
|
||||
{
|
||||
cursor->line = line_num;
|
||||
cursor->column = 1;
|
||||
break;
|
||||
}
|
||||
else if(line_num == line_count)
|
||||
{
|
||||
cursor->line = line_num;
|
||||
cursor->column = line_size+1;
|
||||
}
|
||||
}
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement up (chunk)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_Chunk && delta.y < 0 && cursor->line-1 >= 1)
|
||||
{
|
||||
for(S64 line_num = cursor->line-1; line_num > 0; line_num -= 1)
|
||||
{
|
||||
String8 line = txt_string_from_info_data_line_num(info, data, line_num);
|
||||
U64 line_size = line.size;
|
||||
if(line_size == 0)
|
||||
{
|
||||
cursor->line = line_num;
|
||||
cursor->column = 1;
|
||||
break;
|
||||
}
|
||||
else if(line_num == 1)
|
||||
{
|
||||
cursor->line = line_num;
|
||||
cursor->column = 1;
|
||||
}
|
||||
}
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement down (page)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_Whole && delta.y > 0)
|
||||
{
|
||||
cursor->line += line_count_per_page;
|
||||
cursor->column = 1;
|
||||
cursor->line = Clamp(1, cursor->line, line_count);
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement up (page)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_Whole && delta.y < 0)
|
||||
{
|
||||
cursor->line -= line_count_per_page;
|
||||
cursor->column = 1;
|
||||
cursor->line = Clamp(1, cursor->line, line_count);
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement to endpoint (+)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_EndPoint && (delta.y > 0 || delta.x > 0))
|
||||
{
|
||||
*cursor = txt_pt(line_count, info->lines_count ? dim_1u64(info->lines_ranges[info->lines_count-1])+1 : 1);
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: movement to endpoint (-)
|
||||
if(n->v.delta_unit == UI_NavDeltaUnit_EndPoint && (delta.y < 0 || delta.x < 0))
|
||||
{
|
||||
*cursor = txt_pt(1, 1);
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: stick mark to cursor, when we don't want to keep it in the same spot
|
||||
if(!(n->v.flags & UI_NavActionFlag_KeepMark))
|
||||
{
|
||||
*mark = *cursor;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: valid single-line op => do single-line op
|
||||
else
|
||||
{
|
||||
*cursor = single_line_op.cursor;
|
||||
*mark = single_line_op.mark;
|
||||
*preferred_column = cursor->column;
|
||||
change = 1;
|
||||
taken = 1;
|
||||
}
|
||||
|
||||
//- rjf: copy
|
||||
if(n->v.flags & UI_NavActionFlag_Copy)
|
||||
{
|
||||
String8 text = txt_string_from_info_data_txt_rng(info, data, txt_rng(*cursor, *mark));
|
||||
os_set_clipboard_text(text);
|
||||
}
|
||||
|
||||
//- rjf: consume
|
||||
if(taken)
|
||||
{
|
||||
ui_nav_eat_action_node(nav_actions, n);
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return change;
|
||||
}
|
||||
|
||||
internal B32
|
||||
df_do_txti_controls(TXTI_Handle handle, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column)
|
||||
{
|
||||
|
||||
@@ -1046,6 +1046,7 @@ internal UI_BOX_CUSTOM_DRAW(df_bp_box_draw_extensions);
|
||||
internal DF_CodeSliceSignal df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string);
|
||||
internal DF_CodeSliceSignal df_code_slicef(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...);
|
||||
|
||||
internal B32 df_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column);
|
||||
internal B32 df_do_txti_controls(TXTI_Handle handle, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column);
|
||||
internal B32 df_do_dasm_controls(DASM_Handle handle, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column);
|
||||
|
||||
|
||||
@@ -5503,8 +5503,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
|
||||
{
|
||||
if(text_info_is_ready && visible_line_num_range.max >= visible_line_num_range.min && ui_is_focus_active())
|
||||
{
|
||||
// TODO(rjf): @txt
|
||||
//snap[Axis2_X] = snap[Axis2_Y] = df_do_txti_controls(txti_handle, ClampBot(num_possible_visible_lines, 10) - 10, &tv->cursor, &tv->mark, &tv->preferred_column);
|
||||
snap[Axis2_X] = snap[Axis2_Y] = df_do_txt_controls(&text_info, data, ClampBot(num_possible_visible_lines, 10) - 10, &tv->cursor, &tv->mark, &tv->preferred_column);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,10 +73,10 @@ fs_hash_from_path(String8 path, U64 endt_us)
|
||||
SLLQueuePush(slot->first, slot->last, node);
|
||||
node->path = push_str8_copy(stripe->arena, path);
|
||||
}
|
||||
if(os_now_microseconds() >= ins_atomic_u64_eval(&node->last_time_requested_us)+1000000 &&
|
||||
fs_u2s_enqueue_path(path, endt_us))
|
||||
if(!ins_atomic_u32_eval_cond_assign(&node->is_working, 1, 0) &&
|
||||
!fs_u2s_enqueue_path(path, endt_us))
|
||||
{
|
||||
ins_atomic_u64_eval_assign(&node->last_time_requested_us, os_now_microseconds());
|
||||
ins_atomic_u32_eval_assign(&node->is_working, 0);
|
||||
}
|
||||
result = hs_hash_from_key(path_key, 0);
|
||||
if(u128_match(result, u128_zero()) && os_now_microseconds() <= endt_us)
|
||||
@@ -161,47 +161,75 @@ fs_streamer_thread__entry_point(void *p)
|
||||
for(;;)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
//- rjf: unpack path
|
||||
String8 path = fs_u2s_dequeue_path(scratch.arena);
|
||||
U128 key = hs_hash_from_data(path);
|
||||
U64 slot_idx = key.u64[0]%fs_shared->slots_count;
|
||||
U64 stripe_idx = slot_idx%fs_shared->stripes_count;
|
||||
FS_Slot *slot = &fs_shared->slots[slot_idx];
|
||||
FS_Stripe *stripe = &fs_shared->stripes[stripe_idx];
|
||||
|
||||
//- rjf: load
|
||||
ProfBegin("load \"%.*s\"", str8_varg(path));
|
||||
FileProperties pre_props = os_properties_from_file_path(path);
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite, path);
|
||||
U64 data_arena_size = pre_props.size+ARENA_HEADER_SIZE;
|
||||
data_arena_size += KB(4)-1;
|
||||
data_arena_size -= data_arena_size%KB(4);
|
||||
ProfBegin("allocate");
|
||||
Arena *data_arena = arena_alloc__sized(data_arena_size, data_arena_size);
|
||||
ProfEnd();
|
||||
ProfBegin("read");
|
||||
String8 data = os_string_from_file_range(data_arena, file, r1u64(0, pre_props.size));
|
||||
ProfEnd();
|
||||
os_file_close(file);
|
||||
FileProperties post_props = os_properties_from_file_path(path);
|
||||
|
||||
//- rjf: abort if modification timestamps differ - we did not successfully read the file
|
||||
if(pre_props.modified != post_props.modified)
|
||||
{
|
||||
arena_release(data_arena);
|
||||
MemoryZeroStruct(&data);
|
||||
ProfScope("abort")
|
||||
{
|
||||
arena_release(data_arena);
|
||||
MemoryZeroStruct(&data);
|
||||
data_arena = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: submit
|
||||
else
|
||||
{
|
||||
U128 key = hs_hash_from_data(path);
|
||||
hs_submit_data(key, &data_arena, data);
|
||||
U64 slot_idx = key.u64[0]%fs_shared->slots_count;
|
||||
U64 stripe_idx = slot_idx%fs_shared->stripes_count;
|
||||
FS_Slot *slot = &fs_shared->slots[slot_idx];
|
||||
FS_Stripe *stripe = &fs_shared->stripes[stripe_idx];
|
||||
OS_MutexScopeW(stripe->rw_mutex)
|
||||
ProfScope("submit")
|
||||
{
|
||||
FS_Node *node = 0;
|
||||
for(FS_Node *n = slot->first; n != 0; n = n->next)
|
||||
hs_submit_data(key, &data_arena, data);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: commit info to cache
|
||||
ProfScope("commit to cache") OS_MutexScopeW(stripe->rw_mutex)
|
||||
{
|
||||
FS_Node *node = 0;
|
||||
for(FS_Node *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(str8_match(n->path, path, 0))
|
||||
{
|
||||
if(str8_match(n->path, path, 0))
|
||||
{
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
if(node != 0)
|
||||
}
|
||||
if(node != 0)
|
||||
{
|
||||
if(post_props.modified == pre_props.modified)
|
||||
{
|
||||
node->timestamp = post_props.modified;
|
||||
}
|
||||
ins_atomic_u32_eval_assign(&node->is_working, 0);
|
||||
}
|
||||
os_condition_variable_broadcast(stripe->cv);
|
||||
}
|
||||
os_condition_variable_broadcast(stripe->cv);
|
||||
|
||||
ProfEnd();
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
@@ -226,9 +254,13 @@ fs_detector_thread__entry_point(void *p)
|
||||
for(FS_Node *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
FileProperties props = os_properties_from_file_path(n->path);
|
||||
if(props.modified != n->timestamp && n->last_time_requested_us+100000 < os_now_microseconds())
|
||||
if(props.modified != n->timestamp)
|
||||
{
|
||||
fs_u2s_enqueue_path(n->path, os_now_microseconds()+100000);
|
||||
if(!ins_atomic_u32_eval_cond_assign(&n->is_working, 1, 0) &&
|
||||
!fs_u2s_enqueue_path(n->path, os_now_microseconds()+100000))
|
||||
{
|
||||
ins_atomic_u32_eval_assign(&n->is_working, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ struct FS_Node
|
||||
FS_Node *next;
|
||||
String8 path;
|
||||
U64 timestamp;
|
||||
U64 last_time_requested_us;
|
||||
B32 is_working;
|
||||
};
|
||||
|
||||
typedef struct FS_Slot FS_Slot;
|
||||
|
||||
@@ -84,7 +84,7 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
|
||||
HS_Stripe *stripe = &hs_shared->stripes[stripe_idx];
|
||||
|
||||
//- rjf: commit data to cache - if already there, just bump key refcount
|
||||
OS_MutexScopeW(stripe->rw_mutex)
|
||||
ProfScope("commit data to cache - if already there, just bump key refcount") OS_MutexScopeW(stripe->rw_mutex)
|
||||
{
|
||||
HS_Node *existing_node = 0;
|
||||
for(HS_Node *n = slot->first; n != 0; n = n->next)
|
||||
@@ -123,7 +123,7 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
|
||||
|
||||
//- rjf: commit this hash to key cache
|
||||
U128 key_expired_hash = {0};
|
||||
OS_MutexScopeW(key_stripe->rw_mutex)
|
||||
ProfScope("commit this hash to key cache") OS_MutexScopeW(key_stripe->rw_mutex)
|
||||
{
|
||||
HS_KeyNode *key_node = 0;
|
||||
for(HS_KeyNode *n = key_slot->first; n != 0; n = n->next)
|
||||
@@ -152,7 +152,8 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
|
||||
}
|
||||
|
||||
//- rjf: if this key's history cache was full, dec key ref count of oldest hash
|
||||
if(!u128_match(key_expired_hash, u128_zero()))
|
||||
ProfScope("if this key's history cache was full, dec key ref count of oldest hash")
|
||||
if(!u128_match(key_expired_hash, u128_zero()))
|
||||
{
|
||||
U64 old_hash_slot_idx = key_expired_hash.u64[1]%hs_shared->slots_count;
|
||||
U64 old_hash_stripe_idx = old_hash_slot_idx%hs_shared->stripes_count;
|
||||
|
||||
@@ -1037,6 +1037,17 @@ txt_string_from_info_data_txt_rng(TXT_TextInfo *info, String8 data, TxtRng rng)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
txt_string_from_info_data_line_num(TXT_TextInfo *info, String8 data, S64 line_num)
|
||||
{
|
||||
String8 result = {0};
|
||||
if(1 <= line_num && line_num <= info->lines_count)
|
||||
{
|
||||
result = str8_substr(data, info->lines_ranges[line_num-1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal TXT_LineTokensSlice
|
||||
txt_line_tokens_slice_from_info_data_line_range(Arena *arena, TXT_TextInfo *info, String8 data, Rng1S64 line_range)
|
||||
{
|
||||
|
||||
@@ -279,6 +279,7 @@ internal TXT_TokenArray txt_token_array_from_info_line_num__linear_scan(TXT_Text
|
||||
internal Rng1U64 txt_expr_off_range_from_line_off_range_string_tokens(U64 off, Rng1U64 line_range, String8 line_text, TXT_TokenArray *line_tokens);
|
||||
internal Rng1U64 txt_expr_off_range_from_info_data_pt(TXT_TextInfo *info, String8 data, TxtPt pt);
|
||||
internal String8 txt_string_from_info_data_txt_rng(TXT_TextInfo *info, String8 data, TxtRng rng);
|
||||
internal String8 txt_string_from_info_data_line_num(TXT_TextInfo *info, String8 data, S64 line_num);
|
||||
internal TXT_LineTokensSlice txt_line_tokens_slice_from_info_data_line_range(Arena *arena, TXT_TextInfo *info, String8 data, Rng1S64 line_range);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user