mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
merge revision(s) 22011:
* ext/thread/thread.c (rb_queue_pop, rb_queue_push): should not lock mutex if got an exception while waiting, and should ensure unlocked after signaled. [ruby-dev:37545] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@23047 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
14579de431
commit
fffffd6df2
4 changed files with 67 additions and 10 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
Mon Mar 23 19:00:59 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* ext/thread/thread.c (rb_queue_pop, rb_queue_push): should not lock
|
||||||
|
mutex if got an exception while waiting, and should ensure unlocked
|
||||||
|
after signaled. [ruby-dev:37545]
|
||||||
|
|
||||||
Mon Mar 23 18:12:47 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Mon Mar 23 18:12:47 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* eval.c (rb_thread_value): missed to change at r17874. [ruby-core:17595]
|
* eval.c (rb_thread_value): missed to change at r17874. [ruby-core:17595]
|
||||||
|
|
|
@ -444,6 +444,12 @@ lock_mutex(Mutex *mutex)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
lock_mutex_call(VALUE mutex)
|
||||||
|
{
|
||||||
|
return lock_mutex((Mutex *)mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mutex_lock(VALUE self)
|
rb_mutex_lock(VALUE self)
|
||||||
{
|
{
|
||||||
|
@ -512,6 +518,12 @@ unlock_mutex(Mutex *mutex)
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
unlock_mutex_call(VALUE mutex)
|
||||||
|
{
|
||||||
|
return unlock_mutex((Mutex *)mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mutex_unlock(VALUE self)
|
rb_mutex_unlock(VALUE self)
|
||||||
{
|
{
|
||||||
|
@ -665,8 +677,17 @@ rb_condvar_alloc(VALUE klass)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void condvar_wakeup(Mutex *mutex);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wait_condvar(ConditionVariable *condvar, Mutex *mutex)
|
wait_condvar(ConditionVariable *condvar, Mutex *mutex)
|
||||||
|
{
|
||||||
|
condvar_wakeup(mutex);
|
||||||
|
rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex_call, (VALUE)mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
condvar_wakeup(Mutex *mutex)
|
||||||
{
|
{
|
||||||
VALUE waking;
|
VALUE waking;
|
||||||
|
|
||||||
|
@ -679,7 +700,6 @@ wait_condvar(ConditionVariable *condvar, Mutex *mutex)
|
||||||
if (RTEST(waking)) {
|
if (RTEST(waking)) {
|
||||||
wake_thread(waking);
|
wake_thread(waking);
|
||||||
}
|
}
|
||||||
rb_ensure(wait_list, (VALUE)&condvar->waiting, relock_mutex, (VALUE)mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -761,6 +781,13 @@ signal_condvar(ConditionVariable *condvar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
signal_condvar_call(VALUE condvar)
|
||||||
|
{
|
||||||
|
signal_condvar((ConditionVariable *)condvar);
|
||||||
|
return Qundef;
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_condvar_signal(VALUE self)
|
rb_condvar_signal(VALUE self)
|
||||||
{
|
{
|
||||||
|
@ -985,6 +1012,16 @@ rb_queue_num_waiting(VALUE self)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wait_queue(ConditionVariable *condvar, Mutex *mutex)
|
||||||
|
{
|
||||||
|
condvar_wakeup(mutex);
|
||||||
|
wait_list(&condvar->waiting);
|
||||||
|
lock_mutex(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE queue_pop_inner(VALUE arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Document-method: pop
|
* Document-method: pop
|
||||||
* call_seq: pop(non_block=false)
|
* call_seq: pop(non_block=false)
|
||||||
|
@ -1000,7 +1037,6 @@ rb_queue_pop(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
Queue *queue;
|
Queue *queue;
|
||||||
int should_block;
|
int should_block;
|
||||||
VALUE result;
|
|
||||||
Data_Get_Struct(self, Queue, queue);
|
Data_Get_Struct(self, Queue, queue);
|
||||||
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
|
@ -1018,15 +1054,21 @@ rb_queue_pop(int argc, VALUE *argv, VALUE self)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!queue->values.entries) {
|
while (!queue->values.entries) {
|
||||||
wait_condvar(&queue->value_available, &queue->mutex);
|
wait_queue(&queue->value_available, &queue->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = shift_list(&queue->values);
|
return rb_ensure(queue_pop_inner, (VALUE)queue,
|
||||||
|
unlock_mutex_call, (VALUE)&queue->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
queue_pop_inner(VALUE arg)
|
||||||
|
{
|
||||||
|
Queue *queue = (Queue *)arg;
|
||||||
|
VALUE result = shift_list(&queue->values);
|
||||||
if (queue->capacity && queue->values.size < queue->capacity) {
|
if (queue->capacity && queue->values.size < queue->capacity) {
|
||||||
signal_condvar(&queue->space_available);
|
signal_condvar(&queue->space_available);
|
||||||
}
|
}
|
||||||
unlock_mutex(&queue->mutex);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,11 +1088,11 @@ rb_queue_push(VALUE self, VALUE value)
|
||||||
|
|
||||||
lock_mutex(&queue->mutex);
|
lock_mutex(&queue->mutex);
|
||||||
while (queue->capacity && queue->values.size >= queue->capacity) {
|
while (queue->capacity && queue->values.size >= queue->capacity) {
|
||||||
wait_condvar(&queue->space_available, &queue->mutex);
|
wait_queue(&queue->space_available, &queue->mutex);
|
||||||
}
|
}
|
||||||
push_list(&queue->values, value);
|
push_list(&queue->values, value);
|
||||||
signal_condvar(&queue->value_available);
|
rb_ensure(signal_condvar_call, (VALUE)&queue->value_available,
|
||||||
unlock_mutex(&queue->mutex);
|
unlock_mutex_call, (VALUE)&queue->mutex);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,5 +115,14 @@ class TC_Thread < Test::Unit::TestCase
|
||||||
# Now unlock. The mutex should be free, so Mutex#unlock should return nil
|
# Now unlock. The mutex should be free, so Mutex#unlock should return nil
|
||||||
assert(! m.unlock)
|
assert(! m.unlock)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_queue_rescue
|
||||||
|
require "timeout"
|
||||||
|
queue = Queue.new
|
||||||
|
assert_raises(Timeout::Error) {Timeout.timeout(0.001) {queue.pop}}
|
||||||
|
queue.push(1)
|
||||||
|
assert_nothing_raised("[ruby-dev:37545]") {assert_equal(1, queue.pop)}
|
||||||
|
assert(queue.empty?)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define RUBY_RELEASE_DATE "2009-03-23"
|
#define RUBY_RELEASE_DATE "2009-03-23"
|
||||||
#define RUBY_VERSION_CODE 186
|
#define RUBY_VERSION_CODE 186
|
||||||
#define RUBY_RELEASE_CODE 20090323
|
#define RUBY_RELEASE_CODE 20090323
|
||||||
#define RUBY_PATCHLEVEL 364
|
#define RUBY_PATCHLEVEL 365
|
||||||
|
|
||||||
#define RUBY_VERSION_MAJOR 1
|
#define RUBY_VERSION_MAJOR 1
|
||||||
#define RUBY_VERSION_MINOR 8
|
#define RUBY_VERSION_MINOR 8
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue