Skip to content

Commit 8b165df

Browse files
committed
Added added to ConcurrentDictionary to give possibility of avoiding warning when assigning a new key-value pair. Updated tests
1 parent c191d60 commit 8b165df

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

concurrent_collections/concurrent_dict.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ def __getitem__(self, key: K) -> V:
2929
def __setitem__(self, key: K, value: V) -> None:
3030
warnings.warn(
3131
f"Direct assignment (D[key] = value) is discouraged. "
32-
f"Use update_atomic for thread-safe compound updates.",
32+
f"Use assign_atomic() for assigning a value to a new key safely, "
33+
f"or update_atomic() for thread-safe update of an existing dictionary key.",
3334
stacklevel=2
3435
)
35-
self.update_atomic(key, lambda _: value)
36+
self.assign_atomic(key, value)
3637

3738

3839
def __delitem__(self, key: K) -> None:
@@ -50,17 +51,27 @@ def setdefault(self, key: K, default: V) -> V:
5051
return self._dict.setdefault(key, default)
5152

5253

54+
def assign_atomic(self, key: K, value: V) -> None:
55+
"""
56+
Atomically assign a value to a key.
57+
58+
This method ensures that the assignment is performed atomically,
59+
preventing
60+
"""
61+
self.update_atomic(key, lambda _: value)
62+
63+
5364
def update_atomic(self, key: K, func: Callable[[V], V]) -> None:
5465
"""
55-
Atomically update the value for a key using func(old_value) -> new_value.
66+
Atomically modify the value for a key using func(old_value) -> new_value.
5667
5768
This method ensures that the read-modify-write sequence is performed atomically,
5869
preventing race conditions in concurrent environments.
5970
6071
Example:
6172
d = ConcurrentDictionary({'x': 0})
6273
# Atomically increment the value for 'x'
63-
d.update_atomic('x', lambda v: v + 1)
74+
d.modify_atomic('x', lambda v: v + 1)
6475
"""
6576
with self._lock:
6677
if key in self._dict:

tests/concurrent_dict_test.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,24 @@
1212

1313
def test_concurrentdictionary_update_thread_safe():
1414
dic : ConcurrentDictionary[str, int] = ConcurrentDictionary()
15-
dic["x"] = 0
15+
update_actions : int = 10000
16+
dic.assign_atomic("x", 0)
1617
def worker():
17-
for _ in range(10000):
18-
old = dic['x']
18+
for _ in range(update_actions):
1919
time.sleep(0.00001)
2020
# D.__setitem__('x', old + 1)
2121
dic.update_atomic("x", lambda v: v + 1)
2222

23-
threads = [threading.Thread(target=worker) for _ in range(8)]
23+
threads_num : int = 8
24+
threads = [threading.Thread(target=worker) for _ in range(threads_num)]
2425
for t in threads:
2526
t.start()
2627
for t in threads:
2728
t.join()
2829

2930
# The expected value is 8 * 10000 = 80000
30-
assert dic['x'] == 80000, f"ConcurrentDictionary should be thread-safe, got {dic['x']}"
31+
expected_value = threads_num * update_actions
32+
assert dic['x'] == expected_value, f"ConcurrentDictionary should be thread-safe and with a value of {expected_value} for the `x` key, got {dic['x']}"
3133

3234

3335
def test_concurrentdictionary_setdefault_thread_safe():

0 commit comments

Comments
 (0)