Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #666 from haridutt12/master
thread safe set implementation
- Loading branch information
Showing
7 changed files
with
75 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
require 'concurrent/utility/engine' | ||
require 'concurrent/thread_safe/util' | ||
require 'set' | ||
|
||
module Concurrent | ||
if Concurrent.on_cruby? | ||
|
||
# Because MRI never runs code in parallel, the existing | ||
# non-thread-safe structures should usually work fine. | ||
|
||
# @!macro [attach] concurrent_Set | ||
# | ||
# A thread-safe subclass of Set. This version locks against the object | ||
# itself for every method call, ensuring only one thread can be reading | ||
# or writing at a time. This includes iteration methods like `#each`. | ||
# | ||
# @note `a += b` is **not** a **thread-safe** operation on | ||
# `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set` | ||
# which is union of `a` and `b`, then it writes the union to `a`. | ||
# The read and write are independent operations they do not form a single atomic | ||
# operation therefore when two `+=` operations are executed concurrently updates | ||
# may be lost. Use `#merge` instead. | ||
# | ||
# @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set` | ||
class Set < ::Set; | ||
end | ||
|
||
elsif Concurrent.on_jruby? | ||
require 'jruby/synchronized' | ||
|
||
# @!macro concurrent_Set | ||
class Set < ::Set | ||
include JRuby::Synchronized | ||
end | ||
|
||
elsif Concurrent.on_rbx? || Concurrent.on_truffle? | ||
require 'monitor' | ||
require 'concurrent/thread_safe/util/array_hash_rbx' | ||
|
||
# @!macro concurrent_Set | ||
class Set < ::Set | ||
end | ||
|
||
ThreadSafe::Util.make_synchronized_on_rbx Set | ||
end | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ module Concurrent | |
end | ||
end | ||
end.map(&:join) | ||
expect(ary).to be_empty | ||
end | ||
|
||
describe '#slice' do | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
require 'set' | ||
module Concurrent | ||
RSpec.describe Set do | ||
let!(:set) { described_class.new } | ||
|
||
it 'concurrency' do | ||
(1..THREADS).map do |i| | ||
Thread.new do | ||
1000.times do | ||
v = i | ||
set << v | ||
expect(set).not_to be_empty | ||
set.delete(v) | ||
end | ||
end | ||
end.map(&:join) | ||
expect(set).to be_empty | ||
end | ||
end | ||
end |