# shared-buffer-rs

## A combination of Arc and RefCell for buffer exclusive/shared accessing and sharing between threads.
The purpose of this crate to manage and provide the buffer allocation and access to the
buffer in a RefCell manner but in a way the Arc does.
The crate provides a managing instance to the allocated buffer memeory which can be accessed
exclusivly (write-read) access in the current thread or shared access (read-only) in any thread.
The locking is provided by the atomics with the Accure-Release ordering.
This crate is not tested completly.
It may not work as intended on multithreading tokio instances, but should work in tokio single thread
mode or with threads.
## Version
V2.0
- Fixed errors accure_in_lace().
- Added no_std.
- License changed!
## License:
Sources are available under: MPL-2.0 OR EUPL-1.2
## Examples
The examples are availabe in the directory `examples`.
## Block diagram
```text
┌─────────────┐ ┌──────────────┐
│ │ │ │
│ RwBuffers ┼────► allocate() │
│ │ │ │
└─────────────┘ └──────┬───────┘
│
│
┌────▼───────┐ ┌───────────┐
│ │ │ │
│ RwBuffer ┼────► write() │
│ │ │ │
└──────┬─────┘ └─────┬─────┘
│ │
│ │
│ ┌─────▼─────┐ ┌───────────┐
│ │ │ │ writing │
│ │ WBuffer ◄──────┼ data() │
│ │ │ │ │
│ └─────┬─────┘ └───────────┘
│ │
│ │
│ │
│ ┌────▼────────┐
│ │ │
│ │ downgrade() │
│ │ │
│ └────┬────────┘
│ │
───────────────────┼────────────────┼─────────────────────────────
WBuffer dropped. │ │
┌───────▼───┐ ┌────▼────────┐
│ │ │ │
│ read() │ │ RBuffer │
│ │ │ │
└───────┬───┘ └─────────────┘
│
│
│
┌───────▼───┐
│ │
│ RBuffer │
│ │
└───────────┘
```
## Usage.
Firstly, the base instance should be created:
```Rust
// bounded
let mut bufs = RwBuffers::new(4096, 1, 3).unwrap();
// or unbounded
let mut bufs = RwBuffers::new_unbounded(4096, 1).unwrap();
```
Then a buffer can be obtained from it.
```Rust
let buf: RwBuffer = bufs.allocate().unwrap();
```
The allocate buf `RwBuffer` is stored on the list in `RwBuffers` and another instance
is returned. If it is not required to reuse the instance, the `allocate_in_place` function
allocates the instance without storing it into the `RwBuffers`.
To obtain an exclusive access, use:
```Rust
let buf_w = buf.write().unwrap();
```
The inner buffer can be accessed via dereferencing. The write instance can be downgraded to
shared lock. The `exclusive` instance can not be clonned, send or sync.
In order to obtain a `shared` access, the `exclusive` access should be either downgraded and
clonned (if needed) or dropped.
In order to obtain an `exclusive` access again, all `shared` accesses must be dropped.
The `shared` access can be consumed to return the inner buffer vector, however it should
satisfy the following conditions:
1. Only one shared access
2. No exclusive access
3. No base i.e `RwBuffer` left undropped.
The shared access can be obtained also via:
```Rust
let buf_r: RBuffer = buf.read();
```
The `RBuffer` or `RwBuffer` are Sync and Send. However, by design, only `RBuffer` should be shared.