Skip to content

Commit 52e14b2

Browse files
bonachearouson
authored andcommitted
Add ASSERT_PARALLEL_CALLBACKS define
By default, assert uses `THIS_IMAGE()` in multi-image mode while composing assertion output, and invokes `ERROR STOP` to print the assertion and terminate execution. The ASSERT_PARALLEL_CALLBACKS preprocessor flag enables the client to replace the default use of these two Fortran features with client-provided callbacks. To use this feature, the client must build the library with `-DASSERT_PARALLEL_CALLBACKS`, and then at startup set the `assert_this_image` and `assert_error_stop` procedure pointers to reference the desired callbacks.
1 parent 98cd3ef commit 52e14b2

File tree

4 files changed

+74
-6
lines changed

4 files changed

+74
-6
lines changed

example/false-assertion.F90

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,40 @@
11
program false_assertion
2-
use assert_m, only : assert
2+
use assert_m
33
implicit none
44

5+
#if ASSERT_PARALLEL_CALLBACKS
6+
assert_this_image => assert_callback_this_image
7+
assert_error_stop => assert_callback_error_stop
8+
#endif
9+
510
call assert(.false., "false-assertion: unconditionally failing test")
611

12+
#if ASSERT_PARALLEL_CALLBACKS
13+
! By default, assert uses `THIS_IMAGE()` in multi-image mode while
14+
! composing assertion output, and invokes `ERROR STOP` to print the
15+
! assertion and terminate execution.
16+
!
17+
! The ASSERT_PARALLEL_CALLBACKS preprocessor flag enables the client to replace
18+
! the default use of these two Fortran features with client-provided callbacks.
19+
! To use this feature, the client must build the library with `-DASSERT_PARALLEL_CALLBACKS`,
20+
! and then at startup set the `assert_this_image` and `assert_error_stop`
21+
! procedure pointers to reference the desired callbacks.
22+
contains
23+
24+
pure function assert_callback_this_image() result(this_image_id)
25+
implicit none
26+
integer :: this_image_id
27+
28+
this_image_id = 42
29+
end function
30+
31+
pure subroutine assert_callback_error_stop(stop_code_char)
32+
implicit none
33+
character(len=*), intent(in) :: stop_code_char
34+
35+
error stop "Hello from assert_callback_error_stop!" // NEW_LINE('a') // &
36+
"Your assertion: " // NEW_LINE('a') // stop_code_char
37+
end subroutine
38+
#endif
39+
740
end program

include/assert_features.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@
1111
# endif
1212
#endif
1313

14+
! Whether the library should use client callbacks for parallel features
15+
#ifndef ASSERT_PARALLEL_CALLBACKS
16+
#define ASSERT_PARALLEL_CALLBACKS 0
17+
#endif
18+
1419
#endif

src/assert/assert_subroutine_m.F90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,28 @@ module assert_subroutine_m
3535
private
3636
public :: assert, assert_always
3737

38+
#if ASSERT_PARALLEL_CALLBACKS
39+
public :: assert_this_image_interface, assert_this_image
40+
public :: assert_error_stop_interface, assert_error_stop
41+
42+
abstract interface
43+
pure function assert_this_image_interface() result(this_image_id)
44+
implicit none
45+
integer :: this_image_id
46+
end function
47+
end interface
48+
procedure(assert_this_image_interface), pointer :: assert_this_image
49+
50+
abstract interface
51+
pure subroutine assert_error_stop_interface(stop_code_char)
52+
implicit none
53+
character(len=*), intent(in) :: stop_code_char
54+
end subroutine
55+
end interface
56+
procedure(assert_error_stop_interface), pointer :: assert_error_stop
57+
58+
#endif
59+
3860
#ifndef USE_ASSERTIONS
3961
# if ASSERTIONS
4062
# define USE_ASSERTIONS .true.

src/assert/assert_subroutine_s.F90

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,20 @@
2525
use characterizable_m, only : characterizable_t
2626

2727
character(len=:), allocatable :: header, trailer
28+
integer :: me
2829

2930
check_assertion: &
3031
if (.not. assertion) then
3132

3233
#if ASSERT_MULTI_IMAGE
33-
associate(me=>this_image()) ! work around gfortran bug
34-
header = 'Assertion "' // description // '" failed on image ' // string(me)
35-
end associate
34+
# if ASSERT_PARALLEL_CALLBACKS
35+
me = assert_this_image()
36+
# else
37+
me = this_image()
38+
# endif
39+
header = 'Assertion "' // description // '" failed on image ' // string(me)
3640
#else
37-
header = 'Assertion "' // description // '" failed.'
41+
header = 'Assertion "' // description // '" failed.'
3842
#endif
3943

4044
represent_diagnostics_as_string: &
@@ -64,7 +68,11 @@
6468

6569
end if represent_diagnostics_as_string
6670

67-
error stop header // trailer
71+
#if ASSERT_PARALLEL_CALLBACKS
72+
call assert_error_stop(header // trailer)
73+
#else
74+
error stop (header // trailer)
75+
#endif
6876

6977
end if check_assertion
7078

0 commit comments

Comments
 (0)