Module: Sync_m

Included in:
Sync
Defined in:
lib/sync.rb

Overview

A module that provides a two-phase lock with a counter.

Defined Under Namespace

Classes: Err

Constant Summary collapse

UN =

lock mode

:UN
SH =
:SH
EX =
:EX

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#sync_ex_countObject

Returns the value of attribute sync_ex_count



247
248
249
# File 'lib/sync.rb', line 247

def sync_ex_count
  @sync_ex_count
end

#sync_ex_lockerObject

Returns the value of attribute sync_ex_locker



246
247
248
# File 'lib/sync.rb', line 246

def sync_ex_locker
  @sync_ex_locker
end

#sync_modeObject

Returns the value of attribute sync_mode



241
242
243
# File 'lib/sync.rb', line 241

def sync_mode
  @sync_mode
end

#sync_sh_lockerObject

Returns the value of attribute sync_sh_locker



245
246
247
# File 'lib/sync.rb', line 245

def sync_sh_locker
  @sync_sh_locker
end

#sync_upgrade_waitingObject

Returns the value of attribute sync_upgrade_waiting



244
245
246
# File 'lib/sync.rb', line 244

def sync_upgrade_waiting
  @sync_upgrade_waiting
end

#sync_waitingObject

Returns the value of attribute sync_waiting



243
244
245
# File 'lib/sync.rb', line 243

def sync_waiting
  @sync_waiting
end

Class Method Details

.append_features(cl) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/sync.rb', line 90

def Sync_m.append_features(cl)
  super
  # do nothing for Modules
  # make aliases for Classes.
  define_aliases(cl) unless cl.instance_of?(Module)
  self
end

.define_aliases(cl) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sync.rb', line 78

def Sync_m.define_aliases(cl)
  cl.module_eval %q{
    alias locked? sync_locked?
    alias shared? sync_shared?
    alias exclusive? sync_exclusive?
    alias lock sync_lock
    alias unlock sync_unlock
    alias try_lock sync_try_lock
    alias synchronize sync_synchronize
  }
end

.extend_object(obj) ⇒ Object



98
99
100
101
# File 'lib/sync.rb', line 98

def Sync_m.extend_object(obj)
  super
  obj.sync_extend
end

Instance Method Details

#sync_exclusive?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/sync.rb', line 125

def sync_exclusive?
  sync_mode == EX
end

#sync_extendObject



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/sync.rb', line 103

def sync_extend
  unless (defined? locked? and
          defined? shared? and
          defined? exclusive? and
          defined? lock and
          defined? unlock and
          defined? try_lock and
          defined? synchronize)
    Sync_m.define_aliases(singleton_class)
  end
  sync_initialize
end

#sync_inspectObject



249
250
251
252
# File 'lib/sync.rb', line 249

def sync_inspect
  sync_iv = instance_variables.select{|iv| /^@sync_/ =~ iv.id2name}.collect{|iv| iv.id2name + '=' + instance_eval(iv.id2name).inspect}.join(",")
  print "<#{self.class}.extend Sync_m: #{inspect}, <Sync_m: #{sync_iv}>"
end

#sync_lock(m = EX) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/sync.rb', line 137

def sync_lock(m = EX)
  return unlock if m == UN
  Thread.handle_interrupt(StandardError => :on_blocking) do
    while true
      @sync_mutex.synchronize do
        begin
          if sync_try_lock_sub(m)
            return self
          else
            if sync_sh_locker[Thread.current]
              sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
              sync_sh_locker.delete(Thread.current)
            else
              unless sync_waiting.include?(Thread.current) || sync_upgrade_waiting.reverse_each.any?{|w| w.first == Thread.current }
                sync_waiting.push Thread.current
              end
            end
            @sync_mutex.sleep
          end
        ensure
          sync_waiting.delete(Thread.current)
        end
      end
    end
  end
  self
end

#sync_locked?Boolean

accessing

Returns:

  • (Boolean)


117
118
119
# File 'lib/sync.rb', line 117

def sync_locked?
  sync_mode != UN
end

#sync_shared?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/sync.rb', line 121

def sync_shared?
  sync_mode == SH
end

#sync_synchronize(mode = EX) ⇒ Object



230
231
232
233
234
235
236
237
238
239
# File 'lib/sync.rb', line 230

def sync_synchronize(mode = EX)
  Thread.handle_interrupt(StandardError => :on_blocking) do
    sync_lock(mode)
    begin
      yield
    ensure
      sync_unlock
    end
  end
end

#sync_try_lock(mode = EX) ⇒ Object

locking methods.



130
131
132
133
134
135
# File 'lib/sync.rb', line 130

def sync_try_lock(mode = EX)
  return unlock if mode == UN
  @sync_mutex.synchronize do
    sync_try_lock_sub(mode)
  end
end

#sync_unlock(m = EX) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/sync.rb', line 165

def sync_unlock(m = EX)
  wakeup_threads = []
  @sync_mutex.synchronize do
    if sync_mode == UN
      Err::UnknownLocker.Fail(Thread.current)
    end

    m = sync_mode if m == EX and sync_mode == SH

    runnable = false
    case m
    when UN
      Err::UnknownLocker.Fail(Thread.current)

    when EX
      if sync_ex_locker == Thread.current
        if (self.sync_ex_count = sync_ex_count - 1) == 0
          self.sync_ex_locker = nil
          if sync_sh_locker.include?(Thread.current)
            self.sync_mode = SH
          else
            self.sync_mode = UN
          end
          runnable = true
        end
      else
        Err::UnknownLocker.Fail(Thread.current)
      end

    when SH
      if (count = sync_sh_locker[Thread.current]).nil?
        Err::UnknownLocker.Fail(Thread.current)
      else
        if (sync_sh_locker[Thread.current] = count - 1) == 0
          sync_sh_locker.delete(Thread.current)
          if sync_sh_locker.empty? and sync_ex_count == 0
            self.sync_mode = UN
            runnable = true
          end
        end
      end
    end

    if runnable
      if sync_upgrade_waiting.size > 0
        th, count = sync_upgrade_waiting.shift
        sync_sh_locker[th] = count
        th.wakeup
        wakeup_threads.push th
      else
        wait = sync_waiting
        self.sync_waiting = []
        for th in wait
          th.wakeup
          wakeup_threads.push th
        end
      end
    end
  end
  for th in wakeup_threads
    th.run
  end
  self
end