-- Data abstractions in packages are inherently one user abstractions. -- For multitasking environments, tasks provide better abstractions. -- -- Reference : Ada Letters, Vol V #3-6 Nov,Dec 1985 ACM SIGAda publication -- -- The "traditional" abstraction for a stack is the following package: -- package STACK_PACKAGE is subtype SIZE_SUBTYPE is INTEGER range 0 .. 100 ; procedure PUSH ( ITEM : in CHARACTER ) ; procedure POP ( ITEM : out CHARACTER ) ; function CURRENT_SIZE return SIZE_SUBTYPE ; FULL_STACK_ERROR : exception ; -- may be raised in PUSH EMPTY_STACK_ERROR : exception ; -- may be raised in POP end STACK_PACKAGE ; -- -- In the tasking abstraction, the exceptions are not used - Pushers or Popers -- just wait. Asking for the current size is not useful. It could change -- between the time the function was called and subsequent action. -- package CONCURRENT_STACK_PACKAGE is task STACK_MONITOR is entry PUSH ( ITEM : in CHARACTER ) ; entry POP ( ITEM : out CHARACTER ) ; end STACK_MONITOR ; end CONCURRENT_STACK_PACKAGE ; package body CONCURRENT_STACK_PACKAGE is task body STACK_MONITOR is subtype SIZE_SUBTYPE is INTEGER range 0 .. 100 ; TOP : SIZE_SUBTYPE := 0 ; ELEMENTS : array ( 1 .. SIZE_SUBTYPE'LAST ) of CHARACTER ; begin loop select when TOP < SIZE_SUBTYPE'LAST => accept PUSH ( ITEM : in CHARACTER ) do TOP := TOP + 1 ; ELEMENTS ( TOP ) := ITEM ; end PUSH ; or when TOP > 0 => accept POP ( ITEM : out CHARACTER ) do ITEM := ELEMENTS ( TOP ) ; TOP := TOP - 1 ; end POP ; or terminate ; end select ; end loop ; end STACK_MONITOR ; end CONCURRENT_STACK_PACKAGE ; with TEXT_IO ; use TEXT_IO ; with CONCURRENT_STACK_PACKAGE ; use CONCURRENT_STACK_PACKAGE ; procedure STACK_AS_TASK is task type PUSHERS is end PUSHERS ; task type POPERS is end POPERS ; POP_3 : POPERS ; PUSH_1 , PUSH_2 , PUSH_3 : PUSHERS ; POP_1 , POP_2 : POPERS ; task body PUSHERS is begin for I in 'A' .. 'Z' loop STACK_MONITOR.PUSH ( I ) ; end loop ; end PUSHERS ; task body POPERS is MY_CHARACTER : CHARACTER ; begin for I in 1 .. 26 loop STACK_MONITOR.POP ( MY_CHARACTER ) ; PUT ( MY_CHARACTER ) ; delay 0.01 ; end loop ; end POPERS ; begin PUT_LINE ( " main running " ) ; end STACK_AS_TASK ; -- $ ADA STACK_AS_TASK -- $ ACS LINK STACK_AS_TASK -- $ RUN STACK_AS_TASK -- main running -- AAAHIIKLLMOOPRRSUUVXXYZZZYYXWWWVVUTTTSSRQQQPPONNNMMLKKJJJIHHGGGFFFEEEDDDCCCBBB