A `CommitBarrier` allows multiple transactions on separate threads to perform a single atomic commit. All of the actions performed by all of the atomic blocks executed by members of the barrier will appear to occur as a single atomic action, even though they are spread across multiple threads.
Commit barriers can be used to implement transactors, where actions taken by multiple actors should be atomic as a single unit.
Because there is no ordering possible between the atomic blocks that make up a commit barrier, if those transactions conflict then the only way to avoid deadlock is to roll back all of the barrier’s members.
If you observe a cancel cause of `CommitBarrier.MemberCycle` then this has happened to you, and you need to run more of the logic on a single thread inside a single transaction.
This abstraction is based on Multiverse’s `CountDownCommitBarrier`, by Peter Veentjer.
3 months ago
Ref を作る
object Ref の factory は、impl.STMImpl.instance
impl.STMImpl.instance は、scala.concurrent.stm.ccstm.CCSTM を impl.STMImpl にキャストしたもの
Ref.apply で 1:Int とか渡すと newPrimitiveRef > factory.newRef が呼ばれる
factory は、impl.RefFactory だけど CCSTMRefs.Factory が実体。CCSTM が CCSTMRefs.Factory を extends している
最終的に new IntRef(1) の結果が返る
atomic の呼び出し
atomic > scala.concurrent.stm.TxnExecutor.defaultAtomic > impl.STMImpl.instance > scala.concurrent.stm.ccstm.CCSTM という所までは、Ref と同じ
CCSTM は、CCSTMExecutor を extends している。これの def apply[Z](block: InTxn => Z)(implicit mt: MaybeTxn): Z が呼ばれる
InTxnImpl.apply の中で implicit で渡した mt が InTxnImpl だったら mt をそのまま、そーではなければ、get
一番外側の atomic なら get を、内側なら mt をそのまま返す
get は、ちょっと追えなかったので後で。
5 months ago
結果を全て Either で返すと仮定すると下記となる
(connect(host = "localhost", username = "guest", password = "guest") { conn =>
conn.channel { ch =>
for {
ex <- ch.declareExchange(name = "test.exchange", type = "direct").right
q <- ch.declareQueue(name = "test.queue").right
br <- q.bind(exchange = ex, routingKey = "test").right
pr <- ex.publish(routingKey = "test", payload = "Hello world!".getBytes).right
} yield pr
}
}) match {
case Left(e) => println(e.getMessage)
case _ =>
}
失敗は全て Exception で返すと仮定すると下記となる
try {
connect(host = "localhost", username = "guest", password = "guest") { conn =>
conn.channel { ch =>
val ex = ch.declareExchange(name = "test.exchange", type = "direct")
val q = ch.declareQueue(name = "test.queue")
q.bind(exchange = ex, routingKey = "test")
ex.publish(routingKey = "test", payload = "Hello world!".getBytes)
}
}
} catch {
case e: Exception => println(e.getMessage)
case _ =>
}
見た目も使い勝手も変わらない気がする。Scala は、どちらの記述もサポートしているので、どちらを採用するのが良いのか、さっぱり解らない。
8 months ago
以下、Java 版 RabbitMQ Client の接続例
ConnectionFactory factory = new ConnectionFactory()
factory.setUsername(userName);
factory.setPassword(password);
factory.setVirtualHost(virtualHost);
factory.setHost(hostName);
factory.setPort(portNumber);
Connection conn = factory.newConnection();
これを Scala を使ってラップしたい。
・案1:コールバック内で設定する(implicit 使ってみたい病
val conn = connect {implicit prop =>
username(userName)
password(password) // ..snip..
}
・案2:DSL で Factory を作る
考えたけど挫折
・案3:素直に名前付き引数
val conn = connect(
username -> userName,
password -> password
)
・案4:Map を使う
val conn = connect(Map(
username -> userName,
password -> password
))
Scala が得意な方は、こーいう時は、どうするんだろ?
9 months ago
親族以外の第三者から1000万を贈与された場合。
(贈与額-基礎控除額110万円)×税率-控除額=贈与税額
(1000 - 110) x 0.4 - 125 = 231
以下、参考値
(1110 - 110) x 0.4 - 125 = 275
(710 - 110) x 0.3 - 65 = 115
(510 - 110) x 0.2 - 25 = 55
(410 - 110) x 0.15 - 10 = 35
(310 - 110) x 0.1 - 0 = 20
1 year ago
sbaz install scala-devel-docs すると下記に入る。
/opt/local/share/scala-2.7/doc/scala-devel-docs/api
形式が HTML なので、どうやってコマンドラインから参照できるようにしようか悩み中。
vim からリファレンス見たいなぁ・・・。
1 year ago
/opt/local/var/macports/software/scala27/2.7.7_0/opt/local/share/scala-2.7/misc/scala-tool-support/
vim とかディレクトリがあるので、.vim 配下へごっそりコピー。
1 year ago