diff options
Diffstat (limited to 'vendor/triomphe')
-rw-r--r-- | vendor/triomphe/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/triomphe/Cargo.toml | 55 | ||||
-rw-r--r-- | vendor/triomphe/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | vendor/triomphe/LICENSE-MIT | 27 | ||||
-rw-r--r-- | vendor/triomphe/README.md | 13 | ||||
-rw-r--r-- | vendor/triomphe/src/arc.rs | 887 | ||||
-rw-r--r-- | vendor/triomphe/src/arc_borrow.rs | 116 | ||||
-rw-r--r-- | vendor/triomphe/src/arc_swap_support.rs | 42 | ||||
-rw-r--r-- | vendor/triomphe/src/arc_union.rs | 139 | ||||
-rw-r--r-- | vendor/triomphe/src/header.rs | 378 | ||||
-rw-r--r-- | vendor/triomphe/src/lib.rs | 94 | ||||
-rw-r--r-- | vendor/triomphe/src/offset_arc.rs | 134 | ||||
-rw-r--r-- | vendor/triomphe/src/thin_arc.rs | 329 | ||||
-rw-r--r-- | vendor/triomphe/src/unique_arc.rs | 257 |
14 files changed, 2673 insertions, 0 deletions
diff --git a/vendor/triomphe/.cargo-checksum.json b/vendor/triomphe/.cargo-checksum.json new file mode 100644 index 000000000..712085ef9 --- /dev/null +++ b/vendor/triomphe/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"c202bbb3cde95a6a58173272683abee0935898336a6933ad70d7b672ecb983b5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"15656cc11a8331f28c0986b8ab97220d3e76f98e60ed388b5ffad37dfac4710c","README.md":"b165c87151b13a2a0b639843da6f933249fe6814cd6698259172b6a27b3844a8","src/arc.rs":"dbbd13ac6d47ce2aa11a4b1af6bb858ce9bc077679d3709565d0e710a795d8b8","src/arc_borrow.rs":"df8b6ed97b41839b5be92bec8ff7b40085ae6d9d014f5571024e8bf2595a1170","src/arc_swap_support.rs":"54213ddea959fec13f1af4efb94271a9b85c531c06649899ddf8d6b939615d05","src/arc_union.rs":"b623adb5bf6f0911b5230658ad4e054d76569dc0e75fbccf41fa666112775766","src/header.rs":"051a5537d7f5aceafcb02397caf9f8a53e7e43741a41e934156f9c388bff2a7c","src/lib.rs":"657017eacbbcc9b8720ca9b278342bbfbdc6c6e25e1c6015e70fc87668cb8bb2","src/offset_arc.rs":"ebedbcc3dd46dfebcfb2976cc37252340548819b8c8c513aa4c4b2d4187c917c","src/thin_arc.rs":"dc9ad742fc4226c9f8f9b7e6ea8fb8a4aa7ea369d2723f6dcfa9bd46b4b34b0b","src/unique_arc.rs":"73308e959d0966cacd75aa2b2043a093fcb9d1b494aae9014d48c64fd1f81c8b"},"package":"f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db"}
\ No newline at end of file diff --git a/vendor/triomphe/Cargo.toml b/vendor/triomphe/Cargo.toml new file mode 100644 index 000000000..5cb758241 --- /dev/null +++ b/vendor/triomphe/Cargo.toml @@ -0,0 +1,55 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +name = "triomphe" +version = "0.1.8" +authors = ["The Servo Project Developers"] +description = "A fork of std::sync::Arc with some extra functionality and without weak references (originally servo_arc)" +readme = "README.md" +keywords = [ + "arc", + "ffi", + "sync", + "data-structure", +] +categories = [ + "concurrency", + "data-structures", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/Manishearth/triomphe" + +[dependencies.arc-swap] +version = "1.3.0" +optional = true + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dependencies.stable_deref_trait] +version = "1.1.1" +optional = true +default-features = false + +[dependencies.unsize] +version = "1.1" +optional = true + +[features] +default = [ + "serde", + "stable_deref_trait", + "std", +] +std = [] diff --git a/vendor/triomphe/LICENSE-APACHE b/vendor/triomphe/LICENSE-APACHE new file mode 100644 index 000000000..16fe87b06 --- /dev/null +++ b/vendor/triomphe/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/triomphe/LICENSE-MIT b/vendor/triomphe/LICENSE-MIT new file mode 100644 index 000000000..d74f9e93d --- /dev/null +++ b/vendor/triomphe/LICENSE-MIT @@ -0,0 +1,27 @@ +MIT License + +Copyright (c) 2019 Manish Goregaokar + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/triomphe/README.md b/vendor/triomphe/README.md new file mode 100644 index 000000000..c7615a843 --- /dev/null +++ b/vendor/triomphe/README.md @@ -0,0 +1,13 @@ +# Triomphe + +Fork of Arc. This has the following advantages over std::sync::Arc: + + * `triomphe::Arc` doesn't support weak references: we save space by excluding the weak reference count, and we don't do extra read-modify-update operations to handle the possibility of weak references. + * `triomphe::UniqueArc` allows one to construct a temporarily-mutable `Arc` which can be converted to a regular `triomphe::Arc` later + * `triomphe::OffsetArc` can be used transparently from C++ code and is compatible with (and can be converted to/from) `triomphe::Arc` + * `triomphe::ArcBorrow` is functionally similar to `&triomphe::Arc<T>`, however in memory it's simply `&T`. This makes it more flexible for FFI; the source of the borrow need not be an `Arc` pinned on the stack (and can instead be a pointer from C++, or an `OffsetArc`). Additionally, this helps avoid pointer-chasing. + * `triomphe::Arc` has can be constructed for dynamically-sized types via `from_header_and_iter` + * `triomphe::ThinArc` provides thin-pointer `Arc`s to dynamically sized types + * `triomphe::ArcUnion` is union of two `triomphe:Arc`s which fits inside one word of memory + +This crate is a version of `servo_arc` meant for general community use.
\ No newline at end of file diff --git a/vendor/triomphe/src/arc.rs b/vendor/triomphe/src/arc.rs new file mode 100644 index 000000000..6fe022c46 --- /dev/null +++ b/vendor/triomphe/src/arc.rs @@ -0,0 +1,887 @@ +use alloc::alloc::handle_alloc_error; +use alloc::boxed::Box; +use core::alloc::Layout; +use core::borrow; +use core::cmp::Ordering; +use core::convert::From; +use core::ffi::c_void; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, MaybeUninit}; +use core::ops::Deref; +use core::ptr::{self, NonNull}; +use core::sync::atomic; +use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use core::{isize, usize}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; +#[cfg(feature = "stable_deref_trait")] +use stable_deref_trait::{CloneStableDeref, StableDeref}; + +use crate::{abort, ArcBorrow, HeaderSlice, OffsetArc, UniqueArc}; + +/// A soft limit on the amount of references that may be made to an `Arc`. +/// +/// Going above this limit will abort your program (although not +/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. +const MAX_REFCOUNT: usize = (isize::MAX) as usize; + +/// The object allocated by an Arc<T> +#[repr(C)] +pub(crate) struct ArcInner<T: ?Sized> { + pub(crate) count: atomic::AtomicUsize, + pub(crate) data: T, +} + +unsafe impl<T: ?Sized + Sync + Send> Send for ArcInner<T> {} +unsafe impl<T: ?Sized + Sync + Send> Sync for ArcInner<T> {} + +/// An atomically reference counted shared pointer +/// +/// See the documentation for [`Arc`] in the standard library. Unlike the +/// standard library `Arc`, this `Arc` does not support weak reference counting. +/// +/// [`Arc`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html +#[repr(transparent)] +pub struct Arc<T: ?Sized> { + pub(crate) p: ptr::NonNull<ArcInner<T>>, + pub(crate) phantom: PhantomData<T>, +} + +unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {} +unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} + +impl<T> Arc<T> { + /// Construct an `Arc<T>` + #[inline] + pub fn new(data: T) -> Self { + let ptr = Box::into_raw(Box::new(ArcInner { + count: atomic::AtomicUsize::new(1), + data, + })); + + unsafe { + Arc { + p: ptr::NonNull::new_unchecked(ptr), + phantom: PhantomData, + } + } + } + + /// Reconstruct the Arc<T> from a raw pointer obtained from into_raw() + /// + /// Note: This raw pointer will be offset in the allocation and must be preceded + /// by the atomic count. + /// + /// It is recommended to use OffsetArc for this + #[inline] + pub unsafe fn from_raw(ptr: *const T) -> Self { + // FIXME: when `byte_sub` is stabilized, this can accept T: ?Sized. + + // To find the corresponding pointer to the `ArcInner` we need + // to subtract the offset of the `data` field from the pointer. + let ptr = (ptr as *const u8).sub(offset_of!(ArcInner<T>, data)); + Arc::from_raw_inner(ptr as *mut ArcInner<T>) + } + + /// Temporarily converts |self| into a bonafide OffsetArc and exposes it to the + /// provided callback. The refcount is not modified. + #[inline(always)] + pub fn with_raw_offset_arc<F, U>(&self, f: F) -> U + where + F: FnOnce(&OffsetArc<T>) -> U, + { + // Synthesize transient Arc, which never touches the refcount of the ArcInner. + // Store transient in `ManuallyDrop`, to leave the refcount untouched. + let transient = unsafe { ManuallyDrop::new(Arc::into_raw_offset(ptr::read(self))) }; + + // Expose the transient Arc to the callback, which may clone it if it wants. + f(&transient) + } + + /// Converts an `Arc` into a `OffsetArc`. This consumes the `Arc`, so the refcount + /// is not modified. + #[inline] + pub fn into_raw_offset(a: Self) -> OffsetArc<T> { + unsafe { + OffsetArc { + ptr: ptr::NonNull::new_unchecked(Arc::into_raw(a) as *mut T), + phantom: PhantomData, + } + } + } + + /// Converts a `OffsetArc` into an `Arc`. This consumes the `OffsetArc`, so the refcount + /// is not modified. + #[inline] + pub fn from_raw_offset(a: OffsetArc<T>) -> Self { + let a = ManuallyDrop::new(a); + let ptr = a.ptr.as_ptr(); + unsafe { Arc::from_raw(ptr) } + } + + /// Returns the inner value, if the [`Arc`] has exactly one strong reference. + /// + /// Otherwise, an [`Err`] is returned with the same [`Arc`] that was + /// passed in. + /// + /// # Examples + /// + /// ``` + /// use triomphe::Arc; + /// + /// let x = Arc::new(3); + /// assert_eq!(Arc::try_unwrap(x), Ok(3)); + /// + /// let x = Arc::new(4); + /// let _y = Arc::clone(&x); + /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); + /// ``` + pub fn try_unwrap(this: Self) -> Result<T, Self> { + Self::try_unique(this).map(UniqueArc::into_inner) + } +} + +impl<T: ?Sized> Arc<T> { + /// Convert the Arc<T> to a raw pointer, suitable for use across FFI + /// + /// Note: This returns a pointer to the data T, which is offset in the allocation. + /// + /// It is recommended to use OffsetArc for this. + #[inline] + pub fn into_raw(this: Self) -> *const T { + let this = ManuallyDrop::new(this); + this.as_ptr() + } + + /// Returns the raw pointer. + /// + /// Same as into_raw except `self` isn't consumed. + #[inline] + pub fn as_ptr(&self) -> *const T { + // SAFETY: This cannot go through a reference to `data`, because this method + // is used to implement `into_raw`. To reconstruct the full `Arc` from this + // pointer, it needs to maintain its full provenance, and not be reduced to + // just the contained `T`. + unsafe { ptr::addr_of_mut!((*self.ptr()).data) } + } + + /// Produce a pointer to the data that can be converted back + /// to an Arc. This is basically an `&Arc<T>`, without the extra indirection. + /// It has the benefits of an `&T` but also knows about the underlying refcount + /// and can be converted into more `Arc<T>`s if necessary. + #[inline] + pub fn borrow_arc(&self) -> ArcBorrow<'_, T> { + ArcBorrow(&**self) + } + + /// Returns the address on the heap of the Arc itself -- not the T within it -- for memory + /// reporting. + pub fn heap_ptr(&self) -> *const c_void { + self.p.as_ptr() as *const ArcInner<T> as *const c_void + } + + #[inline] + pub(super) fn into_raw_inner(this: Self) -> *mut ArcInner<T> { + let this = ManuallyDrop::new(this); + this.ptr() + } + + /// Construct an `Arc` from an allocated `ArcInner`. + /// # Safety + /// The `ptr` must point to a valid instance, allocated by an `Arc`. The reference could will + /// not be modified. + pub(super) unsafe fn from_raw_inner(ptr: *mut ArcInner<T>) -> Self { + Arc { + p: ptr::NonNull::new_unchecked(ptr), + phantom: PhantomData, + } + } + + #[inline] + pub(super) fn inner(&self) -> &ArcInner<T> { + // This unsafety is ok because while this arc is alive we're guaranteed + // that the inner pointer is valid. Furthermore, we know that the + // `ArcInner` structure itself is `Sync` because the inner data is + // `Sync` as well, so we're ok loaning out an immutable pointer to these + // contents. + unsafe { &*self.ptr() } + } + + // Non-inlined part of `drop`. Just invokes the destructor. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + let _ = Box::from_raw(self.ptr()); + } + + /// Test pointer equality between the two Arcs, i.e. they must be the _same_ + /// allocation + #[inline] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.ptr() == other.ptr() + } + + pub(crate) fn ptr(&self) -> *mut ArcInner<T> { + self.p.as_ptr() + } + + /// Allocates an `ArcInner<T>` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner<T>`. + /// + /// ## Safety + /// + /// `mem_to_arcinner` must return the same pointer, the only things that can change are + /// - its type + /// - its metadata + /// + /// `value_layout` must be correct for `T`. + #[allow(unused_unsafe)] + pub(super) unsafe fn allocate_for_layout( + value_layout: Layout, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>, + ) -> NonNull<ArcInner<T>> { + let layout = Layout::new::<ArcInner<()>>() + .extend(value_layout) + .unwrap() + .0 + .pad_to_align(); + + // Safety: we propagate safety requirements to the caller + unsafe { + Arc::try_allocate_for_layout(value_layout, mem_to_arcinner) + .unwrap_or_else(|_| handle_alloc_error(layout)) + } + } + + /// Allocates an `ArcInner<T>` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner<T>`. + /// + /// ## Safety + /// + /// `mem_to_arcinner` must return the same pointer, the only things that can change are + /// - its type + /// - its metadata + /// + /// `value_layout` must be correct for `T`. + #[allow(unused_unsafe)] + unsafe fn try_allocate_for_layout( + value_layout: Layout, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>, + ) -> Result<NonNull<ArcInner<T>>, ()> { + let layout = Layout::new::<ArcInner<()>>() + .extend(value_layout) + .unwrap() + .0 + .pad_to_align(); + + let ptr = NonNull::new(alloc::alloc::alloc(layout)).ok_or(())?; + + // Initialize the ArcInner + let inner = mem_to_arcinner(ptr.as_ptr()); + debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout); + + unsafe { + ptr::write(&mut (*inner).count, atomic::AtomicUsize::new(1)); + } + + // Safety: `ptr` is checked to be non-null, + // `inner` is the same as `ptr` (per the safety requirements of this function) + unsafe { Ok(NonNull::new_unchecked(inner)) } + } +} + +impl<H, T> Arc<HeaderSlice<H, [T]>> { + pub(super) fn allocate_for_header_and_slice( + len: usize, + ) -> NonNull<ArcInner<HeaderSlice<H, [T]>>> { + let layout = Layout::new::<H>() + .extend(Layout::array::<T>(len).unwrap()) + .unwrap() + .0 + .pad_to_align(); + + unsafe { + // Safety: + // - the provided closure does not change the pointer (except for meta & type) + // - the provided layout is valid for `HeaderSlice<H, [T]>` + Arc::allocate_for_layout(layout, |mem| { + // Synthesize the fat pointer. We do this by claiming we have a direct + // pointer to a [T], and then changing the type of the borrow. The key + // point here is that the length portion of the fat pointer applies + // only to the number of elements in the dynamically-sized portion of + // the type, so the value will be the same whether it points to a [T] + // or something else with a [T] as its last member. + let fake_slice = ptr::slice_from_raw_parts_mut(mem as *mut T, len); + fake_slice as *mut ArcInner<HeaderSlice<H, [T]>> + }) + } + } +} + +impl<T> Arc<MaybeUninit<T>> { + /// Create an Arc contains an `MaybeUninit<T>`. + pub fn new_uninit() -> Self { + Arc::new(MaybeUninit::<T>::uninit()) + } + + /// Calls `MaybeUninit::write` on the value contained. + /// + /// ## Panics + /// + /// If the `Arc` is not unique. + #[deprecated( + since = "0.1.7", + note = "this function previously was UB and now panics for non-unique `Arc`s. Use `UniqueArc::write` instead." + )] + #[track_caller] + pub fn write(&mut self, val: T) -> &mut T { + UniqueArc::write(must_be_unique(self), val) + } + + /// Obtain a mutable pointer to the stored `MaybeUninit<T>`. + pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> { + unsafe { &mut (*self.ptr()).data } + } + + /// # Safety + /// + /// Must initialize all fields before calling this function. + #[inline] + pub unsafe fn assume_init(self) -> Arc<T> { + Arc::from_raw_inner(ManuallyDrop::new(self).ptr().cast()) + } +} + +impl<T> Arc<[MaybeUninit<T>]> { + /// Create an Arc contains an array `[MaybeUninit<T>]` of `len`. + pub fn new_uninit_slice(len: usize) -> Self { + UniqueArc::new_uninit_slice(len).shareable() + } + + /// Obtain a mutable slice to the stored `[MaybeUninit<T>]`. + #[deprecated( + since = "0.1.8", + note = "this function previously was UB and now panics for non-unique `Arc`s. Use `UniqueArc` or `get_mut` instead." + )] + #[track_caller] + pub fn as_mut_slice(&mut self) -> &mut [MaybeUninit<T>] { + must_be_unique(self) + } + + /// # Safety + /// + /// Must initialize all fields before calling this function. + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T]> { + Arc::from_raw_inner(ManuallyDrop::new(self).ptr() as _) + } +} + +impl<T: ?Sized> Clone for Arc<T> { + #[inline] + fn clone(&self) -> Self { + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object. + // + // As explained in the [Boost documentation][1], Increasing the + // reference counter can always be done with memory_order_relaxed: New + // references to an object can only be formed from an existing + // reference, and passing an existing reference from one thread to + // another must already provide any required synchronization. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + let old_size = self.inner().count.fetch_add(1, Relaxed); + + // However we need to guard against massive refcounts in case someone + // is `mem::forget`ing Arcs. If we don't do this the count can overflow + // and users will use-after free. We racily saturate to `isize::MAX` on + // the assumption that there aren't ~2 billion threads incrementing + // the reference count at once. This branch will never be taken in + // any realistic program. + // + // We abort because such a program is incredibly degenerate, and we + // don't care to support it. + if old_size > MAX_REFCOUNT { + abort(); + } + + unsafe { + Arc { + p: ptr::NonNull::new_unchecked(self.ptr()), + phantom: PhantomData, + } + } + } +} + +impl<T: ?Sized> Deref for Arc<T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.inner().data + } +} + +impl<T: Clone> Arc<T> { + /// Makes a mutable reference to the `Arc`, cloning if necessary + /// + /// This is functionally equivalent to [`Arc::make_mut`][mm] from the standard library. + /// + /// If this `Arc` is uniquely owned, `make_mut()` will provide a mutable + /// reference to the contents. If not, `make_mut()` will create a _new_ `Arc` + /// with a copy of the contents, update `this` to point to it, and provide + /// a mutable reference to its contents. + /// + /// This is useful for implementing copy-on-write schemes where you wish to + /// avoid copying things if your `Arc` is not shared. + /// + /// [mm]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.make_mut + #[inline] + pub fn make_mut(this: &mut Self) -> &mut T { + if !this.is_unique() { + // Another pointer exists; clone + *this = Arc::new(T::clone(&this)); + } + + unsafe { + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the Arc itself to be `mut`, so we're returning the only possible + // reference to the inner data. + &mut (*this.ptr()).data + } + } + + /// Makes a `UniqueArc` from an `Arc`, cloning if necessary. + /// + /// If this `Arc` is uniquely owned, `make_unique()` will provide a `UniqueArc` + /// containing `this`. If not, `make_unique()` will create a _new_ `Arc` + /// with a copy of the contents, update `this` to point to it, and provide + /// a `UniqueArc` to it. + /// + /// This is useful for implementing copy-on-write schemes where you wish to + /// avoid copying things if your `Arc` is not shared. + #[inline] + pub fn make_unique(this: &mut Self) -> &mut UniqueArc<T> { + if !this.is_unique() { + // Another pointer exists; clone + *this = Arc::new(T::clone(&this)); + } + + unsafe { + // Safety: this is either unique or just created (which is also unique) + UniqueArc::from_arc_ref(this) + } + } + + /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the clone. + /// + /// Assuming `arc_t` is of type `Arc<T>`, this function is functionally equivalent to `(*arc_t).clone()`, but will avoid cloning the inner value where possible. + pub fn unwrap_or_clone(this: Arc<T>) -> T { + Self::try_unwrap(this).unwrap_or_else(|this| T::clone(&this)) + } +} + +impl<T: ?Sized> Arc<T> { + /// Provides mutable access to the contents _if_ the `Arc` is uniquely owned. + #[inline] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if this.is_unique() { + unsafe { + // See make_mut() for documentation of the threadsafety here. + Some(&mut (*this.ptr()).data) + } + } else { + None + } + } + + /// Provides unique access to the arc _if_ the `Arc` is uniquely owned. + pub fn get_unique(this: &mut Self) -> Option<&mut UniqueArc<T>> { + Self::try_as_unique(this).ok() + } + + /// Whether or not the `Arc` is uniquely owned (is the refcount 1?). + pub fn is_unique(&self) -> bool { + // See the extensive discussion in [1] for why this needs to be Acquire. + // + // [1] https://github.com/servo/servo/issues/21186 + Self::count(self) == 1 + } + + /// Gets the number of [`Arc`] pointers to this allocation + pub fn count(this: &Self) -> usize { + this.inner().count.load(Acquire) + } + + /// Returns a [`UniqueArc`] if the [`Arc`] has exactly one strong reference. + /// + /// Otherwise, an [`Err`] is returned with the same [`Arc`] that was + /// passed in. + /// + /// # Examples + /// + /// ``` + /// use triomphe::{Arc, UniqueArc}; + /// + /// let x = Arc::new(3); + /// assert_eq!(UniqueArc::into_inner(Arc::try_unique(x).unwrap()), 3); + /// + /// let x = Arc::new(4); + /// let _y = Arc::clone(&x); + /// assert_eq!( + /// *Arc::try_unique(x).map(UniqueArc::into_inner).unwrap_err(), + /// 4, + /// ); + /// ``` + pub fn try_unique(this: Self) -> Result<UniqueArc<T>, Self> { + if this.is_unique() { + // Safety: The current arc is unique and making a `UniqueArc` + // from it is sound + unsafe { Ok(UniqueArc::from_arc(this)) } + } else { + Err(this) + } + } + + pub(crate) fn try_as_unique(this: &mut Self) -> Result<&mut UniqueArc<T>, &mut Self> { + if this.is_unique() { + // Safety: The current arc is unique and making a `UniqueArc` + // from it is sound + unsafe { Ok(UniqueArc::from_arc_ref(this)) } + } else { + Err(this) + } + } +} + +impl<T: ?Sized> Drop for Arc<T> { + #[inline] + fn drop(&mut self) { + // Because `fetch_sub` is already atomic, we do not need to synchronize + // with other threads unless we are going to delete the object. + if self.inner().count.fetch_sub(1, Release) != 1 { + return; + } + + // FIXME(bholley): Use the updated comment when [2] is merged. + // + // This load is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` load. This + // means that use of the data happens before decreasing the reference + // count, which happens before this load, which happens before the + // deletion of the data. + // + // As explained in the [Boost documentation][1], + // + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + // [2]: https://github.com/rust-lang/rust/pull/41714 + self.inner().count.load(Acquire); + + unsafe { + self.drop_slow(); + } + } +} + +impl<T: ?Sized + PartialEq> PartialEq for Arc<T> { + fn eq(&self, other: &Arc<T>) -> bool { + Self::ptr_eq(self, other) || *(*self) == *(*other) + } + + #[allow(clippy::partialeq_ne_impl)] + fn ne(&self, other: &Arc<T>) -> bool { + !Self::ptr_eq(self, other) && *(*self) != *(*other) + } +} + +impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> { + fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> { + (**self).partial_cmp(&**other) + } + + fn lt(&self, other: &Arc<T>) -> bool { + *(*self) < *(*other) + } + + fn le(&self, other: &Arc<T>) -> bool { + *(*self) <= *(*other) + } + + fn gt(&self, other: &Arc<T>) -> bool { + *(*self) > *(*other) + } + + fn ge(&self, other: &Arc<T>) -> bool { + *(*self) >= *(*other) + } +} + +impl<T: ?Sized + Ord> Ord for Arc<T> { + fn cmp(&self, other: &Arc<T>) -> Ordering { + (**self).cmp(&**other) + } +} + +impl<T: ?Sized + Eq> Eq for Arc<T> {} + +impl<T: ?Sized + fmt::Display> fmt::Display for Arc<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +impl<T: ?Sized + fmt::Debug> fmt::Debug for Arc<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<T: ?Sized> fmt::Pointer for Arc<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&self.ptr(), f) + } +} + +impl<T: Default> Default for Arc<T> { + #[inline] + fn default() -> Arc<T> { + Arc::new(Default::default()) + } +} + +impl<T: ?Sized + Hash> Hash for Arc<T> { + fn hash<H: Hasher>(&self, state: &mut H) { + (**self).hash(state) + } +} + +impl<T> From<T> for Arc<T> { + #[inline] + fn from(t: T) -> Self { + Arc::new(t) + } +} + +impl<T: ?Sized> borrow::Borrow<T> for Arc<T> { + #[inline] + fn borrow(&self) -> &T { + &**self + } +} + +impl<T: ?Sized> AsRef<T> for Arc<T> { + #[inline] + fn as_ref(&self) -> &T { + &**self + } +} + +#[cfg(feature = "stable_deref_trait")] +unsafe impl<T: ?Sized> StableDeref for Arc<T> {} +#[cfg(feature = "stable_deref_trait")] +unsafe impl<T: ?Sized> CloneStableDeref for Arc<T> {} + +#[cfg(feature = "serde")] +impl<'de, T: Deserialize<'de>> Deserialize<'de> for Arc<T> { + fn deserialize<D>(deserializer: D) -> Result<Arc<T>, D::Error> + where + D: ::serde::de::Deserializer<'de>, + { + T::deserialize(deserializer).map(Arc::new) + } +} + +#[cfg(feature = "serde")] +impl<T: Serialize> Serialize for Arc<T> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ::serde::ser::Serializer, + { + (**self).serialize(serializer) + } +} + +// Safety: +// This implementation must guarantee that it is sound to call replace_ptr with an unsized variant +// of the pointer retuned in `as_sized_ptr`. The basic property of Unsize coercion is that safety +// variants and layout is unaffected. The Arc does not rely on any other property of T. This makes +// any unsized ArcInner valid for being shared with the sized variant. +// This does _not_ mean that any T can be unsized into an U, but rather than if such unsizing is +// possible then it can be propagated into the Arc<T>. +#[cfg(feature = "unsize")] +unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for Arc<T> { + type Pointee = T; + type Output = Arc<U>; + + fn as_sized_ptr(&mut self) -> *mut T { + // Returns a pointer to the complete inner. The unsizing itself won't care about the + // pointer value and promises not to offset it. + self.p.as_ptr() as *mut T + } + + unsafe fn replace_ptr(self, new: *mut U) -> Arc<U> { + // Fix the provenance by ensuring that of `self` is used. + let inner = ManuallyDrop::new(self); + let p = inner.p.as_ptr() as *mut T; + // Safety: This points to an ArcInner of the previous self and holds shared ownership since + // the old pointer never decremented the reference count. The caller upholds that `new` is + // an unsized version of the previous ArcInner. This assumes that unsizing to the fat + // pointer tag of an `ArcInner<U>` and `U` is isomorphic under a direct pointer cast since + // in reality we unsized *mut T to *mut U at the address of the ArcInner. This is the case + // for all currently envisioned unsized types where the tag of T and ArcInner<T> are simply + // the same. + Arc::from_raw_inner(p.replace_ptr(new) as *mut ArcInner<U>) + } +} + +#[track_caller] +fn must_be_unique<T: ?Sized>(arc: &mut Arc<T>) -> &mut UniqueArc<T> { + match Arc::try_as_unique(arc) { + Ok(unique) => unique, + Err(this) => panic!("`Arc` must be unique in order for this operation to be safe, there are currently {} copies", Arc::count(this)), + } +} + +#[cfg(test)] +mod tests { + use crate::arc::Arc; + use alloc::string::String; + use core::mem::MaybeUninit; + #[cfg(feature = "unsize")] + use unsize::{CoerceUnsize, Coercion}; + + #[test] + fn try_unwrap() { + let x = Arc::new(100usize); + let y = x.clone(); + + // The count should be two so `try_unwrap()` should fail + assert_eq!(Arc::count(&x), 2); + assert!(Arc::try_unwrap(x).is_err()); + + // Since `x` has now been dropped, the count should be 1 + // and `try_unwrap()` should succeed + assert_eq!(Arc::count(&y), 1); + assert_eq!(Arc::try_unwrap(y), Ok(100)); + } + + #[test] + #[cfg(feature = "unsize")] + fn coerce_to_slice() { + let x = Arc::new([0u8; 4]); + let y: Arc<[u8]> = x.clone().unsize(Coercion::to_slice()); + assert_eq!((*x).as_ptr(), (*y).as_ptr()); + } + + #[test] + #[cfg(feature = "unsize")] + fn coerce_to_dyn() { + let x: Arc<_> = Arc::new(|| 42u32); + let x: Arc<_> = x.unsize(Coercion::<_, dyn Fn() -> u32>::to_fn()); + assert_eq!((*x)(), 42); + } + + #[test] + #[allow(deprecated)] + fn maybeuninit() { + let mut arc: Arc<MaybeUninit<_>> = Arc::new_uninit(); + arc.write(999); + + let arc = unsafe { arc.assume_init() }; + assert_eq!(*arc, 999); + } + + #[test] + #[allow(deprecated)] + #[should_panic = "`Arc` must be unique in order for this operation to be safe"] + fn maybeuninit_ub_to_proceed() { + let mut uninit = Arc::new_uninit(); + let clone = uninit.clone(); + + let x: &MaybeUninit<String> = &*clone; + + // This write invalidates `x` reference + uninit.write(String::from("nonononono")); + + // Read invalidated reference to trigger UB + let _ = &*x; + } + + #[test] + #[allow(deprecated)] + #[should_panic = "`Arc` must be unique in order for this operation to be safe"] + fn maybeuninit_slice_ub_to_proceed() { + let mut uninit = Arc::new_uninit_slice(13); + let clone = uninit.clone(); + + let x: &[MaybeUninit<String>] = &*clone; + + // This write invalidates `x` reference + uninit.as_mut_slice()[0].write(String::from("nonononono")); + + // Read invalidated reference to trigger UB + let _ = &*x; + } + + #[test] + fn maybeuninit_array() { + let mut arc: Arc<[MaybeUninit<_>]> = Arc::new_uninit_slice(5); + assert!(arc.is_unique()); + #[allow(deprecated)] + for (uninit, index) in arc.as_mut_slice().iter_mut().zip(0..5) { + let ptr = uninit.as_mut_ptr(); + unsafe { core::ptr::write(ptr, index) }; + } + + let arc = unsafe { arc.assume_init() }; + assert!(arc.is_unique()); + // Using clone to that the layout generated in new_uninit_slice is compatible + // with ArcInner. + let arcs = [ + arc.clone(), + arc.clone(), + arc.clone(), + arc.clone(), + arc.clone(), + ]; + assert_eq!(6, Arc::count(&arc)); + // If the layout is not compatible, then the data might be corrupted. + assert_eq!(*arc, [0, 1, 2, 3, 4]); + + // Drop the arcs and check the count and the content to + // make sure it isn't corrupted. + drop(arcs); + assert!(arc.is_unique()); + assert_eq!(*arc, [0, 1, 2, 3, 4]); + } + + #[test] + fn roundtrip() { + let arc: Arc<usize> = Arc::new(0usize); + let ptr = Arc::into_raw(arc); + unsafe { + let _arc = Arc::from_raw(ptr); + } + } +} diff --git a/vendor/triomphe/src/arc_borrow.rs b/vendor/triomphe/src/arc_borrow.rs new file mode 100644 index 000000000..d53e1a5ea --- /dev/null +++ b/vendor/triomphe/src/arc_borrow.rs @@ -0,0 +1,116 @@ +use core::mem; +use core::mem::ManuallyDrop; +use core::ops::Deref; +use core::ptr; + +use super::Arc; + +/// A "borrowed `Arc`". This is a pointer to +/// a T that is known to have been allocated within an +/// `Arc`. +/// +/// This is equivalent in guarantees to `&Arc<T>`, however it is +/// a bit more flexible. To obtain an `&Arc<T>` you must have +/// an `Arc<T>` instance somewhere pinned down until we're done with it. +/// It's also a direct pointer to `T`, so using this involves less pointer-chasing +/// +/// However, C++ code may hand us refcounted things as pointers to T directly, +/// so we have to conjure up a temporary `Arc` on the stack each time. The +/// same happens for when the object is managed by a `OffsetArc`. +/// +/// `ArcBorrow` lets us deal with borrows of known-refcounted objects +/// without needing to worry about where the `Arc<T>` is. +#[derive(Debug, Eq, PartialEq)] +#[repr(transparent)] +pub struct ArcBorrow<'a, T: ?Sized + 'a>(pub(crate) &'a T); + +impl<'a, T> Copy for ArcBorrow<'a, T> {} +impl<'a, T> Clone for ArcBorrow<'a, T> { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> ArcBorrow<'a, T> { + /// Clone this as an `Arc<T>`. This bumps the refcount. + #[inline] + pub fn clone_arc(&self) -> Arc<T> { + let arc = unsafe { Arc::from_raw(self.0) }; + // addref it! + mem::forget(arc.clone()); + arc + } + + /// For constructing from a reference known to be Arc-backed, + /// e.g. if we obtain such a reference over FFI + /// TODO: should from_ref be relaxed to unsized types? It can't be + /// converted back to an Arc right now for unsized types. + #[inline] + pub unsafe fn from_ref(r: &'a T) -> Self { + ArcBorrow(r) + } + + /// Compare two `ArcBorrow`s via pointer equality. Will only return + /// true if they come from the same allocation + #[inline] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + ptr::eq(this.0 as *const T, other.0 as *const T) + } + + /// Temporarily converts |self| into a bonafide Arc and exposes it to the + /// provided callback. The refcount is not modified. + #[inline] + pub fn with_arc<F, U>(&self, f: F) -> U + where + F: FnOnce(&Arc<T>) -> U, + T: 'static, + { + // Synthesize transient Arc, which never touches the refcount. + let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.0)) }; + + // Expose the transient Arc to the callback, which may clone it if it wants + // and forward the result to the user + f(&transient) + } + + /// Similar to deref, but uses the lifetime |a| rather than the lifetime of + /// self, which is incompatible with the signature of the Deref trait. + #[inline] + pub fn get(&self) -> &'a T { + self.0 + } +} + +impl<'a, T> Deref for ArcBorrow<'a, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + self.0 + } +} + +// Safety: +// This implementation must guarantee that it is sound to call replace_ptr with an unsized variant +// of the pointer retuned in `as_sized_ptr`. We leverage unsizing the contained reference. This +// continues to point to the data of an ArcInner. The reference count remains untouched which is +// correct since the number of owners did not change. This implies the returned instance fulfills +// its safety invariants. +#[cfg(feature = "unsize")] +unsafe impl<'lt, T: 'lt, U: ?Sized + 'lt> unsize::CoerciblePtr<U> for ArcBorrow<'lt, T> { + type Pointee = T; + type Output = ArcBorrow<'lt, U>; + + fn as_sized_ptr(&mut self) -> *mut T { + // Returns a pointer to the inner data. We do not need to care about any particular + // provenance here, only the pointer value, which we need to reconstruct the new pointer. + self.0 as *const T as *mut T + } + + unsafe fn replace_ptr(self, new: *mut U) -> ArcBorrow<'lt, U> { + let inner = ManuallyDrop::new(self); + // Safety: backed by the same Arc that backed `self`. + ArcBorrow(inner.0.replace_ptr(new)) + } +} diff --git a/vendor/triomphe/src/arc_swap_support.rs b/vendor/triomphe/src/arc_swap_support.rs new file mode 100644 index 000000000..195854ed3 --- /dev/null +++ b/vendor/triomphe/src/arc_swap_support.rs @@ -0,0 +1,42 @@ +use arc_swap::RefCnt; + +use crate::{Arc, ThinArc}; +use core::ffi::c_void; + +unsafe impl<H, T> RefCnt for ThinArc<H, T> { + type Base = c_void; + + #[inline] + fn into_ptr(me: Self) -> *mut Self::Base { + ThinArc::into_raw(me) as *mut _ + } + + #[inline] + fn as_ptr(me: &Self) -> *mut Self::Base { + ThinArc::as_ptr(me) as *mut _ + } + + #[inline] + unsafe fn from_ptr(ptr: *const Self::Base) -> Self { + ThinArc::from_raw(ptr) + } +} + +unsafe impl<T> RefCnt for Arc<T> { + type Base = T; + + #[inline] + fn into_ptr(me: Self) -> *mut Self::Base { + Arc::into_raw(me) as *mut _ + } + + #[inline] + fn as_ptr(me: &Self) -> *mut Self::Base { + Arc::as_ptr(me) as *mut _ + } + + #[inline] + unsafe fn from_ptr(ptr: *const Self::Base) -> Self { + Arc::from_raw(ptr) + } +} diff --git a/vendor/triomphe/src/arc_union.rs b/vendor/triomphe/src/arc_union.rs new file mode 100644 index 000000000..6d5cddc8f --- /dev/null +++ b/vendor/triomphe/src/arc_union.rs @@ -0,0 +1,139 @@ +use core::fmt; +use core::marker::PhantomData; +use core::ptr; +use core::usize; + +use super::{Arc, ArcBorrow}; + +/// A tagged union that can represent `Arc<A>` or `Arc<B>` while only consuming a +/// single word. The type is also `NonNull`, and thus can be stored in an Option +/// without increasing size. +/// +/// This is functionally equivalent to +/// `enum ArcUnion<A, B> { First(Arc<A>), Second(Arc<B>)` but only takes up +/// up a single word of stack space. +/// +/// This could probably be extended to support four types if necessary. +pub struct ArcUnion<A, B> { + p: ptr::NonNull<()>, + phantom_a: PhantomData<A>, + phantom_b: PhantomData<B>, +} + +unsafe impl<A: Sync + Send, B: Send + Sync> Send for ArcUnion<A, B> {} +unsafe impl<A: Sync + Send, B: Send + Sync> Sync for ArcUnion<A, B> {} + +impl<A: PartialEq, B: PartialEq> PartialEq for ArcUnion<A, B> { + fn eq(&self, other: &Self) -> bool { + use crate::ArcUnionBorrow::*; + match (self.borrow(), other.borrow()) { + (First(x), First(y)) => x == y, + (Second(x), Second(y)) => x == y, + (_, _) => false, + } + } +} + +/// This represents a borrow of an `ArcUnion`. +#[derive(Debug)] +pub enum ArcUnionBorrow<'a, A: 'a, B: 'a> { + First(ArcBorrow<'a, A>), + Second(ArcBorrow<'a, B>), +} + +impl<A, B> ArcUnion<A, B> { + unsafe fn new(ptr: *mut ()) -> Self { + ArcUnion { + p: ptr::NonNull::new_unchecked(ptr), + phantom_a: PhantomData, + phantom_b: PhantomData, + } + } + + /// Returns true if the two values are pointer-equal. + #[inline] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.p == other.p + } + + /// Returns an enum representing a borrow of either A or B. + pub fn borrow(&self) -> ArcUnionBorrow<A, B> { + if self.is_first() { + let ptr = self.p.as_ptr() as *const A; + let borrow = unsafe { ArcBorrow::from_ref(&*ptr) }; + ArcUnionBorrow::First(borrow) + } else { + let ptr = ((self.p.as_ptr() as usize) & !0x1) as *const B; + let borrow = unsafe { ArcBorrow::from_ref(&*ptr) }; + ArcUnionBorrow::Second(borrow) + } + } + + /// Creates an `ArcUnion` from an instance of the first type. + #[inline] + pub fn from_first(other: Arc<A>) -> Self { + unsafe { Self::new(Arc::into_raw(other) as *mut _) } + } + + /// Creates an `ArcUnion` from an instance of the second type. + #[inline] + pub fn from_second(other: Arc<B>) -> Self { + unsafe { Self::new(((Arc::into_raw(other) as usize) | 0x1) as *mut _) } + } + + /// Returns true if this `ArcUnion` contains the first type. + #[inline] + pub fn is_first(&self) -> bool { + self.p.as_ptr() as usize & 0x1 == 0 + } + + /// Returns true if this `ArcUnion` contains the second type. + #[inline] + pub fn is_second(&self) -> bool { + !self.is_first() + } + + /// Returns a borrow of the first type if applicable, otherwise `None`. + pub fn as_first(&self) -> Option<ArcBorrow<A>> { + match self.borrow() { + ArcUnionBorrow::First(x) => Some(x), + ArcUnionBorrow::Second(_) => None, + } + } + + /// Returns a borrow of the second type if applicable, otherwise None. + pub fn as_second(&self) -> Option<ArcBorrow<B>> { + match self.borrow() { + ArcUnionBorrow::First(_) => None, + ArcUnionBorrow::Second(x) => Some(x), + } + } +} + +impl<A, B> Clone for ArcUnion<A, B> { + fn clone(&self) -> Self { + match self.borrow() { + ArcUnionBorrow::First(x) => ArcUnion::from_first(x.clone_arc()), + ArcUnionBorrow::Second(x) => ArcUnion::from_second(x.clone_arc()), + } + } +} + +impl<A, B> Drop for ArcUnion<A, B> { + fn drop(&mut self) { + match self.borrow() { + ArcUnionBorrow::First(x) => unsafe { + let _ = Arc::from_raw(&*x); + }, + ArcUnionBorrow::Second(x) => unsafe { + let _ = Arc::from_raw(&*x); + }, + } + } +} + +impl<A: fmt::Debug, B: fmt::Debug> fmt::Debug for ArcUnion<A, B> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.borrow(), f) + } +} diff --git a/vendor/triomphe/src/header.rs b/vendor/triomphe/src/header.rs new file mode 100644 index 000000000..e35ec48b0 --- /dev/null +++ b/vendor/triomphe/src/header.rs @@ -0,0 +1,378 @@ +use alloc::alloc::Layout; +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec::Vec; +use core::iter::{ExactSizeIterator, Iterator}; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop}; +use core::ptr::{self, addr_of_mut}; +use core::usize; + +use super::{Arc, ArcInner}; + +/// Structure to allow Arc-managing some fixed-sized data and a variably-sized +/// slice in a single allocation. +#[derive(Debug, Eq, PartialEq, Hash, PartialOrd)] +#[repr(C)] +pub struct HeaderSlice<H, T: ?Sized> { + /// The fixed-sized data. + pub header: H, + + /// The dynamically-sized data. + pub slice: T, +} + +impl<H, T> Arc<HeaderSlice<H, [T]>> { + /// Creates an Arc for a HeaderSlice using the given header struct and + /// iterator to generate the slice. The resulting Arc will be fat. + pub fn from_header_and_iter<I>(header: H, mut items: I) -> Self + where + I: Iterator<Item = T> + ExactSizeIterator, + { + assert_ne!(mem::size_of::<T>(), 0, "Need to think about ZST"); + + let num_items = items.len(); + + let inner = Arc::allocate_for_header_and_slice(num_items); + + unsafe { + // Write the data. + // + // Note that any panics here (i.e. from the iterator) are safe, since + // we'll just leak the uninitialized memory. + ptr::write(&mut ((*inner.as_ptr()).data.header), header); + if num_items != 0 { + let mut current = (*inner.as_ptr()).data.slice.as_mut_ptr(); + for _ in 0..num_items { + ptr::write( + current, + items + .next() + .expect("ExactSizeIterator over-reported length"), + ); + current = current.offset(1); + } + assert!( + items.next().is_none(), + "ExactSizeIterator under-reported length" + ); + } + assert!( + items.next().is_none(), + "ExactSizeIterator under-reported length" + ); + } + + // Safety: ptr is valid & the inner structure is fully initialized + Arc { + p: inner, + phantom: PhantomData, + } + } + + /// Creates an Arc for a HeaderSlice using the given header struct and + /// iterator to generate the slice. The resulting Arc will be fat. + pub fn from_header_and_slice(header: H, items: &[T]) -> Self + where + T: Copy, + { + assert_ne!(mem::size_of::<T>(), 0, "Need to think about ZST"); + + let num_items = items.len(); + + let inner = Arc::allocate_for_header_and_slice(num_items); + + unsafe { + // Write the data. + ptr::write(&mut ((*inner.as_ptr()).data.header), header); + let dst = (*inner.as_ptr()).data.slice.as_mut_ptr(); + ptr::copy_nonoverlapping(items.as_ptr(), dst, num_items); + } + + // Safety: ptr is valid & the inner structure is fully initialized + Arc { + p: inner, + phantom: PhantomData, + } + } + + /// Creates an Arc for a HeaderSlice using the given header struct and + /// vec to generate the slice. The resulting Arc will be fat. + pub fn from_header_and_vec(header: H, mut v: Vec<T>) -> Self { + let len = v.len(); + + let inner = Arc::allocate_for_header_and_slice(len); + + unsafe { + // Safety: inner is a valid pointer, so this can't go out of bounds + let dst = addr_of_mut!((*inner.as_ptr()).data.header); + + // Safety: `dst` is valid for writes (just allocated) + ptr::write(dst, header); + } + + unsafe { + let src = v.as_mut_ptr(); + + // Safety: inner is a valid pointer, so this can't go out of bounds + let dst = addr_of_mut!((*inner.as_ptr()).data.slice) as *mut T; + + // Safety: + // - `src` is valid for reads for `len` (got from `Vec`) + // - `dst` is valid for writes for `len` (just allocated, with layout for appropriate slice) + // - `src` and `dst` don't overlap (separate allocations) + ptr::copy_nonoverlapping(src, dst, len); + + // Deallocate vec without dropping `T` + // + // Safety: 0..0 elements are always initialized, 0 <= cap for any cap + v.set_len(0); + } + + // Safety: ptr is valid & the inner structure is fully initialized + Arc { + p: inner, + phantom: PhantomData, + } + } +} + +impl<H> Arc<HeaderSlice<H, str>> { + /// Creates an Arc for a HeaderSlice using the given header struct and + /// a str slice to generate the slice. The resulting Arc will be fat. + pub fn from_header_and_str(header: H, string: &str) -> Self { + let bytes = Arc::from_header_and_slice(header, string.as_bytes()); + + // Safety: `ArcInner` and `HeaderSlice` are `repr(C)`, `str` has the same layout as `[u8]`, + // thus it's ok to "transmute" between `Arc<HeaderSlice<H, [u8]>>` and `Arc<HeaderSlice<H, str>>`. + // + // `bytes` are a valid string since we've just got them from a valid `str`. + unsafe { Arc::from_raw_inner(Arc::into_raw_inner(bytes) as _) } + } +} + +/// Header data with an inline length. Consumers that use HeaderWithLength as the +/// Header type in HeaderSlice can take advantage of ThinArc. +#[derive(Debug, Eq, PartialEq, Hash, PartialOrd)] +#[repr(C)] +pub struct HeaderWithLength<H> { + /// The fixed-sized data. + pub header: H, + + /// The slice length. + pub length: usize, +} + +impl<H> HeaderWithLength<H> { + /// Creates a new HeaderWithLength. + #[inline] + pub fn new(header: H, length: usize) -> Self { + HeaderWithLength { header, length } + } +} + +impl<T: ?Sized> From<Arc<HeaderSlice<(), T>>> for Arc<T> { + fn from(this: Arc<HeaderSlice<(), T>>) -> Self { + debug_assert_eq!( + Layout::for_value::<HeaderSlice<(), T>>(&this), + Layout::for_value::<T>(&this.slice) + ); + + // Safety: `HeaderSlice<(), T>` and `T` has the same layout + unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) } + } +} + +impl<T: ?Sized> From<Arc<T>> for Arc<HeaderSlice<(), T>> { + fn from(this: Arc<T>) -> Self { + // Safety: `T` and `HeaderSlice<(), T>` has the same layout + unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) } + } +} + +impl<T: Copy> From<&[T]> for Arc<[T]> { + fn from(slice: &[T]) -> Self { + Arc::from_header_and_slice((), slice).into() + } +} + +impl From<&str> for Arc<str> { + fn from(s: &str) -> Self { + Arc::from_header_and_str((), s).into() + } +} + +impl From<String> for Arc<str> { + fn from(s: String) -> Self { + Self::from(&s[..]) + } +} + +// FIXME: once `pointer::with_metadata_of` is stable or +// implementable on stable without assuming ptr layout +// this will be able to accept `T: ?Sized`. +impl<T> From<Box<T>> for Arc<T> { + fn from(b: Box<T>) -> Self { + let layout = Layout::for_value::<T>(&b); + + // Safety: the closure only changes the type of the pointer + let inner = unsafe { Self::allocate_for_layout(layout, |mem| mem as *mut ArcInner<T>) }; + + unsafe { + let src = Box::into_raw(b); + + // Safety: inner is a valid pointer, so this can't go out of bounds + let dst = addr_of_mut!((*inner.as_ptr()).data); + + // Safety: + // - `src` is valid for reads (got from `Box`) + // - `dst` is valid for writes (just allocated) + // - `src` and `dst` don't overlap (separate allocations) + ptr::copy_nonoverlapping(src, dst, 1); + + // Deallocate box without dropping `T` + // + // Safety: + // - `src` has been got from `Box::into_raw` + // - `ManuallyDrop<T>` is guaranteed to have the same layout as `T` + Box::<ManuallyDrop<T>>::from_raw(src as _); + } + + Arc { + p: inner, + phantom: PhantomData, + } + } +} + +impl<T> From<Vec<T>> for Arc<[T]> { + fn from(v: Vec<T>) -> Self { + Arc::from_header_and_vec((), v).into() + } +} + +pub(crate) type HeaderSliceWithLength<H, T> = HeaderSlice<HeaderWithLength<H>, T>; + +#[cfg(test)] +mod tests { + use alloc::boxed::Box; + use alloc::string::String; + use alloc::vec; + use core::iter; + + use crate::{Arc, HeaderSlice}; + + #[test] + fn from_header_and_iter_smoke() { + let arc = Arc::from_header_and_iter( + (42u32, 17u8), + IntoIterator::into_iter([1u16, 2, 3, 4, 5, 6, 7]), + ); + + assert_eq!(arc.header, (42, 17)); + assert_eq!(arc.slice, [1, 2, 3, 4, 5, 6, 7]); + } + + #[test] + fn from_header_and_slice_smoke() { + let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16, 2, 3, 4, 5, 6, 7]); + + assert_eq!(arc.header, (42, 17)); + assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]); + } + + #[test] + fn from_header_and_vec_smoke() { + let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16, 2, 3, 4, 5, 6, 7]); + + assert_eq!(arc.header, (42, 17)); + assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]); + } + + #[test] + fn from_header_and_iter_empty() { + let arc = Arc::from_header_and_iter((42u32, 17u8), iter::empty::<u16>()); + + assert_eq!(arc.header, (42, 17)); + assert_eq!(arc.slice, []); + } + + #[test] + fn from_header_and_slice_empty() { + let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16; 0]); + + assert_eq!(arc.header, (42, 17)); + assert_eq!(arc.slice, []); + } + + #[test] + fn from_header_and_vec_empty() { + let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16; 0]); + + assert_eq!(arc.header, (42, 17)); + assert_eq!(arc.slice, []); + } + + #[test] + fn issue_13_empty() { + crate::Arc::from_header_and_iter((), iter::empty::<usize>()); + } + + #[test] + fn issue_13_consumption() { + let s: &[u8] = &[0u8; 255]; + crate::Arc::from_header_and_iter((), s.iter().copied()); + } + + #[test] + fn from_header_and_str_smoke() { + let a = Arc::from_header_and_str( + 42, + "The answer to the ultimate question of life, the universe, and everything", + ); + assert_eq!(a.header, 42); + assert_eq!( + &a.slice, + "The answer to the ultimate question of life, the universe, and everything" + ); + + let empty = Arc::from_header_and_str((), ""); + assert_eq!(empty.header, ()); + assert_eq!(&empty.slice, ""); + } + + #[test] + fn erase_and_create_from_thin_air_header() { + let a: Arc<HeaderSlice<(), [u32]>> = Arc::from_header_and_slice((), &[12, 17, 16]); + let b: Arc<[u32]> = a.into(); + + assert_eq!(&*b, [12, 17, 16]); + + let c: Arc<HeaderSlice<(), [u32]>> = b.into(); + + assert_eq!(&c.slice, [12, 17, 16]); + assert_eq!(c.header, ()); + } + + #[test] + fn from_box_and_vec() { + let b = Box::new(String::from("xxx")); + let b = Arc::<String>::from(b); + assert_eq!(&*b, "xxx"); + + let v = vec![String::from("1"), String::from("2"), String::from("3")]; + let v = Arc::<[_]>::from(v); + assert_eq!( + &*v, + [String::from("1"), String::from("2"), String::from("3")] + ); + + let mut v = vec![String::from("1"), String::from("2"), String::from("3")]; + v.reserve(10); + let v = Arc::<[_]>::from(v); + assert_eq!( + &*v, + [String::from("1"), String::from("2"), String::from("3")] + ); + } +} diff --git a/vendor/triomphe/src/lib.rs b/vendor/triomphe/src/lib.rs new file mode 100644 index 000000000..13d568bda --- /dev/null +++ b/vendor/triomphe/src/lib.rs @@ -0,0 +1,94 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Fork of Arc. This has the following advantages over std::sync::Arc: +//! +//! * `triomphe::Arc` doesn't support weak references: we save space by excluding the weak reference count, and we don't do extra read-modify-update operations to handle the possibility of weak references. +//! * `triomphe::UniqueArc` allows one to construct a temporarily-mutable `Arc` which can be converted to a regular `triomphe::Arc` later +//! * `triomphe::OffsetArc` can be used transparently from C++ code and is compatible with (and can be converted to/from) `triomphe::Arc` +//! * `triomphe::ArcBorrow` is functionally similar to `&triomphe::Arc<T>`, however in memory it's simply `&T`. This makes it more flexible for FFI; the source of the borrow need not be an `Arc` pinned on the stack (and can instead be a pointer from C++, or an `OffsetArc`). Additionally, this helps avoid pointer-chasing. +//! * `triomphe::Arc` has can be constructed for dynamically-sized types via `from_header_and_iter` +//! * `triomphe::ThinArc` provides thin-pointer `Arc`s to dynamically sized types +//! * `triomphe::ArcUnion` is union of two `triomphe:Arc`s which fits inside one word of memory + +#![allow(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +#[cfg(feature = "std")] +extern crate core; + +#[cfg(feature = "arc-swap")] +extern crate arc_swap; +#[cfg(feature = "serde")] +extern crate serde; +#[cfg(feature = "stable_deref_trait")] +extern crate stable_deref_trait; +#[cfg(feature = "unsize")] +extern crate unsize; + +/// Calculates the offset of the specified field from the start of the named struct. +/// This macro is impossible to be const until feature(const_ptr_offset_from) is stable. +macro_rules! offset_of { + ($ty: path, $field: tt) => {{ + // ensure the type is a named struct + // ensure the field exists and is accessible + let $ty { $field: _, .. }; + + let uninit = <::core::mem::MaybeUninit<$ty>>::uninit(); // const since 1.36 + + let base_ptr: *const $ty = uninit.as_ptr(); // const since 1.59 + + #[allow(unused_unsafe)] + let field_ptr = unsafe { ::core::ptr::addr_of!((*base_ptr).$field) }; // since 1.51 + + // // the const version requires feature(const_ptr_offset_from) + // // https://github.com/rust-lang/rust/issues/92980 + // #[allow(unused_unsafe)] + // unsafe { (field_ptr as *const u8).offset_from(base_ptr as *const u8) as usize } + + (field_ptr as usize) - (base_ptr as usize) + }}; +} + +mod arc; +mod arc_borrow; +#[cfg(feature = "arc-swap")] +mod arc_swap_support; +mod arc_union; +mod header; +mod offset_arc; +mod thin_arc; +mod unique_arc; + +pub use arc::*; +pub use arc_borrow::*; +pub use arc_union::*; +pub use header::*; +pub use offset_arc::*; +pub use thin_arc::*; +pub use unique_arc::*; + +#[cfg(feature = "std")] +use std::process::abort; + +// `no_std`-compatible abort by forcing a panic while already panicing. +#[cfg(not(feature = "std"))] +#[cold] +fn abort() -> ! { + struct PanicOnDrop; + impl Drop for PanicOnDrop { + fn drop(&mut self) { + panic!() + } + } + let _double_panicer = PanicOnDrop; + panic!(); +} diff --git a/vendor/triomphe/src/offset_arc.rs b/vendor/triomphe/src/offset_arc.rs new file mode 100644 index 000000000..9345416d4 --- /dev/null +++ b/vendor/triomphe/src/offset_arc.rs @@ -0,0 +1,134 @@ +use core::fmt; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use core::ops::Deref; +use core::ptr; + +use super::{Arc, ArcBorrow}; + +/// An `Arc`, except it holds a pointer to the T instead of to the +/// entire ArcInner. +/// +/// An `OffsetArc<T>` has the same layout and ABI as a non-null +/// `const T*` in C, and may be used in FFI function signatures. +/// +/// ```text +/// Arc<T> OffsetArc<T> +/// | | +/// v v +/// --------------------- +/// | RefCount | T (data) | [ArcInner<T>] +/// --------------------- +/// ``` +/// +/// This means that this is a direct pointer to +/// its contained data (and can be read from by both C++ and Rust), +/// but we can also convert it to a "regular" `Arc<T>` by removing the offset. +/// +/// This is very useful if you have an Arc-containing struct shared between Rust and C++, +/// and wish for C++ to be able to read the data behind the `Arc` without incurring +/// an FFI call overhead. +#[derive(Eq)] +#[repr(transparent)] +pub struct OffsetArc<T> { + pub(crate) ptr: ptr::NonNull<T>, + pub(crate) phantom: PhantomData<T>, +} + +unsafe impl<T: Sync + Send> Send for OffsetArc<T> {} +unsafe impl<T: Sync + Send> Sync for OffsetArc<T> {} + +impl<T> Deref for OffsetArc<T> { + type Target = T; + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { &*self.ptr.as_ptr() } + } +} + +impl<T> Clone for OffsetArc<T> { + #[inline] + fn clone(&self) -> Self { + Arc::into_raw_offset(self.clone_arc()) + } +} + +impl<T> Drop for OffsetArc<T> { + fn drop(&mut self) { + let _ = Arc::from_raw_offset(OffsetArc { + ptr: self.ptr, + phantom: PhantomData, + }); + } +} + +impl<T: fmt::Debug> fmt::Debug for OffsetArc<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<T: PartialEq> PartialEq for OffsetArc<T> { + fn eq(&self, other: &OffsetArc<T>) -> bool { + *(*self) == *(*other) + } + + #[allow(clippy::partialeq_ne_impl)] + fn ne(&self, other: &OffsetArc<T>) -> bool { + *(*self) != *(*other) + } +} + +impl<T> OffsetArc<T> { + /// Temporarily converts |self| into a bonafide Arc and exposes it to the + /// provided callback. The refcount is not modified. + #[inline] + pub fn with_arc<F, U>(&self, f: F) -> U + where + F: FnOnce(&Arc<T>) -> U, + { + // Synthesize transient Arc, which never touches the refcount of the ArcInner. + let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.ptr.as_ptr())) }; + + // Expose the transient Arc to the callback, which may clone it if it wants + // and forward the result to the user + f(&transient) + } + + /// If uniquely owned, provide a mutable reference + /// Else create a copy, and mutate that + /// + /// This is functionally the same thing as `Arc::make_mut` + #[inline] + pub fn make_mut(&mut self) -> &mut T + where + T: Clone, + { + unsafe { + // extract the OffsetArc as an owned variable + let this = ptr::read(self); + // treat it as a real Arc + let mut arc = Arc::from_raw_offset(this); + // obtain the mutable reference. Cast away the lifetime + // This may mutate `arc` + let ret = Arc::make_mut(&mut arc) as *mut _; + // Store the possibly-mutated arc back inside, after converting + // it to a OffsetArc again + ptr::write(self, Arc::into_raw_offset(arc)); + &mut *ret + } + } + + /// Clone it as an `Arc` + #[inline] + pub fn clone_arc(&self) -> Arc<T> { + OffsetArc::with_arc(self, |a| a.clone()) + } + + /// Produce a pointer to the data that can be converted back + /// to an `Arc` + #[inline] + pub fn borrow_arc(&self) -> ArcBorrow<'_, T> { + ArcBorrow(&**self) + } +} diff --git a/vendor/triomphe/src/thin_arc.rs b/vendor/triomphe/src/thin_arc.rs new file mode 100644 index 000000000..e048468ad --- /dev/null +++ b/vendor/triomphe/src/thin_arc.rs @@ -0,0 +1,329 @@ +use core::ffi::c_void; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::iter::{ExactSizeIterator, Iterator}; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use core::ops::Deref; +use core::ptr; +use core::usize; + +use super::{Arc, ArcInner, HeaderSliceWithLength, HeaderWithLength}; + +/// A "thin" `Arc` containing dynamically sized data +/// +/// This is functionally equivalent to `Arc<(H, [T])>` +/// +/// When you create an `Arc` containing a dynamically sized type +/// like `HeaderSlice<H, [T]>`, the `Arc` is represented on the stack +/// as a "fat pointer", where the length of the slice is stored +/// alongside the `Arc`'s pointer. In some situations you may wish to +/// have a thin pointer instead, perhaps for FFI compatibility +/// or space efficiency. +/// +/// Note that we use `[T; 0]` in order to have the right alignment for `T`. +/// +/// `ThinArc` solves this by storing the length in the allocation itself, +/// via `HeaderSliceWithLength`. +#[repr(transparent)] +pub struct ThinArc<H, T> { + ptr: ptr::NonNull<ArcInner<HeaderSliceWithLength<H, [T; 0]>>>, + phantom: PhantomData<(H, T)>, +} + +unsafe impl<H: Sync + Send, T: Sync + Send> Send for ThinArc<H, T> {} +unsafe impl<H: Sync + Send, T: Sync + Send> Sync for ThinArc<H, T> {} + +// Synthesize a fat pointer from a thin pointer. +// +// See the comment around the analogous operation in from_header_and_iter. +fn thin_to_thick<H, T>( + thin: *mut ArcInner<HeaderSliceWithLength<H, [T; 0]>>, +) -> *mut ArcInner<HeaderSliceWithLength<H, [T]>> { + let len = unsafe { (*thin).data.header.length }; + let fake_slice = ptr::slice_from_raw_parts_mut(thin as *mut T, len); + + fake_slice as *mut ArcInner<HeaderSliceWithLength<H, [T]>> +} + +impl<H, T> ThinArc<H, T> { + /// Temporarily converts |self| into a bonafide Arc and exposes it to the + /// provided callback. The refcount is not modified. + #[inline] + pub fn with_arc<F, U>(&self, f: F) -> U + where + F: FnOnce(&Arc<HeaderSliceWithLength<H, [T]>>) -> U, + { + // Synthesize transient Arc, which never touches the refcount of the ArcInner. + let transient = unsafe { + ManuallyDrop::new(Arc { + p: ptr::NonNull::new_unchecked(thin_to_thick(self.ptr.as_ptr())), + phantom: PhantomData, + }) + }; + + // Expose the transient Arc to the callback, which may clone it if it wants + // and forward the result to the user + f(&transient) + } + + /// Creates a `ThinArc` for a HeaderSlice using the given header struct and + /// iterator to generate the slice. + pub fn from_header_and_iter<I>(header: H, items: I) -> Self + where + I: Iterator<Item = T> + ExactSizeIterator, + { + let header = HeaderWithLength::new(header, items.len()); + Arc::into_thin(Arc::from_header_and_iter(header, items)) + } + + /// Creates a `ThinArc` for a HeaderSlice using the given header struct and + /// a slice to copy. + pub fn from_header_and_slice(header: H, items: &[T]) -> Self + where + T: Copy, + { + let header = HeaderWithLength::new(header, items.len()); + Arc::into_thin(Arc::from_header_and_slice(header, items)) + } + + /// Returns the address on the heap of the ThinArc itself -- not the T + /// within it -- for memory reporting. + #[inline] + pub fn ptr(&self) -> *const c_void { + self.ptr.as_ptr() as *const ArcInner<T> as *const c_void + } + + /// Returns the address on the heap of the Arc itself -- not the T within it -- for memory + /// reporting. + #[inline] + pub fn heap_ptr(&self) -> *const c_void { + self.ptr() + } + + /// # Safety + /// + /// Constructs an ThinArc from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to + /// ThinArc::into_raw. + /// + /// The user of from_raw has to make sure a specific value of T is only dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned ThinArc is never accessed. + #[inline] + pub unsafe fn from_raw(ptr: *const c_void) -> Self { + Self { + ptr: ptr::NonNull::new_unchecked(ptr as *mut c_void).cast(), + phantom: PhantomData, + } + } + + /// Consume ThinArc and returned the wrapped pointer. + #[inline] + pub fn into_raw(self) -> *const c_void { + let this = ManuallyDrop::new(self); + this.ptr.cast().as_ptr() + } + + /// Provides a raw pointer to the data. + /// The counts are not affected in any way and the ThinArc is not consumed. + /// The pointer is valid for as long as there are strong counts in the ThinArc. + #[inline] + pub fn as_ptr(&self) -> *const c_void { + self.ptr() + } +} + +impl<H, T> Deref for ThinArc<H, T> { + type Target = HeaderSliceWithLength<H, [T]>; + + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { &(*thin_to_thick(self.ptr.as_ptr())).data } + } +} + +impl<H, T> Clone for ThinArc<H, T> { + #[inline] + fn clone(&self) -> Self { + ThinArc::with_arc(self, |a| Arc::into_thin(a.clone())) + } +} + +impl<H, T> Drop for ThinArc<H, T> { + #[inline] + fn drop(&mut self) { + let _ = Arc::from_thin(ThinArc { + ptr: self.ptr, + phantom: PhantomData, + }); + } +} + +impl<H, T> Arc<HeaderSliceWithLength<H, [T]>> { + /// Converts an `Arc` into a `ThinArc`. This consumes the `Arc`, so the refcount + /// is not modified. + #[inline] + pub fn into_thin(a: Self) -> ThinArc<H, T> { + let a = ManuallyDrop::new(a); + assert_eq!( + a.header.length, + a.slice.len(), + "Length needs to be correct for ThinArc to work" + ); + let fat_ptr: *mut ArcInner<HeaderSliceWithLength<H, [T]>> = a.ptr(); + let thin_ptr = fat_ptr as *mut [usize] as *mut usize; + ThinArc { + ptr: unsafe { + ptr::NonNull::new_unchecked( + thin_ptr as *mut ArcInner<HeaderSliceWithLength<H, [T; 0]>>, + ) + }, + phantom: PhantomData, + } + } + + /// Converts a `ThinArc` into an `Arc`. This consumes the `ThinArc`, so the refcount + /// is not modified. + #[inline] + pub fn from_thin(a: ThinArc<H, T>) -> Self { + let a = ManuallyDrop::new(a); + let ptr = thin_to_thick(a.ptr.as_ptr()); + unsafe { + Arc { + p: ptr::NonNull::new_unchecked(ptr), + phantom: PhantomData, + } + } + } +} + +impl<H: PartialEq, T: PartialEq> PartialEq for ThinArc<H, T> { + #[inline] + fn eq(&self, other: &ThinArc<H, T>) -> bool { + ThinArc::with_arc(self, |a| ThinArc::with_arc(other, |b| *a == *b)) + } +} + +impl<H: Eq, T: Eq> Eq for ThinArc<H, T> {} + +impl<H: Hash, T: Hash> Hash for ThinArc<H, T> { + fn hash<HSR: Hasher>(&self, state: &mut HSR) { + ThinArc::with_arc(self, |a| a.hash(state)) + } +} + +impl<H: fmt::Debug, T: fmt::Debug> fmt::Debug for ThinArc<H, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<H, T> fmt::Pointer for ThinArc<H, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&self.ptr(), f) + } +} + +#[cfg(test)] +mod tests { + use crate::{Arc, HeaderWithLength, ThinArc}; + use alloc::vec; + use core::clone::Clone; + use core::ops::Drop; + use core::sync::atomic; + use core::sync::atomic::Ordering::{Acquire, SeqCst}; + + #[derive(PartialEq)] + struct Canary(*mut atomic::AtomicUsize); + + impl Drop for Canary { + fn drop(&mut self) { + unsafe { + (*self.0).fetch_add(1, SeqCst); + } + } + } + + #[test] + fn empty_thin() { + let header = HeaderWithLength::new(100u32, 0); + let x = Arc::from_header_and_iter(header, core::iter::empty::<i32>()); + let y = Arc::into_thin(x.clone()); + assert_eq!(y.header.header, 100); + assert!(y.slice.is_empty()); + assert_eq!(x.header.header, 100); + assert!(x.slice.is_empty()); + } + + #[test] + fn thin_assert_padding() { + #[derive(Clone, Default)] + #[repr(C)] + struct Padded { + i: u16, + } + + // The header will have more alignment than `Padded` + let header = HeaderWithLength::new(0i32, 2); + let items = vec![Padded { i: 0xdead }, Padded { i: 0xbeef }]; + let a = ThinArc::from_header_and_iter(header, items.into_iter()); + assert_eq!(a.slice.len(), 2); + assert_eq!(a.slice[0].i, 0xdead); + assert_eq!(a.slice[1].i, 0xbeef); + } + + #[test] + #[allow(clippy::redundant_clone, clippy::eq_op)] + fn slices_and_thin() { + let mut canary = atomic::AtomicUsize::new(0); + let c = Canary(&mut canary as *mut atomic::AtomicUsize); + let v = vec![5, 6]; + let header = HeaderWithLength::new(c, v.len()); + { + let x = Arc::into_thin(Arc::from_header_and_slice(header, &v)); + let y = ThinArc::with_arc(&x, |q| q.clone()); + let _ = y.clone(); + let _ = x == x; + Arc::from_thin(x.clone()); + } + assert_eq!(canary.load(Acquire), 1); + } + + #[test] + #[allow(clippy::redundant_clone, clippy::eq_op)] + fn iter_and_thin() { + let mut canary = atomic::AtomicUsize::new(0); + let c = Canary(&mut canary as *mut atomic::AtomicUsize); + let v = vec![5, 6]; + let header = HeaderWithLength::new(c, v.len()); + { + let x = Arc::into_thin(Arc::from_header_and_iter(header, v.into_iter())); + let y = ThinArc::with_arc(&x, |q| q.clone()); + let _ = y.clone(); + let _ = x == x; + Arc::from_thin(x.clone()); + } + assert_eq!(canary.load(Acquire), 1); + } + + #[test] + fn into_raw_and_from_raw() { + let mut canary = atomic::AtomicUsize::new(0); + let c = Canary(&mut canary as *mut atomic::AtomicUsize); + let v = vec![5, 6]; + let header = HeaderWithLength::new(c, v.len()); + { + type ThinArcCanary = ThinArc<Canary, u32>; + let x: ThinArcCanary = Arc::into_thin(Arc::from_header_and_iter(header, v.into_iter())); + let ptr = x.as_ptr(); + + assert_eq!(x.into_raw(), ptr); + + let _x = unsafe { ThinArcCanary::from_raw(ptr) }; + } + assert_eq!(canary.load(Acquire), 1); + } +} diff --git a/vendor/triomphe/src/unique_arc.rs b/vendor/triomphe/src/unique_arc.rs new file mode 100644 index 000000000..79555fc27 --- /dev/null +++ b/vendor/triomphe/src/unique_arc.rs @@ -0,0 +1,257 @@ +use alloc::{alloc::Layout, boxed::Box}; +use core::convert::TryFrom; +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, MaybeUninit}; +use core::ops::{Deref, DerefMut}; +use core::ptr::{self, NonNull}; +use core::sync::atomic::AtomicUsize; + +use crate::HeaderSlice; + +use super::{Arc, ArcInner}; + +/// An `Arc` that is known to be uniquely owned +/// +/// When `Arc`s are constructed, they are known to be +/// uniquely owned. In such a case it is safe to mutate +/// the contents of the `Arc`. Normally, one would just handle +/// this by mutating the data on the stack before allocating the +/// `Arc`, however it's possible the data is large or unsized +/// and you need to heap-allocate it earlier in such a way +/// that it can be freely converted into a regular `Arc` once you're +/// done. +/// +/// `UniqueArc` exists for this purpose, when constructed it performs +/// the same allocations necessary for an `Arc`, however it allows mutable access. +/// Once the mutation is finished, you can call `.shareable()` and get a regular `Arc` +/// out of it. +/// +/// ```rust +/// # use triomphe::UniqueArc; +/// let data = [1, 2, 3, 4, 5]; +/// let mut x = UniqueArc::new(data); +/// x[4] = 7; // mutate! +/// let y = x.shareable(); // y is an Arc<T> +/// ``` +#[repr(transparent)] +pub struct UniqueArc<T: ?Sized>(Arc<T>); + +impl<T> UniqueArc<T> { + #[inline] + /// Construct a new UniqueArc + pub fn new(data: T) -> Self { + UniqueArc(Arc::new(data)) + } + + /// Construct an uninitialized arc + #[inline] + pub fn new_uninit() -> UniqueArc<MaybeUninit<T>> { + unsafe { + let layout = Layout::new::<ArcInner<MaybeUninit<T>>>(); + let ptr = alloc::alloc::alloc(layout); + let mut p = NonNull::new(ptr) + .unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout)) + .cast::<ArcInner<MaybeUninit<T>>>(); + ptr::write(&mut p.as_mut().count, AtomicUsize::new(1)); + + UniqueArc(Arc { + p, + phantom: PhantomData, + }) + } + } + + /// Gets the inner value of the unique arc + pub fn into_inner(this: Self) -> T { + // Wrap the Arc in a `ManuallyDrop` so that its drop routine never runs + let this = ManuallyDrop::new(this.0); + debug_assert!( + this.is_unique(), + "attempted to call `.into_inner()` on a `UniqueArc` with a non-zero ref count", + ); + + // Safety: We have exclusive access to the inner data and the + // arc will not perform its drop routine since we've + // wrapped it in a `ManuallyDrop` + unsafe { Box::from_raw(this.ptr()).data } + } +} + +impl<T: ?Sized> UniqueArc<T> { + /// Convert to a shareable Arc<T> once we're done mutating it + #[inline] + pub fn shareable(self) -> Arc<T> { + self.0 + } + + /// Creates a new [`UniqueArc`] from the given [`Arc`]. + /// + /// An unchecked alternative to `Arc::try_unique()` + /// + /// # Safety + /// + /// The given `Arc` must have a reference count of exactly one + /// + pub(crate) unsafe fn from_arc(arc: Arc<T>) -> Self { + debug_assert_eq!(Arc::count(&arc), 1); + Self(arc) + } + + /// Creates a new `&mut `[`UniqueArc`] from the given `&mut `[`Arc`]. + /// + /// An unchecked alternative to `Arc::try_as_unique()` + /// + /// # Safety + /// + /// The given `Arc` must have a reference count of exactly one + pub(crate) unsafe fn from_arc_ref(arc: &mut Arc<T>) -> &mut Self { + debug_assert_eq!(Arc::count(&arc), 1); + + // Safety: caller guarantees that `arc` is unique, + // `UniqueArc` is `repr(transparent)` + &mut *(arc as *mut Arc<T> as *mut UniqueArc<T>) + } +} + +impl<T> UniqueArc<MaybeUninit<T>> { + /// Calls `MaybeUninit::write` on the contained value. + pub fn write(&mut self, val: T) -> &mut T { + unsafe { + // Casting *mut MaybeUninit<T> -> *mut T is always fine + let ptr = self.as_mut_ptr() as *mut T; + + // Safety: We have exclusive access to the inner data + ptr.write(val); + + // Safety: the pointer was just written to + &mut *ptr + } + } + + /// Obtain a mutable pointer to the stored `MaybeUninit<T>`. + pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> { + unsafe { &mut (*self.0.ptr()).data } + } + + /// Convert to an initialized Arc. + /// + /// # Safety + /// + /// This function is equivalent to `MaybeUninit::assume_init` and has the + /// same safety requirements. You are responsible for ensuring that the `T` + /// has actually been initialized before calling this method. + #[inline] + pub unsafe fn assume_init(this: Self) -> UniqueArc<T> { + UniqueArc(Arc { + p: ManuallyDrop::new(this).0.p.cast(), + phantom: PhantomData, + }) + } +} + +impl<T> UniqueArc<[MaybeUninit<T>]> { + /// Create an Arc contains an array `[MaybeUninit<T>]` of `len`. + pub fn new_uninit_slice(len: usize) -> Self { + let ptr: NonNull<ArcInner<HeaderSlice<(), [MaybeUninit<T>]>>> = + Arc::allocate_for_header_and_slice(len); + + // Safety: + // - `ArcInner` is properly allocated and initialized. + // - `()` and `[MaybeUninit<T>]` do not require special initialization + // - The `Arc` is just created and so -- unique. + unsafe { + let arc: Arc<HeaderSlice<(), [MaybeUninit<T>]>> = Arc::from_raw_inner(ptr.as_ptr()); + let arc: Arc<[MaybeUninit<T>]> = arc.into(); + UniqueArc(arc) + } + } + + /// # Safety + /// + /// Must initialize all fields before calling this function. + #[inline] + pub unsafe fn assume_init_slice(Self(this): Self) -> UniqueArc<[T]> { + UniqueArc(this.assume_init()) + } +} + +impl<T: ?Sized> TryFrom<Arc<T>> for UniqueArc<T> { + type Error = Arc<T>; + + fn try_from(arc: Arc<T>) -> Result<Self, Self::Error> { + Arc::try_unique(arc) + } +} + +impl<T: ?Sized> Deref for UniqueArc<T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &*self.0 + } +} + +impl<T: ?Sized> DerefMut for UniqueArc<T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + // We know this to be uniquely owned + unsafe { &mut (*self.0.ptr()).data } + } +} + +// Safety: +// This leverages the correctness of Arc's CoerciblePtr impl. Additionally, we must ensure that +// this can not be used to violate the safety invariants of UniqueArc, which require that we can not +// duplicate the Arc, such that replace_ptr returns a valid instance. This holds since it consumes +// a unique owner of the contained ArcInner. +#[cfg(feature = "unsize")] +unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for UniqueArc<T> { + type Pointee = T; + type Output = UniqueArc<U>; + + fn as_sized_ptr(&mut self) -> *mut T { + // Dispatch to the contained field. + unsize::CoerciblePtr::<U>::as_sized_ptr(&mut self.0) + } + + unsafe fn replace_ptr(self, new: *mut U) -> UniqueArc<U> { + // Dispatch to the contained field, work around conflict of destructuring and Drop. + let inner = ManuallyDrop::new(self); + UniqueArc(ptr::read(&inner.0).replace_ptr(new)) + } +} + +#[cfg(test)] +mod tests { + use crate::{Arc, UniqueArc}; + use core::{convert::TryFrom, mem::MaybeUninit}; + + #[test] + fn unique_into_inner() { + let unique = UniqueArc::new(10u64); + assert_eq!(UniqueArc::into_inner(unique), 10); + } + + #[test] + fn try_from_arc() { + let x = Arc::new(10_000); + let y = x.clone(); + + assert!(UniqueArc::try_from(x).is_err()); + assert_eq!( + UniqueArc::into_inner(UniqueArc::try_from(y).unwrap()), + 10_000, + ); + } + + #[test] + #[allow(deprecated)] + fn maybeuninit_smoke() { + let mut arc: UniqueArc<MaybeUninit<_>> = UniqueArc::new_uninit(); + arc.write(999); + + let arc = unsafe { UniqueArc::assume_init(arc) }; + assert_eq!(*arc, 999); + } +} |