README.md in sync_attr-1.0.0 vs README.md in sync_attr-2.0.0

- old
+ new

@@ -1,110 +1,166 @@ -sync_attr +sync_attr [![Build Status](https://secure.travis-ci.org/reidmorrison/sync_attr.png?branch=master)](http://travis-ci.org/reidmorrison/sync_attr) ========= -Thread-safe Ruby class variables with lazy loaded default values and initializers +Thread-safe Ruby class and instance attributes -* http://github.com/ClarityServices/sync_attr +* http://github.com/reidmorrison/sync_attr -### Introduction +## Status -When working in a multithreaded environment it is important to ensure that +Enterprise Production Ready - In daily use in large multi-threaded application + +## Introduction + +When working in a multi-threaded environment it is important to ensure that any attributes that are shared across threads are properly protected to ensure -that inconsistent data is not created. +that inconsistent data is not created. Lazy initializing these safe attributes +improves startup times and only creates resources when they are needed. For example, without sync_attr if two threads attempt to write to the same attribute at the same time it is not deterministic what the results will be. -This condition is made worse when two threads attempt to initialize class variables -at the same time that could take a second or longer to complete. +This condition is made worse when two threads attempt to initialize class instance +attributes at the same time that could take a second or longer to complete. -### Features +A `sync_cattr_reader` is ideal for holding data loaded from configuration files. +Also, shared objects, such as connection pools can be safely initialized and +shared in this way across hundreds of threads. +Once initialized all reads are shared without locks since no writer is defined. -* Adds thread-safe accessors for class attributes -* Allows shared read access to class and instance attributes. This allows - multiple threads to read the attribute, but will block all reads and writes whilst - the attribute is being modified. +Aside from safely sharing reads `sync_cattr_accessor` also ensures that data +is not read while it is being modified. The writes are completely thread-safe +ensuring that only one thread is modifying the value at a time and that reads +are suspended until the write is complete. + +## Features + +* Adds thread-safe accessors for class instance attributes. +* Only one thread can read or write the value at any one time. * Prevents attributes from being read while it is being updated or initialized for the first time. -* Thread-safe attribute lazy initialization +* Thread-safe attribute lazy initialization. Lazy initialization allows class attributes to be loaded only when first read. - As a result it's value can be read for the first time from a database or config file - once and only when needed. -* Avoids having to create yet another Rails initializer -* Avoids costly startup initialization when the initialized data may never be accessed - For example when Rake tasks are run, they may not need access to everything in - the Rails environment -* Not dependent on Rails + As a result it's value can be read for the first time from a database or + configuration file once and only when needed. +* Avoids having to create yet another Rails initializer, when the data can be + fetched or held by a class instance attribute. +* Avoids costly startup initialization when the initialized data may never be accessed. + For example, when Rake tasks are run, they may not need access to everything in + the Rails environment. +* Works with Rails and regular Ruby. -### Synchronized Class Attribute example +## Thread-safe Class Attribute example - require 'sync_attr' +Create a reader for a class attribute and lazy initialize its value on the first +attempt to read it. I.e. Lazy initialize the value. - # Sample class with lazy initialized Synchronized Class Attributes - class Person - include SyncAttr +Very useful for initializing shared services that take time to initialize. +In particular services that may not even be called in a specific process, +for example when running rake, or when opening a console. - # Thread safe Class Attribute reader for name - # with a default value - # Ideal for when name is loaded after startup from a database or config file - sync_cattr_reader :name do - "Joe Bloggs" - end +An optional block can be supplied to initialize the synchronized class attribute +when it is first read. The initializer is thread safe and will block all other +reads to this attribute while it is being initialized. This ensures that the +initializer is only run once and that all threads to call the reader receive the +same value, regardless of how many threads call the reader at the same time. - # Thread safe Class Attribute reader and writer for age - # with a default value - sync_cattr_accessor :age do - 21 - end - end +Example: - puts "The person is #{Person.name} with age #{Person.age}" +```ruby +require 'sync_attr' - Person.age = 22 - puts "The person is #{Person.name} now has age #{Person.age}" +# Sample class with lazy initialized Thread-safe Class Attributes +class Person + # Create a reader for the class attribute :name + # and lazy initialize the value to 'Joe Bloggs' only on the first + # call to the reader. + # Ideal for when :name is loaded from a database or configuration file. + sync_cattr_reader :name do + 'Joe Bloggs' + end - Person.age = Proc.new {|age| age += 1 } - puts "The person is #{Person.name} now has age #{Person.age}" + # Create a reader and a writer for the class attribute :age + # and lazy initialize the value to 21 only on the first + # call to the reader. + sync_cattr_accessor :age do + 21 + end +end -### Synchronized Instance Attribute example +puts "The person is #{Person.name} with age #{Person.age}" - require 'sync_attr' +Person.age = 22 +puts "The person is #{Person.name} now has age #{Person.age}" - # Sample class with lazy initialized Synchronized Class Attributes - class Person - include SyncAttr +# => The person is Joe Bloggs now has age 22 - # Thread safe Attribute reader for name - # with a default value - sync_attr_reader :name do - "Joe Bloggs" - end +Person.age = Proc.new {|age| age += 1 } +puts "The person is #{Person.name} now has age #{Person.age}" - # Thread safe Attribute reader and writer for age - # with a default value - sync_attr_accessor :age do - 21 - end - end +# => The person is Joe Bloggs now has age 23 +``` - person = Person.new - puts "The person is #{person.name} with age #{person.age}" +## Thread-safe Instance Attribute example - person.age = 22 - puts "The person is #{person.name} now has age #{person.age}" +Create a reader for an attribute and lazy initialize its value on the first +attempt to read it. I.e. Lazy initialize the value. - person.age = Proc.new {|age| age += 1 } - puts "The person is #{person.name} now has age #{person.age}" +An optional block can be supplied to initialize the synchronized attribute +when it is first read. The initializer is thread safe and will block all other +reads to this attribute while it is being initialized. This ensures that the +initializer is only run once per object and that all threads to call the reader +receive the same value, regardless of how many threads call the reader at the same time. -### Install +Example: +```ruby +require 'sync_attr' + +# Sample class with lazy initialized Thread-safe attributes +class Person + include SyncAttr::Attributes + + # Create a reader for the thread-safe attribute :name + # and lazy initialize the value to 'Joe Bloggs' only on the first + # call to the reader. + sync_attr_reader :name do + 'Joe Bloggs' + end + + # Create a thread-safe reader and a writer for the attribute :age + # and lazy initialize the value to 21 only on the first + # call to the reader. + sync_attr_accessor :age do + 21 + end +end + +person = Person.new +puts "The person is #{person.name} with age #{person.age}" + +# => The person is Joe Bloggs with age 21 + +person.age = 22 +puts "The person is #{person.name} now has age #{person.age}" + +# => The person is Joe Bloggs now has age 22 + +person.age = Proc.new {|age| age += 1 } +puts "The person is #{person.name} now has age #{person.age}" + +# => The person is Joe Bloggs now has age 23 +``` + +## Install + gem install sync_attr Meta ---- -* Code: `git clone git://github.com/ClarityServices/sync_attr.git` -* Home: <https://github.com/ClarityServices/sync_attr> +* Code: `git clone git://github.com/reidmorrison/sync_attr.git` +* Home: <https://github.com/reidmorrison/sync_attr> * Bugs: <http://github.com/reidmorrison/sync_attr/issues> * Gems: <http://rubygems.org/gems/sync_attr> This project uses [Semantic Versioning](http://semver.org/). @@ -114,10 +170,10 @@ Reid Morrison :: reidmo@gmail.com :: @reidmorrison License ------- -Copyright 2012 Clarity Services, Inc. +Copyright 2012, 2013, 2014, 2015 Reid Morrison Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at