1
- module fortran_subprocess
1
+ submodule (stdlib_system) stdlib_system_subprocess
2
2
use iso_c_binding
3
3
use iso_fortran_env, only: int64, real64
4
4
use stdlib_system
5
5
use stdlib_strings, only: to_c_string, join
6
6
use stdlib_linalg_state, only: linalg_state_type, LINALG_ERROR, linalg_error_handling
7
- implicit none
8
- public
7
+ implicit none (type, external )
9
8
10
- ! Interoperable types
11
- integer , parameter , public :: pid_t = c_int64_t
12
-
13
- logical (c_bool), parameter , private :: C_FALSE = .false. _c_bool
14
- logical (c_bool), parameter , private :: C_TRUE = .true. _c_bool
15
-
16
- ! CPU clock ticks range
17
- integer , parameter , private :: TICKS = int64
18
- integer , parameter , private :: RTICKS = real64
9
+ logical (c_bool), parameter :: C_FALSE = .false. _c_bool
10
+ logical (c_bool), parameter :: C_TRUE = .true. _c_bool
19
11
20
12
! Number of CPU ticks between status updates
21
13
integer (TICKS), parameter :: CHECK_EVERY_TICKS = 100
22
14
23
- ! Default flag for the runner process
24
- integer (pid_t), parameter :: FORKED_PROCESS = 0_pid_t
25
-
26
15
! Interface to C support functions from stdlib_system_subprocess.c
27
16
interface
28
17
29
18
! C wrapper to query process status
30
19
subroutine process_query_status (pid , wait , is_running , exit_code ) &
31
20
bind(C, name= ' process_query_status' )
32
- import c_int, c_bool, pid_t
21
+ import c_int, c_bool, process_ID
33
22
implicit none
34
23
! Process ID
35
- integer (pid_t ), value :: pid
24
+ integer (process_ID ), value :: pid
36
25
! Whether to wait for process completion
37
26
logical (c_bool), value :: wait
38
27
! Whether the process is still running
@@ -43,15 +32,15 @@ end subroutine process_query_status
43
32
44
33
subroutine process_create (cmd , stdin_stream , stdin_file , stdout_file , stderr_file , handle , pid ) &
45
34
bind(C, name= ' process_create' )
46
- import c_char, c_ptr, pid_t
35
+ import c_char, c_ptr, process_ID
47
36
implicit none
48
37
character (c_char), intent (in ) :: cmd(* )
49
38
character (c_char), intent (in ), optional :: stdin_stream(* )
50
39
character (c_char), intent (in ), optional :: stdin_file(* )
51
40
character (c_char), intent (in ), optional :: stdout_file(* )
52
41
character (c_char), intent (in ), optional :: stderr_file(* )
53
42
type (c_ptr) , intent (out ) :: handle
54
- integer (pid_t ), intent (out ) :: pid
43
+ integer (process_ID ), intent (out ) :: pid
55
44
end subroutine process_create
56
45
57
46
subroutine process_wait (seconds ) bind(C,name= ' process_wait' )
@@ -68,52 +57,13 @@ end function process_null_device
68
57
69
58
end interface
70
59
71
- type, public :: process_type
72
-
73
- ! > Process ID (if external); 0 if run by the program process
74
- integer (pid_t) :: id = FORKED_PROCESS
75
- type (c_ptr) :: handle = c_null_ptr
76
-
77
- ! > Process is completed
78
- logical :: completed = .false.
79
- integer (TICKS) :: start_time = 0
80
-
81
- ! > Process exit code
82
- integer :: exit_code = 0
83
-
84
- ! > Stdin file name
85
- character (:), allocatable :: stdin_file
86
-
87
- ! > Standard output
88
- character (:), allocatable :: stdout_file
89
- character (:), allocatable :: stdout
90
-
91
- ! > Error output
92
- character (:), allocatable :: stderr_file
93
- character (:), allocatable :: stderr
94
-
95
- ! > Store time at the last update
96
- integer (TICKS) :: last_update = 0
97
-
98
- contains
99
-
100
- ! > Return process lifetime so far, in seconds
101
- procedure :: elapsed = > process_lifetime
102
-
103
- ! > Live check if a process is still running
104
- procedure :: is_running = > process_is_running
105
- procedure :: is_completed = > process_is_completed
106
-
107
- ! > Wait until a running process is completed
108
- procedure :: wait = > wait_for_completion
109
-
110
- end type process_type
60
+
111
61
112
62
113
63
contains
114
64
115
65
! > Open a new, asynchronous process
116
- type (process_type) function process_open(args,wait,stdin,want_stdout,want_stderr) result(process)
66
+ module type (process_type) function process_open(args,wait,stdin,want_stdout,want_stderr) result(process)
117
67
! > The command and arguments
118
68
character (* ), intent (in ) :: args(:)
119
69
! > Optional character input to be sent to the process via pipe
@@ -178,8 +128,6 @@ type(process_type) function process_open(args,wait,stdin,want_stdout,want_stderr
178
128
179
129
endif
180
130
181
-
182
-
183
131
! Run a first update
184
132
call update_process_state(process)
185
133
@@ -249,7 +197,7 @@ subroutine launch_synchronous(process, args, stdin)
249
197
end subroutine launch_synchronous
250
198
251
199
! > Return the current (or total) process lifetime, in seconds
252
- real(RTICKS) function process_lifetime (process ) result(delta_t)
200
+ module real (RTICKS) function process_lifetime(process) result(delta_t)
253
201
class(process_type), intent (in ) :: process
254
202
255
203
real (RTICKS) :: ticks_per_second
@@ -271,7 +219,7 @@ real(RTICKS) function process_lifetime(process) result(delta_t)
271
219
end function process_lifetime
272
220
273
221
! > Wait for a process to be completed
274
- subroutine wait_for_completion (process , max_wait_time )
222
+ module subroutine wait_for_completion (process , max_wait_time )
275
223
class(process_type), intent (inout ) :: process
276
224
! Optional max wait time in seconds
277
225
real , optional , intent (in ) :: max_wait_time
@@ -310,7 +258,7 @@ subroutine update_process_state(process)
310
258
311
259
real (RTICKS) :: count_rate
312
260
integer (TICKS) :: count_max,current_time
313
- logical (c_bool) :: is_running
261
+ logical (c_bool) :: running
314
262
integer (c_int) :: exit_code
315
263
316
264
! If the process has completed, should not be queried again
@@ -328,9 +276,9 @@ subroutine update_process_state(process)
328
276
if (process% id /= FORKED_PROCESS) then
329
277
330
278
! Query process state
331
- call process_query_status(process% id, wait= C_FALSE, is_running= is_running , exit_code= exit_code)
279
+ call process_query_status(process% id, wait= C_FALSE, is_running= running , exit_code= exit_code)
332
280
333
- process% completed = .not. is_running
281
+ process% completed = .not. running
334
282
335
283
if (process% completed) then
336
284
! Process completed, may have returned an error code
@@ -346,15 +294,15 @@ subroutine save_completed_state(process,delete_files)
346
294
type (process_type), intent (inout ) :: process
347
295
logical , intent (in ) :: delete_files
348
296
349
- logical (c_bool) :: is_running
297
+ logical (c_bool) :: running
350
298
integer (c_int) :: exit_code
351
299
integer :: delete
352
300
353
301
! Same as process ID: process exited
354
302
process% completed = .true.
355
303
356
304
! Clean up process state using waitpid
357
- if (process% id/= FORKED_PROCESS) call process_query_status(process% id, C_TRUE, is_running , exit_code)
305
+ if (process% id/= FORKED_PROCESS) call process_query_status(process% id, C_TRUE, running , exit_code)
358
306
359
307
! Process is over: load stdout/stderr if requested
360
308
if (allocated (process% stderr_file)) then
@@ -376,7 +324,7 @@ subroutine save_completed_state(process,delete_files)
376
324
end subroutine save_completed_state
377
325
378
326
! > Live check if a process is running
379
- logical function process_is_running (process ) result(is_running)
327
+ module logical function process_is_running(process) result(is_running)
380
328
class(process_type), intent (inout ) :: process
381
329
382
330
! Each evaluation triggers a state update
@@ -387,7 +335,7 @@ logical function process_is_running(process) result(is_running)
387
335
end function process_is_running
388
336
389
337
! > Live check if a process has completed
390
- logical function process_is_completed (process ) result(is_completed)
338
+ module logical function process_is_completed(process) result(is_completed)
391
339
class(process_type), intent (inout ) :: process
392
340
393
341
! Each evaluation triggers a state update
@@ -580,4 +528,4 @@ function getfile(fileName,err,delete) result(file)
580
528
581
529
end function getfile
582
530
583
- end module fortran_subprocess
531
+ end submodule stdlib_system_subprocess
0 commit comments