- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I want to ask why, but I should know better:
INTEGER, VOLATILE, TARGET :: I1 = 2 INTEGER, POINTER :: PI1 INTEGER :: I2= 8 ! Body of Interlocked PI1=>I1 if (loc(PI1) == loc(I1)) print *, "true"
prints true?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
LOC is an Intel (and others) extension, so consult the Intel documentation for the expected behaviour. That documentation defines LOC such that for pointer arguments, you get the address of the associated target.
This is consistent with how pointers in Fortran work, outside of a pointer association context you work on or with the target of the pointer.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>outside of a pointer association context you work on or with the target of the pointer
For illustration, consider:
real, allocatable :: Array integer(C_PTR) :: locArray ... allocate(Array(1234)) ... locArray = LOC(Array)
The intention is to return the address of the first cell of the array as opposed to the location of the array descriptor that references Array.
If you really need the address of the pointer, that would be the subject of a different matter.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks and to me both answers are best. There is another closed post about dereferncing c_ptrs, https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/282809 from 2011, and I wonder if anything has changed since then? Assuming Fortran type is known and if array,length, then use CALL C_F_POINTER(PCI1, PFI1 [,shape])?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FWIW
If the Fortran pointer is that to a scalar or to a user defined type (NOT an array) and you wish for the pointer itself to be interlocked... the make a user defined type containing only that pointer
type foo_t ... end type foo_t type p_foo_t type(foo_t), pointer :: p end type p_foo_t ... type node_t type(p_foo_t) :: next type(foo_t) :: foo end type node_t ... a_node => someNode ... ...(LOC(a_node%next), ... ! address of the pointer a_node%next%p
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I will be playing with that for a while....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The confusion here is that a pointer in Fortran is not like a pointer in C. When you "reference" a pointer, you're referencing its target. There is no good way in Fortran to get the address of the pointer itself.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove (Blackbelt) wrote:FWIW
If the Fortran pointer is that to a scalar or to a user defined type (NOT an array) and you wish for the pointer itself to be interlocked... the make a user defined type containing only that pointer ..
Jim,
Fortran standard effectively makes a derived type available for this: C_PTR in the intrinsic ISO_C_BINDING.
I'm not exactly sure what is of interest to OP but using the standard facilities in Fortran rather than any compiler vendor-specific extensions and viewing an object in Fortran with the POINTER attribute as ephemeral but working with the derived type C_PTR for whatever needs there may be for OP may be the better option:
use, intrinsic :: iso_c_binding, only : c_long, c_ptr, c_loc, c_intptr_t, c_f_pointer interface function InterlockedExchangeAdd(Addend,Value) result(r) bind(C, name="InterlockedExchangeAdd") !DIR$ ATTRIBUTES STDCALL :: InterlockedExchangeAdd ! MSDN function prototype: ! https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-interlockedexchangeadd ! LONG InterlockedExchangeAdd( ! LONG volatile *Addend, ! LONG Value !); import :: c_long implicit none ! Argument list integer(c_long), volatile, intent(inout) :: Addend integer(c_long), value, intent(in) :: Value ! Function result integer(c_long) :: r end function end interface ! Local variables integer(c_long) :: I0 = 1 integer(c_long), volatile, target :: I1 = 2 integer(c_long) :: I2 = 42 I0 = InterlockedExchangeAdd(I1, I2) print *, "I0 = ", I0 blk_loc: block ! type(c_ptr) as 'proxy' for integer, pointer type(c_ptr) :: PI1 integer(c_long), pointer :: ptrI1 => null() integer(c_intptr_t) :: add_ptrI1 PI1 = c_loc(I1) call c_f_pointer( PI1, fptr=ptrI1 ) print *, "PI1 = ", ptrI1, "; expected is ", I0+I2 ptrI1 => null() ! view ptrI1 as ephemeral; work with type(c_ptr) :: PI1 instead print *, "Address of PI1 = ", transfer( source=c_loc(PI1), mold=add_ptrI1 ) end block blk_loc stop end
Upon execution,
C:\Temp>ifort /standard-semantics /warn:all /stand:f18 p.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 19.1.0.085 Pre-Release Beta Build 20190522 Copyright (C) 1985-2019 Intel Corporation. All rights reserved. ifort: NOTE: The Beta evaluation period for this product ends on 9-oct-2019 UTC. p.f90(5): warning #7025: This directive is not standard F2018. !DIR$ ATTRIBUTES STDCALL :: InterlockedExchangeAdd ------------^ Microsoft (R) Incremental Linker Version 14.21.27702.2 Copyright (C) Microsoft Corporation. All rights reserved. -out:p.exe -subsystem:console p.obj C:\Temp>p.exe I0 = 2 PI1 = 44 ; expected is 44 Address of PI1 = 18348584 C:\Temp>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The OP desired for the use of an INTEGER, POINTER as the argument of InterlockedExchangeAdd
Using INTEGER(C_PTR) makes the named pointer unusable for use by the Fortran code (statements) as a pointer.
This results in the programmer being required to do some hoop jumping in order to use the Addend of the InterlockedExchangeAdd as a Fortran pointer to integer. The user defined type does this cleanly with the expense of node%nexr%p in the user code. This would be a user preference.
BTW EQUIVALENCE would handle this nicely too.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove (Blackbelt) wrote:The OP desired for the use of an INTEGER, POINTER as the argument of InterlockedExchangeAdd
Using INTEGER(C_PTR) makes the named pointer unusable for use by the Fortran code (statements) as a pointer.
This results in the programmer being required to do some hoop jumping in order to use the Addend of the InterlockedExchangeAdd as a Fortran pointer to integer ..
OP (and any other reader) wanting to perform atomic operations using Windows OS kernel functions can try to use standard Fortran facilities for the interoperation instead of Intel-supplied non-standard compiler-specific options and thus bypass the need to use LOC in the first place and not have to deal with the addresses of objects ..
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page