en:docs:win16:modules:local_heap

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:docs:win16:modules:local_heap [2026/02/24 07:40] – [String Atoms] prokusheven:docs:win16:modules:local_heap [2026/02/24 08:12] (current) – [References] prokushev
Line 1: Line 1:
-===== Win16 Local Heap Functions =====+===== Local Heap and Atom Table =====
  
 ===== Overview ===== ===== Overview =====
Line 149: Line 149:
 ===== Heap Operations ===== ===== Heap Operations =====
  
-* **Allocation (LocalAlloc)** walks the free list, splitting blocks if necessary, and sets up the appropriate arena. For MOVEABLE blocks, it also allocates a handle table entry. +  * **Allocation (LocalAlloc)** walks the free list, splitting blocks if necessary, and sets up the appropriate arena. For MOVEABLE blocks, it also allocates a handle table entry. 
-* **Compaction (LocalCompact)** coalesces adjacent free blocks and may move or discard unlocked MOVEABLE blocks. When a block is moved, its lhe_address is updated. +  * **Compaction (LocalCompact)** coalesces adjacent free blocks and may move or discard unlocked MOVEABLE blocks. When a block is moved, its lhe_address is updated. 
-* **Locking (LocalLock/LocalUnlock)** manipulates the lhe_count field of the handle entry for MOVEABLE blocks; for FIXED blocks, no count is maintained. +  * **Locking (LocalLock/LocalUnlock)** manipulates the lhe_count field of the handle entry for MOVEABLE blocks; for FIXED blocks, no count is maintained. 
-* **Discarding (LocalDiscard)** frees the memory of a MOVEABLE block but keeps the handle entry alive with the LHE_DISCARDED flag set.+  * **Discarding (LocalDiscard)** frees the memory of a MOVEABLE block but keeps the handle entry alive with the LHE_DISCARDED flag set.
  
 ===== Atom Tables ===== ===== Atom Tables =====
Line 199: Line 199:
 Integer atoms are created by passing a string of the form `"#dddd"` (or by using `MAKEINTATOM` with a value ≤ 0xBFFF). They are **not stored in the atom table** and have no associated `ATOMENTRY` structure. Integer atoms are created by passing a string of the form `"#dddd"` (or by using `MAKEINTATOM` with a value ≤ 0xBFFF). They are **not stored in the atom table** and have no associated `ATOMENTRY` structure.
  
-* **Range**: `0x0001` to `0xBFFF` . +  * **Range**: `0x0001` to `0xBFFF` . 
-* **Storage**: None; the value is used directly as the atom. +  * **Storage**: None; the value is used directly as the atom. 
-* **Reference count**: Not applicable. +  * **Reference count**: Not applicable. 
-* **String representation**: Generated on the fly as `"#dddd"` when `GetAtomName` is called. +  * **String representation**: Generated on the fly as `"#dddd"` when `GetAtomName` is called. 
-* **Creation**: `AddAtom("#1234")` or `AddAtom(MAKEINTATOM(0x04D2))`.+  * **Creation**: `AddAtom("#1234")` or `AddAtom(MAKEINTATOM(0x04D2))`.
  
 **How it works:** When a string of the form '#dddd' is passed, the function parses the decimal number and, if it is less than 0xC000, returns it directly without accessing the atom table. Similarly, `FindAtom` for such a string or for a `MAKEINTATOM` value simply returns the number without any lookup. Integer atoms are always considered "found" because any value in the range is valid. **How it works:** When a string of the form '#dddd' is passed, the function parses the decimal number and, if it is less than 0xC000, returns it directly without accessing the atom table. Similarly, `FindAtom` for such a string or for a `MAKEINTATOM` value simply returns the number without any lookup. Integer atoms are always considered "found" because any value in the range is valid.
Line 217: Line 217:
 This macro casts a 16‑bit integer value to a pointer type. When this "pointer" is passed to atom functions, it is interpreted as an integer atom (if the value is ≤ `0xBFFF`) or as a string atom (if ≥ `0xC000`). This macro casts a 16‑bit integer value to a pointer type. When this "pointer" is passed to atom functions, it is interpreted as an integer atom (if the value is ≤ `0xBFFF`) or as a string atom (if ≥ `0xC000`).
  
-* For values ≤ `0xBFFF`, the function treats it as an integer atom and returns the value directly. +  * For values ≤ `0xBFFF`, the function treats it as an integer atom and returns the value directly. 
-* For values ≥ `0xC000`, the function assumes it is an encoded pointer to an `ATOMENTRY` and will dereference it (after shifting left by 2 bits) to access the atom entry.+  * For values ≥ `0xC000`, the function assumes it is an encoded pointer to an `ATOMENTRY` and will dereference it (after shifting left by 2 bits) to access the atom entry.
  
 **Important:** `MAKEINTATOM` does not create a string or allocate any memory; it is simply a type-punning convenience to pass integer atoms to functions that formally expect a string pointer. **Important:** `MAKEINTATOM` does not create a string or allocate any memory; it is simply a type-punning convenience to pass integer atoms to functions that formally expect a string pointer.
Line 224: Line 224:
 ==== Local vs. Global Atom Tables ==== ==== Local vs. Global Atom Tables ====
  
-* **Local atom tables**: Bound to a specific data segment (e.g., an application's DGROUP). Created by calling `InitAtomTable()`. Used for a module's internal needs. Access is only possible when the DS register points to that segment. +  * **Local atom tables**: Bound to a specific data segment (e.g., an application's DGROUP). Created by calling `InitAtomTable()`. Used for a module's internal needs. Access is only possible when the DS register points to that segment. 
-* **Global atom table**: A system-wide table accessible to all applications via `GlobalAddAtom`, `GlobalFindAtom`, and `GlobalDeleteAtom` . Physically, it resides not in an application's data segment but in a special USER data segment (part of the so-called "global atom and text heap") . Its structure is identical to a local atom table. The `Global...` functions internally switch DS to the USER segment and call the ordinary `AddAtom`/`FindAtom`.+  * **Global atom table**: A system-wide table accessible to all applications via `GlobalAddAtom`, `GlobalFindAtom`, and `GlobalDeleteAtom` . Physically, it resides not in an application's data segment but in a special USER data segment (part of the so-called "global atom and text heap") . Its structure is identical to a local atom table. The `Global...` functions internally switch DS to the USER segment and call the ordinary `AddAtom`/`FindAtom`.
  
 ==== Creating Custom Atom Tables (outside DGROUP) ==== ==== Creating Custom Atom Tables (outside DGROUP) ====
Line 231: Line 231:
 Since all atom operations work with the current segment pointed to by DS, you can create and use an atom table in any arbitrary data segment by following three steps: Since all atom operations work with the current segment pointed to by DS, you can create and use an atom table in any arbitrary data segment by following three steps:
  
-1. **Create a local heap** in the target segment using `LocalInit(Selector, Start, End)`. +  -  **Create a local heap** in the target segment using `LocalInit(Selector, Start, End)`. 
-2. **Switch the DS register** to that segment. +  **Switch the DS register** to that segment. 
-3. Call `InitAtomTable(size)` to initialize the atom table in the newly created heap.+  Call `InitAtomTable(size)` to initialize the atom table in the newly created heap.
  
 After that, any subsequent call to `AddAtom`, `FindAtom`, etc., will operate on the custom table if DS is temporarily set to the correct segment. After that, any subsequent call to `AddAtom`, `FindAtom`, etc., will operate on the custom table if DS is temporarily set to the correct segment.
Line 261: Line 261:
 </code> </code>
  
-* `wSegment` – Selector of the segment where the heap will be created. +  * `wSegment` – Selector of the segment where the heap will be created. 
-* `pStart` – Offset of the first byte of the heap area (must be paragraph‑aligned, i.e., a multiple of 16). +  * `pStart` – Offset of the first byte of the heap area (must be paragraph‑aligned, i.e., a multiple of 16). 
-* `pEnd` – Offset of the last byte of the heap area (inclusive). The heap will manage memory from `pStart` to `pEnd`.+  * `pEnd` – Offset of the last byte of the heap area (inclusive). The heap will manage memory from `pStart` to `pEnd`.
  
 If successful, `LocalInit()` returns a non‑zero value. It sets up the `HeapInfo` and `LocalInfo` structures at the beginning of the heap area (starting at `pStart`) and updates the segment’s instance data at offset **06h** (`pLocalHeap`) to point to that `HeapInfo` structure. However, if the segment is not a default data segment (i.e., not DGROUP), the instance data at offset 0 must also contain a zero word to indicate that the NULL segment structure is present; otherwise, the heap may not be recognized by some routines. If successful, `LocalInit()` returns a non‑zero value. It sets up the `HeapInfo` and `LocalInfo` structures at the beginning of the heap area (starting at `pStart`) and updates the segment’s instance data at offset **06h** (`pLocalHeap`) to point to that `HeapInfo` structure. However, if the segment is not a default data segment (i.e., not DGROUP), the instance data at offset 0 must also contain a zero word to indicate that the NULL segment structure is present; otherwise, the heap may not be recognized by some routines.
Line 306: Line 306:
  
 **Important Considerations:** **Important Considerations:**
-* The heap structures themselves occupy space at the beginning of the heap area. The first block (sentinel) resides at `pStart + size of (LocalInfo)`. + 
-* The segment’s instance data (at offset 0) must be properly set up, especially the zero word at offset 0, to avoid confusion with other structures. +  * The heap structures themselves occupy space at the beginning of the heap area. The first block (sentinel) resides at `pStart + size of (LocalInfo)`. 
-* Custom local heaps are not automatically enlarged if they run out of space; they are limited to the range specified in `LocalInit`. +  * The segment’s instance data (at offset 0) must be properly set up, especially the zero word at offset 0, to avoid confusion with other structures. 
-* The `HEAPSIZE` setting in the module’s .DEF file only affects the default DGROUP heap.+  * Custom local heaps are not automatically enlarged if they run out of space; they are limited to the range specified in `LocalInit`. 
 +  * The `HEAPSIZE` setting in the module’s .DEF file only affects the default DGROUP heap.
  
 ==== Creating Atom Tables Outside DGROUP ==== ==== Creating Atom Tables Outside DGROUP ====
Line 317: Line 318:
 ==== Summary of Custom Heap and Atom Table Creation ==== ==== Summary of Custom Heap and Atom Table Creation ====
  
-* Use `LocalInit` on a segment to establish a local heap anywhere in memory. +  * Use `LocalInit` on a segment to establish a local heap anywhere in memory. 
-* The segment must have a valid NULL segment structure (zero word at offset 0) for the heap to be recognized. +  * The segment must have a valid NULL segment structure (zero word at offset 0) for the heap to be recognized. 
-* After `LocalInit`, you can use `LocalAlloc`, `LocalLock`, etc., with near pointers within that segment. +  * After `LocalInit`, you can use `LocalAlloc`, `LocalLock`, etc., with near pointers within that segment. 
-* To create an atom table in a custom heap, switch DS to that segment and call `InitAtomTable`. +  * To create an atom table in a custom heap, switch DS to that segment and call `InitAtomTable`. 
-* All subsequent atom operations must be performed with DS set appropriately (or via wrapper functions). +  * All subsequent atom operations must be performed with DS set appropriately (or via wrapper functions). 
-* Custom heaps and atom tables are useful for isolating memory pools, implementing resource managers, or working with large data structures without polluting the default DGROUP.+  * Custom heaps and atom tables are useful for isolating memory pools, implementing resource managers, or working with large data structures without polluting the default DGROUP.
  
 ===== References ===== ===== References =====
  
-1. Schulman, A., Maxey, D., Pietrek, M. //Undocumented Windows//. Addison-Wesley, 1992. +  - Schulman, A., Maxey, D., Pietrek, M. //Undocumented Windows//. Addison-Wesley, 1992. 
-2. Pietrek, M. //Windows Internals//. Addison-Wesley, 1993. +  Pietrek, M. //Windows Internals//. Addison-Wesley, 1993. 
-3. Chen, R. //The Old New Thing// (blog). Microsoft Developer Blogs. +  Chen, R. //The Old New Thing// (blog). Microsoft Developer Blogs. 
-4. Microsoft OS/2 Version 1.1 Programmer's Reference, Volume 1.+  Microsoft OS/2 Version 1.1 Programmer's Reference, Volume 1.