Raw File
Place.h
/*
  This file is part of the FRED system.

  Copyright (c) 2010-2015, University of Pittsburgh, John Grefenstette,
  Shawn Brown, Roni Rosenfield, Alona Fyshe, David Galloway, Nathan
  Stone, Jay DePasse, Anuroop Sriram, and Donald Burke.

  Licensed under the BSD 3-Clause license.  See the file "LICENSE" for
  more information.
*/

//
//
// File: Place.h
//

#ifndef _FRED_PLACE_H
#define _FRED_PLACE_H

#include <new>
#include <vector>
#include <deque>
#include <map>
#include <set>
using namespace std;

#include "Population.h"
#include "Global.h"
#include "State.h"
#include "Geo.h"
#define DISEASE_TYPES 4

typedef std::vector<Place*> place_vec;

class Neighborhood_Patch;
class Person;

struct Place_State {

  fred::Spin_Mutex mutex;
  // working copies of susceptibles and infectious lists
  std::vector<Person*> susceptibles;
  std::vector<Person*> infectious;

  void add_susceptible(Person* p) {
    fred::Spin_Lock lock(mutex);
    this->susceptibles.push_back(p);
  }

  void clear_susceptibles() {
    fred::Spin_Lock lock(mutex);
    this->susceptibles.clear();
  }

  size_t susceptibles_size() {
    fred::Spin_Lock lock(mutex);
    return this->susceptibles.size();
  }

  std::vector<Person*> &get_susceptible_vector() {
    return this->susceptibles;
  }

  void add_infectious(Person* p) {
    fred::Spin_Lock lock(mutex);
    this->infectious.push_back(p);
  }

  void clear_infectious() {
    fred::Spin_Lock lock(mutex);
    this->infectious.clear();
  }

  size_t infectious_size() {
    fred::Spin_Lock lock(mutex);
    return this->infectious.size();
  }

  std::vector<Person*> &get_infectious_vector() {
    return this->infectious;
  }

  void clear() {
    this->susceptibles.clear();
    this->infectious.clear();
  }

  void reset() {
    if(this->susceptibles.size() > 0) {
      this->susceptibles = std::vector<Person*>();
    }

    if(this->infectious.size() > 0) {
      this->infectious = std::vector<Person*>();
    }
  }

};

struct Place_State_Merge : Place_State {

  void operator()(const Place_State & state) {
    fred::Spin_Lock lock(mutex);
    this->susceptibles.insert(this->susceptibles.end(),
                              state.susceptibles.begin(),
                              state.susceptibles.end());
    this->infectious.insert(this->infectious.end(),
                            state.infectious.begin(),
                            state.infectious.end());
  }
};


class Place {

public:
  
  // place-specific transmission mode parameters
  static bool Enable_Neighborhood_Density_Transmission;
  static bool Enable_Density_Transmission_Maximum_Infectees;
  static int Density_Transmission_Maximum_Infectees;

  // static seasonal transmission parameters
  static double Seasonal_Reduction;
  static double* Seasonality_multiplier;

  // place type codes
  static char HOUSEHOLD;
  static char NEIGHBORHOOD;
  static char SCHOOL;
  static char CLASSROOM;
  static char WORKPLACE;
  static char OFFICE;
  static char HOSPITAL;
  static char COMMUNITY;

  virtual ~Place() {}

  /**
   *  Sets the id, label, logitude, latitude of this Place
   *  Allocates disease-related memory for this place
   *
   *  @param lab this Place's label
   *  @param lon this Place's longitude
   *  @param lat this Place's latitude
   */
  void setup(const char* lab, fred::geo lon, fred::geo lat);

  static void initialize_static_variables();

  /**
   * Get this place ready
   */
  virtual void prepare();

  /**
   * Perform a daily update of this place.  The vectors
   * containing infectious and symptomatics will be cleared.
   */
  virtual void update(int day);

  void reset_place_state(int disease_id);

  /**
   * The daily count arrays will all be reset.
   */
  void reset_visualization_data(int day);

  void reset_vector_data(int day);

  /**
   * Display the information for a given disease.
   *
   * @param disease an integer representation of the disease
   */
  virtual void print(int disease_id);

  /**
   * Add a person to the place. This method increments the number of people in
   * the place.
   *
   * @param per a pointer to a Person object that may be added to the place
   */
  virtual void enroll(Person* per);

  /**
   * Remove a person from the place. This method decrements the number of people in
   * the place.
   *
   * @param per a pointer to a Person object that may be removed to the place
   */
  virtual void unenroll(Person* per);

  /**
   * Get the number of adults in the household.
   * @return the number of adults
   */
  int get_adults();

  /**
   * Get the number of children in the household.
   * @return the number of children
   */
  int get_children();

  void register_as_an_infectious_place(int disease_id);

  void add_visitors_if_infectious(int day);
  void add_visitors_to_infectious_place(int day, int disease_id);

  /**
   * Add a susceptible person to the place. This method adds the person to the susceptibles vector.
   *
   * @param disease_id an integer representation of the disease
   * @param per a pointer to a Person object that will be added to the place for a given diease
   */
  void add_susceptible(int disease_id, Person* per);
  void add_nonsusceptible(int disease_id, Person* per);

  /**
   * Add a infectious person to the place. This method adds the person to the infectious vector.
   *
   * @param disease_id an integer representation of the disease
   * @param per a pointer to a Person object that will be added to the place for a given diease
   */
  void add_infectious(int disease_id, Person* per);

  /**
   * Prints the id of every person in the susceptible vector for a given diease.
   *
   * @param disease_id an integer representation of the disease
   */
  void print_susceptibles(int disease_id);

  /**
   * Prints the id of every person in the infectious vector for a given diease.
   *
   * @param disease_id an integer representation of the disease
   */
  void print_infectious(int disease_id);

  /**
   * Attempt to spread the infection for a given diease on a given day.
   *
   * @param day the simulation day
   * @param disease_id an integer representation of the disease
   */
  void spread_infection(int day, int disease_id);

  void default_transmission_model(int day, int disease_id);
  void age_based_transmission_model(int day, int disease_id);
  void pairwise_transmission_model(int day, int disease_id);
  void density_transmission_model(int day, int disease_id);

  /**
   * Is the place open on a given day?
   *
   * @param day the simulation day
   * @return <code>true</code> if the place is open; <code>false</code> if not
   */
  virtual bool is_open(int day) {
    return true;
  }

  /**
   * Test whether or not any infectious people are in this place.
   *
   * @return <code>true</code> if any infectious people are here; <code>false</code> if not
   */
  bool is_infectious(int disease_id) {
    return this->infectious_bitset.test(disease_id);
  }
  
  bool is_infectious() {
    return this->infectious_bitset.any();
  }
  
  bool is_human_infectious(int disease_id) {
    return this->human_infectious_bitset.test(disease_id);
  }  

  void set_human_infectious (int disease_id) {
    if(!(this->human_infectious_bitset.test(disease_id))) {
      this->human_infectious_bitset.set(disease_id);
    }
  }
    
  void reset_human_infectious() {
    this->human_infectious_bitset.reset();
  }
    
  void set_exposed(int disease_id) {
    this->exposed_bitset.set(disease_id);
  }
  
  void reset_exposed() {
    this->exposed_bitset.reset();
  }

  bool is_exposed(int disease_id) {
    return this->exposed_bitset.test(disease_id);
  }
  
  void set_recovered(int disease_id) {
    this->recovered_bitset.set(disease_id);
  }
  
  void reset_recovered() {
    this->recovered_bitset.reset();
  }
  
  bool is_recovered(int disease_id) {
    return this->recovered_bitset.test(disease_id);
  }
  
  /**
   * Sets the static variables for the class from the parameter file for a given number of disease_ids.
   *
   * @param disease_id an integer representation of the disease
   */
  virtual void get_parameters(int disease_id) = 0;

  /**
   * Get the age group for a person given a particular disease_id.
   *
   * @param disease_id an integer representation of the disease
   * @param per a pointer to a Person object
   * @return the age group for the given person for the given diease
   */
  virtual int get_group(int disease_id, Person * per) = 0;

  /**
   * Get the transmission probability for a given diease between two Person objects.
   *
   * @param disease_id an integer representation of the disease
   * @param i a pointer to a Person object
   * @param s a pointer to a Person object
   * @return the probability that there will be a transmission of disease_id from i to s
   */
  virtual double get_transmission_prob(int disease_id, Person * i, Person * s) = 0;

  /**
   * Get the contacts for a given diease.
   *
   * @param disease_id an integer representation of the disease
   * @return the contacts per day for the given diease
   */
  virtual double get_contacts_per_day(int disease_id) = 0; // access functions

  /**
   * Determine if the place should be open. It is dependent on the disease_id and simulation day.
   *
   * @param day the simulation day
   * @param disease_id an integer representation of the disease
   * @return <code>true</code> if the place should be open; <code>false</code> if not
   */
  virtual bool should_be_open(int day, int disease_id) = 0;

  /**
   * Get the id.
   * @return the id
   */
  int get_id() {
    return this->id;
  }

  /**
   * Get the label.
   *
   * @return the label
   */
  char* get_label() {
    return this->label;
  }

  /**
   * Get the type (H)OME, (W)ORK, (S)CHOOL, (C)OMMUNITY).
   *
   * @return the type
   */
  char get_type() {
    return this->type;
  }

  // test place types
  bool is_household() {
    return this->type == Place::HOUSEHOLD;
  }
  
  bool is_neighborhood() {
    return this->type == Place::NEIGHBORHOOD;
  }
  
  bool is_school() {
    return this->type == Place::SCHOOL;
  }
  
  bool is_classroom() {
    return this->type == Place::CLASSROOM;
  }
  
  bool is_workplace(){
    return this->type == Place::WORKPLACE;
  }
  
  bool is_office() {
    return this->type == Place::OFFICE;
  }
  
  bool is_hospital() {
    return this->type == Place::HOSPITAL;
  }
  
  bool is_community() {
    return this->type == Place::COMMUNITY;
  }

  // test place subtypes
  bool is_college(){
    return this->subtype == fred::PLACE_SUBTYPE_COLLEGE;
  }
  
  bool is_prison(){
    return this->subtype == fred::PLACE_SUBTYPE_PRISON;
  }
  
  bool is_nursing_home(){
    return this->subtype == fred::PLACE_SUBTYPE_NURSING_HOME;
  }
  
  bool is_military_base(){
    return this->subtype == fred::PLACE_SUBTYPE_MILITARY_BASE;
  }
    
  bool is_healthcare_clinic(){
    return this->subtype == fred::PLACE_SUBTYPE_HEALTHCARE_CLINIC;
  }

  bool is_mobile_healthcare_clinic(){
    return this->subtype == fred::PLACE_SUBTYPE_MOBILE_HEALTHCARE_CLINIC;
  }
    
  bool is_group_quarters() {
    return (is_college() || is_prison() || is_military_base() || is_nursing_home());
  }

  // test for household types
  bool is_college_dorm(){
    return is_household() && is_college();
  }
  
  bool is_prison_cell(){
    return  is_household() && is_prison();
  }
  
  bool is_military_barracks() {
    return is_household() && is_military_base();
  }

  /**
   * Get the latitude.
   *
   * @return the latitude
   */
  fred::geo get_latitude() {
    return this->latitude;
  }

  /**
   * Get the longitude.
   *
   * @return the longitude
   */
  fred::geo get_longitude() {
    return this->longitude;
  }

  double get_distance(Place *place) {
    double x1 = this->get_x();
    double y1 = this->get_y();
    double x2 = place->get_x();
    double y2 = place->get_y();
    double distance = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
    return distance;
  }

  /**
   * Get the count of agents in this place.
   *
   * @return the count of agents
   */
  int get_size() {
    return this->N;
  }

  virtual int get_container_size() {
    return get_size();
  }

  int get_orig_size() {
    return this->N_orig;
  }

  /**
   * Get the simulation day (an integer value of days from the start of the simulation) when the place will close.
   *
   * @return the close_date
   */
  int get_close_date() {
    return this->close_date;
  }

  /**
   * Get the simulation day (an integer value of days from the start of the simulation) when the place will open.
   *
   * @return the open_date
   */
  int get_open_date() {
    return this->open_date;
  }

  /**
   * Set the type.
   *
   * @param t the new type
   */
  void set_type(char t) {
    this->type = t;
  }

  /**
   * Set the latitude.
   *
   * @param x the new latitude
   */
  void set_latitude(double x) {
    this->latitude = x;
  }

  /**
   * Set the longitude.
   *
   * @param x the new longitude
   */
  void set_longitude(double x) {
    this->longitude = x;
  }

  /**
   * Set the simulation day (an integer value of days from the start of the simulation) when the place will close.
   *
   * @param day the simulation day when the place will close
   */
  void set_close_date(int day) {
    this->close_date = day;
  }

  /**
   * Set the simulation day (an integer value of days from the start of the simulation) when the place will open.
   *
   * @param day the simulation day when the place will open
   */
  void set_open_date(int day) {
    this->open_date = day;
  }

  /**
   * Get the patch where this place is.
   *
   * @return a pointer to the patch where this place is
   */
  Neighborhood_Patch* get_patch() {
    return this->patch;
  }

  /**
   * Set the patch where this place will be.
   *
   * @param p the new patch
   */
  void set_patch(Neighborhood_Patch* p) {
    this->patch = p;
  }
  
  int get_output_count(int disease_id, int output_code);

  void turn_workers_into_teachers(Place* school);
  void reassign_workers(Place* place);

  double get_x() {
    return Geo::get_x(this->longitude);
  }

  double get_y() {
    return Geo::get_y(this->latitude);
  }

  void add_new_infection(int disease_id) {
#pragma omp atomic
    this->new_infections[disease_id]++;
#pragma omp atomic
    this->total_infections[disease_id]++;
  }
  
  void add_current_infection(int disease_id) {
#pragma omp atomic
    this->current_infections[disease_id]++;
  }
  
  void add_new_symptomatic_infection(int disease_id) {
#pragma omp atomic
    this->new_symptomatic_infections[disease_id]++;
#pragma omp atomic
    this->total_symptomatic_infections[disease_id]++;
  }
  
  void add_current_symptomatic_infection(int disease_id) {
#pragma omp atomic
    this->current_symptomatic_infections[disease_id]++;
  }
  
  int get_new_infections(int disease_id) {
    return this->new_infections[disease_id];
  }

  int get_current_infections(int disease_id) {
    return this->current_infections[disease_id];
  }

  int get_total_infections(int disease_id) {
    return this->total_infections[disease_id];
  }

  int get_new_symptomatic_infections(int disease_id) {
    return this->new_symptomatic_infections[disease_id];
  }

  int get_current_symptomatic_infections(int disease_id) {
    return this->current_symptomatic_infections[disease_id];
  }

  int get_total_symptomatic_infections(int disease_id) {
    return this->total_symptomatic_infections[disease_id];
  }

  int get_current_infectious_visitors(int disease_id) {
    return this->current_infectious_visitors[disease_id];
  }

  int get_current_symptomatic_visitors(int disease_id) {
    return this->current_symptomatic_visitors[disease_id];
  }

  /**
   * Get the number of cases of a given disease for day.
   *
   * @param disease_id an integer representation of the disease
   * @return the count of cases for a given diease
   */
  int get_current_cases(int disease_id) {
    return get_current_symptomatic_visitors(disease_id);
  }

  /**
   * Get the number of deaths from a given disease for a day.
   * The member variable deaths gets reset when <code>update()</code> is called, which for now is on a daily basis.
   *
   * @param disease_id an integer representation of the disease
   * @return the count of deaths for a given disease
   */
  int get_new_deaths(int disease_id) {
    return 0 /* new_deaths[disease_id] */;
  }

  int get_recovereds(int disease_id);

  /**
   * Get the number of cases of a given disease for the simulation thus far.
   *
   * @param disease_id an integer representation of the disease
   * @return the count of cases for a given disease
   */
  int get_total_cases(int disease_id) {
    return this->total_symptomatic_infections[disease_id];
  }

  /**
   * Get the number of deaths from a given disease for the simulation thus far.
   *
   * @param disease_id an integer representation of the disease
   * @return the count of deaths for a given disease
   */
  int get_total_deaths(int disease_id) {
    return 0 /* total_deaths[disease_id] */;
  }

  /**
   * Get the number of cases of a given disease for the simulation thus far divided by the
   * number of agents in this place.
   *
   * @param disease_id an integer representation of the disease
   * @return the count of rate of cases per people for a given disease
   */
  double get_incidence_rate(int disease_id) {
    return (double)this->total_symptomatic_infections[disease_id] / (double)this->N;
  }
  
  /**
   * Get the clincal attack rate = 100 * number of cases thus far divided by the
   * number of agents in this place.
   *
   * @param disease_id an integer representation of the disease
   * @return the count of rate of cases per people for a given disease
   */
  double get_symptomatic_attack_rate(int disease_id) {
    return (100.0 * this->total_symptomatic_infections[disease_id]) / (double) this->N;
  }
  
  /**
   * Get the attack rate = 100 * number of infections thus far divided by the
   * number of agents in this place.
   *
   * @param disease_id an integer representation of the disease
   * @return the count of rate of cases per people for a given disease
   */
  double get_attack_rate(int disease_id) {
    return(this->N ? (100.0 * this->total_infections[disease_id]) / (double)this->N : 0.0);
  }

  int get_first_day_infectious() {
    return this->first_day_infectious;
  }

  int get_last_day_infectious() {
    return this->last_day_infectious;
  }

  Person* get_enrollee(int i) {
    return this->enrollees[i];
  }

  int get_enrollee_index(Person* person) {
    for(int i = 0; i < this->enrollees.size(); i++) {
      if(this->enrollees[i] == person) {
        return i;
      }
    }
    return -1;
  }

  void set_index(int _index) {
    this->index = _index;
  }
  
  int get_index() {
    return this->index;
  }

  void set_subtype(fred::place_subtype _subtype) {
    this->subtype = _subtype;
  }
  
  fred::place_subtype get_subtype() {
    return this->subtype;
  }
  
  int get_staff_size() {
    return this->staff_size;
  }
  
  void set_staff_size(int _staff_size) {
    this->staff_size = _staff_size;
  }

  // vector transmission model
  void setup_vector_model();
  void set_temperature();
  void vector_transmission(int day, int disease_id);
  void infect_vectors(int day);
  void vectors_transmit_to_hosts(int day, int disease_id);
  void update_vector_population(int day);
  int get_vector_population_size() {
    return this->N_vectors;
  }
    
  bool has_infectious_vectors(int disease_id) {
    return this->I_vectors[disease_id] > 0;
  }
    
  // int get_number_of_infected_hosts(int disease_id) { return E_hosts[disease_id]; }
  double get_temperature() {
    return this->temperature;
  }
    
  double get_seeds(int dis, int day);
  int get_infected_vectors() {
    int n = 0;
    for(int i = 0; i < DISEASE_TYPES; ++i) {
      n += this->E_vectors[i] + this->I_vectors[i];
    }
    return n;
  }

  int get_infectious_vectors() {
    int n = 0;
    for (int i = 0; i < DISEASE_TYPES; ++i) {
      n += this->I_vectors[i];
    }
    return n;
  }

  void add_host(Person* person) {
    this->unique_visitors.insert(person);
  }

  static void clear_infectious_places(int capacity) {
    int size = Place::infectious_places.size();
    for (int i = 0; i < size; ++i) {
      Place* place = Place::infectious_places[i];
      place->is_registered_as_an_infectous_place = false;
    }
    Place::infectious_places.clear();
    Place::infectious_places.reserve(capacity);
  }

  static int count_infectious_places() {
    return Place::infectious_places.size();
  }

  static Place* get_infectious_place(int n) {
    return Place::infectious_places[n];
  }
  
  int get_household_fips() {
    return this->household_fips;
  }

  void set_household_fips(int input_fips) {
    this->household_fips = input_fips;
  }
  
  void set_county_index(int _county_index) {
    this->county_index = _county_index;
  }

  int get_county_index() {
    return this->county_index;
  }

  void set_census_tract_index(int _census_tract_index) {
    this->census_tract_index = _census_tract_index;
  }

  int get_census_tract_index() {
    return this->census_tract_index;
  }
  
  static char* get_place_label(Place* p);

protected:
  // list of places that are infectious today
  static place_vec infectious_places;

  // true if this place is on the above list
  bool is_registered_as_an_infectous_place;

  //  collects list of susceptible visitors (per disease)
  //  collects list of infectious visitors (per disease)
  State< Place_State > place_state[Global::MAX_NUM_DISEASES];

  // temporary working copy of:
  //  list of susceptible visitors (per disease); size of which gives the susceptibles count
  //  list of infectious visitors (per disease); size of which gives the infectious count
  Place_State_Merge place_state_merge;

  // track whether or not place is infectious with each disease
  fred::disease_bitset infectious_bitset; 
  fred::disease_bitset human_infectious_bitset;
  fred::disease_bitset recovered_bitset; 
  fred::disease_bitset exposed_bitset; 

  char label[32];         // external id
  char type;              // HOME, WORK, SCHOOL, COMMUNITY, etc;
  fred::place_subtype subtype;
  char worker_profile;
  int id;                 // place id
  fred::geo latitude;     // geo location
  fred::geo longitude;    // geo location
  vector <Person*> enrollees;
  int close_date;         // this place will be closed during:
  int open_date;          //   [close_date, open_date)
  int N;                  // total number of potential visitors
  int N_orig;		  // orig number of potential visitors
  double intimacy;	  // prob of intimate contact
  static double** prob_contact;
  int index;		  // index for households
  int staff_size;			// outside workers in this place

  int household_fips;
  int county_index;
  int census_tract_index;
  
  Neighborhood_Patch* patch;       // geo patch for this place
  
  // infection stats
  int new_infections[Global::MAX_NUM_DISEASES]; // new infections today
  int current_infections[Global::MAX_NUM_DISEASES]; // current active infections today
  int total_infections[Global::MAX_NUM_DISEASES]; // total infections over all time

  int new_symptomatic_infections[Global::MAX_NUM_DISEASES]; // new sympt infections today
  int current_symptomatic_infections[Global::MAX_NUM_DISEASES]; // current active sympt infections
  int total_symptomatic_infections[Global::MAX_NUM_DISEASES]; // total sympt infections over all time

  // these counts refer to today's visitors:
  int current_infectious_visitors[Global::MAX_NUM_DISEASES]; // total infectious visitors today
  int current_symptomatic_visitors[Global::MAX_NUM_DISEASES]; // total sympt infections today

  // NOT IMPLEMENTED YET:
  // int new_deaths[ Global::MAX_NUM_DISEASES ];	    // deaths today
  // int total_deaths[ Global::MAX_NUM_DISEASES ];     // total deaths

  int first_day_infectious;
  int last_day_infectious;

  double get_contact_rate(int day, int disease_id);
  int get_contact_count(Person* infector, int disease_id, int day, double contact_rate);
  bool attempt_transmission(double transmission_prob, Person * infector, Person * infectee, int disease_id, int day);

  // Place_List, Neighborhood_Layer and Neighborhood_Patch are friends so that they can access
  // the Place Allocator.  
  friend class Place_List;
  friend class Neighborhood_Layer;
  friend class Neighborhood_Patch;

  // friend Place_List can assign id
  void set_id(int _id) {
    this->id = _id;
  }

  void add_infectious_visitor(int disease_id) { 
#pragma omp atomic
    this->current_infectious_visitors[disease_id]++;
  }
  
  void add_symptomatic_visitor(int disease_id) {
#pragma omp atomic
    this->current_symptomatic_visitors[disease_id]++;
  }
  
  // data for vector transmission model
  double death_rate;
  double birth_rate;
  double bite_rate;
  double incubation_rate;
  double suitability;
  double transmission_efficiency;
  double infection_efficiency;

  // vectors per host
  double temperature;
  double vectors_per_host;
  double pupae_per_host;
  double life_span;
  double sucess_rate;
  double female_ratio;
  double development_time;

  // counts for vectors
  int N_vectors;
  int S_vectors;
  int E_vectors[DISEASE_TYPES];
  int I_vectors[DISEASE_TYPES];
  // proportion of imported or born infectious
  double place_seeds[DISEASE_TYPES];
  // day on and day off of seeding mosquitoes in the patch
  int day_start_seed[DISEASE_TYPES];
  int day_end_seed[DISEASE_TYPES];

  std::set<Person *> unique_visitors;

  // counts for hosts
  int N_hosts;
  bool vectors_not_infected_yet;

  // Place Allocator reserves chunks of memory and hands out pointers for use
  // with placement new
  template<typename Place_Type>
  struct Allocator {
    Place_Type* allocation_array;
    int current_allocation_size;
    int current_allocation_index;
    int number_of_contiguous_blocks_allocated;
    int remaining_allocations;
    int allocations_made;

    Allocator() {
      remaining_allocations = 0;
      number_of_contiguous_blocks_allocated = 0;
      allocations_made = 0;
      current_allocation_index = 0;
      current_allocation_size = 0;
      allocation_array = NULL;
    }

    bool reserve( int n = 1 ) {
      if(remaining_allocations == 0) {
        current_allocation_size = n;
        allocation_array = new Place_Type[n];
        remaining_allocations = n; 
        current_allocation_index = 0;
        ++(number_of_contiguous_blocks_allocated);
        allocations_made += n;
        return true;
      }
      return false;
    }

    Place_Type* get_free() {
      if(remaining_allocations == 0) {
        reserve();
      }
      Place_Type* place_pointer = allocation_array + current_allocation_index;
      --(remaining_allocations);
      ++(current_allocation_index);
      return place_pointer;
    }

    int get_number_of_remaining_allocations() {
      return remaining_allocations;
    }

    int get_number_of_contiguous_blocks_allocated() {
      return number_of_contiguous_blocks_allocated;
    }

    int get_number_of_allocations_made() {
      return allocations_made;
    }

    Place_Type* get_base_pointer() {
      return allocation_array;
    }

    int size() {
      return allocations_made;
    }
  }; // end Place Allocator

};


#endif // _FRED_PLACE_H
back to top