Spec-Zone.ru › Ruby 2.4

класс Thread::Mutex

Родитель:
Объект

Mutex

Публичные методы класса

new → mutex Показать исходный код
static VALUE
mutex_initialize(VALUE self)
{
    return self;
}

Создаёт новый Mutex

Публичные методы экземпляра

lock → self Показать исходный код
VALUE
rb_mutex_lock(VALUE self)
{
    rb_thread_t *th = GET_THREAD();
    rb_mutex_t *mutex;
    GetMutexPtr(self, mutex);

    /* When running trap handler */
    if (!mutex->allow_trap && th->interrupt_mask & TRAP_INTERRUPT_MASK) {
        rb_raise(rb_eThreadError, "can't be called from trap context");
    }

    if (rb_mutex_trylock(self) == Qfalse) {
        if (mutex->th == th) {
            rb_raise(rb_eThreadError, "deadlock; recursive locking");
        }

        while (mutex->th != th) {
            int interrupted;
            enum rb_thread_status prev_status = th->status;
            volatile int timeout_ms = 0;
            struct rb_unblock_callback oldubf;

            set_unblock_function(th, lock_interrupt, mutex, &oldubf, FALSE);
            th->status = THREAD_STOPPED_FOREVER;
            th->locking_mutex = self;

            native_mutex_lock(&mutex->lock);
            th->vm->sleeper++;
            /*
             * Carefully! while some contended threads are in lock_func(),
             * vm->sleepr is unstable value. we have to avoid both deadlock
             * and busy loop.
             */
            if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
                !patrol_thread) {
                timeout_ms = 100;
                patrol_thread = th;
            }

            GVL_UNLOCK_BEGIN();
            interrupted = lock_func(th, mutex, (int)timeout_ms);
            native_mutex_unlock(&mutex->lock);
            GVL_UNLOCK_END();

            if (patrol_thread == th)
                patrol_thread = NULL;

            reset_unblock_function(th, &oldubf);

            th->locking_mutex = Qfalse;
            if (mutex->th && interrupted == 2) {
                rb_check_deadlock(th->vm);
            }
            if (th->status == THREAD_STOPPED_FOREVER) {
                th->status = prev_status;
            }
            th->vm->sleeper--;

            if (mutex->th == th) mutex_locked(th, self);

            if (interrupted) {
                RUBY_VM_CHECK_INTS_BLOCKING(th); /* may release mutex */
                if (!mutex->th) {
                    mutex->th = th;
                    mutex_locked(th, self);
                }
            }
        }
    }
    return self;
}

Попытка захватить блокировку и ожидание, если она недоступна. Вызывает ThreadError , если mutex была заблокирована текущей нитью.

locked? → true или false Показать исходный код
VALUE
rb_mutex_locked_p(VALUE self)
{
    rb_mutex_t *mutex;
    GetMutexPtr(self, mutex);
    return mutex->th ? Qtrue : Qfalse;
}

Возвращает true, если эта блокировка в данный момент удерживается какой-то нитью.

owned? → true или false Показать исходный код
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;
}

Возвращает true, если эта блокировка в данный момент удерживается текущей нитью.

sleep(timeout = nil) → число Показать исходный код
static VALUE
mutex_sleep(int argc, VALUE *argv, VALUE self)
{
    VALUE timeout;

    rb_scan_args(argc, argv, "01", &timeout);
    return rb_mutex_sleep(self, timeout);
}

Освобождает блокировку и засыпает на timeout секунд, если это значение задано и не равно nil, или навсегда. Вызывает ThreadError , если mutex не была заблокирована текущей нитью.

Когда нить проснётся, она попытается повторно получить блокировку.

Обратите внимание, что этот метод может проснуться без явного вызова Thread#wakeup. Например, при получении сигнала и так далее.

synchronize { ... } → результат блока Показать исходный код
static VALUE
rb_mutex_synchronize_m(VALUE self, VALUE args)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eThreadError, "must be called with a block");
    }

    return rb_mutex_synchronize(self, rb_yield, Qundef);
}

Получает блокировку, выполняет блок и освобождает блокировку по завершении блока. См. пример в Mutex.

try_lock → true или false Показать исходный код
VALUE
rb_mutex_trylock(VALUE self)
{
    rb_mutex_t *mutex;
    VALUE locked = Qfalse;
    GetMutexPtr(self, mutex);

    native_mutex_lock(&mutex->lock);
    if (mutex->th == 0) {
        rb_thread_t *th = GET_THREAD();
        mutex->th = th;
        locked = Qtrue;

        mutex_locked(th, self);
    }
    native_mutex_unlock(&mutex->lock);

    return locked;
}

Попытка получить блокировку и немедленное возвращение. Возвращает true, если блокировка была получена.

unlock → self Показать исходный код
VALUE
rb_mutex_unlock(VALUE self)
{
    const char *err;
    rb_mutex_t *mutex;
    GetMutexPtr(self, mutex);

    err = rb_mutex_unlock_th(mutex, GET_THREAD());
    if (err) rb_raise(rb_eThreadError, "%s", err);

    return self;
}

Освобождает блокировку. Вызывает ThreadError , если mutex не была заблокирована текущей нитью.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API