Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 84 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Containers-Buffer
A Circular Buffer implementation providing efficient temporary storage with fixed capacity and automatic wraparound functionality.
A Circular Buffer implementation providing efficient temporary storage with fixed capacity and automatic wraparound functionality. Available in both FIFO (First In, First Out) and LIFO (Last In, First Out) variants.

![Pharo Version](https://img.shields.io/badge/Pharo-10+-blue)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
Expand All @@ -8,6 +8,30 @@ A Circular Buffer implementation providing efficient temporary storage with fixe

A Buffer (also known as a circular buffer or ring buffer) is a data structure that uses a fixed-size array as if it were connected end-to-end. It provides efficient insertion and removal operations with constant time complexity O(1). When the buffer reaches its maximum capacity, new elements overwrite the oldest ones, making it perfect for streaming data and producer-consumer scenarios.

### We provide two types of buffers:
- FIFO Buffer - First In, First Out (Queue behavior)
- LIFO Buffer - Last In, First Out (Stack behavior)

## Loading
The following script installs Containers-Buffer in Pharo.

```smalltalk
Metacello new
baseline: 'ContainersBuffer';
repository: 'github://pharo-containers/Containers-Buffer/src';
load.
```

## If you want to depend on it

Add the following code to your Metacello baseline or configuration

```smalltalk
spec
baseline: 'ContainersBuffer'
with: [ spec repository: 'github://pharo-containers/Containers-Buffer/src' ].
```

## Why use Containers-Buffer?
Buffers solve a critical problem in modern applications: **handling continuous data streams safely**. Perfect for keeping "recent N items" automatically without memory bloat or performance degradation.

Expand All @@ -16,35 +40,81 @@ Buffers solve a critical problem in modern applications: **handling continuous d
- **O(1) Performance**: Lightning-fast operations regardless of data volume
- **Zero Memory Leaks**: Automatic cleanup of old data
- **Streaming Optimized**: Designed for continuous data flow
- **Flexible Ordering**: Choose FIFO or LIFO based on your needs


## FIFO Buffer Use Cases

### Chat Applications
This example demonstrates how to use a FIFO buffer to maintain a chat history, automatically removing the oldest messages when new ones are added.

```smalltalk
"Chat room - keep last 50 messages automatically"
chat := CTBuffer withCapacity: 50.
chat := CTFIFOBuffer withCapacity: 50.

chat put: 'User1: Hello everyone!'.
chat put: 'User2: How are you doing?'.
chat push: 'User1: Hello everyone!'.
chat push: 'User2: How are you doing?'.

"... more messages flow in ..."
chat put: 'User3: Good morning!'. "Oldest message automatically removed"
chat push: 'User3: Good morning!'. "Oldest message automatically removed"

"Always has recent 50 messages, zero manual cleanup"
```

### File Processing in Chunks
This example shows how to process large files in manageable chunks without loading the entire file into memory, using a FIFO buffer to handle data efficiently.

```smalltalk
"Process massive files without loading everything into memory"
fileBuffer := CTBuffer withCapacity: 1024. "1KB processing chunks"
fileBuffer := CTFIFOBuffer withCapacity: 1024. "1KB processing chunks"
stream := 'huge-dataset.csv' asFileReference readStream.
[ stream atEnd ] whileFalse: [
chunk := stream next: 1024.
fileBuffer put: chunk.
self processDataChunk: fileBuffer get "Process and auto-remove"
fileBuffer push: chunk.
self processDataChunk: fileBuffer pop "Process and auto-remove"
].

"Memory usage stays constant - handles files of any size!"
```

## LIFO Buffer Use Cases

### Undo/Redo Functionality
This example shows how to implement undo/redo functionality in an editor using a LIFO buffer, allowing users to revert their last actions easily.

```smalltalk
"Implementing undo/redo in an editor"
undoBuffer := CTLIFOBuffer withCapacity: 20. "Keep last 20 actions"
undoBuffer push: 'Hello World'.
undoBuffer push: 'Add bold formatting'.
undoBuffer push: 'Add italic formatting'.

"User presses undo"
lastAction := undoBuffer pop. "Returns 'Add italic formatting' and removes it"

"User can redo by pushing it back"
undoBuffer push: lastAction. "Puts 'Add italic formatting' back on top"
"Now 'Add italic formatting' is on top, ready to be undone next"
```

### Browser History
This example demonstrates how to implement a simple browser history using a LIFO buffer, allowing users to navigate back through their most recent pages.

```smalltalk
"Browser back button - show most recent pages first"
browserHistory := CTLIFOBuffer withCapacity: 20.

browserHistory push: 'https://pharo.org'.
browserHistory push: 'https://github.com/pharo-containers'.
browserHistory push: 'https://stackoverflow.com/questions/...'.

"Back button gets most recent page"
previousPage := browserHistory pop. "Gets 'https://stackoverflow.com/questions/...' (most recent)"
previousPage := browserHistory pop. "Gets 'https://github.com/pharo-containers' (second most recent)"
previousPage := browserHistory pop. "Gets 'https://pharo.org' (third most recent)"
```


### Performance Degradation
```smalltalk
"OrderedCollection - Gets slower and slower"
Expand All @@ -58,43 +128,20 @@ log := OrderedCollection new.
"Performance degrades from 1ms to 100ms+ per operation"

"Buffer - Lightning fast forever"
log := CTBuffer withCapacity: 1000.
log := CTFIFOBuffer withCapacity: 1000.
1 to: 100000 do: [ :i |
log put: 'entry ', i asString. "O(1) operation - always instant!"
log push: 'entry ', i asString. "O(1) operation - always instant!"
].

"Consistent 0.01ms performance whether it's operation #10 or #10,000,000"
```

### Performance Comparison

| Operation | OrderedCollection | Array | CTBuffer |
|-----------|------------------|--------|----------|
| Add item | O(1) | O(n)* | O(1) |
### Comparison
| Operation | OrderedCollection | Array | CTFIFOBuffer |
|-----------|------------------|--------|-------------|
| Add item | O(1) | O(1) | O(1) |
| Remove old | O(n) | O(n) | O(1) |
| Memory usage | Unlimited growth | Fixed/reallocated | Fixed |
| Cache efficiency | Poor (fragmented) | Good | Excellent |


## Loading
The following script installs Containers-Buffer in Pharo.

```smalltalk
Metacello new
baseline: 'ContainersBuffer';
repository: 'github://pharo-containers/Containers-Buffer/src';
load.
```

## If you want to depend on it

Add the following code to your Metacello baseline or configuration

```smalltalk
spec
baseline: 'ContainersBuffer'
with: [ spec repository: 'github://pharo-containers/Containers-Buffer/src' ].
```

## Contributing

Expand Down
Loading
Loading