@@ -832,6 +832,93 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
832
832
ptr:: read ( src as * const T as * const U )
833
833
}
834
834
835
+ /// Copies a value while making no assumptions about the result.
836
+ ///
837
+ /// This essentially tells the compiler that the value may have changed since it
838
+ /// was last read, and that it should not make any assumptions or or perform
839
+ /// optimisations on the returned value based upon previous computations
840
+ /// involving `x`.
841
+ ///
842
+ /// Usually, this is done when `x` is located in memory that may be modified by
843
+ /// something other than the running program, like an I/O device or the
844
+ /// operating system.
845
+ ///
846
+ /// However, this function can also be used to force the compiler to determine
847
+ /// the value of `x` before the copy can be used, preventing optimisations
848
+ /// across the boundaries of this function. This is very useful in benchmarking
849
+ /// when you want to ensure that a specific part of a computation is run
850
+ /// completely and not optimised out.
851
+ ///
852
+ /// Note that this does not always guarantee that the value of `x` is computed,
853
+ /// or that a copy is made; if the final computation involving the copy is
854
+ /// unused, this function call may still be optimised out.
855
+ #[ inline]
856
+ #[ unstable( feature = "safe_volatile" , issue = "0" ) ]
857
+ pub fn copy_opaque < T : Copy > ( x : & T ) -> T {
858
+ // this is okay because `T` is `Copy` and doesn't implement `Drop`
859
+ unsafe { ptr:: read_volatile ( x as * const T ) }
860
+ }
861
+
862
+ /// Moves a value while making no assumptions about the result.
863
+ ///
864
+ /// This is a version of `copy_opaque` that moves the value instead of copying
865
+ /// it. This can also be used to force the compiler to determine the value of
866
+ /// `x` before continuing, preventing optimisations across the boundaries of
867
+ /// this function. This is very useful in benchmarking when you want to ensure
868
+ /// that a specific part of a computation is run completely and not optimised
869
+ /// out.
870
+ ///
871
+ /// Note that this does not always guarantee that the value of `x` is computed;
872
+ /// if the final computation involving the value is unused, this function call
873
+ /// may still be optimised out.
874
+ #[ inline]
875
+ #[ unstable( feature = "safe_volatile" , issue = "0" ) ]
876
+ pub fn move_opaque < T > ( x : T ) -> T {
877
+ let y = unsafe { ptr:: read_volatile ( & x as * const T ) } ;
878
+
879
+ // if we don't do this, `x` will be dropped twice
880
+ forget ( x) ;
881
+
882
+ // return the volatile version of the value
883
+ y
884
+ }
885
+
886
+ /// Replaces a value while guaranteeing that it is written.
887
+ ///
888
+ /// This essentially tells the compiler that the value in `dest` may have been
889
+ /// changed and be read in the future, and that it must compute the value of
890
+ /// `dest` and `src`, and write `src` into `dest`.
891
+ ///
892
+ /// Usually, this is done when `dest` is located in memory that may be read by
893
+ /// something other than the running program, like an I/O device or the
894
+ /// operating system.
895
+ ///
896
+ /// However, this function can also be used to force the compiler to determine
897
+ /// the value of `dest` and `src` before the original value of `dest` can be
898
+ /// used, preventing optimisations across the boundaries of this function. This
899
+ /// is very useful in benchmarking when you want to ensure that a specific part
900
+ /// of a computation is run completely and not optimised out.
901
+ #[ inline]
902
+ #[ unstable( feature = "safe_volatile" , issue = "0" ) ]
903
+ pub fn replace_opaque < T > ( dest : & mut T , src : T ) -> T {
904
+ let temp = unsafe { ptr:: read_volatile ( dest) } ;
905
+ unsafe { ptr:: write_volatile ( dest, src) ; }
906
+ temp
907
+ }
908
+
909
+ /// Drops a value while guaranteeing that it was computed.
910
+ ///
911
+ /// This is very useful in benchmarking when you want to ensure that a specific
912
+ /// computation is run completely and not optimised out.
913
+ #[ inline]
914
+ #[ unstable( feature = "safe_volatile" , issue = "0" ) ]
915
+ pub fn drop_opaque < T > ( x : T ) {
916
+ // move `x` into `y`, which will be dropped
917
+ let mut y = unsafe { uninitialized ( ) } ;
918
+ unsafe { ptr:: write_volatile ( & mut y, x) ; }
919
+ }
920
+
921
+
835
922
/// Opaque type representing the discriminant of an enum.
836
923
///
837
924
/// See the `discriminant` function in this module for more information.
0 commit comments