Shop OBEX P1 Docs P2 Docs Learn Events
Newbie - question regarding sharing of memory between cogs and compiler variabl — Parallax Forums

Newbie - question regarding sharing of memory between cogs and compiler variabl

GarchGarch Posts: 3
edited 2009-10-27 14:44 in Propeller 1
Hi,
·
I am a newbie to the propeller and would very much appreciate some guidance re. sharing of memory between cogs. I have read the propeller manual and the beginners section of this forum. I have question regarding the global variable scope between separate objects and cogs. Please see example below.
·
  1. How does the compiler resolve the scope of a global variable defined in the root (top most) object and calls to reference that global variable in instanced daughter objects?
  2. Should the “top most” object pass-by-reference the global variable defined in it via a daughter’s method’s parameter?
  3. Should the “top most” object pass-by-value (ie a copy) the global variable defined in it via a daughter’s method’s parameter? I can’t see how this would work as you’d be passing a copy of the global variable into the temporary stack created when the daughter method is called, which would be lost when the method exited and the stack was unwound. ·
  4. Is the global variable in the “top most” object visible to all daughter object instances? If so, how is the “name” of the variable e.g. sharedLong, passed into scope of the daughter objects. Surely a daughter object cannot just reference “sharedLong” as it has not been defined within the daughter objects VAR declaration and the compiler won’t know what is being referenced.
  5. Is there a simpler way of achieving this that I am missing?
·
·
ROOT OBJECT (Top most object)
·
VAR ··· LONG· sharedLong
·
OBJ ···· objectAInstance : "ObjectA" ,· objectBInstance : "ObjectB"
·
·
PUB MAIN
·
··········· objectAInstance.Start(sharedLong)········· ‘ by value; OR….
··········· objectAInstance.Start(@sharedLong)······ ‘ by reference
··········· objectBInstance.Start(@sharedLong)
···········
DAUGHTER OBJECT:
·
===== Filename = “ObjectA.spin” ======
·
·
VAR ··· LONG·· passedParameter, stack[noparse][[/noparse]30]
·
·
PUB Start(sharedLongParameter)
·
··········· Passedparameter := sharedLongParameter
··········· cognew(DoSomethingInACog, @stack)
·
·
PUB DoSomethingInACog | aMethodVariable
·
··· Repeat
··········· aMethodvariable := sharedLong + 1········ ‘ Read from memory
·
·
DAUGHTER OBJECT:
·
===== Filename = “ObjectB.spin” ======
·
·
VAR ··· LONG·· passedParameter, stack[noparse][[/noparse]30]
·
·
PUB Start(sharedLongParameter)
·
··········· Passedparameter := sharedLongParameter
··········· cognew(DoSomethingInACog, @stack)
·
·
PUB DoSomethingInACog | aMethodVariable
·
··· Repeat
··········· passedParameter := passedParameter + 1· ‘ Write to memory
·
···········

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2009-10-27 12:50
    SPIN does not support the concept of overall-global variables!
    VAR     LONG  sharedLong
     
    OBJ      objectAInstance : "ObjectA" ,  objectBInstance : "ObjectB"
     
    PUB MAIN
                [color=green]objectAInstance.Start(sharedLong)[/color]        ‘ by value; OR…. [color=green]If you are only interested in the current value that's fine ... say you want to pass the pin number to[/color]
    [color=green]                                                                      the TV driver ...
    [/color]            objectAInstance.Start([color=green]@sharedLong[/color])       ‘ by reference   [color=green]That's fine if you need to watch the content of the variable during runtime, for example as
    [/color]            objectBInstance.Start([color=green]@sharedLong[/color])                        [color=green]communication buffer between COGs[/color]
    
    DAUGHTER OBJECT:
    ===== Filename = “ObjectA.spin” ======
    VAR     LONG   passedParameter, stack[noparse][[/noparse]30]
     
    PUB Start(sharedLongParameter)
                Passedparameter := sharedLongParameter
                cognew(DoSomethingInACog, @stack)
     
    PUB DoSomethingInACog | aMethodVariable
        Repeat
                aMethodvariable := [color=red]sharedLong[/color] + 1         ‘ Read from memory    [color=red]That code won't compile. Object A does not know this symbol![/color]
     
     
    DAUGHTER OBJECT:
    ===== Filename = “ObjectB.spin” ======
    VAR     LONG   passedParameter, stack[noparse][[/noparse]30]
     
    PUB Start(sharedLongParameter)
                Passedparameter := sharedLongParameter
                cognew(DoSomethingInACog, @stack)
     
    PUB DoSomethingInACog | aMethodVariable
        Repeat
                passedParameter := [color=red]passedParameter[/color] + 1  ‘ Write to memory       [color=red]That won't work as you expect it. In passedParameter you have the adress of sharedLong and not[/color]
    [color=red]                                                                            the value of sharedLong. If you want to access the content of sharedLong you have to write:[/color]
     
                [color=green]long[noparse][[/noparse] passedParameter ] := long[noparse][[/noparse] passedParameter ] + 1
    [/color]
    

    In one object you can have object-global variables. You simply put that variable into a DAT section. So, for example when you have ObjectAInstance1 and ObjectAInstance2 they can share such a variable - even if both objects run in different COGs (when we talk about SPIN).
    ·
  • GarchGarch Posts: 3
    edited 2009-10-27 13:37
    Great! Thanks. Helps a lot.

    Just to confirm then, the following would work within spin? And there would be no resource conflicts (ie reading and writing simultaneously) due to the round-robin nature of the hub?

    TOP MOST OBJECT:
    VAR LONG sharedLong

    OBJ objectAInstance : "ObjectA" , objectBInstance : "ObjectB"

    PUB MAIN

    objectAInstance.Start(@sharedLong) ‘ pass object global VAR by reference objectBInstance.Start(@sharedLong) ‘ pass object global VAR by reference



    DAUGHTER OBJECT (Write Object)
    ===== Filename = “ObjectA.spin” ======
    VAR LONG passedParameter, stack[noparse][[/noparse]30]

    PUB Start(sharedLongParameter)
    Passedparameter := sharedLongParameter
    cognew(DoSomethingInACog, @stack)

    PUB DoSomethingInACog | aMethodVariable
    Repeat
    long[noparse][[/noparse] passedParameter ] := long[noparse][[/noparse] passedParameter ] + 1 ‘ Write to shared memory



    DAUGHTER OBJECT (Read Object)
    ===== Filename = “ObjectB.spin” ======
    VAR LONG passedParameter, stack[noparse][[/noparse]30]

    PUB Start(sharedLongParameter)
    Passedparameter := sharedLongParameter
    cognew(DoSomethingInACog, @stack)

    PUB DoSomethingInACog | aMethodVariable
    Repeat
    aMethodVariable := long[noparse][[/noparse] passedParameter ] ‘ Read from shared memory
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-10-27 14:02
    No, you don't have resource problems as such, as each COG has an individual window for accessing HUB-RAM ... BUT ... if you have problems in your code or not is something different
    long[noparse][[/noparse] passedParameter ] := long[noparse][[/noparse] passedParameter ] + 1 ‘ Write to shared memory
    
    

    How is this part processed:
    1. read content of the global variable
    2. add 1
    3. write back the new content

    As it is in SPIN a lot of HUB-RAM access windows will have passed between read and write. So, what can happen?
    a) In the current version the·read-only Object has a good chance to read the same value several times
    b) Maybe it reads the value after step 1. but before 3.
    c) If code of the modifying object is faster than the code of the reading object you might miss values.

    If you have more complex data this might cause inconsistencies. For example if you have 2 longs that belong together - say a timestamp and a temperature. Object A updates these, Object B displays the data. So, if you don't synchronize the access, Object B might read the a combination where timestamp has already been updated, but the temperature is still the older temperature.
    That's why the locks have been invented.
  • GarchGarch Posts: 3
    edited 2009-10-27 14:44
    Would this work ie would the use of locks work with the example below? Thanks.


    TOP MOST OBJECT:
    VAR···· LONG· sharedLong
    ········· BYTE SemID

    OBJ····· objectAInstance : "ObjectA" ,· objectBInstance : "ObjectB"

    PUB MAIN
    ·if (SemID := locknew) == -1
    ··········· ‘ error, no locks available
    else
    ······· objectAInstance.Start(@sharedLong, @SemID)······ ‘ pass object global VAR by reference·······················
    ······· objectBInstance.Start(@sharedLong, @SemID)····· ‘ pass object global VAR by reference···················

    DAUGHTER OBJECT (Write Object)
    ===== Filename = “ObjectB.spin” ======
    VAR···· LONG·· passedParameter, stack[noparse][[/noparse]30]
    ········· BYTE··· mySemID

    PUB Start(sharedLongParameter, semIDparameter)
    ··········· Passedparameter := sharedLongParameter
    ··········· mySemID := semIDparameter
    ··········· cognew(DoSomethingInACog, @stack)

    PUB DoSomethingInACog | aMethodVariable
    ··
    ··········· repeat until not lockset(@mySemID)
    ··········· long[noparse][[/noparse] passedParameter ] := long[noparse][[/noparse] passedParameter ] + 1· ‘ Write to shared memory
    ··········· lockclr (@mySemID)
    ·········

    DAUGHTER OBJECT (Read Object)
    ===== Filename = “ObjectA.spin” ======
    VAR···· LONG·· passedParameter, stack[noparse][[/noparse]30]
    ········· BYTE··· mySemID

    PUB Start(sharedLongParameter, semIDparameter)
    ··········· Passedparameter := sharedLongParameter
    ··········· cognew(DoSomethingInACog, @stack)

    PUB DoSomethingInACog | aMethodVariable·······
    ··········· repeat until not lockset(@mySemID)
    ··········· aMethodVariable := long[noparse][[/noparse] passedParameter ]····· ‘ Read from shared memory
    ··········· lockclr (@mySemID)

    ·
Sign In or Register to comment.