Skip to content

Commit

Permalink
Refactor to return default Fortran logical kind (#340)
Browse files Browse the repository at this point in the history
Many routines were returning logical(kind=c_bool) which is not the
same default kind used for logicals by some compilers (e.g. GCC
sets logical to be kind=4). Now these functions return the default
logical kind so that users will not have to import iso_c_binding
into their code.

[ committed by @ashao ]
[ reviewed by @billschereriii ]
  • Loading branch information
ashao authored May 11, 2023
1 parent 913bdd0 commit 8138be1
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 33 deletions.
5 changes: 5 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ To be released at some future point in time

Description

- Refactor Fortran methods to return default logical kind
- Update CI/CD tests to use a modern version of MacOS
- Fix the spelling of the Dataset destructor's C interface (now DeallocateDataSet)
- Update Redis++ version to 1.3.8
Expand All @@ -17,13 +18,17 @@ Description

Detailed Notes

- Many Fortran routines were returning logical kind = c_bool which turns out not to be
the same default kind of most Fortran compilers. These have now been refactored so that
users need not import `iso_c_binding` in their own applications (PR340_)
- Update MacOS version in CI/CD tests from 10.15 to 12.0 (PR339_)
- Correct the spelling of the C DataSet destruction interface from DeallocateeDataSet to DeallocateDataSet (PR338_)
- Updated the version of Redis++ to v1.3.8 to pull in a change that ensures the redis++.pc file properly points to the generated libraries (PR334_)
- Third-party software dependency installation is now handled in the Makefile instead of separate scripts
- New pip-install target in Makefile will be a dependency of the lib target going forward so that users don't have to manually pip install SmartRedis in the future (PR330_)
- Added ConfigOptions class and API, which will form the backbone of multiDB support (PR303_)

.. _PR340: https://github.com/CrayLabs/SmartRedis/pull/340
.. _PR339: https://github.com/CrayLabs/SmartRedis/pull/339
.. _PR338: https://github.com/CrayLabs/SmartRedis/pull/338
.. _PR334: https://github.com/CrayLabs/SmartRedis/pull/334
Expand Down
66 changes: 44 additions & 22 deletions src/fortran/client.F90
Original file line number Diff line number Diff line change
Expand Up @@ -291,67 +291,75 @@ end function get_c_pointer
function key_exists(self, key, exists)
class(client_type), intent(in) :: self !< The client
character(len=*), intent(in) :: key !< The key to check
logical(kind=c_bool), intent(out) :: exists !< Receives whether the key exists
logical, intent(out) :: exists !< Receives whether the key exists
integer(kind=enum_kind) :: key_exists

! Local variables
character(kind=c_char, len=len_trim(key)) :: c_key
integer(kind=c_size_t) :: c_key_length
logical(kind=c_bool) :: c_exists

c_key = trim(key)
c_key_length = len_trim(key)

key_exists = key_exists_c(self%client_ptr, c_key, c_key_length, exists)
key_exists = key_exists_c(self%client_ptr, c_key, c_key_length, c_exists)
exists = c_exists
end function key_exists

!> Check if the specified model exists in the database
function model_exists(self, model_name, exists) result(code)
class(client_type), intent(in) :: self !< The client
character(len=*), intent(in) :: model_name !< The model to check
logical(kind=c_bool), intent(out) :: exists !< Receives whether the model exists
logical, intent(out) :: exists !< Receives whether the model exists
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char, len=len_trim(model_name)) :: c_model_name
integer(kind=c_size_t) :: c_model_name_length
logical(kind=c_bool) :: c_exists

c_model_name = trim(model_name)
c_model_name_length = len_trim(model_name)

code = model_exists_c(self%client_ptr, c_model_name, c_model_name_length, exists)
code = model_exists_c(self%client_ptr, c_model_name, c_model_name_length, c_exists)
exists = c_exists
end function model_exists

!> Check if the specified tensor exists in the database
function tensor_exists(self, tensor_name, exists) result(code)
class(client_type), intent(in) :: self !< The client
character(len=*), intent(in) :: tensor_name !< The tensor to check
logical(kind=c_bool), intent(out) :: exists !< Receives whether the model exists
logical, intent(out) :: exists !< Receives whether the model exists
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char, len=len_trim(tensor_name)) :: c_tensor_name
integer(kind=c_size_t) :: c_tensor_name_length
logical(kind=c_bool) :: c_exists

c_tensor_name = trim(tensor_name)
c_tensor_name_length = len_trim(tensor_name)

code = tensor_exists_c(self%client_ptr, c_tensor_name, c_tensor_name_length, exists)
code = tensor_exists_c(self%client_ptr, c_tensor_name, c_tensor_name_length, c_exists)
exists = c_exists
end function tensor_exists

!> Check if the specified dataset exists in the database
function dataset_exists(this, dataset_name, exists) result(code)
class(client_type), intent(in) :: this !< The client
character(len=*), intent(in) :: dataset_name !< The dataset to check
logical(kind=c_bool), intent(out) :: exists !< Receives whether the model exists
logical, intent(out) :: exists !< Receives whether the model exists
integer(kind=enum_kind) :: code

character(kind=c_char, len=len_trim(dataset_name)) :: c_dataset_name
integer(kind=c_size_t) :: c_dataset_name_length
logical(kind=c_bool) :: c_exists

c_dataset_name = trim(dataset_name)
c_dataset_name_length = len_trim(dataset_name)

code = dataset_exists_c(this%client_ptr, c_dataset_name, c_dataset_name_length, exists)
code = dataset_exists_c(this%client_ptr, c_dataset_name, c_dataset_name_length, c_exists)
exists = c_exists
end function dataset_exists

!> Repeatedly poll the database until the tensor exists or the number of tries is exceeded
Expand All @@ -360,20 +368,22 @@ function poll_tensor(self, tensor_name, poll_frequency_ms, num_tries, exists) re
character(len=*), intent(in) :: tensor_name !< name in the database to poll
integer, intent(in) :: poll_frequency_ms !< Frequency at which to poll the database (ms)
integer, intent(in) :: num_tries !< Number of times to poll the database before failing
logical(kind=c_bool), intent(out) :: exists !< Receives whether the tensor exists
logical, intent(out) :: exists !< Receives whether the tensor exists
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char,len=len_trim(tensor_name)) :: c_tensor_name
integer(kind=c_size_t) :: c_tensor_name_length
integer(kind=c_int) :: c_poll_frequency, c_num_tries
logical(kind=c_bool) :: c_exists

c_tensor_name = trim(tensor_name)
c_tensor_name_length = len_trim(tensor_name)
c_num_tries = num_tries
c_poll_frequency = poll_frequency_ms

code = poll_tensor_c(self%client_ptr, c_tensor_name, c_tensor_name_length, c_poll_frequency, c_num_tries, exists)
code = poll_tensor_c(self%client_ptr, c_tensor_name, c_tensor_name_length, c_poll_frequency, c_num_tries, c_exists)
exists = c_exists
end function poll_tensor

!> Repeatedly poll the database until the dataset exists or the number of tries is exceeded
Expand All @@ -383,19 +393,21 @@ function poll_dataset(self, dataset_name, poll_frequency_ms, num_tries, exists)
character(len=*), intent(in) :: dataset_name !< Name in the database to poll
integer, intent(in) :: poll_frequency_ms !< Frequency at which to poll the database (ms)
integer, intent(in) :: num_tries !< Number of times to poll the database before failing
logical(kind=c_bool), intent(out) :: exists !< Receives whether the tensor exists
logical, intent(out) :: exists !< Receives whether the tensor exists

! Local variables
character(kind=c_char,len=len_trim(dataset_name)) :: c_dataset_name
integer(kind=c_size_t) :: c_dataset_name_length
integer(kind=c_int) :: c_poll_frequency, c_num_tries
logical(kind=c_bool) :: c_exists

c_dataset_name = trim(dataset_name)
c_dataset_name_length = len_trim(dataset_name)
c_num_tries = num_tries
c_poll_frequency = poll_frequency_ms

poll_dataset = poll_dataset_c(self%client_ptr, c_dataset_name, c_dataset_name_length, c_poll_frequency, c_num_tries, exists)
poll_dataset = poll_dataset_c(self%client_ptr, c_dataset_name, c_dataset_name_length, c_poll_frequency, c_num_tries, c_exists)
exists = c_exists
end function poll_dataset

!> Repeatedly poll the database until the model exists or the number of tries is exceeded
Expand All @@ -404,20 +416,22 @@ function poll_model(self, model_name, poll_frequency_ms, num_tries, exists) resu
character(len=*), intent(in) :: model_name !< Name in the database to poll
integer, intent(in) :: poll_frequency_ms !< Frequency at which to poll the database (ms)
integer, intent(in) :: num_tries !< Number of times to poll the database before failing
logical(kind=c_bool), intent(out) :: exists !< Receives whether the model exists
logical, intent(out) :: exists !< Receives whether the model exists
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char,len=len_trim(model_name)) :: c_model_name
integer(kind=c_size_t) :: c_model_name_length
integer(kind=c_int) :: c_poll_frequency, c_num_tries
logical(kind=c_bool) :: c_exists

c_model_name = trim(model_name)
c_model_name_length = len_trim(model_name)
c_num_tries = num_tries
c_poll_frequency = poll_frequency_ms

code = poll_model_c(self%client_ptr, c_model_name, c_model_name_length, c_poll_frequency, c_num_tries, exists)
code = poll_model_c(self%client_ptr, c_model_name, c_model_name_length, c_poll_frequency, c_num_tries, c_exists)
exists = c_exists
end function poll_model

!> Repeatedly poll the database until the key exists or the number of tries is exceeded
Expand All @@ -426,20 +440,22 @@ function poll_key(self, key, poll_frequency_ms, num_tries, exists) result(code)
character(len=*), intent(in) :: key !< Key in the database to poll
integer, intent(in) :: poll_frequency_ms !< Frequency at which to poll the database (ms)
integer, intent(in) :: num_tries !< Number of times to poll the database before failing
logical(kind=c_bool), intent(out) :: exists !< Receives whether the key exists
logical, intent(out) :: exists !< Receives whether the key exists
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char, len=len_trim(key)) :: c_key
integer(kind=c_size_t) :: c_key_length
integer(kind=c_int) :: c_poll_frequency, c_num_tries
logical(kind=c_bool) :: c_exists

c_key = trim(key)
c_key_length = len_trim(key)
c_num_tries = num_tries
c_poll_frequency = poll_frequency_ms

code = poll_key_c(self%client_ptr, c_key, c_key_length, c_poll_frequency, c_num_tries, exists)
code = poll_key_c(self%client_ptr, c_key, c_key_length, c_poll_frequency, c_num_tries, c_exists)
exists = c_exists
end function poll_key

!> Put a tensor whose Fortran type is the equivalent 'int8' C-type
Expand Down Expand Up @@ -1679,13 +1695,14 @@ function poll_list_length(self, list_name, list_length, poll_frequency_ms, num_t
integer, intent(in ) :: list_length !< The desired length of the list
integer, intent(in ) :: poll_frequency_ms !< Frequency at which to poll the database (ms)
integer, intent(in ) :: num_tries !< Number of times to poll the database before failing
logical(kind=c_bool), intent( out) :: poll_result !< True if the list is the requested length, False if not after num_tries.
logical, intent( out) :: poll_result !< True if the list is the requested length, False if not after num_tries.
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char, len=len_trim(list_name)) :: list_name_c
integer(kind=c_size_t) :: list_name_length
integer(kind=c_int) :: c_poll_frequency, c_num_tries, c_list_length
logical(kind=c_bool) :: c_poll_result

list_name_c = trim(list_name)
list_name_length = len_trim(list_name)
Expand All @@ -1694,7 +1711,8 @@ function poll_list_length(self, list_name, list_length, poll_frequency_ms, num_t
c_list_length = list_length

code = poll_list_length_c(self%client_ptr, list_name_c, list_name_length, &
c_list_length, c_poll_frequency, c_num_tries, poll_result)
c_list_length, c_poll_frequency, c_num_tries, c_poll_result)
poll_result = c_poll_result
end function poll_list_length

!> Get the length of the aggregation list
Expand All @@ -1704,13 +1722,14 @@ function poll_list_length_gte(self, list_name, list_length, poll_frequency_ms, n
integer, intent(in ) :: list_length !< The desired length of the list
integer, intent(in ) :: poll_frequency_ms !< Frequency at which to poll the database (ms)
integer, intent(in ) :: num_tries !< Number of times to poll the database before failing
logical(kind=c_bool), intent( out) :: poll_result !< True if the list is the requested length, False if not after num_tries.
logical, intent( out) :: poll_result !< True if the list is the requested length, False if not after num_tries.
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char, len=len_trim(list_name)) :: list_name_c
integer(kind=c_size_t) :: list_name_length
integer(kind=c_int) :: c_poll_frequency, c_num_tries, c_list_length
logical(kind=c_bool) :: c_poll_result

list_name_c = trim(list_name)
list_name_length = len_trim(list_name)
Expand All @@ -1719,7 +1738,8 @@ function poll_list_length_gte(self, list_name, list_length, poll_frequency_ms, n
c_list_length = list_length

code = poll_list_length_gte_c(self%client_ptr, list_name_c, list_name_length, &
c_list_length, c_poll_frequency, c_num_tries, poll_result)
c_list_length, c_poll_frequency, c_num_tries, c_poll_result)
poll_result = c_poll_result
end function poll_list_length_gte

!> Get the length of the aggregation list
Expand All @@ -1729,13 +1749,14 @@ function poll_list_length_lte(self, list_name, list_length, poll_frequency_ms, n
integer, intent(in) :: list_length !< The desired length of the list
integer, intent(in) :: poll_frequency_ms !< Frequency at which to poll the database (ms)
integer, intent(in) :: num_tries !< Number of times to poll the database before failing
logical(kind=c_bool), intent(out) :: poll_result !< True if the list is the requested length, False if not after num_tries.
logical, intent(out) :: poll_result !< True if the list is the requested length, False if not after num_tries.
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char, len=len_trim(list_name)) :: list_name_c
integer(kind=c_size_t) :: list_name_length
integer(kind=c_int) :: c_poll_frequency, c_num_tries, c_list_length
logical(kind=c_bool) :: c_poll_result

list_name_c = trim(list_name)
list_name_length = len_trim(list_name)
Expand All @@ -1744,7 +1765,8 @@ function poll_list_length_lte(self, list_name, list_length, poll_frequency_ms, n
c_list_length = list_length

code = poll_list_length_lte_c(self%client_ptr, list_name_c, list_name_length, &
c_list_length, c_poll_frequency, c_num_tries, poll_result)
c_list_length, c_poll_frequency, c_num_tries, c_poll_result)
poll_result = c_poll_result
end function poll_list_length_lte

!> Get datasets from an aggregation list. Note that this will deallocate an existing list.
Expand Down
12 changes: 7 additions & 5 deletions src/fortran/configoptions.F90
Original file line number Diff line number Diff line change
Expand Up @@ -155,21 +155,23 @@ end function get_string_option

!> Check whether a configuration option is set
function is_configured(self, option_name, result) result(code)
class(configoptions_type), intent(in) :: self !< The configoptions
character(len=*), intent(in) :: option_name !< The name of the configuration
class(configoptions_type), intent(in) :: self !< The configoptions
character(len=*), intent(in) :: option_name !< The name of the configuration
!! option to check
logical(kind=c_bool), intent(inout) :: result !< Receives value of option
integer(kind=enum_kind) :: code
logical, intent(inout) :: result !< Receives value of option
integer(kind=enum_kind) :: code

! Local variables
character(kind=c_char, len=len_trim(option_name)) :: c_option_name
integer(kind=c_size_t) :: c_option_name_length
logical(kind=c_bool) :: c_result

c_option_name = trim(option_name)
c_option_name_length = len_trim(option_name)

code = is_configured_c( &
self%configoptions_ptr, c_option_name, c_option_name_length, result)
self%configoptions_ptr, c_option_name, c_option_name_length, c_result)
result = c_result
end function is_configured

!> Override the value of a numeric configuration option
Expand Down
2 changes: 1 addition & 1 deletion src/fortran/dataset.F90
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

module smartredis_dataset

use iso_c_binding, only : c_ptr, c_bool, c_null_ptr, c_char, c_int
use iso_c_binding, only : c_ptr, c_char, c_int
use iso_c_binding, only : c_int8_t, c_int16_t, c_int32_t, c_int64_t, c_float, c_double, c_size_t
use iso_c_binding, only : c_loc, c_f_pointer

Expand Down
2 changes: 1 addition & 1 deletion tests/fortran/client_test_configoptions.F90
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ program main
type(configoptions_type) :: co
integer :: result
integer(kind=8) :: ivalue, iresult ! int
logical(kind=c_bool) :: bvalue, bresult ! bool
logical :: bvalue, bresult ! bool
character(kind=c_char, len=:), allocatable :: svalue, sresult ! string

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Expand Down
2 changes: 1 addition & 1 deletion tests/fortran/client_test_dataset.F90
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ program main
integer :: result
integer :: ttype
integer :: mdtype
logical(kind=c_bool) :: exists
logical :: exists
character(kind=c_char, len=:), allocatable :: dumpstr

call random_number(true_array_real_32)
Expand Down
2 changes: 1 addition & 1 deletion tests/fortran/client_test_ensemble.F90
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ program main
real, dimension(10) :: tensor
type(client_type) :: client
integer :: result
logical(kind=c_bool) :: exists
logical :: exists

ensemble_keyout = "producer_0"
call setenv("SSKEYIN", "producer_0,producer_1")
Expand Down
2 changes: 1 addition & 1 deletion tests/fortran/client_test_misc_tensor.F90
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ program main

integer :: err_code
integer :: result
logical(kind=c_bool) :: exists
logical :: exists

result = client%initialize(use_cluster(), "client_test_misc_tensor")
if (result .ne. SRNoError) error stop
Expand Down
2 changes: 1 addition & 1 deletion tests/fortran/client_test_prefixing.F90
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ program main
type(client_type) :: client
type(dataset_type) :: dataset
integer :: result
logical(kind=c_bool) :: exists
logical :: exists

prefix = "prefix_test"
call setenv("SSKEYIN", prefix)
Expand Down

0 comments on commit 8138be1

Please sign in to comment.