Announcement

Collapse
No announcement yet.

Question about EMS.

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

  • Eric Pearson
    replied
    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][email protected]</A>



    [This message has been edited by Eric Pearson (edited March 21, 2000).]

    Leave a comment:


  • Sebastian Groeneveld
    replied
    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>

    Leave a comment:


  • Hans Ruegg
    replied
    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

    Leave a comment:


  • Michael Mattias
    replied
    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]

    Leave a comment:


  • Guest's Avatar
    Guest replied
    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]

    Leave a comment:


  • Lance Edmonds
    replied
    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> )

    Leave a comment:


  • Guest's Avatar
    Guest replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    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

    Leave a comment:


  • Guest's Avatar
    Guest started a topic Question about EMS.

    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).]
Working...
X