aboutsummaryrefslogtreecommitdiffstats
path: root/README.rst
blob: f956f33741d5dcb41c7c8706552a180ec42e9e7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
range-lock - Multithread range lock for Vec
===========================================

`Project home <https://bues.ch/>`_

`Git repository <https://bues.ch/cgit/rangelockrs.git>`_

`Github repository <https://github.com/mbuesch/rangelockrs>`_

This crate provides locks/mutexes for multi-threaded access to a single Vec<T> instance.

Any thread can request exclusive access to a slice of the Vec.
Such access is granted, if no other thread is simultaneously holding the permission to access an overlapping slice.


Usage
=====

Add this to your Cargo.toml:

.. code:: toml

    [dependencies]
    range-lock = "0.2"


VecRangeLock example usage
--------------------------

General purpose VecRangeLock:

.. code:: rust

    use range_lock::VecRangeLock;
    use std::sync::Arc;
    use std::thread;

    let lock = Arc::new(VecRangeLock::new(vec![1, 2, 3, 4, 5]));

    thread::spawn(move || {
        let mut guard = lock.try_lock(2..4).expect("Failed to lock range 2..4");
        assert_eq!(guard[0], 3);
        guard[0] = 10;
    });


RepVecRangeLock example usage
-----------------------------

The RepVecRangeLock is a restricted range lock, that provides access to interleaved patterns of slices to the threads.

Locking a RepVecRangeLock is more lightweight than locking a VecRangeLock.
The threads can not freely choose slice ranges, but only choose a repeating slice pattern by specifying a pattern offset.

Please see the example below.

.. code:: rust

    use range_lock::RepVecRangeLock;
    use std::sync::Arc;
    use std::thread;

    let data = vec![1, 2, 3,  // <- cycle 0
                    4, 5, 6]; // <- cycle 1
    //              ^  ^  ^
    //              |  |  |
    //              |  |  offset-2
    //       offset-0  offset-1

    let lock = Arc::new(RepVecRangeLock::new(data,
                                             1,    // slice_len: Each slice has 1 element.
                                             3));  // cycle_len: Each cycle has 3 slices (offsets).
    thread::spawn(move || {
        // Lock slice offset 1:
        let mut guard = lock.try_lock(1).expect("Failed to lock offset.");

        assert_eq!(guard[0][0], 2);     // Cycle 0, Slice element 0
        assert_eq!(guard[1][0], 5);     // Cycle 1, Slice element 0

        guard[0][0] = 20;               // Cycle 0, Slice element 0
        guard[1][0] = 50;               // Cycle 1, Slice element 0
    });


TODOs for future releases
=========================

The following new features might be candidates for future releases:

* Sleeping lock, in case of lock contention.
* Add support for arrays.


License
=======

Copyright (c) 2021-2023 Michael Büsch <m@bues.ch>

Licensed under the Apache License version 2.0 or the MIT license, at your option.
bues.ch cgit interface