home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / misc_programming / TEST / BANK.ADA next >
Encoding:
Text File  |  1990-06-28  |  8.5 KB  |  271 lines

  1. with    ada_io;        use     ada_io;
  2. with    random_integer;
  3.  
  4.  
  5. procedure bank is
  6.  
  7.   -- These 2 constants can be altered to change
  8.   --  the behavior of the simulation
  9.   number_of_tellers : constant integer := 4;
  10.   number_of_customers : constant integer := 5;
  11.  
  12.   -- These 2 ranges can be altered to change
  13.   --  the behavior of the simulation
  14.   subtype transaction_time_range is integer range 1 .. 10;
  15.   subtype time_between_visits_range is integer range 1 .. 100;
  16.  
  17.   -- Global types
  18.   subtype money is integer range 0 .. integer'last;
  19.   type status is ( success, insufficient_funds, bad_cust_id );
  20.   subtype cust_id is integer range 0 .. number_of_customers;
  21.  
  22.   subtype teller_id is character;
  23.   last_teller_id : teller_id := character'pred('A');
  24.  
  25.   -- Task specifications
  26.  
  27.   task type customer;           -- Requestor task type, no entries
  28.   task type teller is
  29.     -- Entries to do simple transactions and return status
  30.     entry deposit ( id : cust_id; val : in  money; stat : out status );
  31.     entry withdraw( id : cust_id; val : in  money; stat : out status );
  32.     entry balance ( id : cust_id; val : out money; stat : out status );
  33.   end teller;
  34.  
  35.   -- Arrays of tasks
  36.   tellers : array( 1 .. number_of_tellers ) of teller;
  37.   customers : array ( 1 .. number_of_customers ) of customer;
  38.  
  39.   task accounts_manager is
  40.     -- Opens accounts, establishes new customer id's
  41.     entry new_account( new_id : out cust_id );
  42.   end accounts_manager;
  43.  
  44.   task bank_database is
  45.     -- Maintains bank's internal data about open accounts and balances
  46.     entry enter_cust_id ( id : cust_id );
  47.     entry verify_cust_id( id : cust_id; legal  : out boolean );
  48.     entry deposit       ( id : cust_id; amount : in  money   );
  49.     entry withdraw      ( id : cust_id; amount : in  money   );
  50.     entry balance       ( id : cust_id; amount : out money   );
  51.   end bank_database;
  52.  
  53.   function next_teller_id return teller_id is
  54.   begin
  55.     last_teller_id := character'succ( last_teller_id );
  56.     return last_teller_id;
  57.   end;
  58.  
  59.   procedure put_secs( secs : integer ) is
  60.   begin
  61.     put( secs, 2 );  put( " second" );
  62.     if secs = 1 then
  63.       put( ' ' );
  64.     else
  65.       put( 's' );
  66.     end if;
  67.   end;
  68.  
  69.   task body teller is
  70.     current_balance : money;
  71.     valid   : boolean;
  72.     last_id : cust_id;
  73.     del     : integer;
  74.     tel_id  : teller_id;
  75.  
  76.     function random_transaction_time return integer is
  77.       length : constant integer := transaction_time_range'last -
  78.                    transaction_time_range'first + 1;
  79.     begin
  80.       return (random_integer.next mod length) + transaction_time_range'first;
  81.     end;
  82.  
  83.   begin
  84.     put( "Teller - activation done" );  new_line;
  85.     tel_id := next_teller_id;
  86.     loop
  87.       select                    -- Wait for any transaction request
  88.     accept deposit( id : cust_id; val : in money; stat : out status ) do
  89.       last_id := id;
  90.       bank_database.verify_cust_id( id, valid );
  91.       if not valid then
  92.         stat := bad_cust_id;
  93.       else
  94.         bank_database.deposit( id, val );
  95.         stat := success;
  96.       end if;
  97.     end deposit;
  98.       or
  99.     accept withdraw( id : cust_id; val : in money; stat : out status ) do
  100.       last_id := id;
  101.       bank_database.verify_cust_id( id, valid );
  102.       if not valid then
  103.         stat := bad_cust_id;
  104.       else
  105.         bank_database.balance( id, current_balance );
  106.         if current_balance < val then
  107.           stat := insufficient_funds;
  108.           put( "Account #" ); put( integer(id) ); put( " -" );
  109.           put( integer(val), 6 ); put( " = insufficient funds" ); new_line;
  110.         else
  111.           bank_database.withdraw( id, val );
  112.           stat := success;
  113.         end if;
  114.       end if;
  115.     end withdraw;
  116.       or
  117.     accept balance( id : cust_id; val : out money; stat : out status ) do
  118.       last_id := id;
  119.       bank_database.verify_cust_id( id, valid );
  120.       if not valid then
  121.         stat := bad_cust_id;
  122.       else
  123.         bank_database.balance( id, val );
  124.         stat := success;
  125.       end if;
  126.     end balance;
  127.       end select;
  128.       del := random_transaction_time;
  129.       put( "Teller   " ); put( tel_id );
  130.       put( " waits " ); put_secs( del );
  131.       put( " after handling account #" );
  132.       put( last_id ); new_line;
  133.       delay duration(del);
  134.       put( "Teller   " ); put( tel_id );
  135.       put( " wait done" ); new_line;
  136.     end loop;                   -- Simulate transaction time
  137.   end teller;
  138.  
  139.   task body customer is
  140.     -- Local type
  141.     type transaction is ( deposit, withdraw, balance );
  142.  
  143.     subtype money_range is money range 1 .. 1000;
  144.  
  145.     -- Local variables
  146.     id : cust_id;
  147.     amount : money;
  148.     stat : status;
  149.     del : integer;
  150.  
  151.     function random_transaction return transaction is
  152.       length : constant integer := transaction'pos(transaction'last) -
  153.                    transaction'pos(transaction'first) + 1;
  154.     begin
  155.       return transaction'val( (random_integer.next mod length) +
  156.                   transaction'pos(transaction'first) );
  157.     end;
  158.  
  159.     function random_teller return integer is
  160.     begin
  161.       return (random_integer.next mod number_of_tellers) + 1;
  162.     end;
  163.  
  164.     function random_amount return money is
  165.       length : constant integer := money_range'last - money_range'first + 1;
  166.     begin
  167.       return money_range'val( (random_integer.next mod length) +
  168.                   money_range'pos(money_range'first) );
  169.     end;
  170.  
  171.     function random_time_between_visits return integer is
  172.       length : constant integer := time_between_visits_range'last -
  173.                    time_between_visits_range'first + 1;
  174.     begin
  175.       return (random_integer.next mod length) + time_between_visits_range'first;
  176.     end;
  177.  
  178.   begin
  179.     put( "Customer - activation done" );  new_line;
  180.     accounts_manager.new_account( id );                 -- Get new cust id
  181.     loop
  182.       del := random_time_between_visits;
  183.       put( "Account #" ); put( id );
  184.       put( " waits " ); put_secs( del );  new_line;
  185.       delay duration(del);
  186.       put( "Account #" ); put( id );
  187.       put( " wait done" ); new_line;
  188.       case random_transaction is        -- Pick random transaction
  189.     when deposit =>
  190.       tellers(random_teller).deposit ( id, random_amount, stat );
  191.     when withdraw =>
  192.       tellers(random_teller).withdraw( id, random_amount, stat );
  193.     when balance =>
  194.       tellers(random_teller).balance ( id, amount, stat );
  195.       end case;
  196.     end loop;
  197.   end customer;
  198.  
  199.   task body accounts_manager is
  200.     next : cust_id := 0;
  201.   begin
  202.     put( "Accounts_manager - activation done" );  new_line;
  203.     next := 0;
  204.     loop
  205.       accept new_account( new_id : out cust_id ) do
  206.     new_id := next;
  207.     bank_database.enter_cust_id( next );
  208.     next := next + 1;
  209.       end new_account;
  210.     end loop;
  211.   end accounts_manager;
  212.  
  213.   task body bank_database is
  214.     -- In real situations, more elaborate data structures are needed
  215.     balances : array(cust_id) of money;
  216.     valid_id : array(cust_id) of boolean := (others => false);
  217.   begin
  218.     put( "Bank_database - activation done" );  new_line;
  219.     for vind in valid_id'range loop
  220.       valid_id(vind) := false;
  221.     end loop;
  222.     loop
  223.       select
  224.     accept enter_cust_id( id : cust_id ) do
  225.       valid_id(id) := true;
  226.       balances(id) := 0;
  227.       put( "Account #" );  put( id );  put( " is now open" ); new_line;
  228.     end enter_cust_id;
  229.       or
  230.     accept verify_cust_id( id : cust_id; legal : out boolean ) do
  231.       legal := valid_id(id);
  232.       put( "Account #" );  put( id );
  233.       if valid_id(id) then
  234.         put( " is valid" );
  235.       else
  236.         put( " is not valid" );
  237.       end if;
  238.       new_line;
  239.     end verify_cust_id;
  240.       or
  241.     accept deposit( id : cust_id; amount : in money ) do
  242.       balances(id) := balances(id) + amount;
  243.       put( "Account #" );  put( id );
  244.       put( " +" ); put( integer(amount), 6 );
  245.       put( " = " );  put( integer(balances(id)), 5 ); new_line;
  246.     end deposit;
  247.       or
  248.     accept withdraw( id : cust_id; amount : in money ) do
  249.       balances(id) := balances(id) - amount;
  250.       put( "Account #" );  put( id );
  251.       put( " -" ); put( integer(amount), 6 );
  252.       put( " = " );  put( integer(balances(id)), 5 ); new_line;
  253.     end withdraw;
  254.       or
  255.     accept balance( id : cust_id; amount : out money ) do
  256.       amount := balances(id);
  257.       put( "Account #" );  put( id );
  258.       put( " balance = " );  put( integer(balances(id)), 5 ); new_line;
  259.     end balance;
  260.       end select;
  261.     end loop;
  262.   end bank_database;
  263.  
  264. begin   -- Main body of bank simulation
  265.   -- Activation of customer and teller task collections
  266.   --  and band_database and accounts_manager tasks occurs here.
  267.   null;
  268.   -- This program runs forever
  269.   -- Procedure bank_simulation is completed but not terminated
  270. end bank;
  271.