Skip to content

Commit 43ff418

Browse files
committed
Bump minor version.
1 parent fb8cb63 commit 43ff418

File tree

5 files changed

+207
-11
lines changed

5 files changed

+207
-11
lines changed

context/getting-started.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# Getting Started
2+
3+
This guide explains how to use `async-safe` to detect thread safety violations in your Ruby code.
4+
5+
## Installation
6+
7+
Add the gem to your project:
8+
9+
~~~ bash
10+
$ bundle add async-safe
11+
~~~
12+
13+
## Usage
14+
15+
Enable monitoring in your test suite or development environment:
16+
17+
~~~ ruby
18+
require 'async/safe'
19+
20+
# Enable monitoring
21+
Async::Safe.enable!
22+
23+
# Your concurrent code here...
24+
~~~
25+
26+
When a violation is detected, an `Async::Safe::ViolationError` will be raised immediately with details about the object, method, and execution contexts involved.
27+
28+
## Single-Owner Model
29+
30+
By default, all objects are assumed to follow a **single-owner model** - they should only be accessed from one fiber/thread at a time:
31+
32+
~~~ ruby
33+
class MyBody
34+
def initialize(chunks)
35+
@chunks = chunks
36+
@index = 0
37+
end
38+
39+
def read
40+
chunk = @chunks[@index]
41+
@index += 1
42+
chunk
43+
end
44+
end
45+
46+
body = MyBody.new(["a", "b", "c"])
47+
body.read # OK - accessed from main fiber
48+
49+
Fiber.schedule do
50+
body.read # 💥 Raises Async::Safe::ViolationError!
51+
end
52+
~~~
53+
54+
## Marking Async-Safe Classes
55+
56+
Mark entire classes as safe for concurrent access:
57+
58+
~~~ ruby
59+
class MyQueue
60+
async_safe!
61+
62+
def initialize
63+
@queue = Thread::Queue.new
64+
end
65+
66+
def push(item)
67+
@queue.push(item)
68+
end
69+
70+
def pop
71+
@queue.pop
72+
end
73+
end
74+
75+
queue = MyQueue.new
76+
queue.push("item")
77+
78+
Fiber.schedule do
79+
queue.push("another") # ✅ OK - class is marked async-safe
80+
end
81+
~~~
82+
83+
Alternatively, you can manually set the constant:
84+
85+
~~~ ruby
86+
class MyQueue
87+
ASYNC_SAFE = true
88+
89+
# ... implementation
90+
end
91+
~~~
92+
93+
## Marking Async-Safe Methods
94+
95+
Mark specific methods as async-safe:
96+
97+
~~~ ruby
98+
class MixedSafety
99+
include Async::Safe
100+
101+
async_safe :safe_read
102+
103+
def initialize(data)
104+
@data = data
105+
@count = 0
106+
end
107+
108+
def safe_read
109+
@data # Async-safe method
110+
end
111+
112+
def increment
113+
@count += 1 # Not async-safe
114+
end
115+
end
116+
117+
obj = MixedSafety.new("data")
118+
119+
Fiber.schedule do
120+
obj.safe_read # ✅ OK - method is marked async-safe
121+
obj.increment # 💥 Raises Async::Safe::ViolationError!
122+
end
123+
~~~
124+
125+
## Transferring Ownership
126+
127+
Explicitly transfer ownership between fibers:
128+
129+
~~~ ruby
130+
request = create_request
131+
process_in_main_fiber(request)
132+
133+
Fiber.schedule do
134+
Async::Safe.transfer(request) # Transfer ownership
135+
process_in_worker_fiber(request) # ✅ OK now
136+
end
137+
~~~
138+
139+
## Integration with Tests
140+
141+
Add to your test helper (e.g., `config/sus.rb` or `spec/spec_helper.rb`):
142+
143+
~~~ ruby
144+
require 'async/safe'
145+
146+
Async::Safe.enable!
147+
~~~
148+
149+
Then run your tests normally:
150+
151+
~~~ bash
152+
$ bundle exec sus
153+
~~~
154+
155+
Any thread safety violations will cause your tests to fail immediately with a clear error message showing which object was accessed incorrectly and from which fibers.
156+
157+
## How It Works
158+
159+
1. **Default Assumption**: All objects follow a single-owner model (not thread-safe).
160+
2. **TracePoint Monitoring**: Tracks which fiber/thread first accesses each object.
161+
3. **Violation Detection**: Raises an exception when a different fiber/thread accesses the same object.
162+
4. **Explicit Safety**: Objects/methods can be marked as thread-safe to allow concurrent access.
163+
5. **Zero Overhead**: Monitoring is only active when explicitly enabled.
164+
165+
## Use Cases
166+
167+
- **Detecting concurrency bugs** in development and testing.
168+
- **Validating thread safety assumptions** in async/fiber-based code.
169+
- **Finding race conditions** before they cause production issues.
170+
- **Educational tool** for learning about thread safety in Ruby.
171+
172+
## Performance
173+
174+
- **Zero overhead when disabled** - TracePoint is not activated.
175+
- **Minimal overhead when enabled** - suitable for development/test environments.
176+
- **Not recommended for production** - use only in development/testing.

context/index.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Automatically generated context index for Utopia::Project guides.
2+
# Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
3+
---
4+
description: Runtime thread safety monitoring for concurrent Ruby code.
5+
metadata:
6+
documentation_uri: https://socketry.github.io/async-safe/
7+
source_code_uri: https://github.com/socketry/async-safe
8+
files:
9+
- path: getting-started.md
10+
title: Getting Started
11+
description: This guide explains how to use `async-safe` to detect thread safety
12+
violations in your Ruby code.

lib/async/safe/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
module Async
77
module Safe
8-
VERSION = "0.0.0"
8+
VERSION = "0.1.0"
99
end
1010
end
1111

readme.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@ Enable it in your tests to get immediate feedback when objects are incorrectly s
1616

1717
Please see the [project documentation](https://socketry.github.io/async-safe/) for more details.
1818

19-
- [Getting Started](https://socketry.github.io/async-safe/guides/getting-started/index) - This guide explains how to use `async-safe` to detect thread safety violations.
19+
- [Getting Started](https://socketry.github.io/async-safe/guides/getting-started/index) - This guide explains how to use `async-safe` to detect thread safety violations in your Ruby code.
2020

2121
## Releases
2222

23-
There are no documented releases.
23+
Please see the [project releases](https://socketry.github.io/async-safe/releases/index) for all releases.
24+
25+
### v0.1.0
26+
27+
- Implement TracePoint-based ownership tracking.
28+
- Add `Async::Safe::Concurrent` module for marking thread-safe classes.
29+
- Add `thread_safe` class method for marking thread-safe methods.
30+
- Add `Async::Safe.transfer` for explicit ownership transfer
31+
- Add violation detection and reporting
32+
- Zero overhead when monitoring is disabled
2433

2534
## See Also
2635

releases.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
# Releases
22

3-
## Unreleased
4-
5-
- Implement TracePoint-based ownership tracking.
6-
- Add `Async::Safe::Concurrent` module for marking thread-safe classes.
7-
- Add `thread_safe` class method for marking thread-safe methods.
8-
- Add `Async::Safe.transfer` for explicit ownership transfer
9-
- Add violation detection and reporting
10-
- Zero overhead when monitoring is disabled
3+
## v0.1.0
114

5+
- Implement TracePoint-based ownership tracking.
6+
- Add `Async::Safe::Concurrent` module for marking thread-safe classes.
7+
- Add `thread_safe` class method for marking thread-safe methods.
8+
- Add `Async::Safe.transfer` for explicit ownership transfer
9+
- Add violation detection and reporting
10+
- Zero overhead when monitoring is disabled

0 commit comments

Comments
 (0)