Home AMX User Forum NetLinx Studio

Structure

I have used array to store by buttons number in my Netlinx program. I am wondering if I can use the structure to store those information and then use them in the Button_Event.

Comments

  • If you mean code like this:

    DEFINE_DEVICE
    dvPANEL = 128:1:0

    DEFINE_VARIABLE
    nBTN_MYBUTTONS[] = { 5,6 }

    DEFINE_EVENT
    BUTON_EVENT[dvPANEL,nBTN_MYBUTTONS]
    {
    PUSH:
    {
    SWITCH(GET_LAST(nBTN_MYBUTTONS))
    {
    CASE 1: { } // means a PUSH[dvPANEL,nBTN_MYBUTTONS[1]]
    CASE 2: { } // means a PUSH[dvPANEL,nBTN_MYBUTTONS[2]]
    }
    }
    }

    With that kind of coding, at Compiling time internally single BUTTON_EVENTs with any possible combination of DEVICE and CHANNEL are created. So inside the master, you'll have 2 BUTTON_EVENTs [dvPANEL,5] and [dvPANEL,6]

    You can pass any combination of single DEVICE/CHANNEL , but also a mix like above, or a combination of a DEV array and a "CHANNEL" array.

    AFAIK there is a limitation of about 1000 combinations into one single BUTTON_EVENT.

    It's a cool way for programming, because aou are managing your Device and Channels only at the top of your code, and then you are only working with indices.

    Hope this helps.
    Marc
  • kennyannkennyann Posts: 113
    That is how I am currently using code. But I am trying to avoid using arrays completely and use structures since it uses a whole lot less memory. The structure allows the code to run faster - it is very beneficial in larger programs. I am sure I can declare the structure and then put button values in the startup code and then use it Button_event. I have not tested that process yet so I am not sure whether that would be faster.
  • Joe HebertJoe Hebert Posts: 2,159
    Originally posted by kennyann
    I am sure I can declare the structure and then put button values in the startup code and then use it Button_event.
    The EVENT table is built before DEFINE_START and does not change after that so initializing the structure in DEFINE_START will not yield the results you are expecting.

    Check out tech note 383 a further explanation:

    Netlinx Event Programming Rules and Parameters

    Cheers,
    Joe
  • Chip MoodyChip Moody Posts: 727
    I'm trying to figure out why a structure holding a certain data type would use less memory than an array that's doing the same thing...(?)

    - Chip
  • kennyannkennyann Posts: 113
    The reason why is that an array when declared espcially a large one it uses a certain amount of memory space. But when you call it calls it quickly. A structure is created it does not actually use that much memory. It is the way you call a structure it uses less memory. Programming Two course gives you an expamle of CD List of how much memory you are saving by using a strucuture. I not the best person to explain how structure works vs array. If I not mistaken AMX may have written some code behind their software for us to use structure moe efficiently. I will adivse anyone to look up the example in programmin two course on CD list.
  • Spire_JeffSpire_Jeff Posts: 1,917
    As I recall, the CD example used an array of CDs the also contained grouping info. Say you have an array defined like:

    CHAR sCDS[3][400][30]

    The first bracket is the group where 1 = country, 2= rock, 3=alternative. The second bracket is the location of the CD in the changer and the third bracket is for the character string of the CD title (30 Characters is the most you can use in the CD title.) When this array is created, it uses 3*400*30 bytes of memory. Even if you only have 1 CD in the rock group, the rock group still uses 12000 bytes of memory. The other problem with this is that you have to enter the CD in one time for each group it is in so if you have a CD that belongs in the Rock group and the Alternative group, you would have the enter the info 2 times. This makes for a greater possibility of entry errors and makes it more difficult to update when CDs change locations. Even if you feel like overcoming the programming required to manage this data, the memory use is very ineffiecient as is demonstrated by adding another group say 4=classical. Now you have 48000 bytes and each CD may have to be entered up to 4 times. Every group you add increases the memory usage by 12000 bytes. Another issue is track info such as song names and play time. With arrays, you would have to enter the song info for each CD once for each group it was in and the SONG names would take up even more memory, regardless of the number of CDs in each group. For example:

    CHAR sTRACK[3][400][15][30]

    This would allow 15 tracks per CD with 30 characters per track name. The memory use would be 3*400*15*30 or 540000 bytes. So, for 3 groups in a 400 disc changer allowing up to 15 tracks per CD, you would use 576000 bytes of memory.

    With a structure, it is very easy to group different types of data efficiently. such as:

    DEFINE_TYPE

    STRUCTURE _sCD_INFO
    {
    CHAR Title[30]
    INTEGER Group[3]
    CHAR Track[15][30]
    }

    DEFINE_VARIABLE

    _sCD_INFO uCDS[400]

    Each instance of the structure uses 30 + 3*2 + 15*30 or 486 bytes of memory so the entire array uCDS uses 194400 bytes of memory. So, to get the same information, you can use 576000 bytes of memory with an array or 194400 bytes with a structure.
    I also lied when I said the structure is providing the same information. The structure actually allows more information. Each CD can belong to only 3 groups, but with an array of group names, you could use the uCDS.Group array to point to up to three different group names and the memory usage increase would be almost nothing compared to the increase in adding groups to the array method.

    Does this mean structures run quicker than arrays? I doubt it, but they do make for more efficient use of available memory.

    With that said, to address the initial poster wanting to use structures over arrays because they use less memory. The data is allows going to take up the same ammount of space... one byte for each character is always going to be one byte in size. The reason structures use less memory than arrays is because they allow you to reduce the number of time you have to use that one byte. I don't think that the program will allow you to use structures, but more importantly, I don't think it will save you any memory nor increase your performance. Now, I am speaking from a Netlinx stand point and I have very little experience with Axcess, but if you are running with an Axcess processor and having problems with performance, I would highly suggest moving to a Netlinx processor. The small gains you might see by modifying your code will never compare to the improved performance of a netlinx processor.

    I hope this helps a little and if you need any further clarification, lemme know... I'll see if I can reword something. Also, don't be afraid to tell me I'm wrong..... I've only been programming AMX for a short time and I am constantly learning new things )

    Jeff


    Originally posted by kennyann
    The reason why is that an array when declared espcially a large one it uses a certain amount of memory space. But when you call it calls it quickly. A structure is created it does not actually use that much memory. It is the way you call a structure it uses less memory. Programming Two course gives you an expamle of CD List of how much memory you are saving by using a strucuture. I not the best person to explain how structure works vs array. If I not mistaken AMX may have written some code behind their software for us to use structure moe efficiently. I will adivse anyone to look up the example in programmin two course on CD list.
  • Chip MoodyChip Moody Posts: 727
    Forgetting about structures for a minute, that's a really bad example of how to use arrays! To get efficient use, you'd do something like this:

    INTEGER CD_Type[400]
    CHAR CD_Name[400][30]
    CHAR CD_Track[400][15][30]

    That would let you keep track of info for CDs in a 400 disk changer efficiently - or at least more efficiently than the example...

    Yes, you can do this with a structure instead:

    STRUCTURE CD
    {
    INTEGER CD_Type
    CHAR CD_Name[30]
    CHAR CD_Track[15][30]
    }

    Then in DEFINE_VAR

    CD My_CDs[400]

    But... That doesn't save any memory. Just makes the code easier to read, and perhaps run a little quicker.

    - Chip



    Originally posted by Spire_Jeff
    As I recall, the CD example used an array of CDs the also contained grouping info. Say you have an array defined like:

    CHAR sCDS[3][400][30]

    This would allow 15 tracks per CD with 30 characters per track name. The memory use would be 3*400*15*30 or 540000 bytes. So, for 3 groups in a 400 disc changer allowing up to 15 tracks per CD, you would use 576000 bytes of memory.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Originally posted by Chip Moody
    Forgetting about structures for a minute, that's a really bad example of how to use arrays!

    I agree that it is poor use of arrays. That is the example they used in Programming 2 or at least as close to it as best I can remember. Sorry to promote poor array usage.

    Jeff
  • kennyannkennyann Posts: 113
    Help me understand this better. As far as I know from all my reading and my involvement in my programming courses - I understand that when you declare an array - it blocks out a specfic set of location in memory. This allows a programmer to quickly call what ever elements you want from an array. But the memory location is locked out and can only be used by the array. On the other hand if a programmer uses a structure - it is declaraed and the memory is only used when call by the structure - thereby using less memory. This allows more efficient uses of memory since you only have to call what you want and not block a set of memory location,
  • Joe HebertJoe Hebert Posts: 2,159
    kennyann,

    A structure is simply a user defined data type that is used to group intrinsic data types (i.e., INTEGER, CHAR) together and/or other user defined data types together in a logical and object-like manner.

    If one compares apples to apples, using arrays or structures makes no difference in memory allocation. (There might even be a little overhead for a structure, I'm not sure.) The example in class was a poor one and it would have been a better comparison had they used something like what Chip posted just above.

    Even though the example wasn't fair, that doesn't diminish the importance of structures. I love structures and use them extensively since they make the code much easier to read, maintain, debug, and modify. Structures are also great for VARIABLE_TO_XML and XML_TO_VARIABLE. I don't know if structures run the code any quicker or not.

    As far as I know, there is no way to dynamically "new" up or release memory in Netlinx (other than data that is pushed onto and popped off of the stack) If there is, I'd love to hear about it.

    Hope this clears it up for you a bit. If I've mislead you in any way hopefully someone from AMX will set it straight.

    Cheers,
    Joe
  • Chip MoodyChip Moody Posts: 727
    I never got terribly far in writing computer apps, but I have to say there have been a few times in writing NetLinx code that I've missed having the ability to dynamically allocate/deallocate chunks of memory for data structures.

    "What? You want to add a 101th element to a list that only has 100? Sure! Just call 'NewPtr' after checking the available memory pool size!"

    <sigh> I should be counting my blessings. I'd much rather be writing software to control A/V gear than making the next spreadsheet or page layout package. :)

    - Chip

    Originally posted by Joe Hebert
    kennyann,

    As far as I know, there is no way to dynamically "new" up or release memory in Netlinx (other than data that is pushed onto and popped off of the stack) If there is, I'd love to hear about it.

  • frthomasfrthomas Posts: 176
    Well I figure AMX always left that out for simplicity's stake. Dynamic memory mangement is neat but comes with its own set of problems (namely memory leaks, either by the programmer or the garbage collection mechanism). And in an always running 24/7 control system, leaks are a BAD thing (because the thing only crashes once the installer is long gone...)

    Now proposing some form of well thought out "dynamic" list mechanism (stack or queue) would be a middle ground. You would not be able to directly manipulate memory, just add or delete something from the list. (list elements being structures of course).

    Fred
  • frthomasfrthomas Posts: 176
    Originally posted by Joe Hebert
    (There might even be a little overhead for a structure, I'm not sure.)
    Given Netlinx is statically typed (i.e. it does not do funky type checks at run time, only at compile time), and that is does not support any type smaller than 1 byte, there should be no memory overhead in structures.

    As far as I know, there is no way to dynamically "new" up or release memory in Netlinx (other than data that is pushed onto and popped off of the stack) If there is, I'd love to hear about it.
    There is no way to do it in a way that manages memory, but you can implement routines that implement any type of list (stack, queue, linked list, whatever) using arrays.
    In practice anyway, what would be the practical benefit of using dynamic memory? By using arrays, you will never "run out" of memory dynamically, you will know it at compile time...
    Fred
  • Joe HebertJoe Hebert Posts: 2,159
    frthomas writes:
    In practice anyway, what would be the practical benefit of using dynamic memory?
    Generally speaking, more efficient use of memory and flexibility. Take for example the CD code posted above one more time. Whether you have only one CD in your collection or 400 CDs, the amount of memory reserved is the same since you must quantify the maximum amount of memory needed. (One could say there is plenty of memory and there is no need to worry about running out. Then again, Bill Gates once said that 64K of memory is more than anyone will ever need.)

    Now what if the user wants to add CD #401? You?ll need to go into the code and increase the upper limits of the structure. It would be nice to be able to read data out of a file (like CD information) and then new up memory as CDs are added. There would be no need to define your limits ahead of time.

    With that said though, I agree 100% that the cons out number the pros by a great margin. Memory leaks or stepping out of bounds and writing over memory that you shouldn?t be writing over is a bad bad thing. If you?re in the control business and your program goes out of control that would be another bad bad thing. Netlinx does a great job in making sure that you don?t shoot yourself in the foot. So I agree we're definitely better off with Netlinx keeping the gun locked up and out of our hands.

    Joe
  • Chip MoodyChip Moody Posts: 727
    Joe, you're such a party-pooper. :)

    And wasn't that statement by Bill Gates 640K?

    - Chip

    Originally posted by Joe Hebert
    ...I agree we're definitely better off with Netlinx keeping the gun locked up and out of our hands.

    Joe
  • Spire_JeffSpire_Jeff Posts: 1,917
    Bill Gates did say 640k. 640k was the limit of memory supported by the early versions of DOS. As memory prices dropped and processors increased in speed, that limit was dealt with creatively usinig extended memory..... it's been years since I last played with the stuff, but as I recall the 640k limit was still there as the amount of memory available to programs for execution and extanded memory was there to allow faster swapping to the execution memory. I'm gonna stop typing now because my brain is starting to hurt thinking about all of the problems I use to have freeing up memory in DOS.

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Chip writes:
    And wasn't that statement by Bill Gates 640K?
    Oops. What's a zero between friends? :)

    As Michael Keaton told Martin Mull in Mr. Mom - 220,221, whatever it takes.

    Joe
  • DHawthorneDHawthorne Posts: 4,584
    I've found the most flexible arrangement to be simply making an integer array for my device channels, populating it at declaration, and passing it as a second parameter to the BUTTON_EVENT . For code I intend to re-use, I put that in an include file, so I only need adjust the channel numbers per project. Then the first parameter of the BUTTON_EVENT can be a single user interface or an array of interfaces, as needed. For example:
    DEFINE_VARIABLE
    
    INTEGER iAudPanelButtons[] =  {    // Panel Buttons
                                       // Zone Selection 1- 16
                                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
                                       // ALL OFF - 17
                                          17,
                                       // Source selection 18-25
                                          21, 22, 23, 24, 25, 26, 27, 28,
                                       // Current zone OFF - 26
                                          99, 
                                       // Volume, Balance, Bass,   Treble, Loudness  27-35
                                          31, 32, 33, 34,  35, 36, 37, 38, 39
                                  }
    
    DEV dvPanels[] = {dvTP1, dvTP2, dvTP3}
    
    DEFINE_EVENT
    
    BUTTON_EVENT [dvPanels, iAudPanelButtons]
    {
         PUSH:
         {
               INTEGER iPanelIndex
               INTEGER iButton
     
               iPanelIndex = GET_LAST(dvPanels)
               iButton = GET_LAST(iButtons)
    
               // run code on values here
         }
    }
    

    Your arrays are static once compiled, but it's only a matter of editing the variable declarations and re-compiling to make any changes.
Sign In or Register to comment.