mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-05 13:28:40 +00:00
non-helper os_properties_from_file_path - can use accelerated path here which just looks at path for properties, rather than having to open a handle; also tweak txti layer to gracefully fail if a write happened between its load of file data
This commit is contained in:
+149
-142
@@ -976,17 +976,20 @@ txti_mut_thread_entry_point(void *p)
|
||||
TXTI_Stripe *stripe = &txti_state->entity_map_stripes.v[stripe_idx];
|
||||
|
||||
//- rjf: load file if we need it
|
||||
B32 load_valid = 0;
|
||||
String8 file_contents = {0};
|
||||
TXTI_LangKind lang_kind = TXTI_LangKind_Null;
|
||||
U64 timestamp = 0;
|
||||
if(msg->kind == TXTI_MsgKind_Reload)
|
||||
{
|
||||
FileProperties pre_load_props = os_properties_from_file_path(msg->string);
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite, msg->string);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
timestamp = props.modified;
|
||||
file_contents = os_string_from_file_range(scratch.arena, file, r1u64(0, props.size));
|
||||
timestamp = pre_load_props.modified;
|
||||
file_contents = os_string_from_file_range(scratch.arena, file, r1u64(0, pre_load_props.size));
|
||||
lang_kind = txti_lang_kind_from_extension(str8_skip_last_dot(msg->string));
|
||||
os_file_close(file);
|
||||
FileProperties post_load_props = os_properties_from_file_path(msg->string);
|
||||
load_valid = (post_load_props.modified == pre_load_props.modified);
|
||||
}
|
||||
|
||||
//- rjf: nonzero lang kind -> unpack lang info
|
||||
@@ -1003,6 +1006,7 @@ txti_mut_thread_entry_point(void *p)
|
||||
|
||||
//- rjf: detect line end kind
|
||||
TXTI_LineEndKind line_end_kind = TXTI_LineEndKind_Null;
|
||||
if(load_valid)
|
||||
{
|
||||
U64 lf_count = 0;
|
||||
U64 cr_count = 0;
|
||||
@@ -1029,7 +1033,7 @@ txti_mut_thread_entry_point(void *p)
|
||||
|
||||
//- rjf: obtain initial buffer_apply_gen, reset byte processing counters
|
||||
U64 initial_buffer_apply_gen = 0;
|
||||
OS_MutexScopeR(stripe->rw_mutex)
|
||||
if(load_valid) OS_MutexScopeR(stripe->rw_mutex)
|
||||
{
|
||||
TXTI_Entity *entity = 0;
|
||||
for(TXTI_Entity *e = slot->first; e != 0; e = e->next)
|
||||
@@ -1052,16 +1056,56 @@ txti_mut_thread_entry_point(void *p)
|
||||
}
|
||||
|
||||
//- rjf: apply edits
|
||||
for(U64 buffer_apply_idx = 0;
|
||||
buffer_apply_idx < TXTI_ENTITY_BUFFER_COUNT;
|
||||
buffer_apply_idx += 1)
|
||||
if(load_valid)
|
||||
{
|
||||
// rjf: last buffer we're going to edit? -> bump buffer_apply_gen,
|
||||
// so that before we touch this last buffer, all readers of this
|
||||
// entity will get the already-modified buffers.
|
||||
if(buffer_apply_idx == TXTI_ENTITY_BUFFER_COUNT-1)
|
||||
for(U64 buffer_apply_idx = 0;
|
||||
buffer_apply_idx < TXTI_ENTITY_BUFFER_COUNT;
|
||||
buffer_apply_idx += 1)
|
||||
{
|
||||
OS_MutexScopeW(stripe->rw_mutex)
|
||||
// rjf: last buffer we're going to edit? -> bump buffer_apply_gen,
|
||||
// so that before we touch this last buffer, all readers of this
|
||||
// entity will get the already-modified buffers.
|
||||
if(buffer_apply_idx == TXTI_ENTITY_BUFFER_COUNT-1)
|
||||
{
|
||||
OS_MutexScopeW(stripe->rw_mutex)
|
||||
{
|
||||
TXTI_Entity *entity = 0;
|
||||
for(TXTI_Entity *e = slot->first; e != 0; e = e->next)
|
||||
{
|
||||
if(e->id == id)
|
||||
{
|
||||
entity = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(entity != 0)
|
||||
{
|
||||
entity->buffer_apply_gen += 1;
|
||||
if(line_end_kind != TXTI_LineEndKind_Null)
|
||||
{
|
||||
entity->line_end_kind = line_end_kind;
|
||||
}
|
||||
if(lang_kind != TXTI_LangKind_Null)
|
||||
{
|
||||
entity->lang_kind = lang_kind;
|
||||
}
|
||||
if(timestamp != 0)
|
||||
{
|
||||
entity->timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: apply edit to this buffer.
|
||||
//
|
||||
// NOTE(rjf): all edits can apply *with a shared mutex lock*,
|
||||
// because only the mutator thread for this buffer can touch the
|
||||
// non-currently-viewable buffers. we only need to have an
|
||||
// exclusive lock to bump the buffer_apply_gen (to change the
|
||||
// actively viewable buffer).
|
||||
//
|
||||
OS_MutexScopeR(stripe->rw_mutex)
|
||||
{
|
||||
TXTI_Entity *entity = 0;
|
||||
for(TXTI_Entity *e = slot->first; e != 0; e = e->next)
|
||||
@@ -1074,147 +1118,110 @@ txti_mut_thread_entry_point(void *p)
|
||||
}
|
||||
if(entity != 0)
|
||||
{
|
||||
entity->buffer_apply_gen += 1;
|
||||
if(line_end_kind != TXTI_LineEndKind_Null)
|
||||
{
|
||||
entity->line_end_kind = line_end_kind;
|
||||
}
|
||||
if(lang_kind != TXTI_LangKind_Null)
|
||||
{
|
||||
entity->lang_kind = lang_kind;
|
||||
}
|
||||
if(timestamp != 0)
|
||||
{
|
||||
entity->timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: apply edit to this buffer.
|
||||
//
|
||||
// NOTE(rjf): all edits can apply *with a shared mutex lock*,
|
||||
// because only the mutator thread for this buffer can touch the
|
||||
// non-currently-viewable buffers. we only need to have an
|
||||
// exclusive lock to bump the buffer_apply_gen (to change the
|
||||
// actively viewable buffer).
|
||||
//
|
||||
OS_MutexScopeR(stripe->rw_mutex)
|
||||
{
|
||||
TXTI_Entity *entity = 0;
|
||||
for(TXTI_Entity *e = slot->first; e != 0; e = e->next)
|
||||
{
|
||||
if(e->id == id)
|
||||
{
|
||||
entity = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(entity != 0)
|
||||
{
|
||||
TXTI_Buffer *buffer = &entity->buffers[(initial_buffer_apply_gen+1+buffer_apply_idx)%TXTI_ENTITY_BUFFER_COUNT];
|
||||
|
||||
// rjf: clear old analysis data
|
||||
arena_clear(buffer->analysis_arena);
|
||||
buffer->lines_count = 0;
|
||||
buffer->lines_ranges = 0;
|
||||
buffer->lines_max_size = 0;
|
||||
MemoryZeroStruct(&buffer->tokens);
|
||||
|
||||
// rjf: perform edit to buffer data
|
||||
switch(msg->kind)
|
||||
{
|
||||
default:{}break;
|
||||
TXTI_Buffer *buffer = &entity->buffers[(initial_buffer_apply_gen+1+buffer_apply_idx)%TXTI_ENTITY_BUFFER_COUNT];
|
||||
|
||||
// rjf: replace range
|
||||
case TXTI_MsgKind_Append: ProfScope("append")
|
||||
{
|
||||
U8 *append_data_buffer = push_array_no_zero(buffer->data_arena, U8, msg->string.size);
|
||||
MemoryCopy(append_data_buffer, msg->string.str, msg->string.size);
|
||||
buffer->data.size += msg->string.size;
|
||||
if(buffer->data.str == 0 && msg->string.size != 0)
|
||||
{
|
||||
buffer->data.str = append_data_buffer;
|
||||
}
|
||||
}break;
|
||||
// rjf: clear old analysis data
|
||||
arena_clear(buffer->analysis_arena);
|
||||
buffer->lines_count = 0;
|
||||
buffer->lines_ranges = 0;
|
||||
buffer->lines_max_size = 0;
|
||||
MemoryZeroStruct(&buffer->tokens);
|
||||
|
||||
// rjf: reload from disk
|
||||
case TXTI_MsgKind_Reload: ProfScope("reload")
|
||||
// rjf: perform edit to buffer data
|
||||
switch(msg->kind)
|
||||
{
|
||||
arena_clear(buffer->data_arena);
|
||||
if(file_contents.size != 0)
|
||||
default:{}break;
|
||||
|
||||
// rjf: replace range
|
||||
case TXTI_MsgKind_Append: ProfScope("append")
|
||||
{
|
||||
buffer->data = push_str8_copy(buffer->data_arena, file_contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryZeroStruct(&buffer->data);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: parse & store line range info
|
||||
{
|
||||
// rjf: count # of lines
|
||||
U64 line_count = 1;
|
||||
U64 byte_process_start_idx = 0;
|
||||
for(U64 idx = 0; idx < buffer->data.size; idx += 1)
|
||||
{
|
||||
if(buffer_apply_idx == 0 && idx-byte_process_start_idx >= 1000)
|
||||
{
|
||||
ins_atomic_u64_add_eval(&entity->bytes_processed, (idx-byte_process_start_idx));
|
||||
byte_process_start_idx = idx;
|
||||
}
|
||||
if(buffer->data.str[idx] == '\n' || buffer->data.str[idx] == '\r')
|
||||
{
|
||||
line_count += 1;
|
||||
if(buffer->data.str[idx] == '\r')
|
||||
U8 *append_data_buffer = push_array_no_zero(buffer->data_arena, U8, msg->string.size);
|
||||
MemoryCopy(append_data_buffer, msg->string.str, msg->string.size);
|
||||
buffer->data.size += msg->string.size;
|
||||
if(buffer->data.str == 0 && msg->string.size != 0)
|
||||
{
|
||||
idx += 1;
|
||||
buffer->data.str = append_data_buffer;
|
||||
}
|
||||
}break;
|
||||
|
||||
// rjf: reload from disk
|
||||
case TXTI_MsgKind_Reload: ProfScope("reload")
|
||||
{
|
||||
arena_clear(buffer->data_arena);
|
||||
if(file_contents.size != 0)
|
||||
{
|
||||
buffer->data = push_str8_copy(buffer->data_arena, file_contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryZeroStruct(&buffer->data);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: parse & store line range info
|
||||
{
|
||||
// rjf: count # of lines
|
||||
U64 line_count = 1;
|
||||
U64 byte_process_start_idx = 0;
|
||||
for(U64 idx = 0; idx < buffer->data.size; idx += 1)
|
||||
{
|
||||
if(buffer_apply_idx == 0 && idx-byte_process_start_idx >= 1000)
|
||||
{
|
||||
ins_atomic_u64_add_eval(&entity->bytes_processed, (idx-byte_process_start_idx));
|
||||
byte_process_start_idx = idx;
|
||||
}
|
||||
if(buffer->data.str[idx] == '\n' || buffer->data.str[idx] == '\r')
|
||||
{
|
||||
line_count += 1;
|
||||
if(buffer->data.str[idx] == '\r')
|
||||
{
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: allocate & store line ranges
|
||||
buffer->lines_count = line_count;
|
||||
buffer->lines_ranges = push_array_no_zero(buffer->analysis_arena, Rng1U64, buffer->lines_count);
|
||||
U64 line_idx = 0;
|
||||
U64 line_start_idx = 0;
|
||||
for(U64 idx = 0; idx <= buffer->data.size; idx += 1)
|
||||
{
|
||||
if(idx == buffer->data.size || buffer->data.str[idx] == '\n' || buffer->data.str[idx] == '\r')
|
||||
{
|
||||
Rng1U64 line_range = r1u64(line_start_idx, idx);
|
||||
U64 line_size = dim_1u64(line_range);
|
||||
buffer->lines_ranges[line_idx] = line_range;
|
||||
buffer->lines_max_size = Max(buffer->lines_max_size, line_size);
|
||||
line_idx += 1;
|
||||
line_start_idx = idx+1;
|
||||
if(idx < buffer->data.size && buffer->data.str[idx] == '\r')
|
||||
{
|
||||
line_start_idx += 1;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: allocate & store line ranges
|
||||
buffer->lines_count = line_count;
|
||||
buffer->lines_ranges = push_array_no_zero(buffer->analysis_arena, Rng1U64, buffer->lines_count);
|
||||
U64 line_idx = 0;
|
||||
U64 line_start_idx = 0;
|
||||
for(U64 idx = 0; idx <= buffer->data.size; idx += 1)
|
||||
// rjf: lex file contents
|
||||
if(lex_function != 0)
|
||||
{
|
||||
if(idx == buffer->data.size || buffer->data.str[idx] == '\n' || buffer->data.str[idx] == '\r')
|
||||
{
|
||||
Rng1U64 line_range = r1u64(line_start_idx, idx);
|
||||
U64 line_size = dim_1u64(line_range);
|
||||
buffer->lines_ranges[line_idx] = line_range;
|
||||
buffer->lines_max_size = Max(buffer->lines_max_size, line_size);
|
||||
line_idx += 1;
|
||||
line_start_idx = idx+1;
|
||||
if(idx < buffer->data.size && buffer->data.str[idx] == '\r')
|
||||
{
|
||||
line_start_idx += 1;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
buffer->tokens = lex_function(buffer->analysis_arena, buffer_apply_idx == 0 ? &entity->bytes_processed : 0, buffer->data);
|
||||
}
|
||||
|
||||
// rjf: mark final process counter
|
||||
if(buffer_apply_idx == 0)
|
||||
{
|
||||
ins_atomic_u64_eval_assign(&entity->bytes_processed, entity->bytes_to_process);
|
||||
}
|
||||
|
||||
// rjf: mark task completion
|
||||
if(buffer_apply_idx == TXTI_ENTITY_BUFFER_COUNT-1)
|
||||
{
|
||||
ins_atomic_u64_eval_assign(&entity->working_count, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: lex file contents
|
||||
if(lex_function != 0)
|
||||
{
|
||||
buffer->tokens = lex_function(buffer->analysis_arena, buffer_apply_idx == 0 ? &entity->bytes_processed : 0, buffer->data);
|
||||
}
|
||||
|
||||
// rjf: mark final process counter
|
||||
if(buffer_apply_idx == 0)
|
||||
{
|
||||
ins_atomic_u64_eval_assign(&entity->bytes_processed, entity->bytes_to_process);
|
||||
}
|
||||
|
||||
// rjf: mark task completion
|
||||
if(buffer_apply_idx == TXTI_ENTITY_BUFFER_COUNT-1)
|
||||
{
|
||||
ins_atomic_u64_eval_assign(&entity->working_count, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user