Class: Monitor

Inherits:
Object
  • Object
show all
Defined in:
lib/monitor.rb,
monitor.c

Overview

Use the Monitor class when you want to have a lock object for blocks with mutual exclusion.

require 'monitor'

lock = Monitor.new
lock.synchronize do
  # exclusive access
end

Instance Method Summary collapse

Instance Method Details

#enternil Also known as: mon_enter

Enters exclusive section.

Returns:

  • (nil)


87
88
89
90
91
92
93
94
95
96
97
98
# File 'monitor.c', line 87

static VALUE
monitor_enter(VALUE monitor)
{
    struct rb_monitor *mc = monitor_ptr(monitor);
    if (!mc_owner_p(mc)) {
        rb_mutex_lock(mc->mutex);
        RB_OBJ_WRITE(monitor, &mc->owner, rb_fiber_current());
        mc->count = 0;
    }
    mc->count++;
    return Qnil;
}

#exitnil Also known as: mon_exit

Leaves exclusive section.

Returns:

  • (nil)


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'monitor.c', line 117

static VALUE
monitor_exit(VALUE monitor)
{
    monitor_check_owner(monitor);

    struct rb_monitor *mc = monitor_ptr(monitor);

    if (mc->count <= 0) rb_bug("monitor_exit: count:%d", (int)mc->count);
    mc->count--;

    if (mc->count == 0) {
        RB_OBJ_WRITE(monitor, &mc->owner, Qnil);
        rb_mutex_unlock(mc->mutex);
    }
    return Qnil;
}

#mon_check_ownerObject

:nodoc:



101
102
103
104
105
106
107
108
109
# File 'monitor.c', line 101

static VALUE
monitor_check_owner(VALUE monitor)
{
    struct rb_monitor *mc = monitor_ptr(monitor);
    if (!mc_owner_p(mc)) {
        rb_raise(rb_eThreadError, "current fiber not owner");
    }
    return Qnil;
}

#mon_locked?Boolean

:nodoc:

Returns:

  • (Boolean)


135
136
137
138
139
140
# File 'monitor.c', line 135

static VALUE
monitor_locked_p(VALUE monitor)
{
    struct rb_monitor *mc = monitor_ptr(monitor);
    return rb_mutex_locked_p(mc->mutex);
}

#mon_owned?Boolean

:nodoc:

Returns:

  • (Boolean)


143
144
145
146
147
148
# File 'monitor.c', line 143

static VALUE
monitor_owned_p(VALUE monitor)
{
    struct rb_monitor *mc = monitor_ptr(monitor);
    return (rb_mutex_locked_p(mc->mutex) && mc_owner_p(mc)) ? Qtrue : Qfalse;
}

#new_condObject

Creates a new MonitorMixin::ConditionVariable associated with the Monitor object.



263
264
265
# File 'lib/monitor.rb', line 263

def new_cond
  ::MonitorMixin::ConditionVariable.new(self)
end

#synchronize { ... } ⇒ Object Also known as: mon_synchronize

Enters exclusive section and executes the block. Leaves the exclusive section automatically when the block exits. See example under MonitorMixin.

Yields:



226
227
228
229
230
231
# File 'monitor.c', line 226

static VALUE
monitor_synchronize(VALUE monitor)
{
    monitor_enter(monitor);
    return rb_ensure(monitor_sync_body, monitor, monitor_sync_ensure, monitor);
}

#try_enterBoolean Also known as: try_mon_enter, mon_try_enter

Attempts to enter exclusive section. Returns false if lock fails.

Returns:

  • (Boolean)


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'monitor.c', line 65

static VALUE
monitor_try_enter(VALUE monitor)
{
    struct rb_monitor *mc = monitor_ptr(monitor);

    if (!mc_owner_p(mc)) {
        if (!rb_mutex_trylock(mc->mutex)) {
            return Qfalse;
        }
        RB_OBJ_WRITE(monitor, &mc->owner, rb_fiber_current());
        mc->count = 0;
    }
    mc->count += 1;
    return Qtrue;
}

#wait_for_cond(cond, timeout) ⇒ Object

:nodoc:



191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'monitor.c', line 191

static VALUE
monitor_wait_for_cond(VALUE monitor, VALUE cond, VALUE timeout)
{
    VALUE count = monitor_exit_for_cond(monitor);
    struct wait_for_cond_data data = {
        monitor,
        cond,
        timeout,
        count,
    };

    return rb_ensure(monitor_wait_for_cond_body, (VALUE)&data,
                     monitor_enter_for_cond, (VALUE)&data);
}