Announcement

Collapse
No announcement yet.

Question about EMS.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Question about EMS.

    Is it legal to do something like this, and if so, exactly what happens?:

    Code:
    $DYNAMIC
    
    a=0
    IF a=1 THEN
      DIM VIRTUAL TestMe(2) AS INTEGER
    ELSE
      DIM DYNAMIC TestMe(2) AS INTEGER
    END IF
    The compiler compiles it with no problems. But I don't think this is doing what I would like it to do.

    On my win98 computer it works..but on another computer running CCI DOS, with no EMS enabled, it blows up with error 202.


    Thanks,
    Jason

    [This message has been edited by Jason McCarver (edited 09-21-99).]

  • #2
    That's a problem with the compiler. It should not compile this code, as you have attempted to tell the compiler that Testme() is BOTH a "regular" array and a "virtual" array and it cannot be both.

    So the direct answer is, "No it's not legal."

    MCM

    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      I have two related questions which I think have been discussed before but never really answered.

      1) Is it possible to test for the presence of EMS and accordingly choose between a virtual and normal dynamic array? It seems that the inclusion of virtual arrays in a program, even if never called, will generate an error if EMS is not available.


      2) If we do manage to get past (1) assuming that the main program has to use different names for alternative VIRTUAL and DYNAMIC arrays, can you pass either type of array to the same SUB or would you need separate SUBs too.


      -------------
      The PC Guru, Austin Tx
      Working on data recovery tools.

      Comment


      • #4
        Any application that is going to use virtual arrays should begin by testing FRE(-11) to query the availability of EMS. If there is no EMS, then your program should end gracefully, otherwise a run-time error will occur when the RTL attempts an EMS allocation.

        Therefore, there are two choice for you, either your application *requires* EMS or it does not. The easiest way is to distribute/create two versions of the app... one for EMS, the other not. The easiest way to achieve this is to use compile time directives ($IF/$ENDIF), so the array type is defined at compile time, not runtime as Jason tried a few months ago. ie:
        Code:
        'Psuedo code
        %UseEMS = -1
        $IF %UseEMS
          DIM VIRTUAL MyArray(....
        $ELSE
          DIM HUGE MyARRAY(...
        $END IF
        The reason for this becomes more clear when we answer your 2nd question:

        At compile time, the compiler generates code (to perform array access within a sub/function) depending on the type of array the prototype parameter defines. If it were possible to pass *either* a conventional array or a virtual array, then the compiler would need to create twice as much array handling code to handle the possibility of either array type being passed at runtime. This immediately adds bloat and inefficiency, not to mention slower execution time (because additional overhead to determine the type of array being passed would be required too).

        I've heard a few people comment that they would like this type of flexibility, but my personal opinion is that EMS memory is already available to DOS apps in the majority of PC's, and it's easily added to PC's that dont already have it. Anyone running recent editions of Windows is likely to have it available to DOS sessions by default. Therefore, changing the compiler to suit older PC's is a step backwards (IMHO).

        YMMV!


        -------------
        Lance
        PowerBASIC Support
        ( mailto:[email protected][email protected]</A> )
        Lance
        mailto:[email protected]

        Comment


        • #5
          Here's what I've done, I don't know how "legal" this is, but it seems to work for me.

          In the MAIN part of the program (in this case, a CHAIN PBC file), I do something like this:

          Code:
          SHARED UseVirtArray%
          IF FRE(-11) THEN
            UseVirtArray%=-1
            DIM VIRTUAL vTest(x) AS WhateverType
            SHARED vTest()
          ELSE
            UseVirtArray%=0
            DIM Test(x) AS WhateverType
            SHARED Test()
          END IF
          Then, later when I want to get something out of the array, I call a sub that looks at UseVirtArray% and uses the appropriate array.

          Code:
          SUB GetArrayData (Elem%,OutData AS WhateverType)
            IF UseVirtArray THEN
              OutData=vTest(Elem%)
            ELSE
              OutData=Test(Elem%)
            END IF
          END SUB
          Now, I personally think this is horrible coding and I'm not real sure why it works, but it does. On a machine with no EMS, it will run just fine, never causing an error. Our program runs on a DOS-like OS called CCI. Some of our stores also run a program that will cause the OS to stack dump and generally do bad things if EMS is enabled (it causes DOS/Windows to lock up). We don't know why this program acts this way, but since it's not one of our own, we can do nothing about it. We are working on a replacement for it, but until then, many of our stores simply cannot have EMS turned on. But for the ones that can use EMS, we want to be able to use it. Especially since if we can't use EMS, some parts of our program must resort to using a disk-based array which is MUCH slower than memory.

          Anyway, this is what I've ended up with in one part of our program.....

          Jason
          [email protected]

          Comment


          • #6
            I don't think using a SHARED flag is bad coding at all; it shows creativity and resourcefullness. (And I might do it that way).

            Nonetheless, there IS a way to use the same routine for "regular" and VIRTUAL arrays in PB/DOS. I did some unit testing with this about eight months ago, and found that by putting the array access into a separate unit (PBU) file, and insuring the VIRTUAL routines are includied in the unit, you can call something like:

            CALL GetItem (thearray(), elementnumber)

            .. and it will work with either kind of array.

            Not sure that helps a lot in this specific instance, but give me a couple of weeks to play with it and I'll post something over in the source code forum.



            -------------
            Michael Mattias
            Racine WI USA
            [email protected]
            Michael Mattias
            Tal Systems Inc. (retired)
            Racine WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              I had the same problem some time ago when I tried to get a program
              to use EMS if it is available, and not to use it when there is not,
              and found that if the statement VIRTUAL is somewhere in the code,
              even if it is not actually executed, I get automatically an EMS error
              if there is no EMS.
              There is another "solution" which I am not really satisfied with, but it
              works also:
              You can DIMension your arrays in to alternative chain files, one
              which DImensions them as DYNAMIC and another which DIMensions them
              as VIRTUAL. In the main program, you check for the presence of EMS
              with FRE(-11). If there is no EMS available, you chain to the first
              chain file and then back to the main program. If there is enough EMS,
              you chain to the second chain file and then back. If all arrays are
              declared COMMON in all files, the main program will accept the same
              array name either as DYNAMIC or as VIRTUAL, according to how it was
              DIMensioned in the chain file. The code was something like this
              (I do not have the exact code available right now):

              'Main program MAIN.EXE
              COMMON retflag AS INTEGER
              COMMON testarray(1)
              IF retflag<>0 THEN GOTO nochain '(already returning from chain)
              IF FRE(-11)<1 THEN CHAIN "noems.pbc" ELSE CHAIN "ems.pbc"
              nochain:
              'program goes on from here

              ===============================
              'File NOEMS.PBC
              COMMON retflag AS INTEGER
              COMMON testarray(1)
              REDIM testarray(10000)
              retflag=1
              CHAIN "MAIN.EXE"
              ===============================
              'File EMS.PBC
              COMMON retflag AS INTEGER
              COMMON testarray(1)
              DIM VIRTUAL testarray(100000)
              retflag=1
              CHAIN "MAIN.EXE"
              ================================

              As I said above, I am not quite satisfied with this solution,
              because it is clumsy and it cannot be used if you need to REDIM
              an array in the middle of your program - but at least it works.
              (There might be some minor errors in the code above as I am typing
              it only from memory.)

              Hans Ruegg

              Comment


              • #8
                DIM statements can not be considered as normal statements. They are not 'executed', they just inform the compiler (at compile-time) to reserve memory.
                Therefore the code
                Code:
                IF UseEMS% THEN
                   DIM VIRTUAL vTest(x) AS WhateverType
                ELSE
                   DIM Test(x) AS WhateverType
                END IF
                will reserve memory for two arrays (vTest and Test). The IF/END IF structure has no effect here. There is a compile-time IF/END IF possible though, as Lance demonstrated:
                Code:
                $IF %UseEMS
                   DIM VIRTUAL vTest(x) AS WhateverType
                $ELSE
                   DIM Test(x) AS WhateverType
                $ENDIF
                Now only one of the two arrays is dimensioned by the compiler, dependent on the value of the constant %UseEMS.


                ------------------
                Sebastian Groeneveld
                mailto:[email protected][email protected]</A>
                Sebastian Groeneveld
                mailto:[email protected][email protected]</A>

                Comment


                • #9
                  Sebastian --

                  > Therefore the code
                  >
                  Code:
                  >  IF UseEMS% THEN
                  >     DIM VIRTUAL vTest(x) AS WhateverType
                  >  ELSE
                  >     DIM Test(x) AS WhateverType
                  >  END IF
                  >
                  > will reserve memory for two arrays (vTest and Test).

                  That's not entirely accurate. For example this code (based on your example)...

                  Code:
                   UseEMS% = 1
                   X = 10
                   IF UseEMS% THEN
                           DIM VIRTUAL vTest(X) AS LONG
                   ELSE
                           DIM Test(X) AS LONG
                   END IF
                   PRINT Test(0)
                  ...will produce a Subscript Out Of Range error on the PRINT line because the Test() array will not be dimensioned at compile time or at run time.

                  The difference is "dynamic" vs. "static" arrays. If the array is static, the compiler will create it at compile-time as you described. For example, if you change DIM Test(x) to DIM Test(10) the error will go away. But if you then change it to DIM DYNAMIC Test(10) the error will come back.

                  Arrays are created dynamically (at runtime) if 1) the subscript is not a numeric literal value, or 2) if you explicitly tell the compiler to DIM DYNAMIC.

                  -- Eric


                  ------------------
                  Perfect Sync: Perfect Sync Development Tools
                  Email: mailto:[email protected]s[email protected]</A>



                  [This message has been edited by Eric Pearson (edited March 21, 2000).]
                  "Not my circus, not my monkeys."

                  Comment

                  Working...
                  X