subroutine get_memory_info(mem_free, mem_total)
!< Get the current CPU-memory status.
!< @NOTE Currently implemented only per Unix/Linux based systems. Return -1 if failing.
!<```fortran
!< use penf
!< real(R8P), allocatable :: a(:,:,:)
!< integer(I8P) :: mem_free_1, mem_free_2, mem_total
!< logical :: is_present
!< integer(I4P) :: n, i, j, k
!< call get_memory_info(mem_free_1, mem_total)
!< inquire(file='/proc/meminfo', exist=is_present)
!< if (is_present) then
!< n = 800
!< allocate(a(1:n,1:n,1:n))
!< else
!< print*, .true.
!< stop
!< endif
!< a = 1._R8P
!< do k=2, n
!< do j=2, n
!< do i=2, n
!< a(i,j,k) = 1._R8P / 2._R8P * exp(a(i-1,j,k)) - a(i-1,j,k)
!< enddo
!< enddo
!< enddo
!< call get_memory_info(mem_free_2, mem_total)
!< print*, mem_free_1 > mem_free_2
!<```
!=> T <<<
integer(I8P), intent(out) :: mem_free !< Free memory.
integer(I8P), intent(out) :: mem_total !< Total memory.
logical :: is_present !< Logical flag to check the presence of '/proc/meminfo' system file.
integer(I4P) :: file_unit !< File unit.
character(999) :: line !< Line buffer.
mem_free = -1_I8P
mem_total = -1_I8P
inquire(file='/proc/meminfo', exist=is_present)
if (is_present) then
open(newunit=file_unit, file='/proc/meminfo', status='old')
read(file_unit, '(A)') line ! total memory
call parse_line(l=line, v=mem_total)
read(file_unit, '(A)') line ! free memory
call parse_line(l=line, v=mem_free)
close(file_unit)
endif
contains
subroutine parse_line(l,v)
!< Parse input line and return memory value.
character(*), intent(in) :: l !< Input line.
integer(I8P), intent(out) :: v !< Memory value.
integer(I4P) :: colon !< Index of colon (name/value separator) char in line.
character(:), allocatable :: memval !< Memory value, string.
colon = index(l, ':') ! find name/value separator position
memval = trim(adjustl(l(colon+1:))) ! get memory value, string
memval = trim(memval(:len(memval)-2)) ! remove memory unit, e.g. kb
v = cton(str=memval, knd=1_I8P) ! cast to string to integer
endsubroutine parse_line
endsubroutine get_memory_info