Skip to content

Commit

Permalink
Merge pull request #240 from karl-zylinski/tracking-allocator-section
Browse files Browse the repository at this point in the history
Move tracking allocator example to a subsection of allocators
  • Loading branch information
gingerBill authored Sep 28, 2024
2 parents fd9b64a + e146f36 commit 422cec4
Showing 1 changed file with 50 additions and 40 deletions.
90 changes: 50 additions & 40 deletions content/docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,8 @@ when ODIN_ARCH == .i386 {

The `when` statement is very useful for writing platform specific code. This is akin to the `#if` construct in C's preprocessor. However, in Odin, it is type checked.

See the [Conditional compilation section](#when-statements) for examples of built-in constants you can use with `when` statements.

### Branch statements
#### `break` statement
A for loop or a switch statement can be left prematurely with a `break` statement. It leaves the innermost construct, unless a label of a construct is given:
Expand Down Expand Up @@ -2932,12 +2934,15 @@ Please see the procedure attribute [`@(test)`](https://odin-lang.org/docs/overvi

### `when` statements

Sometimes you only want to include a small number of statements or declarations for compilation, if a certain compile-time expression evaluates
to `true`.
This expression can be any compile-time-known expression which results in a value of type `bool`.
Sometimes you only want compile a block of code if a certain compile-time expression evaluates to `true`. This can be done using the [when statements](#when-statement):

```
when ODIN_OS == .Linux {
// Do Linux stuff
}
```

The compiler provides a set of builtin constants which are available in all files in a compilation, and which can be used in a `when` condition.
Here is a comprehensive list of them:
The compiler provides a set of builtin constants which are available in all files in a compilation, and which can be used in a `when` condition. Here is a comprehensive list of them:

| Name | Description |
|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Expand All @@ -2962,41 +2967,7 @@ Here is a comprehensive list of them:
| `ODIN_VENDOR` | String which identifies the compiler being used. The official compiler sets this to `"odin"`. |
| `ODIN_VALGRIND_SUPPORT` | `true` if Valgrind integration is supported on the target. |

What follows is an example of when you might use this approach.
It sets the initial allocator to one that tracks memory leaks and incorrect frees when the user has asked for debug information to be emitted.
```odin
package main
import "core:fmt"
import "core:mem"
main :: proc() {
when ODIN_DEBUG {
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
defer {
if len(track.allocation_map) > 0 {
fmt.eprintf("=== %v allocations not freed: ===\n", len(track.allocation_map))
for _, entry in track.allocation_map {
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
}
}
if len(track.bad_free_array) > 0 {
fmt.eprintf("=== %v incorrect frees: ===\n", len(track.bad_free_array))
for entry in track.bad_free_array {
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
}
}
mem.tracking_allocator_destroy(&track)
}
}
do_stuff()
}
```
See the [tracking allocator](#tracking-allocator) for an example of something that uses the `ODIN_DEBUG` constant in a `when` statement.

### Command-line defines

Expand Down Expand Up @@ -3167,6 +3138,45 @@ To see more uses of allocators and allocation-related procedures, please see [`p

For more information regarding memory allocation strategies in general, please see [Ginger Bill's Memory Allocation Strategy](https://www.gingerbill.org/series/memory-allocation-strategies/) series.

#### Tracking allocator

In the core collection you'll find a tracking allocator that warns you if your progarm is leaking memory or if it does bad frees. Here's how to set it up:
```odin
package main
import "core:fmt"
import "core:mem"
main :: proc() {
when ODIN_DEBUG {
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
defer {
if len(track.allocation_map) > 0 {
fmt.eprintf("=== %v allocations not freed: ===\n", len(track.allocation_map))
for _, entry in track.allocation_map {
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
}
}
if len(track.bad_free_array) > 0 {
fmt.eprintf("=== %v incorrect frees: ===\n", len(track.bad_free_array))
for entry in track.bad_free_array {
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
}
}
mem.tracking_allocator_destroy(&track)
}
}
do_stuff()
}
```
This uses a [when statement](#when-statements) to only enable the tracking allocator when the `-debug` compilation flag is set. Since it sets the tracking alloator on the context in the beginning of `main`, the rest of the program will use this tracking allocator.

Note that `when` blocks do not have a real scope, the curly braces `{}` are just there to group code. Any changes to the `context` within a `when` block are valid after the `when` block ends.

#### Explicit `context` Definition
Procedures which do not use the `"odin"` calling convention must explicitly assign the `context` if something within its body requires it.

Expand Down

0 comments on commit 422cec4

Please sign in to comment.