@ -1,6 +1,6 @@
( import
"FileHelper.cake" "FileSystem.cake" "Treemap.cake" "TreemapOpenGL.cake" "Utilities.cake"
"Dictionary.cake" "SDL.cake" &with-decls "Math.cake"
"Dictionary.cake" "SDL.cake" "TaskSystem.cake" &with-decls "Math.cake"
&comptime-only "CHelpers.cake" )
( comptime-cond
@ -10,12 +10,15 @@
( true
( import "ProfilerNull.cake" ) ) )
( c-import "<c stdio>" )
( c-import "<stdio.h >" )
( c-import "SDL_thread.h" "SDL_mutex.h" "SDL_ timer.h"
( c-import "SDL_thread.h" "SDL_timer.h"
;; For Uint64
&with-decls "SDL_stdinc.h" )
;; TODO Need infect
( module-use-sdl-build-options )
( add-c-search-directory-module "Dependencies/enkiTS/src" )
( forward-declare ( struct treemap-file-system-multithreaded-state ) )
@ -72,20 +75,20 @@
( dynarray-free ( path state > classifications ) )
( free state ) )
( defenum treemap-running-state
treemap-running-state-not-started
treemap-running-state-working
treemap-running-state-done )
( defstruct-local treemap-file-system-multithreaded-state
current-treemap-state-dir dynstring
current-treemap-state ( * treemap-file-system-state )
future-treemap-state-dir dynstring
future-treemap-scan-start-time Uint64
refresh-requested bool
future-treemap-state ( * treemap-file-system-state )
future-treemap-thread-handle ( * SDL_Thread )
future-state-thread-should-run SDL_atomic_t ;; For shutting down worker
future-state-thread-work-done bool ;; Tracked by main thread once it gets the lock again
future-state-thread-state treemap-running-state
future-state-lock ( * SDL_mutex )
colorizers ( * file-colorizer ) ) ;; Dynarray, used only by the future state thread
@ -95,28 +98,17 @@
( memset new-state 0 ( sizeof ( type treemap-file-system-multithreaded-state ) ) )
( set ( path new-state > current-treemap-state-dir ) null )
( set ( path new-state > current-treemap-state ) ( create-treemap-file-system-state ) )
( set ( path new-state > future-treemap-thread-handle ) null )
( set ( path new-state > future-treemap-state-dir ) null )
( set ( path new-state > future-treemap-state ) ( create-treemap-file-system-state ) )
( set ( path new-state > future-state-lock ) ( SDL_CreateMutex ) )
( return new-state ) )
( defun free-treemap-file-system-multithreaded-state ( state ( * treemap-file-system-multithreaded-state ) )
( SDL_LockMutex ( path state > future-state-lock ) )
( when ( path state > future-treemap-thread-handle )
( SDL_AtomicSet ( addr ( path state > future-state-thread-should-run ) ) 0 )
( var status int 0 )
( SDL_WaitThread ( path state > future-treemap-thread-handle ) ( addr status ) ) )
( dynarray-free ( path state > current-treemap-state-dir ) )
( free-treemap-file-system-state ( path state > current-treemap-state ) )
( dynarray-free ( path state > future-treemap-state-dir ) )
( free-treemap-file-system-state ( path state > future-treemap-state ) )
( dynarray-free ( path state > colorizers ) )
( SDL_UnlockMutex ( path state > future-state-lock ) )
( SDL_DestroyMutex ( path state > future-state-lock ) ) )
( dynarray-free ( path state > colorizers ) ) )
( defun-local treemap-scan-filesystem-recursive ( directory-to-scan ( * ( const char ) )
directories-out ( * ( * treemap-directory ) )
@ -333,7 +325,7 @@
( dynarray-push ( deref paths-out ) ( path this-entry-details > path ) )
( each-in-range 4 coord
( dynarray-push ( deref coordinates-out )
( at ( + ( * 4 i ) coord ) this-dir-coordinates ) ) ) ) ) ) )
( at ( + ( * 4 i ) coord ) this-dir-coordinates ) ) ) ) ) ) )
( scope ;; For setting sane pre-allocations
( fprintf stderr "Final capacity of this-directory-entries: %d\n"
@ -491,37 +483,36 @@
( set ( deref picked-index-out ) -1 )
( return null ) )
( defun-local treemap-future-state-needs-update ( state ( * treemap-file-system-multithreaded-state )
&return bool )
( return ( and ( path state > future-treemap-state-dir )
( or ( not ( path state > current-treemap-state-dir ) )
( != 0 ( strcmp ( path state > future-treemap-state-dir )
( path state > current-treemap-state-dir ) ) )
( and
( not ( path state > future-state-thread-work-done ) )
( path state > refresh-requested ) ) ) ) ) )
( defun-local treemap-update-future-state-worker-thread ( user-data ( * void ) &return int )
( var-cast-to state ( * treemap-file-system-multithreaded-state ) user-data )
( while ( SDL_AtomicGet ( addr ( path state > future-state-thread-should-run ) ) )
;; TODO This sucks
( SDL_LockMutex ( path state > future-state-lock ) )
( when ( treemap-future-state-needs-update state )
( fprintf stderr "Doing job\n" )
( update-treemap-with-file-sizes-internal
( path state > future-treemap-state-dir )
( path state > future-treemap-state )
( path state > colorizers ) )
( set ( path state > future-state-thread-work-done ) true )
( fprintf stderr "Done doing job\n" ) )
( SDL_UnlockMutex ( path state > future-state-lock ) )
( SDL_Delay 25 ) )
( return 0 ) )
( defenum treemap-running-state
treemap-running-state-not-started
treemap-running-state-working
treemap-running-state-done )
( def-task treemap-update-future-state-task ( state ( * treemap-file-system-multithreaded-state ) )
( fprintf stderr "Doing job\n" )
( update-treemap-with-file-sizes-internal
( path state > future-treemap-state-dir )
( path state > future-treemap-state )
( path state > colorizers ) ) )
( def-task treemap-update-future-state-done ( state ( * treemap-file-system-multithreaded-state ) )
;; The swap of future->current always happens on the main thread
( var temp-state ( * treemap-file-system-state ) ( path state > current-treemap-state ) )
( set ( path state > current-treemap-state ) ( path state > future-treemap-state ) )
( set ( path state > future-treemap-state ) temp-state )
( dynarray-clear ( path state > current-treemap-state-dir ) )
( dynstring-append ( addr ( path state > current-treemap-state-dir ) )
( path state > future-treemap-state-dir ) )
( var classification-colors ( * float ) null )
( dynarray-set-length classification-colors ( * 3 ( dynarray-length ( path state > colorizers ) ) ) )
( unless ( dynarray-length classification-colors ) ( dynarray-set-length classification-colors 3 ) )
( each-item-addr-in-dynarray ( path state > colorizers ) colorizer-index colorizer ( * file-colorizer )
( memcpy ( addr ( at ( * 3 colorizer-index ) classification-colors ) )
( path colorizer > color )
( sizeof ( path colorizer > color ) ) ) )
( treemap-opengl-update ( path state > current-treemap-state > coordinates )
( / ( dynarray-length ( path state > current-treemap-state > coordinates ) ) 4 )
( path state > current-treemap-state > classifications )
classification-colors )
( dynarray-free classification-colors )
( set ( path state > future-state-thread-state ) treemap-running-state-done ) )
( defun treemap-update-state ( state ( * treemap-file-system-multithreaded-state )
desired-dir ( * ( const char ) )
@ -529,80 +520,34 @@
layout-display-size vec3
num-entries-scanned-out ( * ( unsigned int ) )
&return treemap-running-state )
;; Worker is working
( unless ( = 0 ( SDL_TryLockMutex ( path state > future-state-lock ) ) )
( when ( and num-entries-scanned-out ;; Get count "from" worker thread
( not ( path state > future-state-thread-work-done ) ) )
( when ( = treemap-running-state-working ( path state > future-state-thread-state ) )
( when num-entries-scanned-out ;; Get count "from" worker thread
( set ( deref num-entries-scanned-out )
( type-cast
( SDL_AtomicGet ( addr ( path state > future-treemap-state > num-entries-scanned ) ) )
( unsigned int ) ) ) )
;; TODO This was in effort to prevent flickering on the off chance that the mutex was locked at
;; just the right time, but it doesn't quite work
( return ( ? ( not ( path state > future-state-thread-work-done ) )
treemap-running-state-working
treemap-running-state-done ) ) )
;; Work just finished
( when ( path state > future-state-thread-work-done )
;; The swap of future->current always happens on the main thread
( var temp-state ( * treemap-file-system-state ) ( path state > current-treemap-state ) )
( set ( path state > current-treemap-state ) ( path state > future-treemap-state ) )
( set ( path state > future-treemap-state ) temp-state )
( dynarray-clear ( path state > current-treemap-state-dir ) )
( dynstring-append ( addr ( path state > current-treemap-state-dir ) )
( path state > future-treemap-state-dir ) )
( var classification-colors ( * float ) null )
( dynarray-set-length classification-colors ( * 3 ( dynarray-length ( path state > colorizers ) ) ) )
( unless ( dynarray-length classification-colors ) ( dynarray-set-length classification-colors 3 ) )
( each-item-addr-in-dynarray ( path state > colorizers ) colorizer-index colorizer ( * file-colorizer )
( memcpy ( addr ( at ( * 3 colorizer-index ) classification-colors ) )
( path colorizer > color )
( sizeof ( path colorizer > color ) ) ) )
( treemap-opengl-update ( path state > current-treemap-state > coordinates )
( / ( dynarray-length ( path state > current-treemap-state > coordinates ) ) 4 )
( path state > current-treemap-state > classifications )
classification-colors )
( dynarray-free classification-colors )
( set ( path state > future-state-thread-state ) treemap-running-state-done )
( set ( path state > refresh-requested ) false )
( set ( path state > future-state-thread-work-done ) false ) )
( return ( path state > future-state-thread-state ) ) )
;; Already displaying desired. Nothing to do
( when ( and desired-dir ( path state > current-treemap-state-dir ) )
( when ( and ( = 0 ( strcmp desired-dir ( path state > current-treemap-state-dir ) ) )
( <= request-refresh-time ( path state > future-treemap-scan-start-time ) ) )
( SDL_UnlockMutex ( path state > future-state-lock ) )
( return treemap-running-state-done ) ) )
;; Future state is being computed for the desired dir. Nothing to start
( when ( = ( path state > future-state-thread-state )
treemap-running-state-working )
( SDL_UnlockMutex ( path state > future-state-lock ) )
( return treemap-running-state-working ) )
( fprintf stderr "Start task to get dir %s\n" desired-dir )
;; Lazy create work thread
( unless ( path state > future-treemap-thread-handle )
( SDL_AtomicSet ( addr ( path state > future-state-thread-should-run ) ) 1 )
( set ( path state > future-treemap-thread-handle )
( SDL_CreateThread treemap-update-future-state-worker-thread
"TreemapFutureState" state ) ) )
( set ( path state > future-treemap-scan-start-time ) ( SDL_GetPerformanceCounter ) )
( set ( path state > refresh-requested ) true )
( set ( path state > future-state-thread-state ) treemap-running-state-working )
( dynarray-clear ( path state > future-treemap-state-dir ) )
( dynstring-append ( addr ( path state > future-treemap-state-dir ) ) desired-dir )
( set ( path state > future-state-thread-work-done ) false )
;; Copy colorizer for the other thread
( dynarray-set-length ( path state > colorizers ) ( dynarray-length g-file-colorizers ) )
( memcpy ( path state > colorizers ) g-file-colorizers ( dynarray-length-sizeof g-file-colorizers ) )
( set ( path state > future-treemap-state > layout-display-size ) layout-display-size )
( SDL_AtomicSet ( addr ( path state > future-treemap-state > num-entries-scanned ) ) 0 )
( SDL_UnlockMutex ( path state > future-state-lock ) )
( task-system-execute
( treemap-update-future-state-task state )
( treemap-update-future-state-done :pin-to-main-thread state ) )
( return treemap-running-state-working ) )