Author: marshall Date: Mon Mar 14 18:07:32 2016 New Revision: 263506 URL: http://llvm.org/viewvc/llvm-project?rev=263506&view=rev Log: Implement LWG2577: {shared,unique}_lock</tt> should use std::addressof
Modified: libcxx/trunk/include/__mutex_base libcxx/trunk/include/shared_mutex libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp libcxx/trunk/www/cxx1z_status.html Modified: libcxx/trunk/include/__mutex_base URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__mutex_base?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/include/__mutex_base (original) +++ libcxx/trunk/include/__mutex_base Mon Mar 14 18:07:32 2016 @@ -109,24 +109,24 @@ public: unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} _LIBCPP_INLINE_VISIBILITY explicit unique_lock(mutex_type& __m) - : __m_(&__m), __owns_(true) {__m_->lock();} + : __m_(addressof(__m)), __owns_(true) {__m_->lock();} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT - : __m_(&__m), __owns_(false) {} + : __m_(addressof(__m)), __owns_(false) {} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, try_to_lock_t) - : __m_(&__m), __owns_(__m.try_lock()) {} + : __m_(addressof(__m)), __owns_(__m.try_lock()) {} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, adopt_lock_t) - : __m_(&__m), __owns_(true) {} + : __m_(addressof(__m)), __owns_(true) {} template <class _Clock, class _Duration> _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) - : __m_(&__m), __owns_(__m.try_lock_until(__t)) {} + : __m_(addressof(__m)), __owns_(__m.try_lock_until(__t)) {} template <class _Rep, class _Period> _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) - : __m_(&__m), __owns_(__m.try_lock_for(__d)) {} + : __m_(addressof(__m)), __owns_(__m.try_lock_for(__d)) {} _LIBCPP_INLINE_VISIBILITY ~unique_lock() { Modified: libcxx/trunk/include/shared_mutex URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/shared_mutex?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/include/shared_mutex (original) +++ libcxx/trunk/include/shared_mutex Mon Mar 14 18:07:32 2016 @@ -319,25 +319,25 @@ public: _LIBCPP_INLINE_VISIBILITY explicit shared_lock(mutex_type& __m) - : __m_(&__m), + : __m_(addressof(__m)), __owns_(true) {__m_->lock_shared();} _LIBCPP_INLINE_VISIBILITY shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT - : __m_(&__m), + : __m_(addressof(__m)), __owns_(false) {} _LIBCPP_INLINE_VISIBILITY shared_lock(mutex_type& __m, try_to_lock_t) - : __m_(&__m), + : __m_(addressof(__m)), __owns_(__m.try_lock_shared()) {} _LIBCPP_INLINE_VISIBILITY shared_lock(mutex_type& __m, adopt_lock_t) - : __m_(&__m), + : __m_(addressof(__m)), __owns_(true) {} @@ -345,7 +345,7 @@ public: _LIBCPP_INLINE_VISIBILITY shared_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __abs_time) - : __m_(&__m), + : __m_(addressof(__m)), __owns_(__m.try_lock_shared_until(__abs_time)) {} @@ -353,7 +353,7 @@ public: _LIBCPP_INLINE_VISIBILITY shared_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __rel_time) - : __m_(&__m), + : __m_(addressof(__m)), __owns_(__m.try_lock_shared_for(__rel_time)) {} Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp Mon Mar 14 18:07:32 2016 @@ -18,17 +18,33 @@ #include <shared_mutex> #include <cassert> +#include "nasty_containers.hpp" -std::shared_timed_mutex m0; -std::shared_timed_mutex m1; int main() { - std::shared_lock<std::shared_timed_mutex> lk0(m0); - std::shared_lock<std::shared_timed_mutex> lk1(m1); + { + typedef std::shared_timed_mutex M; + M m0; + M m1; + std::shared_lock<M> lk0(m0); + std::shared_lock<M> lk1(m1); lk1 = std::move(lk0); - assert(lk1.mutex() == &m0); + assert(lk1.mutex() == std::addressof(m0)); assert(lk1.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); + } + { + typedef nasty_mutex M; + M m0; + M m1; + std::shared_lock<M> lk0(m0); + std::shared_lock<M> lk1(m1); + lk1 = std::move(lk0); + assert(lk1.mutex() == std::addressof(m0)); + assert(lk1.owns_lock() == true); + assert(lk0.mutex() == nullptr); + assert(lk0.owns_lock() == false); + } } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_ctor.pass.cpp Mon Mar 14 18:07:32 2016 @@ -18,14 +18,28 @@ #include <shared_mutex> #include <cassert> +#include "nasty_containers.hpp" int main() { - std::shared_timed_mutex m; - std::shared_lock<std::shared_timed_mutex> lk0(m); - std::shared_lock<std::shared_timed_mutex> lk = std::move(lk0); - assert(lk.mutex() == &m); + { + typedef std::shared_timed_mutex M; + M m; + std::shared_lock<M> lk0(m); + std::shared_lock<M> lk = std::move(lk0); + assert(lk.mutex() == std::addressof(m)); assert(lk.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); + } + { + typedef nasty_mutex M; + M m; + std::shared_lock<M> lk0(m); + std::shared_lock<M> lk = std::move(lk0); + assert(lk.mutex() == std::addressof(m)); + assert(lk.owns_lock() == true); + assert(lk0.mutex() == nullptr); + assert(lk0.owns_lock() == false); + } } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp Mon Mar 14 18:07:32 2016 @@ -18,12 +18,24 @@ #include <shared_mutex> #include <cassert> +#include "nasty_containers.hpp" int main() { - std::shared_timed_mutex m; - m.lock_shared(); - std::shared_lock<std::shared_timed_mutex> lk(m, std::adopt_lock); - assert(lk.mutex() == &m); + { + typedef std::shared_timed_mutex M; + M m; + m.lock(); + std::unique_lock<M> lk(m, std::adopt_lock); + assert(lk.mutex() == std::addressof(m)); assert(lk.owns_lock() == true); + } + { + typedef nasty_mutex M; + M m; + m.lock(); + std::unique_lock<M> lk(m, std::adopt_lock); + assert(lk.mutex() == std::addressof(m)); + assert(lk.owns_lock() == true); + } } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp Mon Mar 14 18:07:32 2016 @@ -18,11 +18,22 @@ #include <shared_mutex> #include <cassert> +#include "nasty_containers.hpp" int main() { - std::shared_timed_mutex m; - std::shared_lock<std::shared_timed_mutex> lk(m, std::defer_lock); - assert(lk.mutex() == &m); + { + typedef std::shared_timed_mutex M; + M m; + std::unique_lock<M> lk(m, std::defer_lock); + assert(lk.mutex() == std::addressof(m)); assert(lk.owns_lock() == false); + } + { + typedef nasty_mutex M; + M m; + std::unique_lock<M> lk(m, std::defer_lock); + assert(lk.mutex() == std::addressof(m)); + assert(lk.owns_lock() == false); + } } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.fail.cpp Mon Mar 14 18:07:32 2016 @@ -16,16 +16,18 @@ #include <mutex> #include <cassert> -std::mutex m0; -std::mutex m1; - int main() { - std::unique_lock<std::mutex> lk0(m0); - std::unique_lock<std::mutex> lk1(m1); + { + typedef std::mutex M; + M m0; + M m1; + std::unique_lock<M> lk0(m0); + std::unique_lock<M> lk1(m1); lk1 = lk0; assert(lk1.mutex() == &m0); assert(lk1.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); + } } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.fail.cpp Mon Mar 14 18:07:32 2016 @@ -16,14 +16,16 @@ #include <mutex> #include <cassert> -std::mutex m; - int main() { - std::unique_lock<std::mutex> lk0(m); - std::unique_lock<std::mutex> lk = lk0; + { + typedef std::mutex M; + M m; + std::unique_lock<M> lk0(m); + std::unique_lock<M> lk = lk0; assert(lk.mutex() == &m); assert(lk.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); + } } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp Mon Mar 14 18:07:32 2016 @@ -17,19 +17,34 @@ #include <mutex> #include <cassert> - -std::mutex m0; -std::mutex m1; +#include "nasty_containers.hpp" int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - std::unique_lock<std::mutex> lk0(m0); - std::unique_lock<std::mutex> lk1(m1); + { + typedef std::mutex M; + M m0; + M m1; + std::unique_lock<M> lk0(m0); + std::unique_lock<M> lk1(m1); + lk1 = std::move(lk0); + assert(lk1.mutex() == std::addressof(m0)); + assert(lk1.owns_lock() == true); + assert(lk0.mutex() == nullptr); + assert(lk0.owns_lock() == false); + } + { + typedef nasty_mutex M; + M m0; + M m1; + std::unique_lock<M> lk0(m0); + std::unique_lock<M> lk1(m1); lk1 = std::move(lk0); - assert(lk1.mutex() == &m0); + assert(lk1.mutex() == std::addressof(m0)); assert(lk1.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); + } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp Mon Mar 14 18:07:32 2016 @@ -17,17 +17,30 @@ #include <mutex> #include <cassert> - -std::mutex m; +#include "nasty_containers.hpp" int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - std::unique_lock<std::mutex> lk0(m); - std::unique_lock<std::mutex> lk = std::move(lk0); - assert(lk.mutex() == &m); + { + typedef std::mutex M; + M m; + std::unique_lock<M> lk0(m); + std::unique_lock<M> lk = std::move(lk0); + assert(lk.mutex() == std::addressof(m)); + assert(lk.owns_lock() == true); + assert(lk0.mutex() == nullptr); + assert(lk0.owns_lock() == false); + } + { + typedef nasty_mutex M; + M m; + std::unique_lock<M> lk0(m); + std::unique_lock<M> lk = std::move(lk0); + assert(lk.mutex() == std::addressof(m)); assert(lk.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); + } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp Mon Mar 14 18:07:32 2016 @@ -17,12 +17,24 @@ #include <mutex> #include <cassert> +#include "nasty_containers.hpp" int main() { - std::mutex m; + { + typedef std::mutex M; + M m; m.lock(); - std::unique_lock<std::mutex> lk(m, std::adopt_lock); - assert(lk.mutex() == &m); + std::unique_lock<M> lk(m, std::adopt_lock); + assert(lk.mutex() == std::addressof(m)); assert(lk.owns_lock() == true); + } + { + typedef nasty_mutex M; + M m; + m.lock(); + std::unique_lock<M> lk(m, std::adopt_lock); + assert(lk.mutex() == std::addressof(m)); + assert(lk.owns_lock() == true); + } } Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp (original) +++ libcxx/trunk/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp Mon Mar 14 18:07:32 2016 @@ -17,11 +17,22 @@ #include <mutex> #include <cassert> +#include "nasty_containers.hpp" int main() { - std::mutex m; - std::unique_lock<std::mutex> lk(m, std::defer_lock); - assert(lk.mutex() == &m); + { + typedef std::mutex M; + M m; + std::unique_lock<M> lk(m, std::defer_lock); + assert(lk.mutex() == std::addressof(m)); assert(lk.owns_lock() == false); + } + { + typedef nasty_mutex M; + M m; + std::unique_lock<M> lk(m, std::defer_lock); + assert(lk.mutex() == std::addressof(m)); + assert(lk.owns_lock() == false); + } } Modified: libcxx/trunk/www/cxx1z_status.html URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=263506&r1=263505&r2=263506&view=diff ============================================================================== --- libcxx/trunk/www/cxx1z_status.html (original) +++ libcxx/trunk/www/cxx1z_status.html Mon Mar 14 18:07:32 2016 @@ -223,7 +223,7 @@ <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2574">2574</a></td><td>[fund.ts.v2] <tt>std::experimental::function::operator=(F&&)</tt> should be constrained</td><td>Jacksonville</td><td></td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2575">2575</a></td><td>[fund.ts.v2] <tt>experimental::function::assign</tt> should be removed</td><td>Jacksonville</td><td></td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2576">2576</a></td><td><tt>istream_iterator</tt> and <tt>ostream_iterator</tt> should use <tt>std::addressof</tt></td><td>Jacksonville</td><td></td></tr> - <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2577">2577</a></td><td><tt>{shared,unique}_lock</tt> should use <tt>std::addressof</tt></td><td>Jacksonville</td><td></td></tr> + <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2577">2577</a></td><td><tt>{shared,unique}_lock</tt> should use <tt>std::addressof</tt></td><td>Jacksonville</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2579">2579</a></td><td>Inconsistency wrt Allocators in <tt>basic_string</tt> assignment vs. <tt>basic_string::assign</tt></td><td>Jacksonville</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2581">2581</a></td><td>Specialization of <tt><type_traits></tt> variable templates should be prohibited</td><td>Jacksonville</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2582">2582</a></td><td>§[res.on.functions]/2's prohibition against incomplete types shouldn't apply to type traits</td><td>Jacksonville</td><td></td></tr> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits