F#というか.NETにJavaのAtomicBooleanがなかったので実装してみた

タイトルの通り、.NETにはJavaのAtomicBoolean(CAS操作のできるBoolean)が存在しないので、適当に実装してみた。スレッドセーフを保障しつつ、一回だけ処理を走らせたい場合なんかに使うと思う。

実装例

ここの例はF#だけど、Interlockedを使ってるだけなので、C#で書いても同じようなコードになるはず。

open System.Threading

type InterlockedBool(?initValue) =
    let TrueValue = 1L
    let FalseValue = 0L
    let toBool x = if x = TrueValue then true else false
    let toInt64 x = if x then TrueValue else FalseValue
    let valueRef = defaultArg initValue false |> toInt64 |> ref

    (* AtomicBoolean#getAndSetと同等 *)
    member this.Exchange(value) =
        Interlocked.Exchange(valueRef, toInt64 value) |> toBool

    (* AtomicBoolean#compareAndSetと同等だが引数の順番が異なる *)
    member this.CompareExchange(value, comparand) =
        Interlocked.CompareExchange(valueRef, 
                                    toInt64 value,
                                    toInt64 comparand) |> toBool

    member this.Read() =
        Interlocked.Read(valueRef) |> toBool

Exchange()の利用例(一回だけ処理を走らせる)

let isUnprocessed = new InterlockedBool(true)

(* 現在の値を取得 *)
isUnprocessed.Read() |> printfn "%b"

(* Exchange()すると指定した値で上書きつつ、元々格納されていた値が返される *)
if isUnprocessed.Exchange(false) then
    printfn "うごいた!"

CompareExchange()の利用例はぱっと思いつかなかった。