1------------------------------------------------------------------------------- 2-- storage_pool_handler.adb -- 3-- -- 4-- Purposes: Manages memory resources. As a result memory leakage problem -- 5-- will be thing of the past. -- 6-- -- 7-- Anh Vo - 01 March 2000 -- 8-- -- 9-- C/C++ is for money. Java is for fame and money. Ada is for reliability. -- 10-- -- 11------------------------------------------------------------------------------- 12 13with Ada.Exceptions; 14with Ada.Text_IO; 15with System.Address_To_Access_Conversions; 16with System.Storage_Elements; 17 18package body Storage_Pool_Handler is 19 20 use Ada; 21 use Text_IO; 22 23 use type System.Address; 24 use type System.Storage_Elements.Storage_Count; 25 26 Package_Name : constant String := "Storage_Pool_Handler."; 27 28 29 -- used by General Pool to link memory together 30 type Address_Linker is 31 record 32 Next_Address : System.Address := System.Null_Address; 33 Size_Elements : System.Storage_Elements.Storage_Count; 34 end record; 35 36 -- storage elements needed by General Pool 37 Link_Storage : constant System.Storage_Elements.Storage_Count := 38 Address_Linker'Max_Size_In_Storage_Elements; 39 40 package Address_Access_Conversion is new 41 System.Address_To_Access_Conversions (Address_Linker); 42 43 44 -- used by Detailed Pool to link the memory together 45 type Holder is 46 record 47 Next_Address : System.Address := System.Null_Address; 48 end record; 49 50 -- storage elements needed by Holder record. 51 Holder_Storage : constant System.Storage_Elements.Storage_Count := 52 Holder'Max_Size_In_Storage_Elements; 53 54 package Address_Access_Conv is new 55 System.Address_To_Access_Conversions (Holder); 56 57 58 function Aligned ( 59 Size : System.Storage_Elements.Storage_Count; 60 Alignment : System.Storage_Elements.Storage_Count) 61 return System.Storage_Elements.Storage_Count; 62 function Aligned ( 63 Size : System.Storage_Elements.Storage_Count; 64 Alignment : System.Storage_Elements.Storage_Count) 65 return System.Storage_Elements.Storage_Count is 66 begin 67 if Size rem Alignment /= 0 then 68 return Size + Alignment - (Size mod Alignment); 69 else 70 return Size; 71 end if; 72 end Aligned; 73 74 75 procedure Allocate ( 76 Pool : in out General_Pool; 77 Storage_Address : out System.Address; 78 Size_In_Storage_Elements : in System.Storage_Elements.Storage_Count; 79 Alignment : in System.Storage_Elements.Storage_Count) is 80 81 Previous : System.Address := System.Null_Address; 82 Current : System.Address := Pool.Addr_Head; 83 Desired_Size : System.Storage_Elements.Storage_Count := 84 Size_In_Storage_Elements; 85 86 begin -- Allocate 87 88 while Current /= System.Null_Address loop 89 if Address_Access_Conversion.To_Pointer (Current).Size_Elements = 90 Desired_Size then 91 92 -- select the matched memory block 93 if Previous = System.Null_Address then 94 Pool.Addr_Head := 95 Address_Access_Conversion.To_Pointer (Current).Next_Address; 96 else 97 -- examine the next memory block 98 Address_Access_Conversion.To_Pointer (Previous).Next_Address := 99 Address_Access_Conversion.To_Pointer (Current).Next_Address; 100 end if; 101 102 Storage_Address := Current; 103 return; -- mission complete 104 105 else -- check the next address of the link 106 107 Previous := Current; 108 Current := 109 Address_Access_Conversion.To_Pointer (Current).Next_Address; 110 end if; 111 end loop; 112 113 -- nothing found from storage reuse, grap storage elements from pool 114 if Pool.Size - Pool.Addr_Index > Desired_Size then 115 Storage_Address := Pool.Data (Pool.Addr_Index)'Address; 116 Pool.Addr_Index := Pool.Addr_Index + Desired_Size; 117 else 118 Exceptions.Raise_Exception (Storage_Pool_Error'Identity, 119 Message => Pool.User.all & "'s General Storage Pool is exhausted"); 120 end if; 121 122 end Allocate; 123 124 procedure Deallocate ( 125 Pool : in out General_Pool; 126 Storage_Address : in System.Address; 127 Size_In_Storage_Elements : in System.Storage_Elements.Storage_Count; 128 Alignment : in System.Storage_Elements.Storage_Count) is 129 130 New_Object : Address_Access_Conversion.Object_Pointer; 131 Desired_Size : System.Storage_Elements.Storage_Count := 132 Size_In_Storage_Elements; 133 134 begin -- Deallocate 135 136 New_Object := Address_Access_Conversion.To_Pointer (Storage_Address); 137 138 New_Object.all := (Next_Address => Pool.Addr_Head, 139 Size_Elements => Desired_Size); 140 141 Pool.Addr_Head := Storage_Address; 142 143 end Deallocate; 144 145 146 function Storage_Size (Pool : General_Pool) 147 return System.Storage_Elements.Storage_Count is 148 begin 149 return Pool.Size; 150 end Storage_Size; 151 152 153 function Client_Id (Pool : General_Pool) return String is 154 begin 155 return Pool.User.all; 156 end Client_Id; 157 158 function Storage_Available (Pool : General_Pool) 159 return System.Storage_Elements.Storage_Count is 160 begin 161 return Pool.Size - Pool.Addr_Index + 1; 162 end Storage_Available; 163 164 function Largest_Block (Pool : General_Pool) 165 return System.Storage_Elements.Storage_Count is 166 Free_Block : System.Storage_Elements.Storage_Count := 0; 167 Addr_Index : System.Address := Pool.Addr_Head; 168 The_Object : Address_Access_Conversion.Object_Pointer; 169 begin 170 while Addr_Index /= System.Null_Address loop 171 The_Object := Address_Access_Conversion.To_Pointer (Addr_Index); 172 173 if The_Object.Size_Elements > Free_Block then 174 Free_Block := The_Object.Size_Elements; 175 else 176 Addr_Index := 177 Address_Access_Conversion.To_Pointer (Addr_Index).Next_Address; 178 end if; 179 end loop; 180 181 if Free_Block >= Pool.Size - Pool.Addr_Index + 1 then 182 return Free_Block; 183 else 184 return Pool.Size - Pool.Addr_Index + 1; 185 end if; 186 end Largest_Block; 187 188 procedure Initialize (Pool : in out General_Pool) is 189 begin 190 191 if Pool.Size < Link_Storage then 192 -- fatal error - No go 193 Exceptions.Raise_Exception (Storage_Pool_Error'Identity, 194 Pool.User.all & "'s pool size specification is terribly wrong." & 195 " The requirements are: Size must be at least" & 196 System.Storage_Elements.Storage_Count'Image (Link_Storage) & 197 " elements long"); 198 end if; 199 200 if Pool.User.all = "" then 201 -- serious usage error 202 Exceptions.Raise_Exception (Unidentified_User'Identity, 203 "Pool User, you did not have a meaningful name"); 204 end if; 205 206-- Put_Line (Pool.User.all & " user has the pool size of" & 207-- System.Storage_Elements.Storage_Count'Image (Pool.Size)); 208 end Initialize; 209 210 procedure Finalize (Pool : in out General_Pool) is 211 Free_Count : System.Storage_Elements.Storage_Count := 0; 212 Addr_Index : System.Address := Pool.Addr_Head; 213 The_Object : Address_Access_Conversion.Object_Pointer; 214 begin 215 while Addr_Index /= System.Null_Address loop 216 The_Object := Address_Access_Conversion.To_Pointer (Addr_Index); 217 Free_Count := Free_Count + The_Object.Size_Elements; 218 Addr_Index := 219 Address_Access_Conversion.To_Pointer (Addr_Index).Next_Address; 220 end loop; 221 222 if Free_Count /= Pool.Addr_Index - 1 then 223 Put_Line (Standard_Output, "Memory Leakage Detected!!! " & 224 Pool.User.all & "'s codes had memory leakage of" & 225 System.Storage_Elements.Storage_Count'Image ( 226 Pool.Addr_Index - 1 - Free_Count) & " storage elements."); 227 end if; 228 229-- Put_Line (Pool.User.all & "'s " & "Free_Count = " & 230-- System.Storage_Elements.Storage_Count'Image (Free_Count)); 231-- Put_Line (Pool.User.all & "'s " & "Addr_Index = " & 232-- System.Storage_Elements.Storage_Count'Image (Pool.Addr_Index)); 233 234 end Finalize; 235 236 237 ---------------------------------------------------------------------------- 238 -- Detailed memory blocks size are handled by this pool -- 239 ---------------------------------------------------------------------------- 240 procedure Allocate ( 241 Pool : in out Detailed_Pool; 242 Storage_Address : out System.Address; 243 Size_In_Storage_Elements : in System.Storage_Elements.Storage_Count; 244 Alignment : in System.Storage_Elements.Storage_Count) is 245 begin 246 247 if Pool.Head_Keeper /= System.Null_Address then 248 Storage_Address := Pool.Head_Keeper; 249 Pool.Head_Keeper := 250 Address_Access_Conv.To_Pointer (Pool.Head_Keeper).Next_Address; 251 else 252 Exceptions.Raise_Exception ( 253 E => Storage_Pool_Error'Identity, 254 Message => Pool.User.all & "'s Fixed Storage Pool is exhausted"); 255 end if; 256 257 end Allocate; 258 259 procedure Deallocate ( 260 Pool : in out Detailed_Pool; 261 Storage_Address : in System.Address; 262 Size_In_Storage_Elements : in System.Storage_Elements.Storage_Count; 263 Alignment : in System.Storage_Elements.Storage_Count) is 264 begin 265 Address_Access_Conv.To_Pointer (Storage_Address).Next_Address := 266 Pool.Head_Keeper; 267 Pool.Head_Keeper := Storage_Address; 268 end Deallocate; 269 270 function Storage_Size (Pool : in Detailed_Pool) 271 return System.Storage_Elements.Storage_Count is 272 begin 273 return Pool.Size; 274 end Storage_Size; 275 276 function User_Id (Pool : Detailed_Pool) return String is 277 begin 278 return Pool.User.all; 279 end User_Id; 280 281 282 function Memory_Left (Pool : Detailed_Pool) 283 return System.Storage_Elements.Storage_Count is 284 Memory_Remain : constant Natural := Block_Remain (Pool); 285 begin 286 return System.Storage_Elements.Storage_Count (Memory_Remain); 287 end Memory_Left; 288 289 function Status (Pool : Detailed_Pool) return String is 290 begin 291 return (Pool.User.all & " has" & 292 Natural'Image (Block_Remain (Pool)) & " blocks free out of" & 293 Natural'Image (Pool.Block_Count) & "Block or" & 294 Natural'Image (Block_Remain (Pool) * Natural (Pool.Max)) & 295 " out of " & Natural'Image (Pool.Block_Count * Natural (Pool.Max))); 296 end Status; 297 298 299 function Block_Remain (Pool : Detailed_Pool) return Natural is 300 Count : Natural := 0; 301 Temp_Addr : System.Address := Pool.Head_Keeper; 302 begin 303 while Temp_Addr /= System.Null_Address loop 304 Count := Count + 1; 305 Temp_Addr := Address_Access_Conv.To_Pointer (Temp_Addr).Next_Address; 306 end loop; 307 return Count; 308 end Block_Remain; 309 310 procedure Initialize (Pool : in out Detailed_Pool) is 311 Temp_Addr : System.Address := System.Null_Address; 312 Addr_Index : System.Storage_Elements.Storage_Count := 1; 313 314 begin -- Initialize 315 316 if Pool.Max < Holder_Storage or else Pool.Size < Pool.Max then 317 -- fatal error - No go 318 Exceptions.Raise_Exception (Storage_Pool_Error'Identity, 319 Pool.User.all & "'s pool size specification is terribly wrong." & 320 " The requirements are: Size must be at least" & 321 System.Storage_Elements.Storage_Count'Image (Holder_Storage) & 322 " elements and Max must be at least" & 323 System.Storage_Elements.Storage_Count'Image (Pool.Size) & 324 " elements long"); 325 end if; 326 327 if Pool.User.all = "" then 328 -- serious usage error 329 Exceptions.Raise_Exception (Unidentified_User'Identity, 330 "Pool user, you did not have a meaningful name"); 331 end if; 332 333 while Pool.Size >= Addr_Index + Pool.Max - 1 loop 334 Temp_Addr := Pool.Data (Addr_Index)'Address; 335 Addr_Index := Addr_Index + Pool.Max; 336 Address_Access_Conv.To_Pointer (Temp_Addr).Next_Address := 337 Pool.Head_Keeper; 338 Pool.Head_Keeper := Temp_Addr; 339 Pool.Block_Count := Pool.Block_Count + 1; 340 end loop; 341 342-- Put_Line (Pool.User.all & " user has" & 343-- Integer'Image (Pool.Block_Count) & " blocks with block Size of" & 344-- System.Storage_Elements.Storage_Count'Image (Pool.Max) & 345-- " for the total size of" & 346-- System.Storage_Elements.Storage_Count'Image (Pool.Size)); 347 end Initialize; 348 349 procedure Finalize (Pool : in out Detailed_Pool) is 350 begin 351 if Block_Remain (Pool) /= Pool.Block_Count then 352 Put_Line (Standard_Output, "Memory Leakage Detected!!! " & 353 Pool.User.all & "'s codes had memory leakage of" & 354 Natural'Image ((Pool.Block_Count - 355 Block_Remain (Pool)) * Integer (Pool.Max)) & 356 " storage elements."); 357 end if; 358 end Finalize; 359 360end Storage_Pool_Handler; 361