MAPL_Throw.F90 Source File


Files dependent on this one

sourcefile~~mapl_throw.f90~~AfferentGraph sourcefile~mapl_throw.f90 MAPL_Throw.F90 sourcefile~init_tests.f90 init_tests.F90 sourcefile~init_tests.f90->sourcefile~mapl_throw.f90 sourcefile~mapl_errorhandling.f90 MAPL_ErrorHandling.F90 sourcefile~mapl_errorhandling.f90->sourcefile~mapl_throw.f90 sourcefile~mapl_exceptionhandling.f90 MAPL_ExceptionHandling.F90 sourcefile~mapl_exceptionhandling.f90->sourcefile~mapl_throw.f90 sourcefile~mapl_initialize.f90 MAPL_Initialize.F90 sourcefile~mapl_initialize.f90->sourcefile~mapl_throw.f90 sourcefile~maplshared.f90 MaplShared.F90 sourcefile~maplshared.f90->sourcefile~mapl_throw.f90

Source Code

module MAPL_ThrowMod
   implicit none
   private

   public :: MAPL_throw_exception
   public :: MAPL_set_throw_method

   abstract interface
      subroutine throw(filename, line_number, message)
         character(len=*), intent(in) :: filename
         integer, intent(in) :: line_number
         character(len=*), optional, intent(in) :: message
      end subroutine throw
   end interface

   procedure (throw), pointer :: throw_method => null()
   logical, save :: initialized = .false.

contains

   subroutine MAPL_set_throw_method(method)
      procedure (throw) :: method
      if (.not. initialized) call initialize()
      throw_method => method
   end subroutine MAPL_set_throw_method

   subroutine initialize()
      throw_method => MAPL_Fail
      initialized = .true.
   end subroutine initialize

   
   subroutine MAPL_throw_exception(filename, line_number, message)
      character(len=*), intent(in) :: filename
      integer, intent(in) :: line_number
      character(len=*), optional, intent(in) :: message

      if (.not. initialized) then
         call initialize()
      end if

      call throw_method(filename, line_number, message=message)
      
   end subroutine MAPL_throw_exception


   subroutine MAPL_Fail(filename, line, message)
      use MPI
      use, intrinsic :: iso_fortran_env, only: ERROR_UNIT
      character(*), intent(in) :: filename
      integer, intent(in) :: line
      character(*), optional, intent(in) :: message

      integer, parameter :: FIELD_WIDTH=40
      character(FIELD_WIDTH) :: use_name
      character(3) :: prefix
      character(:), allocatable :: base_name
      
      integer :: rank, ierror
      logical :: is_mpi_initialized

      call MPI_Initialized(is_mpi_initialized,ierror)
  
      base_name = get_base_name(filename)
      if (len(base_name) > FIELD_WIDTH) then
         prefix = '...'
         use_name = base_name(2:)
      else
         prefix = '   '
         use_name = base_name
      end if

      ! Could use ADVANCE='no', but this may increase the chance
      ! that the output lines are not interrupted by messages from
      ! other PEs
      if (is_mpi_initialized) then
         call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierror)
         !$omp critical (MAPL_Throw1)
         write(ERROR_UNIT,'(a,i5.5,1x,a,i5.5,1x,a3,a40,1x,a)') &
              & 'pe=', rank, 'FAIL at line=', line, prefix, use_name, &
              & '<'//adjustl(trim(message))//'>'
         !$omp end critical (MAPL_Throw1)
      else
         !$omp critical (MAPL_Throw1)
         write(ERROR_UNIT,'(a,i5.5,1x,a3,a40,1x,a)') &
              & 'FAIL at line=', line, prefix, use_name, &
              & '<'//adjustl(trim(message))//'>'
         !$omp end critical (MAPL_Throw1)
      end if


      
   end subroutine MAPL_Fail



   ! TODO: Rather than taking the last N characters, it might make
   ! more sense for the following procedure to omit just the middle
   ! characters in a long string.  The trick is to intelligently split on
   ! directories.    Maybe specify a max depth at both ends?
   function get_short_name(filename, maxlen) result(short_name)
      character(:), allocatable :: short_name
      character(*), intent(in) :: filename
      integer, optional, intent(in) :: maxlen
      integer, parameter :: MAX_LEN_SHORT_NAME = 60

      integer :: maxlen_
      integer :: n

      maxlen_ = MAX_LEN_SHORT_NAME
      if (present(maxlen)) maxlen_ = maxlen
      
      n = len_trim(filename)
      short_name = filename(max(1,n+1-maxlen_):)

   end function get_short_name


   function get_base_name(filename) result(base_name)
      character(:), allocatable :: base_name
      character(*), intent(in) :: filename

      integer :: idx

      idx = scan(filename, '/', back=.true.)

      base_name = filename(idx+1:)

   end function get_base_name



end module MAPL_ThrowMod