You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+21-26Lines changed: 21 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,16 +4,16 @@
4
4
5
5
## Introduction
6
6
7
-
This is a small header-only library, providing a unique-ownership smart pointer that can be observed with weak pointers. It is a mixture of `std::unique_ptr` and `std::shared_ptr`: it borrows the unique-ownership semantic of `std::unique_ptr` (movable, non-copiable), but allows creating `std::weak_ptr` instances to monitor the lifetime of the pointed object.
7
+
This is a small header-only library, providing a unique-ownership smart pointer `observable_unique_ptr`that can be observed with non-owning pointers`observer_ptr`. It is a mixture of `std::unique_ptr` and `std::shared_ptr`: it borrows the unique-ownership semantic of `std::unique_ptr` (movable, non-copiable), but allows creating `observer_ptr`to monitor the lifetime of the pointed object (like `std::weak_ptr` for `std::shared_ptr`).
8
8
9
-
This is useful for cases where the shared-ownership of `std::shared_ptr` is not desirable, e.g., when lifetime must be carefully controlled and not be allowed to extend, yet non-owning "weak" references to the object may exist after the object has been deleted.
9
+
This is useful for cases where the shared-ownership of `std::shared_ptr` is not desirable, e.g., when lifetime must be carefully controlled and not be allowed to extend, yet non-owning/weak/observer references to the object may exist after the object has been deleted.
10
10
11
-
Note: Because of the unique ownership model, weak pointers locking cannot extend the lifetime of the pointed object, hence `observable_unique_ptr` provides less thread-safety compared to `std::shared_ptr`. This is also true of `std::unique_ptr`, and is a fundamental limitation of unique ownership. Do not use this library if the lifetime of your objects is not well understood.
11
+
Note: Because of the unique ownership model, observer pointers cannot extend the lifetime of the pointed object, hence `observable_unique_ptr`/`observer_ptr` provides less thread-safety compared to `std::shared_ptr`/`std::weak_ptr`. This is also true of `std::unique_ptr`, and is a fundamental limitation of unique ownership. If this is an issue, you will need either to add your own explicit locking logic, or use `std::shared_ptr`/`std::weak_ptr`.
12
12
13
13
14
14
## Usage
15
15
16
-
This is a header-only library. You have multiple ways to set it up:
16
+
This is a header-only library requiring a C++17-compliant compiler. You have multiple ways to set it up:
17
17
- just include this repository as a submodule in your own git repository and use CMake `add_subdirectory`,
18
18
- use CMake `FetchContent`,
19
19
- download the header and include it in your own sources.
@@ -28,35 +28,34 @@ From there, include the single header `<oup/observable_unique_ptr.hpp>`, and dir
28
28
#include<cassert>
29
29
30
30
intmain() {
31
-
// Weak pointer that will outlive the object
32
-
oup::weak_ptr<std::string> wptr;
31
+
// Non-owning pointer that will outlive the object
32
+
oup::observer_ptr<std::string> obs_ptr;
33
33
34
34
{
35
35
// Unique pointer that owns the object
36
-
auto ptr = oup::make_observable_unique<std::string>("hello");
36
+
auto owner_ptr = oup::make_observable_unique<std::string>("hello");
37
37
38
-
// Make the weak pointer observe the object
39
-
wptr = ptr;
38
+
// Make the observer pointer point to the object
39
+
obs_ptr = owner_ptr;
40
40
41
-
// Weak pointer is valid
42
-
assert(!wptr.expired());
41
+
// Observer pointer is valid
42
+
assert(!obs_ptr.expired());
43
43
44
-
// It can be locked to get a (non-owning!) pointer to the object
45
-
std::string* s = wptr.lock();
46
-
assert(s != nullptr);
47
-
std::cout << *s << std::endl;
44
+
// It can be used like a regular raw pointer
45
+
assert(obs_ptr != nullptr);
46
+
std::cout << *obs_ptr << std::endl;
48
47
49
48
// The unique pointer cannot be copied
50
-
auto tmp_copied = ptr; // error!
49
+
auto tmp_copied = owner_ptr; // error!
51
50
52
51
// ... but it can be moved
53
-
auto tmp_moved = std::move(ptr); // OK
52
+
auto tmp_moved = std::move(owner_ptr); // OK
54
53
}
55
54
56
55
// The unique pointer has gone out of scope, the object is deleted,
57
-
// the weak pointer is now null.
58
-
assert(wptr.expired());
59
-
assert(wptr.lock() == nullptr);
56
+
// the observer pointer is now null.
57
+
assert(obs_ptr.expired());
58
+
assert(obs_ptr == nullptr);
60
59
61
60
return 0;
62
61
}
@@ -65,16 +64,12 @@ int main() {
65
64
66
65
## Limitations
67
66
68
-
The follownig limitations are imposed by the current implementation (reusing the parts from `std::shared_ptr` and `std::weak_ptr`), or features that were not implemented simply because of lack of motivation. A higher quality implementation of this API could get rid of most (if not all) of them.
67
+
The follownig limitations are features that were not implemented simply because of lack of motivation.
69
68
70
69
-`observable_unique_ptr` does not support pointers to arrays, but `std::unique_ptr` and `std::shared_ptr` both do.
71
70
-`observable_unique_ptr` does not support custom allocators, but `std::shared_ptr` does.
72
-
-`observable_unique_ptr` does not have a `release()` function to let go of the ownership, which `std::unique_ptr` has.
73
-
-`observable_unique_ptr` allows moving from other `observable_unique_ptr` only if the deleter type is exactly the same, while `std::unique_ptr` allows moving from a convertible deleter.
74
-
- Contrary to `std::unique_ptr`, which stores the deleter in-place next to the pointer to the owned object, an `observable_unique_ptr` follows the model from `std::shared_ptr` where the deleter is type-erased and stored on the heap. Therefore, an `observable_unique_ptr` may or may not own a deleter instance; if in doubt, check `has_deleter()` before calling `get_deleter()`, or use `try_get_deleter()`.
75
-
- A moved-from `observable_unique_ptr` will not own a deleter instance.
76
71
77
72
78
73
## Notes
79
74
80
-
An alternative implementation of an "observable unique pointer" can be found [here](https://www.codeproject.com/articles/1011134/smart-observers-to-use-with-unique-ptr). It does not compile out of the box with gcc unfortunately, but it does contain more features (like creating an observer pointer from a raw `this`) and a lower-overhead implementation (not based on `std::shared_ptr`/`std::weak_ptr`). Have a look to check if this better suits your needs.
75
+
An alternative implementation of an "observable unique pointer" can be found [here](https://www.codeproject.com/articles/1011134/smart-observers-to-use-with-unique-ptr). It does not compile out of the box with gcc unfortunately, but it does contain more features (like creating an observer pointer from a raw `this`). Have a look to check if this better suits your needs.
0 commit comments