Search code examples
stmchapeltransactional-memory

Convert a 'ref dataType' argument to a 'ptr(dataType)' in Chapel


Is there an official way to convert an argument passed by reference to a pointer to the exact same type? I know that during the CodeGen phase of compilation that ref int becomes int *, and I know that you can do so with extern for C interoperability sake, but what about for the sake of writing Chapel abstractions? Furthermore, what about the case of wide references and wide pointers? How would you handle something like that.

For those curious, I'm experimenting with some PGAS-STM (Partitioned Global Address Space - Software Transactional Memory) and one of the things I need to do is to allow semantics as follows...

Prepend to list using STM:

// Global variables
var head : node(eltType);

// Local variables
var newHead = new node(eltType);
var retry = false;
var stm = manager.getDescriptor();

do {
   retry = false;
   try! {
      stm.begin();
      // Takes pointer of 'head' via its reference...
      // What happens if its a wide reference???
      var h = stm.read(head);
      newHead.next = h;
      stm.write(head, nextHead);
      stm.commit();
   } catch retry : STMRetry {
      retry = true;
   }
} while retry;

Yes it is currently ugly, but it is a very early prototype.

Edit: Changed naming for STMBegin to begin


Solution

  • Is there an official way to convert an argument passed by reference to a pointer to the exact same type?

    I don't know about "official", but my instinct was to try using c_ptrTo as follows, which seems to work as of Chapel 1.16. Given these files:

    testit.chpl:

    extern proc bar(x: c_ptr(int));
    
    require "testit.h";
    
    var i = 42;
    foo(i);
    writeln("after foo, i is: ", i);
    
    proc foo(ref x: int) {
      var c_ptr_to_x: c_ptr(int) = c_ptrTo(x);
      bar(c_ptr_to_x);
      writeln("after bar, x is: ", x);
      x = 22;
    }
    

    testit.h:

    #include <stdint.h>
    #include <stdio.h>
    #include <inttypes.h>
    
    static void bar(int64_t* x) {
      printf("bar got: %"PRId64"\n", *x);
      *x = 32;
    }
    

    the result seems to work as I'd hoped:

    $ chpl testit.chpl
    $ ./testit
    bar got: 42
    after bar, x is: 32
    after foo, i is: 22
    

    what about for the sake of writing Chapel abstractions?

    I'd argue that c_ptr() types are really only intended for interoperability with C, not as a means of writing pointer-based abstractions within Chapel itself.

    Furthermore, what about the case of wide references and wide pointers?

    These are implementation concepts rather than abstractions that are exposed at the language level to end-users, so I'm not sure there's a prescribed user-level way to work with these types within Chapel.