Shop OBEX P1 Docs P2 Docs Learn Events
Is it possible to reallocate arrays in Spin? (Solved) — Parallax Forums

Is it possible to reallocate arrays in Spin? (Solved)

mikeologistmikeologist Posts: 337
edited 2017-12-03 16:18 in Propeller 1
OBJ
  terminal  : "Parallax Serial Terminal Plus"

VAR
  byte data[2]
  byte index

PUB main
  new(4)
  data[0] := 77
  data[1] := 78
  data[2] := 80
  data[3] := 81

  terminal.Position(5, 5)      'loop to print all values in array
  repeat index from 0 to (size-1)
    terminal.Char(data[index])  
  

PUB new(size_in)
  size := size_in
  data := @byte [4]

DAT
  size  long $2

This only retrieves 2 values.
Is there a way to dynamically allocate the array on object creation?
Or to reallocate the array at run-time?
Or do I just have to make them a max size by default? (I'm fine with this option, but either of the other two would be better)

Thanks a bunch

Comments

  • Unless I'm missing something you have only declared a 2-element array in your VAR block. According to PUB main you need data[4].
  • Is there a way to dynamically allocate the array on object creation?
    No. Because of this, I am rewriting many of my objects in a manner that allows the application to set the array size. A pointer to this array and its size is sent to the .start() method.
    Or to reallocate the array at run-time?
    No.
    Or do I just have to make them a max size by default? (I'm fine with this option, but either of the other two would be better)
    Only if you put the array inside your object. For example, the next target on my list is my DMX driver. A DMX universe requires 513 bytes, but in most instances I am only talking to a few fixtures. By moving the DMX array to the application I can prevent wasted memory.

    I first used this strategy in my pixel driver. It's in ObEx: http://obex.parallax.com/object/868
  • lardom wrote: »
    Unless I'm missing something you have only declared a 2-element array in your VAR block. According to PUB main you need data[4].
    PUB new(size_in)
      size := size_in
      data := @byte [4]
    

    trying to reallocate it to sized 4 here
  • JonnyMac wrote: »

    I first used this strategy in my pixel driver. It's in ObEx: http://obex.parallax.com/object/868

    I looked through your pixel driver. I do not see a mention of DMX it's also a very complicated object and I do not see clearly what you are talking about.

    I hate to ask but do you have a simpler application of the concept that I could study, please?
  • I wrote a heap manager many moons ago that permits dynamic memory allocation for arrays and strings:

    http://forums.parallax.com/discussion/85772/dynamic-strings-heap-manager-formatted-output

    You don't have to use the strings part if you don't need it.

    -Phil
  • I wrote a heap manager many moons ago that permits dynamic memory allocation for arrays and strings:

    http://forums.parallax.com/discussion/85772/dynamic-strings-heap-manager-formatted-output

    You don't have to use the strings part if you don't need it.

    -Phil

    I will read through this very carefully, thank you
  • I wrote a heap manager many moons ago that permits dynamic memory allocation for arrays and strings:

    http://forums.parallax.com/discussion/85772/dynamic-strings-heap-manager-formatted-output

    You don't have to use the strings part if you don't need it.

    -Phil

    A reading from the demo down the classes I quickly found myself at first_fit.
    This is very well written.
    If I'm understanding this:
    You use semaphore (locks) for mvcc. Very nice to allow multiple cogs access multiple heaps.

    From the demo class:
    CON
      HEAP_SIZE     = 2000 
    
    VAR
      long  Heap_array[HEAP_SIZE]
    

    From fit_first:
    'from new(heap_addr, heap_longs) : heap | link, bytes
    
    longfill(heap_addr, $FFFFFFFF, heap_longs)        '         Yes: Fill the heap with $FF.
          heap_base[heap] := heap_addr                      '              Put the heap address into the table.
          heap_first[heap] := heap_last[heap] := heap_addr += 2 '          Initialize free pointers.
          heap_bytes[heap] := bytes := heap_longs << 2      '              Save the size.
          word[heap_addr] := word[heap_addr + bytes - 6] := bytes - 4 '    Construct the free area.
    

    Essentially you are making a large empty map and the dynamically allocating the already reserved space within for new "variables" of arbitrary length, quantity, and name.
    Am I interpreting this correctly?
  • Essentially you are making a large empty map and the dynamically allocating the already reserved space within for new "variables" of arbitrary length, quantity, and name.
    Am I interpreting this correctly?
    Yes.

    -Phil
  • mikeologistmikeologist Posts: 337
    edited 2017-12-03 05:06
    Essentially you are making a large empty map and the dynamically allocating the already reserved space within for new "variables" of arbitrary length, quantity, and name.
    Am I interpreting this correctly?
    Yes.

    -Phil

    That's slick. While the variable are exceptionally dynamic the map is static.
    Now these reside in the shared memory and the cog uses the heap ID and the semaphore for exclusively access through all read and write operations?
    If so then the primary point is the flexibility as well as the ability to offload this variable storage to the shared memory?

    Looks like no matter how I do it I have to I'm forced to allocate all space at compile-time, one way or the other.

    I was planning on making my stack in one big string with bounds checking.
    For speed in a single cog program, would you recommend that I try your method or mine?

    Thank you for taking the time :-)
  • I was planning on making my stack in one big string with bounds checking.
    For speed in a single cog program, would you recommend that I try your method or mine?
    My method probably excels where multiple arrays keep changing size, like strings. If you don't need that, the heap manager's overhead might be more than you want to pay.

    -Phil
  • I was planning on making my stack in one big string with bounds checking.
    For speed in a single cog program, would you recommend that I try your method or mine?
    My method probably excels where multiple arrays keep changing size, like strings. If you don't need that, the heap manager's overhead might be more than you want to pay.

    -Phil

    Excellent advise, again my thanks
  • I looked through your pixel driver. I do not see a mention of DMX it's also a very complicated object and I do not see clearly what you are talking about.

    DMX is a separate object.

    In my older pixel drivers, there was an array of 256 longs (1K bytes); this was allocated even if the parent application was only controlling a 16-pixel string, hence was wasteful.

    In the new version, the pixel data buffer is declared in the application code, not in the driver object. This allows me to set the size of the pixel buffer for the application. The start methods for the pixel driver now expect a pointer to the application's array, as well as the size. Again, this strategy is to prevent wasted RAM for generic objects. Phil's heap manager has you covered if you do in fact need to change array sizes as the program runs.
  • JonnyMac wrote: »
    I looked through your pixel driver. I do not see a mention of DMX it's also a very complicated object and I do not see clearly what you are talking about.

    DMX is a separate object.

    In my older pixel drivers, there was an array of 256 longs (1K bytes); this was allocated even if the parent application was only controlling a 16-pixel string, hence was wasteful.

    In the new version, the pixel data buffer is declared in the application code, not in the driver object. This allows me to set the size of the pixel buffer for the application. The start methods for the pixel driver now expect a pointer to the application's array, as well as the size. Again, this strategy is to prevent wasted RAM for generic objects. Phil's heap manager has you covered if you do in fact need to change array sizes as the program runs.

    That is a very clear explanation.
    I'm making a symbol stack on top of a large string, I can use your neat trick and make the string in my main program, call it something_stack, then just pass the pointer to the stack class functions for manipulation. The stack class can easily hold the tracking data.

    Very good, well between the two of you taking the time I think I've got enough to make what I need.
    Thanks for taking the time.

    I'll share on obex and link here when I'm finished.
Sign In or Register to comment.