mirror of
https://github.com/sbrow/envr.git
synced 2026-06-27 18:48:33 -04:00
perf: Replaced fd with custom internals.
This commit is contained in:
128
findr/repos.odin
Normal file
128
findr/repos.odin
Normal file
@@ -0,0 +1,128 @@
|
||||
package findr
|
||||
|
||||
import "core:strings"
|
||||
import "core:sync"
|
||||
import "core:sys/linux"
|
||||
import "core:thread"
|
||||
|
||||
RepoPool :: struct {
|
||||
queue: [dynamic]string,
|
||||
queue_mutex: sync.Mutex,
|
||||
queue_sema: sync.Atomic_Sema,
|
||||
results: ^[dynamic]string,
|
||||
results_lock: sync.Mutex,
|
||||
active: i64,
|
||||
done: sync.One_Shot_Event,
|
||||
threads: []^thread.Thread,
|
||||
}
|
||||
|
||||
find_repos :: proc(roots: []string, results: ^[dynamic]string, thread_count: int) {
|
||||
if len(roots) == 0 do return
|
||||
|
||||
pool := new(RepoPool)
|
||||
pool.queue = make([dynamic]string)
|
||||
pool.results = results
|
||||
pool.active = i64(len(roots))
|
||||
pool.threads = make([]^thread.Thread, thread_count)
|
||||
|
||||
for root in roots {
|
||||
root_clone, _ := strings.clone(root)
|
||||
append(&pool.queue, root_clone)
|
||||
sync.atomic_sema_post(&pool.queue_sema)
|
||||
}
|
||||
|
||||
for i in 0 ..< thread_count {
|
||||
t := thread.create(repo_worker)
|
||||
t.data = rawptr(pool)
|
||||
t.init_context = context
|
||||
thread.start(t)
|
||||
pool.threads[i] = t
|
||||
}
|
||||
|
||||
sync.one_shot_event_wait(&pool.done)
|
||||
|
||||
for _ in 0 ..< thread_count {
|
||||
sync.atomic_sema_post(&pool.queue_sema)
|
||||
}
|
||||
|
||||
for t in pool.threads {
|
||||
thread.destroy(t)
|
||||
}
|
||||
delete(pool.threads)
|
||||
|
||||
for path in pool.queue {
|
||||
delete(path)
|
||||
}
|
||||
delete(pool.queue)
|
||||
|
||||
free(pool)
|
||||
}
|
||||
|
||||
repo_worker :: proc(t: ^thread.Thread) {
|
||||
pool := cast(^RepoPool)t.data
|
||||
|
||||
for {
|
||||
sync.atomic_sema_wait(&pool.queue_sema)
|
||||
|
||||
sync.mutex_lock(&pool.queue_mutex)
|
||||
if len(pool.queue) == 0 {
|
||||
sync.mutex_unlock(&pool.queue_mutex)
|
||||
if sync.atomic_load_explicit(&pool.active, .Acquire) == 0 {
|
||||
sync.one_shot_event_signal(&pool.done)
|
||||
}
|
||||
break
|
||||
}
|
||||
last := len(pool.queue) - 1
|
||||
dir_path := pool.queue[last]
|
||||
ordered_remove(&pool.queue, last)
|
||||
sync.mutex_unlock(&pool.queue_mutex)
|
||||
|
||||
process_repo_dir(pool, dir_path)
|
||||
delete(dir_path)
|
||||
|
||||
old := sync.atomic_sub_explicit(&pool.active, 1, .Release)
|
||||
if old == 1 {
|
||||
sync.one_shot_event_signal(&pool.done)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process_repo_dir :: proc(pool: ^RepoPool, dir_path: string) {
|
||||
cpath := strings.clone_to_cstring(dir_path)
|
||||
if cpath == nil do return
|
||||
defer delete(cpath)
|
||||
|
||||
fd, open_err := linux.open(cpath, {.DIRECTORY, .CLOEXEC})
|
||||
if open_err != .NONE do return
|
||||
defer linux.close(fd)
|
||||
|
||||
if has_git_dir(fd) {
|
||||
cloned, _ := strings.clone(dir_path)
|
||||
sync.mutex_lock(&pool.results_lock)
|
||||
append(pool.results, cloned)
|
||||
sync.mutex_unlock(&pool.results_lock)
|
||||
}
|
||||
|
||||
buf: [32 * 1024]u8
|
||||
|
||||
for {
|
||||
n, errno := linux.getdents(fd, buf[:])
|
||||
if n <= 0 || errno != .NONE do break
|
||||
|
||||
offs := 0
|
||||
for d in linux.dirent_iterate_buf(buf[:n], &offs) {
|
||||
name := linux.dirent_name(d)
|
||||
if name == "." || name == ".." do continue
|
||||
if name == ".git" do continue
|
||||
|
||||
if d.type == .DIR {
|
||||
child_path := join_path(dir_path, name)
|
||||
sync.atomic_add_explicit(&pool.active, 1, .Relaxed)
|
||||
sync.mutex_lock(&pool.queue_mutex)
|
||||
append(&pool.queue, child_path)
|
||||
sync.mutex_unlock(&pool.queue_mutex)
|
||||
sync.atomic_sema_post(&pool.queue_sema)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user