async-safe 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e20fdea7f6f63f3a47aa8be85492fa2725e6b3ea2c0284de63dd6fe45af6f49c
4
- data.tar.gz: 6556e3ed8f46cfe8157983229d4584a6b01eb0e8f2b36f83fe3ec5f541211830
3
+ metadata.gz: 52f743f5c66ba254659d3f6afb52e8f6bf1189f395ca931e708890eea1fe4e00
4
+ data.tar.gz: 4a89412e5fd61a9c4c5bdac4d90a6897e70fbeccac5301b58e56a3cf622542a8
5
5
  SHA512:
6
- metadata.gz: 6a02637fc476e5e38a6b1952394ad99ca3fbe13b106b6d7ac0abbafc7f285167f3a0ef9302a28ac0e12f29a70edce7158ea2690b88d309e99a5d1f073da58580
7
- data.tar.gz: 24fbc11d3be799f80649e1a487edc6f1b4040fbb0e4688d590f2caafceb76b761c298569a3b2384939844753eec8b788ff0bf70d8f820b3fbe4c9d9403183542
6
+ metadata.gz: b7b6981fe90ffdbef57060678ba4988202333120848cc40d4528873b9a6ccd5b39a53549d35886d75a08343db12697855eb56c74af9d06c9434e2a153d6caef5
7
+ data.tar.gz: 8a0ec23a746938beeadd581af8e7aaa19dc0219826343a40ef9d93071e34b2956e67fcab1c33c3529940716195b7958e2f99a127c2e6c47ca72e333f0c783f61
checksums.yaml.gz.sig CHANGED
Binary file
@@ -25,7 +25,7 @@ Async::Safe.enable!
25
25
 
26
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
27
 
28
- ## Single-Owner Model
28
+ ### Single-Owner Model
29
29
 
30
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
31
 
@@ -51,7 +51,7 @@ Fiber.schedule do
51
51
  end
52
52
  ~~~
53
53
 
54
- ## Marking Async-Safe Classes
54
+ ### Marking Async-Safe Classes
55
55
 
56
56
  Mark entire classes as safe for concurrent access:
57
57
 
@@ -90,7 +90,7 @@ class MyQueue
90
90
  end
91
91
  ~~~
92
92
 
93
- ## Marking Async-Safe Methods
93
+ ### Marking Async-Safe Methods
94
94
 
95
95
  Mark specific methods as async-safe:
96
96
 
@@ -122,7 +122,7 @@ Fiber.schedule do
122
122
  end
123
123
  ~~~
124
124
 
125
- ## Transferring Ownership
125
+ ### Transferring Ownership
126
126
 
127
127
  Explicitly transfer ownership between fibers:
128
128
 
@@ -20,3 +20,30 @@ Fiber::ASYNC_SAFE = true
20
20
 
21
21
  # ObjectSpace::WeakMap is async-safe:
22
22
  ObjectSpace::WeakMap::ASYNC_SAFE = true
23
+
24
+ module Async
25
+ module Safe
26
+ module TransferableThreadQueue
27
+ def pop(...)
28
+ object = super(...)
29
+ Async::Safe.transfer(object)
30
+ object
31
+ end
32
+
33
+ def deq(...)
34
+ object = super(...)
35
+ Async::Safe.transfer(object)
36
+ object
37
+ end
38
+
39
+ def shift(...)
40
+ object = super(...)
41
+ Async::Safe.transfer(object)
42
+ object
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ Thread::Queue.prepend(Async::Safe::TransferableThreadQueue)
49
+ Thread::SizedQueue.prepend(Async::Safe::TransferableThreadQueue)
@@ -64,10 +64,13 @@ module Async
64
64
  ASYNC_SAFE = true
65
65
 
66
66
  # Initialize a new monitor instance.
67
- def initialize
67
+ #
68
+ # @parameter logger [Object | Nil] Optional logger to use for violations instead of raising exceptions.
69
+ def initialize(logger: nil)
68
70
  @owners = ObjectSpace::WeakMap.new
69
71
  @mutex = Thread::Mutex.new
70
72
  @trace_point = nil
73
+ @logger = logger
71
74
  end
72
75
 
73
76
  attr :owners
@@ -128,12 +131,11 @@ module Async
128
131
  if owner = @owners[object]
129
132
  # Violation if accessed from different fiber:
130
133
  if owner != current
131
- raise ViolationError.new(
132
- target: object,
133
- method: method,
134
- owner: owner,
135
- current: current,
136
- )
134
+ if @logger
135
+ @logger.warn(self, "Async::Safe violation detected!", klass: klass, method: method, owner: owner, current: current, backtrace: caller_locations(3..))
136
+ else
137
+ raise ViolationError.new(target: object, method: method, owner: owner, current: current)
138
+ end
137
139
  end
138
140
  else
139
141
  # First access - record owner:
@@ -5,7 +5,7 @@
5
5
 
6
6
  module Async
7
7
  module Safe
8
- VERSION = "0.1.0"
8
+ VERSION = "0.2.0"
9
9
  end
10
10
  end
11
11
 
data/lib/async/safe.rb CHANGED
@@ -61,8 +61,14 @@ module Async
61
61
  #
62
62
  # This activates a TracePoint that tracks object access across fibers and threads.
63
63
  # There is no performance overhead when monitoring is disabled.
64
- def enable!
65
- @monitor ||= Monitor.new
64
+ #
65
+ # @parameter logger [Object | Nil] Optional logger to use for violations instead of raising exceptions.
66
+ def enable!(logger: nil)
67
+ if @monitor
68
+ raise "Async::Safe is already enabled!"
69
+ end
70
+
71
+ @monitor = Monitor.new(logger: logger)
66
72
  @monitor.enable!
67
73
  end
68
74
 
data/readme.md CHANGED
@@ -22,6 +22,11 @@ Please see the [project documentation](https://socketry.github.io/async-safe/) f
22
22
 
23
23
  Please see the [project releases](https://socketry.github.io/async-safe/releases/index) for all releases.
24
24
 
25
+ ### v0.2.0
26
+
27
+ - `Thread::Queue` transfers ownership of objects popped from it.
28
+ - Add support for `logger:` option in `Async::Safe.enable!` which logs violations instead of raising errors.
29
+
25
30
  ### v0.1.0
26
31
 
27
32
  - Implement TracePoint-based ownership tracking.
data/releases.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Releases
2
2
 
3
+ ## v0.2.0
4
+
5
+ - `Thread::Queue` transfers ownership of objects popped from it.
6
+ - Add support for `logger:` option in `Async::Safe.enable!` which logs violations instead of raising errors.
7
+
3
8
  ## v0.1.0
4
9
 
5
10
  - Implement TracePoint-based ownership tracking.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-safe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
metadata.gz.sig CHANGED
Binary file