diff --git a/ChangeLog b/ChangeLog index 32136aea00..3137a4b388 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Wed Dec 5 00:56:21 2012 KOSAKI Motohiro + + * thread.c (rb_mutex_owned_p): new method that return current + thread have the target mutex or not. [Feature #7505] [ruby-dev:46697] + * test/ruby/test_thread.rb (test_mutex_owned, test_mutex_owned2): + test for the above. + * NEWS: new for the above. + Wed Dec 5 00:05:47 2012 Masatoshi SEKI * lib/erb.rb (make_compiler, add_put_cmd, add_insert_cmd): extract diff --git a/NEWS b/NEWS index d4c19a5a90..db31e6773f 100644 --- a/NEWS +++ b/NEWS @@ -113,6 +113,9 @@ with all sufficient information, see the ChangeLog file. Object.const_get("Foo::Bar::Baz") * Mutex + * added method: + * added Mutex#owned? which returns the mutex is held by current + thread or not. [experimental] * incompatible changes: * Mutex#lock, Mutex#unlock, Mutex#try_lock, Mutex#synchronize and Mutex#sleep are no longer allowed to be used from trap handler diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index 0149e17d53..e180310505 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -797,4 +797,33 @@ Thread.new(Thread.current) {|mth| sleep 0.01 assert_equal(ary, ["run", "aborting", "aborting"]) end + + def test_mutex_owned + mutex = Mutex.new + + assert_equal(mutex.owned?, false) + mutex.synchronize { + # Now, I have the mutex + assert_equal(mutex.owned?, true) + } + assert_equal(mutex.owned?, false) + end + + def test_mutex_owned2 + begin + mutex = Mutex.new + th = Thread.new { + # lock forever + mutex.lock + sleep + } + + sleep 0.01 until th.status == "sleep" + # acquired another thread. + assert_equal(mutex.locked?, true) + assert_equal(mutex.owned?, false) + ensure + th.kill if th + end + end end diff --git a/thread.c b/thread.c index b1127a7e3a..3aeebaf13a 100644 --- a/thread.c +++ b/thread.c @@ -4251,6 +4251,28 @@ rb_mutex_lock(VALUE self) return self; } +/* + * call-seq: + * mutex.owned? -> true or false + * + * Returns +true+ if this lock is currently held by current thread. + * This API is experimental, and subject to change. + */ +static VALUE +rb_mutex_owned_p(VALUE self) +{ + VALUE owned = Qfalse; + rb_thread_t *th = GET_THREAD(); + rb_mutex_t *mutex; + + GetMutexPtr(self, mutex); + + if (mutex->th == th) + owned = Qtrue; + + return owned; +} + static const char * rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th) { @@ -4874,6 +4896,7 @@ Init_Thread(void) rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0); rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1); rb_define_method(rb_cMutex, "synchronize", rb_mutex_synchronize_m, 0); + rb_define_method(rb_cMutex, "owned?", rb_mutex_owned_p, 0); recursive_key = rb_intern("__recursive_key__"); rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);