Module: Concurrent::Dereferenceable

Included in:
Agent, MVar, Obligation, TimerTask
Defined in:
lib/concurrent/dereferenceable.rb

Overview

Object references in Ruby are mutable. This can lead to serious problems when the #value of a concurrent object is a mutable reference. Which is always the case unless the value is a Fixnum, Symbol, or similar “primitive” data type. Most classes in this library that expose a #value getter method do so using this mixin module.

Instance Method Summary collapse

Instance Method Details

#init_mutexObject

Note:

This method must be called from within the constructor of the including class.

Initializes the internal Mutex.

See Also:



56
57
58
# File 'lib/concurrent/dereferenceable.rb', line 56

def init_mutex
  @mutex = Mutex.new
end

#mutexMutex

A mutex lock used for synchronizing thread-safe operations. Methods defined by Dereferenceable are synchronized using the Mutex returned from this method. Operations performed by the including class that operate on the @value instance variable should be locked with this Mutex.

Returns:

  • (Mutex)

    the synchronization object



45
46
47
# File 'lib/concurrent/dereferenceable.rb', line 45

def mutex
  @mutex
end

#set_deref_options(opts = {}) ⇒ Object

Note:

Most classes that include this module will call #set_deref_options

Set the options which define the operations #value performs before returning data to the caller (dereferencing).

from within the constructor, thus allowing these options to be set at object creation.

Parameters:

  • opts (Hash) (defaults to: {})

    the options defining dereference behavior.

Options Hash (opts):

  • :dup_on_deref (String) — default: false

    call #dup before returning the data

  • :freeze_on_deref (String) — default: false

    call #freeze before returning the data

  • :copy_on_deref (String) — default: nil

    call the given Proc passing the internal value and returning the value returned from the proc



74
75
76
77
78
79
80
81
# File 'lib/concurrent/dereferenceable.rb', line 74

def set_deref_options(opts = {})
  mutex.synchronize do
    @dup_on_deref = opts[:dup_on_deref] || opts[:dup]
    @freeze_on_deref = opts[:freeze_on_deref] || opts[:freeze]
    @copy_on_deref = opts[:copy_on_deref] || opts[:copy]
    @do_nothing_on_deref = ! (@dup_on_deref || @freeze_on_deref || @copy_on_deref)
  end
end

#valueObject Also known as: deref

Return the value this object represents after applying the options specified by the #set_deref_options method.

When multiple deref options are set the order of operations is strictly defined. The order of deref operations is:

  • :copy_on_deref

  • :dup_on_deref

  • :freeze_on_deref

Because of this ordering there is no need to #freeze an object created by a provided :copy_on_deref block. Simply set :freeze_on_deref to true. Setting both :dup_on_deref to true and :freeze_on_deref to +true is as close to the behavior of a “pure” functional language (like Erlang, Clojure, or Haskell) as we are likely to get in Ruby.

This method is thread-safe and synchronized with the internal #mutex.

Returns:

  • (Object)

    the current value of the object



28
29
30
31
32
# File 'lib/concurrent/dereferenceable.rb', line 28

def value
  mutex.synchronize do
    apply_deref_options(@value)
  end
end