Initialization of arrays of movable pointers

Technical questions regarding the XTC tools and programming with XMOS.
cjameshuff
Member++
Posts: 22
Joined: Mon Sep 26, 2016 6:08 pm

Initialization of arrays of movable pointers

Post by cjameshuff »

I am trying to manage blocks of data stored in an array of movable pointers, and have run into a bit of a chicken-or-egg issue.

I can declare an array of movable pointers with no problems. I then try to fill it with pointers to elements in another array with a loop in an init function. However, this can't be done as just "pointers[j] = &data[j]", since I'm not initializing the array at this point.

I need movable pointers to fill it with, and the only way I see to create a movable pointer is by declaring a movable pointer variable. However, that variable must have the same value it was initialized with when it goes out of scope, which defeats the purpose in an initialization loop:

Code: Select all

void bfifo_init(block_fifo_t & fifo)
{
    for(int j = 0; j < BLOCK_COUNT; ++j)
    {
        fifo.blocks[j] = &fifo.block_data[j];// doesn't work, since RHS isn't a move expression
        
        fifo_block_t * movable tmp = &fifo.block_data[j];
        fifo.blocks[j] = move(tmp);
        ...tmp goes out of scope here, and needs its pointer back...
    }
    ...
}
Is there any way to achieve this without having to manually initialize the array at declaration?


User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Hmm - this does seem a bit of an issue. I can think of an obvious solution initially which is to use unsafe pointers. These behave like C pointers and any safety is up to you.

However, movable pointers do add some nice checks which are worth having if you are not looking for every last cycle. I can't think how many times XC runtime checks, such as array bounds checking, have saved my bacon..

So movable pointers have some strict rules to ensure that things aren't left in a messy state.

One slightly verbose idea is to have a task which handles initialisation of the pointers and then moves ownership across an interface. As long as the "working task" is a while(1) you should be OK, although it would be safest to add a second method to transfer ownership if you ever did leave the scope.

By making the init task distributable, it won't use an extra thread..

Does this help you?

Code: Select all

interface my_interface {
  int * movable init_ptrs(void);
};


void working_task(client interface my_interface i_s){

    int * movable ptr;
    ptr = i_s.init_ptrs();
    printf("%p\n", *ptr);

}

void init_task(server interface my_interface i_s){
    int my_val = 6;
    int * movable p = &my_val;
    while(1){
        select{
            case i_s.init_ptrs(void) -> int * movable ret:
            int * movable tmp;
            ret = move(p);
            break;

        }
    }
}

int main(void){
    interface my_interface i_s;
    par{
        working_task(i_s);
        init_task(i_s);
    }
    return 0;
}
cjameshuff
Member++
Posts: 22
Joined: Mon Sep 26, 2016 6:08 pm

Post by cjameshuff »

Unfortunately, I'd then have to create an array of interfaces and an init task for each element of the array, which would be a ridiculous excess of code for initializing one array with pointers to the contents of another, or hand-write the code for initializing N elements, taking me back to what I was trying to avoid. I've settled on using macros to generate the initialization code, which is ugly but works (at least in this specific case).

This seems like a bit of an oversight in movable pointer semantics...there needs to be a way to handle cases where initialization is not simultaneous with declaration. Perhaps a way to generate movable pointers directly from variables (which could be done with similar constraints, making the variable inaccessible directly until the pointer is "moved back").