├── .gitignore ├── LICENCE ├── Makefile ├── README.md ├── examples ├── multi │ └── multi.f90 └── simple │ └── simple.f90 └── src └── pthread.f90 /.gitignore: -------------------------------------------------------------------------------- 1 | # C extensions 2 | *.so 3 | 4 | # Distribution / packaging 5 | env/ 6 | build/ 7 | dist/ 8 | var/ 9 | 10 | # Other stuff 11 | *.swp 12 | *.pyc 13 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Philipp Engel 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose 4 | with or without fee is hereby granted, provided that the above copyright notice 5 | and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 12 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 13 | THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .POSIX: 2 | .SUFFIXES: 3 | 4 | FC = gfortran 5 | PREFIX = /usr/local 6 | FFLAGS = -Wall -fmax-errors=1 7 | LDFLAGS = -I$(PREFIX)/include/ -L$(PREFIX)/local/lib/ 8 | LDLIBS = -lpthread 9 | TARGET = pthread.o 10 | 11 | EXAMPLES = examples 12 | SIMPLE = simple 13 | MULTI = multi 14 | 15 | .PHONY: all clean 16 | 17 | all: $(OBJ) $(SIMPLE) $(MULTI) 18 | 19 | $(TARGET): 20 | $(FC) -c src/pthread.f90 21 | 22 | $(SIMPLE): $(TARGET) 23 | $(FC) $(FFLAGS) $(LDFLAGS) -o $(SIMPLE) $(EXAMPLES)/$(SIMPLE)/$(SIMPLE).f90 $(LDLIBS) 24 | 25 | $(MULTI): $(TARGET) 26 | $(FC) $(FFLAGS) $(LDFLAGS) -o $(MULTI) $(EXAMPLES)/$(MULTI)/$(MULTI).f90 $(LDLIBS) 27 | 28 | clean: 29 | rm *.mod *.o $(SIMPLE) $(MULTI) 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fortran-pthread 2 | Proof of concept of Fortran 2003 interfaces to POSIX Threads. 3 | 4 | ## Build 5 | Use the provided `Makefile` to build the interfaces: 6 | 7 | ``` 8 | $ make 9 | ``` 10 | 11 | Or, run your favourite Fortran compiler directly: 12 | 13 | ``` 14 | $ gfortran -c src/pthread.f90 15 | ``` 16 | 17 | ## Examples 18 | Please check directory `examples` for demos: 19 | 20 | * **simple** runs a routine inside a `pthread`. 21 | * **multi** runs a routine inside several `pthreads`. 22 | 23 | Compile the examples with: 24 | 25 | ``` 26 | $ make 27 | ``` 28 | 29 | ## Licence 30 | ISC 31 | -------------------------------------------------------------------------------- /examples/multi/multi.f90: -------------------------------------------------------------------------------- 1 | ! multi.f90 2 | ! 3 | ! Example that shows how to run a routine inside several pthreads. 4 | ! 5 | ! Author: Philipp Engel 6 | ! Licence: ISC 7 | module util 8 | implicit none 9 | public :: hello 10 | contains 11 | subroutine hello(n) 12 | integer, intent(in) :: n 13 | integer :: i 14 | 15 | do i = 1, 10 16 | call sleep(1) 17 | print '("Thread #", i0, " - ", i2)', n, i 18 | end do 19 | end subroutine hello 20 | end module util 21 | 22 | program main 23 | use, intrinsic :: iso_c_binding 24 | use :: pthread 25 | use :: util 26 | integer, parameter :: NTHREADS = 5 27 | integer :: i, rc 28 | 29 | type(pthread_t), target :: threads(NTHREADS) 30 | integer, target :: routines(NTHREADS) = [ (i, i = 1, NTHREADS) ] 31 | 32 | do i = 1, NTHREADS 33 | rc = pthread_create(c_loc(threads(i)), c_null_ptr, c_funloc(hello), c_loc(routines(i))) 34 | end do 35 | 36 | do i = 1, NTHREADS 37 | rc = pthread_join(threads(i), c_loc(routines(i))) 38 | end do 39 | end program main 40 | -------------------------------------------------------------------------------- /examples/simple/simple.f90: -------------------------------------------------------------------------------- 1 | ! simple.f90 2 | ! 3 | ! Example that shows how to run a routine inside a pthread. 4 | ! 5 | ! Author: Philipp Engel 6 | ! Licence: ISC 7 | module util 8 | implicit none 9 | public :: hello 10 | contains 11 | subroutine hello() 12 | integer :: i 13 | 14 | do i = 1, 10 15 | print '(i2, ": Hello, World!")', i 16 | end do 17 | end subroutine hello 18 | end module util 19 | 20 | program main 21 | use, intrinsic :: iso_c_binding 22 | use :: pthread 23 | use :: util 24 | implicit none 25 | type(pthread_t), target :: thread 26 | integer :: rc 27 | 28 | rc = pthread_create(c_loc(thread), c_null_ptr, c_funloc(hello), c_null_ptr) 29 | rc = pthread_join(thread, c_null_ptr) 30 | end program main 31 | -------------------------------------------------------------------------------- /src/pthread.f90: -------------------------------------------------------------------------------- 1 | ! pthread.f90 2 | ! 3 | ! Fortran 2003 ISO C binding interfaces to POSIX Threads. 4 | ! 5 | ! Author: Philipp Engel 6 | ! Licence: ISC 7 | module pthread 8 | use, intrinsic :: iso_c_binding 9 | implicit none 10 | private 11 | integer, parameter :: SIZE_OF_TYPE = 2 12 | 13 | type, bind(c), public :: pthread_t 14 | private 15 | integer(kind=c_int) :: hidden(SIZE_OF_TYPE) 16 | end type pthread_t 17 | 18 | public :: pthread_create 19 | public :: pthread_join 20 | 21 | interface 22 | ! int pthread_create(pthread_t *, const pthread_attr_t *, void *(void *), void *) 23 | function pthread_create(thread, attr, start_routine, arg) bind(c, name='pthread_create') 24 | import :: c_int, c_ptr, c_funptr 25 | type(c_ptr), intent(in), value :: thread 26 | type(c_ptr), intent(in), value :: attr 27 | type(c_funptr), intent(in), value :: start_routine 28 | type(c_ptr), intent(in), value :: arg 29 | integer(kind=c_int) :: pthread_create 30 | end function pthread_create 31 | 32 | ! int pthread_join(pthread_t, void **) 33 | function pthread_join( thread, value_ptr) bind(c, name='pthread_join') 34 | import :: c_int, c_ptr, pthread_t 35 | type(pthread_t), intent(in), value :: thread 36 | type(c_ptr), intent(in) :: value_ptr 37 | integer(kind=c_int) :: pthread_join 38 | end function pthread_join 39 | end interface 40 | end module pthread 41 | --------------------------------------------------------------------------------