Fix race condition in Action by associating an atomic state value
Fix race condition in Action by associating an atomic state value

See https://github.com/ReactiveCocoa/ReactiveSwift/issues/88 for
context.

There is a race condition inherent in this code:

    let input: Property<Int?>

    // (1) input value is checked to see if it is non-nil
    let action = Action(enabledIf: input.map { $0 != nil }) {
      // (2) input value is read _again_, and could have changed concurrently
      let input = input.value!
    }

Because the property is read twice, the reads are not atomic and there's
no guarantee the value will be the same at both (1) and (2).

This change adds the ability for `Action` to atomically observe changes to
a generic `State` property. It changes `enabledIf` to be a function that
returns a `Bool` based on the current state. By storing this generic,
opaque state value atomically, we can read the value once, and guarantee
that it has not changed between checking the `enabledIf` predicate and
then passing it into the `execute` closure:

    let input: Action<Int?>

    // (1) action state is read, and the value passed to `enabledIf`
    let action = Action(state: input, enabledIf: { $0 != nil }) { input, _ in
      // (2) the same value, which was read atomically, is passed into `execute`
      //     making this force-unwrap safe
      foo.bar(with: input!)
    }

The convenience initialiser `Action(input:_:)` is now implemented in
terms of this generic state initialiser, encapsulating the pattern of a
property that operates on its input while non-nil.

ReactiveCocoa/ReactiveSwift,ReactiveCocoa/ReactiveSwift,ReactiveCocoa/ReactiveSwift