We were previously using array_slice to get the storage
that we were copying the new elements into, using the current
length as the offset: `copy(data[len:], ..elems)`
However, array_slice returns a slice over `data[0:len]` -- we
were using it as if it was `data[0:cap]`.
Add array_cap_slice that does this instead. :^)
Provides a way to go from a enum value name string to an actual enum value.
```
E :: enum { A, B }
// ...
s := "B";
v, ok := enum_from_name(E, s);
assert(ok && v == E.B);
```
When locking, we were not loading m.serving atomically and so the optimizer
could have hoisted the check out of the loop, thus resulting in an infinite loop.
Currently, `make(map[K]V, 0)` asserts, because trying `reserve` zero items does not set the allocator; it early-outs.
`__dynamic_map_reserve` assumed that `__dynamic_array_reserve` would always set the allocator - even if given a desired capacity of `0`.
Rather than making `__slice_resize` just _also_ set the default allocator if there isn't one, this makes `__dynamic_array_reserve` always set the allocator, even if it is about to early out.
This is because users are lead to understand that `append` will set the allocator if one is not already set - `reserve` should work the same way.
- Set the allocator, even if memory allocation fails.
Right now it doesn't, which means that if allocation fails, it'll use
the context allocator instead. This memory will be leaked if the user
doesn't understand that this happened.
- Only set len and cap of the array returned from make iif the memory allocation
succeeded.
This means that reserve will return false if you do this:
```
a := make([dynamic]int, failing_allocator);
if !reserve(&a, 5) do return; // or whatever indicates failure
```
Also do some cleanup and refactoring of the thread, sync and time APIs.
- remove 'semaphore_release' because 'post' and 'wait' is easier to understand
- change 'semaphore_wait' to '*_wait_for' to match Condition
- pthreads can be given a stack, but doing so requires the user to set up the guard
pages manually. BE WARNED. The alignment requirements of the stack are also
platform-dependant; it may need to be page size aligned on some systems.
Unclear which systems, however. See 'os.get_page_size', and 'mem.make_aligned'.
HOWEVER: I was unable to get custom stacks with guard pages working reliably,
so while you can do it, the API does not support it.
- add 'os.get_page_size', 'mem.make_aligned', and 'mem.new_aligned'.
- removed thread return values because windows and linux are not consistent; windows returns 'i32'
and pthreads return 'void*'; besides which, if you really wanted to communicate how the
thread exited, you probably wouldn't do it with the thread's exit code.
- fixed 'thread.is_done' on Windows; it didn't report true immediately after calling 'thread.join'.
- moved time related stuff out of 'core:os' to 'core:time'.
- add 'mem.align_backward'
- fixed default allocator alignment
The heap on Windows, and calloc on Linux, both have no facility to request alignment.
It's a bit of hack, but the heap_allocator now overallocates; `size + alignment` bytes,
and aligns things to at least 2.
It does both of these things to ensure that there is at least two bytes before the payload,
which it uses to store how much padding it needed to insert in order to fulfil the alignment
requested.
- make conditions more sane by matching the Windows behaviour.
The fact that they were signalled now lingers until a thread tries to wait,
causing them to just pass by uninterrupted, without sleeping or locking the
underlying mutex, as it would otherwise need to do.
This means that a thread no longer has to be waiting in order to be signalled, which
avoids timing bugs that causes deadlocks that are hard to debug and fix.
See the comment on the `sync.Condition.flag` field.
- add thread priority: `thread.create(worker_proc, .High)`
Changes the usage information to this:
```
D:\Software\odin\odin.exe is a tool for managing Odin source code
Usage:
D:\Software\odin\odin.exe command [arguments]
Commands:
build compile .odin file, or directory of .odin files, as an executable.
one must contain the program's entry point, all must be in the same package.
run same as 'build', but also then runs the newly compiled executable.
check parse and type check .odin file
query parse, type check, and output a .json file containing information about the program
docs generate documentation for a .odin file
version print version
```