Smart pointer that allows shared ownership of an object with exclusive access.
More...
template<typename T>
class BPrivate::Network::BExclusiveBorrow< T >
Smart pointer that allows shared ownership of an object with exclusive access.
This smart pointer was designed to support the particular pattern where a non-threadsafe or non-lockable needs to be shared between two threads, where only one can have access to the underlying object at the time.
When creating a new object, the underlying object can be accessed using the dereference operator overloads as if with any other smart pointer. This ownership can then be borrowed by creating a BBorrow object. At that stage, the original owner can no longer access the underlying object, until the borrow is returned. The borrow can access the object as long as they retain the borrow. The borrow is returned by the borrow object going out of scope, or by the borrow object being assigned a nullptr
object. At that stage, the original owner regains access.
owner->SetTo("New value set by owner");
try {
owner->SetTo("Another value set by owner");
} catch (const BorrowError& e) {
}
try {
BBorrow<BString> secondBorrow = BBorrow<BString>(owner);
} catch (const BorrowError& e) {
}
borrow->SetTo("A value set by the borrower");
borrow = nullptr;
assert(*owner == "A value set by the borrower");
Smart pointer that borrows an object from a BExclusiveBorrow owner.
Definition: ExclusiveBorrow.h:196
Smart pointer that allows shared ownership of an object with exclusive access.
Definition: ExclusiveBorrow.h:109
- Object Lifetime Management
- The BExclusiveBorrow and BBorrow pair manage the lifetime of the underlying object, meaning the memory will be freed when the object is no longer referenced by either the owner or the borrower. It is possible to get the ownership of the underlying object through the BExclusiveBorrow::Release() method. This returns a
unique_ptr
.
- Creating New Objects
- When creating a BExclusiveBorrow object, you can use the BExclusiveBorrow(T* object) constructor to create a new smart pointer that takes an existing underlying object. Note that the smart pointer will assume ownership, meaning that you should also have ownership of that object. If you want to create a BExclusiveBorrow object for a new object, then you can use the make_exclusive_borrow() function to create a new object.
- Move Semantics and Empty Objects
- The template class is designed around having an underlying object value, and in most cases will have an underlying object. However, there may be cases where a BExclusiveOwner or BBorrow object will not have an internal value. This either happens when it is explicitly assigned an empty value, or after the object has been moved. You can check whether the object has a value through the HasValue() method. Trying to access an empty object will throw a BBorrowError.
- Checked Access
- The semantics of the exclusive ownership are enforced by this class. The rules are:
- There can only be one owner. The object cannot be copied, only moved.
- There can only be one borrower at a time. The borrow object cannot be copied, only moved.
- If one tries to create an additional borrow, an exception is thrown.
- If an object is borrowed, accessing it through the owner will throw exceptions.
- Casting Pointers between Owner and Borrower
- For some design patterns, you may want to be able to cast the type of the owner to a related type for the borrower. For example, the Network Services kit accepts a
BBorrow<BDataIO>
type in order to allow the user to specify where to write the content of a network request to. The BDataIO itself is an abstract interface to read and write data from an object. A user will most likely use a BFile or BMallocIO as underlying objects, both of which have BDataIO as their base class.
- Due to the specialized constructor of BBorrow, it is possible to cast between compatible pointer types, without loosing the advantages of properly cleaning up the object when the borrow and the owner go out of scope. In the internals of the template, a type erasure technique similar to that of
std::shared_ptr
is used.
- Multithread Safety, and Performance Cost
- This smart object uses atomics to synchronize the ownership and borrows of the object, and to enforce all the checks that were mentioned previously. The atomics guarantee that when you want to access the object in BExclusiveBorrow, that this only succeeds after any outstanding borrow is completed, otherwise an exception is thrown. While atomics can be used as a method of synchronization, this templace class is not designed for that and it does not have the tools to help doing that. If you need to synchronize object access between through threads, you should use semaphores or thread joins instead.
- Template Parameters
-
T | The type of object for this smart pointer. |
- Since
- Haiku R1