Created
September 30, 2012 07:07
-
-
Save gakuzzzz/3806119 to your computer and use it in GitHub Desktop.
ThreadSafe jetty server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.yuroyoro.websocket | |
import javax.servlet.http._ | |
import org.eclipse.jetty.websocket._ | |
import org.eclipse.jetty.websocket.WebSocket.Outbound | |
import java.util.concurrent.atomic._ | |
class ChatServlet extends WebSocketServlet { | |
val clients = new AtomicReference[Set[ChatWebSocket]](Set()) | |
override def doGet(req:HttpServletRequest, res:HttpServletResponse ) = | |
getServletContext.getNamedDispatcher("default").forward(req, res) | |
override def doWebSocketConnect(req:HttpServletRequest, protocol:String ) = | |
new ChatWebSocket | |
class ChatWebSocket extends WebSocket { | |
@volatile var outbound:Outbound = _ | |
override def onConnect(outbound:Outbound ) = { | |
this.outbound = outbound | |
clients.lazySet(clients.get + this) | |
onMessage( 0, "WebSocket is success!!!"); | |
} | |
override def onMessage(frame:Byte, data:Array[Byte], offset:Int, length:Int ) = {} | |
override def onMessage(frame:Byte, data:String ) = | |
clients.get.foreach{ c => c.outbound.sendMessage( frame, data ) } | |
override def onDisconnect = clients.lazySet(clients.get - this) | |
} | |
} |
ミソっていうか、immutable版のSet使いたかったらこうなるって感じですかね。
mutable版のSetで良ければ素直に CopyOnWriteArraySet 使っちゃうのがいいと思います。
connect/disconnect よりも message の方が多いっぽいですし。
調べました。
なるほど、CopyOnWriteArraySetってのは、イテレータ(以下Ite)を回している最中にSetに変更があったら、別のSetを作って変更を受け入れるのですね。
メリット
Ite走査中に更新が走っても、Ite側は影響を受けない
デメリット
頻繁に更新が発生すると(Ite走査と更新がバッティングすると)パフォーマンスが落ちる
Immutableじゃない
そのため、Ite走査が多く、更新が少ないSet(List)の場合効果が高い。
対して、immutable版は、Immutableなコレクションとは、変更不可なため、参照さえ保持して入れば、過去のすべてのバージョンを見ることが出来る。
そのため、Iteが走査するSetは、必然的に過去のいつかのバージョンのSetとなり、そもそも他から影響を受けることはない。
その代わり、Setに要素を追加する度に新しいSetへの参照を保持する必要がある。Scalaの場合は、そのへんはmutableにすることが出きるが、Haskellなんかだと、参照を保持する側もImmutableなんで、新しい参照が必要で・・・と、どこまでも連鎖してしまう。この辺のところはモナドで何とかするのかな?
Haskell の場合は、このCASループの様なことを内部的にやってくれる STM っていうモナドがあったりします。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
おお。これはカッコいい。
これなら、パフォーマンスへの影響も少なそうですね。
自分もこんな感じの処理にしたかったんですが、力不足で、単純なSynchronizedにしちゃいました。てへ
immutable版のSetを使っている?ところがミソ?