shared-buffer-rs 0.2.0

A library which combines Arc and RefCell for Send and Sync
Documentation
# shared-buffer-rs 

![600 logo](https://gitlab.com/4neko/shared-buffer-rs/-/raw/master/logo_500.png?ref_type=heads&inline=true)

## 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.