I wanted to learn arenas, so I implemented my own. Then I noticed the existing arena crates were not to my liking. So I created this project.
Experimental: do not use unless you are a 🤡.
- Person: thread
- Notebook: arena
- Chapter: set of commonly aligned pages
- Page: fixed sized buffer of raw bytes
- Utensil: implementation of allocation
Notebooks start out blank. A person can write into a notebook. Depending on if they use pencil or pen, they may or may not be able to erase their notes. A person can pass a notebook to another person. Any person can write in the notebook, but only one at a time. Any number of people can read from a notebook at the same time.
This analogy is not perfect, but it's way better than what 'arena' has to offer! 😁
- Thread safe
- Safe interface
- Ergonomic
- Fast
- Lean
- Configurable
- Building block for data structures
- No external dependencies
- Documented
- Unsafe implementation details
- Lookup is out of scope (this is not an ECS library)
In rough priority order:
- CI
- Stable Tests
- Nightly Tests
- Channel aware
- CD
- Publish experimental versions
- Publish beta versions
- Publish stable versions
- No dependencies
- Well documented
- Thread-local notebooks
Personal*Notebook: Send
- Thread-safe notebooks
Public*Notebook: Send + Sync
- Implemented
- Thread-safety ensured
- Zero panics
- Graceful handling of memory errors
- Bump allocation
Pen: Utensil
- Deallocation
Pencil: Utensil
- Compiles on stable rust
- Publish first experimental version
- Publish first beta version
- Publish first stable version
- Heterogeneous notebook
*MultiNotebook: Notebook
- Homogeneous notebook
*MonoNotebook<T>: TypedNotebook<T>
- All allocations are aligned
- Integrate with the
allocator_api
feature*MultiNotebook: std::alloc::Allocator
- Requires nightly
- Configurable base size of page
SizeStrategy
- Configurable growth rate of page
GrowthStrategy
- Non-dropping exclusive references
alloc<T>(&self) -> &mut T
alloc_zero<T>(&self) -> &mut T
alloc_init<T>(&self, t: T) -> &mut T
alloc_t(&self) -> &mut T
alloc_zero_t(&self) -> &mut T
alloc_init_t(&self, t: T) -> &mut T
- Auto-dropping handles
new<T>(&self, t: T) -> Handle<T>
new_t(&self, t: T) -> Handle<T>
- Notebook merging
-
combine(notebooks: Vec<PersonalMultiNotebook>) -> PersonalMultiNotebook
-
combine<T>(notebooks: Vec<PersonalMonoNotebook<T>>) -> PersonalMonoNotebook<T>
- Zero page allocations
-
use bookcase_alloc::{
GrowthStrategy,
Handle,
Notebook,
Pen,
PersonalMultiNotebook,
SizeStrategy,
StdAllocator,
};
fn main() -> Result<(), ()> {
let notebook = PersonalMultiNotebook::<_, Pen>::new(
StdAllocator,
SizeStrategy::WordsPerPage(4096),
GrowthStrategy::Constant,
);
let my_str: Handle<String> = notebook.new(String::from("Hello, World!")).ok_or(())?;
println!("{}", my_str);
Ok(())
// my_str is dropped
// notebook is dropped
}
- Backwards compatibility is like falling asleep to the sound of ocean waves breaking on the beach.
- Assuming backwards compatibility is like torturing puppies.
Conclusion: SemVer is 🐍🛢
Unfortunately, cargo is tied to SemVer. Fortunately, SemVer is versioned. This means I can create my
own version of SemVer! 😈 Call it SemVer Maggie.1.0
. Here's how it works:
Assume all versions are breaking.
Strive to keep breaking changes to an absolute minimum.
Each dot separated number represents a release channel:
This channel is the only one suitable for production use.
This channel is for collecting well baked ideas that are preparing for stabilization.
This channel is the wild west where all bets are off and clown behavior is the norm.
- The version is in the experimental channel when
experimental > 0
, otherwise... - The version is in the beta channel when
beta > 0
, otherwise... - The version is in the stable channel when
stable > 0
, otherwise... - The version is invalid.
Therefore all stable releases are a bump to the "major" version suggesting to the downstream
developer they should consider The Ironclad Rule even if they are unfamiliar
with SemVer Maggie.1.0
.
=1.0.0
- stablev1
=1.2.0
- betav2
based off stablev1
=1.2.3
- experimentalv3
based off betav2
based off stablev1
=2.0.1
- experimentalv1
based off stablev2
=0.0.0
- invalid
Then get accustomed to compiler errors. A version within a release channel will only compile with
its respective feature enabled. The default feature is of course stable
. Enabling more than one
will also fail to compile. This is to prevent accidental use of beta and experimental channels in
production user code.
Maggie is my pet 🐷. She sucks at first, but you will eventually grow to love her.
bookcase_alloc_macros
is itself required to enforce the rules of SemVer Maggie.1.0
. As such, it
will only have a stable release channel.
I created a discord channel. As of this writing it has a population of me. Read the Goals, Concessions, and Progress sections for ideas on what to work on, and speak with me about how to make changes I am likely to accept. You can also just ask questions and give me feedback: feature requests, tell me my code is terrible or that I'm being too edgy. All feedback is welcome!