Merge branch 'main' of feistymeow.org:feisty_meow
[feisty_meow.git] / structures / memory_limiter.h
1 #ifndef MEMORY_LIMITER_CLASS
2 #define MEMORY_LIMITER_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : memory_limiter                                                    *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 2001-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include <basis/astring.h>
19 #include <basis/contracts.h>
20 #include <structures/set.h>
21
22 namespace structures {
23
24 // forward.
25 class ml_memory_record;
26 class ml_memory_state_meter;
27
28 //! Tracks memory currently in use by memory manager objects.
29 /*!
30   The manager is given the ability to control overall memory usage as well
31   as to track memory usage per each user of the memory (assuming that the
32   memory is granted to unique users indexable via an integer).
33 */
34
35 class memory_limiter
36 {
37 public:
38   memory_limiter(int overall_limit, int individual_limit);
39     //!< creates a limiter that allows "overall_limit" bytes to be in use.
40     /*!< any attempts to add new memory after that limit is reached will be
41     rejected.  if "overall_limit" is zero, then no limit is enforced on the
42     amount of memory that can be used in total.  the "individual_limit"
43     specifies per-user limits, where each user of memory is identified by a
44     unique integer and where all users are granted equal rights to allocate
45     memory.  "individual_limit" can also be given as zero, meaning no limit
46     is enforced per individual.  note that "overall_limit" should usually be
47     many multiples of the "individual_limit", as appropriate to how many users
48     are expected. */
49
50   virtual ~memory_limiter();
51
52   DEFINE_CLASS_NAME("memory_limiter");
53
54   int overall_limit() const { return _overall_limit; }
55     //!< returns the current overall limit.
56   int individual_limit() const { return _individual_limit; }
57     //!< returns the current individual limit.
58
59   int overall_usage() const { return _overall_size; }
60     //!< returns the size used by all managed memory.
61
62   int overall_space_left() const { return overall_limit() - overall_usage(); }
63     //!< returns the overall space left for allocation.
64
65   int individual_usage(int individual) const;
66     //!< returns the amount of memory used by "individual".
67
68   int individual_space_left(int individual) const;
69     //!< returns the space left for the individual specified.
70
71   basis::astring text_form(int indent = 0) const;
72     //!< returns a string that lists out the overall plus individual limits.
73     /*!< "indent" is used for spacing the printed rows of information. */
74
75   bool okay_allocation(int individual, int memory_desired);
76     //!< returns true if "individual" may allocate "memory_desired" bytes.
77     /*!< false indicates that this memory must not be allocated if the limits
78     are to be adhered to, either because there is already too much used in
79     the system at large or because this user is already using their limit. */
80
81   bool record_deletion(int individual, int memory_deleted);
82     //!< acknowledges that the "individual" freed "memory_deleted" bytes.
83     /*!< returns true if the "individual" is known and if "memory_deleted"
84     could be subtracted from that object's usage count.  failure of this method
85     indicates that this class is not being used properly; if memory was
86     okayed to be granted in okay_allocation, then the paired record_deletion
87     will always succeed (in any arbitrary order where the okay_allocation
88     succeeds and proceeds the matching record_deletion).  if there are no
89     remaining allocations for this individual, then its record is removed. */
90
91   void reset();
92     //!< returns the object to a pristine state.
93
94   const structures::int_set &individuals_listed() const;
95     //!< reports the current set of individuals using memory.
96     /*!< to know whether one is using this class appropriately, check the
97     returned set.  if one does not think there should be any memory in use,
98     then the set should be empty and overall_usage() should return zero.
99     if the overall_usage() is zero, but there are members in the set, then
100     there is an implementation error in memory_limiter.  otherwise, if the
101     set is non-empty, then deleted memory has not been recorded. */
102
103 private:
104   int _overall_limit;  //!< how many total bytes allowed?
105   int _individual_limit;  //!< how many bytes may each user consume?
106   int _overall_size;  //!< the current measured overall memory usage in bytes.
107   ml_memory_state_meter *_individual_sizes;  //!< tracks memory per individual.
108
109   ml_memory_record *find_individual(int individual) const;
110     //!< locates the record held for the "individual" specified or returns NULL_POINTER.
111 };
112
113 } //namespace.
114
115 #endif
116