function acquire_lock(cache_dir, project_name, wait) result(success)
character(len=*), intent(in) :: cache_dir, project_name
logical, intent(in), optional :: wait
logical :: success, locked
character(len=512) :: lock_file
logical :: should_wait
integer :: wait_time, unit, iostat, pid
character(len=32) :: pid_str, timestamp
should_wait = .true.
if (present(wait)) should_wait = wait
lock_file = get_lock_file_path(cache_dir, project_name)
wait_time = 0
success = .false.
! Ensure cache directory exists (only create if it doesn't exist)
block
logical :: dir_exists
inquire (file=trim(cache_dir), exist=dir_exists)
if (.not. dir_exists) then
call mkdir(cache_dir)
end if
end block
do
! First check if lock already exists
inquire (file=lock_file, exist=locked)
! DEBUG
! print *, 'DEBUG acquire_lock: lock exists=', locked, ' for ', trim(lock_file)
if (.not. locked) then
! Try to create lock file atomically
if (try_create_lock(lock_file)) then
success = .true.
exit
else
! Failed to create, but file doesn't exist - race condition?
success = .false.
if (.not. should_wait) then
exit
end if
end if
else
! Lock exists, check if it's stale
if (is_lock_stale(lock_file)) then
call remove_lock(lock_file)
cycle
end if
! Lock exists and is not stale
success = .false.
! DEBUG
! print *, 'DEBUG: Lock exists and not stale, setting success=F, should_wait=', should_wait
! If not waiting, fail immediately
if (.not. should_wait) then
exit
end if
end if
! Wait and retry
call sys_sleep(1)
wait_time = wait_time + 1
if (wait_time >= MAX_WAIT_TIME) then
call debug_print('Cache lock timeout after ' // int_to_char(MAX_WAIT_TIME) // ' seconds for ' // trim(project_name))
exit
end if
end do
end function acquire_lock