Shop OBEX P1 Docs P2 Docs Learn Events
Abstract Data Structure (AN003) question — Parallax Forums

Abstract Data Structure (AN003) question

RforbesRforbes Posts: 281
edited 2013-05-30 03:52 in Propeller 1
Hey all,

I'd like to get some input about an object and it's methods. I'm using an array of external objects set up as an abstract data structure as described in http://www.parallaxsemiconductor.com/sites/default/files/appnotes/AN003-AbstractDataStructures-v1.0_1.pdf

My data structure object is very simple:
{{
SensorValues.spin        --->   Sensor data structure.
}}

CON
  _xinfreq = 5_000_000                     
  _clkmode = xtal1 + pll16x                               

Var

long Sensor                      'Value for attached sensor

Pub Sensor_(Val)                 'Sensor Value: WRITES value to variable. (Val)= value to store. 
      Sensor:=Val

Pub _Sensor                      'Sensor Value: READS value of variable. Returns stored value.
      return Sensor

I'm running 16 of these objects in my top level object. My top level object starts up 4 different cogs, as outlined below.
{{
  Application- runs 4 cogs. 1 cog writes the sensor value, 3 cogs read it.
}}

OBJ
  Node[16]: "SensorValues"  
pub main
{
 Cog 1 will write the sensor value using Node[x].Sensor_(DataIn[x])
   -This cog repeats every 100 ms
   -Will cycle through all 16 values

 Cog 2,3,4 will read the sensor value using temp:=Node[x]._Sensor     where x= the sensor to read
   -Cog 2 repeats every second
   -Cog 3 repeats every 4 seconds
   -Cog 4 repeats on defined input
   -Each will cycle through all 16 values
}

Cogs 2,3 and 4 do different stuff with the sensor value at different times, and they are all started within the top level object- not by/as different objects. There is a chance that multiple cogs will attempt to read the sensor value at exactly the same time, or read it when it's being written to.

Since the hub does that "round robbin" thing I think this is ok, insofar is preventing memory collisions on the sensor data since it's a single long. (Please correct my if I'm wrong on this point)

But- what about calling the Node[x]._Sensor method simultaneously from different cogs? For example, If cog 2 and 3 both attempt to run temp:=Node[x]._Sensor at the same time, what happens?

I haven't implemented a lock for this method, and I haven't seen any real issues with the sensor data. However, that could simply be because two or more cogs haven't accessed the method as I've described above... yet.

I'm not completely sure how I'd go about testing it thoroughly. Does a lock need to be used to prevent problems here?

Thanks in advance,
Robert

Comments

  • JasonDorieJasonDorie Posts: 1,930
    edited 2013-05-29 13:01
    Since the _Sensor method only returns a value (gets the value from the sensor) there's no problem. Even if your cogs were using the Sensor_ method, and trying to set different values from from multiple cogs to the same memory location, in your case there'd still be no real issue. The prop handles 32 bit values atomically, so if two cogs attempt to write to the same HUB memory location at the same time, the last one to perform the write will be the one that sticks. There will be no chance of other code getting a partial read - You'll never have an instance where a single LONG value contains half of an old value and half a new value or anything like that.

    If your sensor code contained two or more values that were being read or written, then you might have an issue. For example, if you were recording a pressure and temperature value. If both values came from the sensor, and needed to be "together" to be correct, you'd need a lock. Without the lock, you could have one cog writing both values from your sensor, and have another cog read the values while the first was in the middle of writing them. You could get a temperature value from sample #1, but the pressure value from sample #2, so in this case you'd need a lock to properly deal with it.

    In the simple case of a single long / word / byte value, you don't need a lock. Calling the same method from multiple cogs is also safe, as each cog will have its own stack for local variable use. If a method makes use of non-local variables, and you call the method on the same object instance from multiple cogs, then you might also have an issue.
  • RforbesRforbes Posts: 281
    edited 2013-05-29 16:21
    @JasonDorie

    Ok, that's what I thought concerning the singular long read and write with regards to collisions.

    I don't think I quite understand what you're telling me here:
    If a method makes use of non-local variables, and you call the method on the same object instance from multiple cogs, then you might also have an issue.

    Are you saying that if my abstract data structure object (SensorValue.spin in the example above) wrote the supplied parameter to a global variable via something like long[global_var] which was defined in the top level object it might be a problem? I'm not intending to do something like that, but I'd like to know what you mean. Sorry, I'm just a tad confused here! :)
  • JasonDorieJasonDorie Posts: 1,930
    edited 2013-05-29 18:29
    What I mean is, if your method used members of an object as temporary values, and you called the method from multiple cogs, you could run into trouble because each cog would be using the same memory location to store its copy of the value, which might be different. For example:
    VAR
      long counter
    
    PUB MyMethod( size )
      repeat counter from 0 to size
        ' Do something meaningful here
    

    By using the counter value in the object, instead of having a local (stack) variable for it, calling this method from two different cogs would be problematic unless each cog had its own copy of the object.

    Does that make more sense?
  • RforbesRforbes Posts: 281
    edited 2013-05-30 03:52
    Yep- that makes sense. Alright, thanks much. I appreciate ya!
Sign In or Register to comment.