123456789_123456789_123456789_123456789_123456789_

Module: Concurrent::Concern::Dereferenceable

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Defined in: lib/concurrent-ruby/concurrent/concern/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 the Dereferenceable mixin module.

## Copy Options

::Object references in Ruby are mutable. This can lead to serious problems when the #value of an object is a mutable reference. Which is always the case unless the value is a Fixnum, Symbol, or similar “primitive” data type. Each instance can be configured with a few options that can help protect the program from potentially dangerous operations. Each of these options can be optionally set when the object instance is created:

  • :dup_on_deref When true the object will call the #dup method on the #value object every time the #value method is called (default: false)

  • :freeze_on_deref When true the object will call the #freeze method on the #value object every time the #value method is called (default: false)

  • :copy_on_deref When given a Proc object the Proc will be run every time the #value method is called. The Proc will be given the current #value as its only argument and the result returned by the block will be the return value of the #value call. When nil this option will be ignored (default: nil)

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.

Instance Attribute Summary

  • #value ⇒ Object (also: #deref) readonly

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

Instance Method Summary

Instance Attribute Details

#valueObject (rw) Also known as: #deref

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

Returns:

  • (Object)

    the current value of the object

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/concern/dereferenceable.rb', line 21

def value
  synchronize { apply_deref_options(@value) }
end

Instance Method Details

#apply_deref_options(value) (private)

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/concern/dereferenceable.rb', line 63

def apply_deref_options(value)
  return nil if value.nil?
  return value if @do_nothing_on_deref
  value = @copy_on_deref.call(value) if @copy_on_deref
  value = value.dup if @dup_on_deref
  value = value.freeze if @freeze_on_deref
  value
end

#deref

Alias for #value.

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/concern/dereferenceable.rb', line 24

alias_method :deref, :value

#ns_set_deref_options(opts) (private)

Note:

Most classes that include this module will call #set_deref_options from within the constructor, thus allowing these options to be set at object creation.

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

Parameters:

  • opts (Hash)

    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

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/concern/dereferenceable.rb', line 54

def ns_set_deref_options(opts)
  @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)
  nil
end