Slide 1

Slide 1 text

Make your own synchronization mechanism. ಉظϝΧΛϙνοͱͳɻ [email protected]

Slide 2

Slide 2 text

slide sponsors !LPV ؙٔ،؝٦سծ荈歋ח⢪ִ׷اؿزؐؑ،׾Ꟛ涪ׅ׷➂׾⹫꧊ չؙٔ،؝٦سػحث䱰欽պד嗚稊 !NBNF ְַ׃׋خ؎٦زח鸨ְ׋ְז׵չהגַպח꧊ת׶ת׃׳ ֲ 㹋遤㨻㆞ꞿ⤘״׶  !KVOF ꟼׁ׿ךز٦ؙכծ䞸׸ׇׁせ鎉׌ה䙼׏ג耮ֻהׁ׵ח嚂׃׭ ׷״ֲחז׶תׅ !UTVCPJ3VCZ,BJHJח遤ֽזְךדծ✮皾׾ֿ׍׵ח䫎♴׃תׅկ״ְ涪邌 ׾կ !1613-׮⿫⸇ׅ׷הגַדכծׁ׵ז׷⿫⸇罏׾ֶת׍׃גְתׅկ !IJSBZBTVؿؑ؎ز׍ׯ׿ַ׻ְְ״IUUQXXXGBUFNPF !PHJKVO֮הד剅ֻ !ZBODZB!IJTBTIJN!WFTUJHF@!OPQMBOT!USBDL

Slide 3

Slide 3 text

sticker sponsors

Slide 4

Slide 4 text

T-shirts sponsors TV[VSJKQN@TFLJ

Slide 5

Slide 5 text

RubyHiroba toRuby and guRuby Tochigi/Gunma Ruby meetup 2014-9-21 9:30

Slide 6

Slide 6 text

ͱͪ͗ςετͷձٞ03 2014−10−4 Ӊ౎ٶେֶ #toteka

Slide 7

Slide 7 text

no commit is good commit ERB/dRuby/Rinda

Slide 8

Slide 8 text

Buy!!! dRuby ʹΑΔ ؔকढ़ஶ ෼ࢄ ɾ Web ϓϩάϥϛϯά

Slide 9

Slide 9 text

Goͷਓؾ͕ౄ·͍͠ Goνϟωϧ͕͍͢͝ਓؾʂ RubyͷQueueΈ͍ͨͳͷ͕͙͢࢖͑Δ ͜Ε͸ένΛ͚ͭͳͯ͘͸ͳΒͳ͍

Slide 10

Slide 10 text

ࠓ೔͓࿩͢Δ͜ͱ Rubyͷ͓·͚ͷಉظͷ࢓૊Έͷ͓͞Β͍ Go෩νϟωϧͷ࡞੒Λ௨ͯ͡ಘΒΕͨૉ੖ Β͍͠஌ݟ ։ൃ೔هΛݩʹ਺λʔϯͰ

Slide 11

Slide 11 text

খ͍͞ࠒʹಡΜͩຊ

Slide 12

Slide 12 text

MINIXຊ ͍ΖΜͳಉظͷ࿩͕ग़ͯ͘Δ ಉظϝΧχζϜ͕ͳʹ͔Ұͭ͋Δͱɺଞͷछ ྨͷಉظϝΧχζϜ͕࣮૷Ͱ͖Δ

Slide 13

Slide 13 text

ಌΕ ੈքͷ࢓૊Έͷߏங ੈքͷجૅͱͳΔҰ൪খ͞ͳػೳ ਥೋ ԶͷಉظϝΧ

Slide 14

Slide 14 text

Rubyʹ͍ͭͯΔಉظϝΧ ଴ͪ߹Θͤͦͷ΋ͷ ଴ͪ߹Θͤͱ৘ใͷަ׵

Slide 15

Slide 15 text

଴߹ͤͷͨΊͷಉظϝΧ Monitorྨ Mutex MonitorMixin

Slide 16

Slide 16 text

ಉظϝΧͷ஫ҙ ަࠩ఺ͷ৴߸ػ ΈΜͳ͕कΔͱ͏·͍͘͘ कΒͳ͍ͱࣄނ͕͓͖Δ͜ͱ͕͋Δ ͓͖ͳ͍͜ͱ΋͋Δ ࣄނ͕͓͖ͳ͔͔ͬͨΒͱݴͬͯਖ਼͍͠ ͱ͸ݶΒͳ͍

Slide 17

Slide 17 text

৘ใͷަ׵΋͢ΔಉظϝΧ Queue΍TupleSpace socket, pipe ৘ใΛަ׵͢Δ ަ׵ͷ͍ͭͰʹ଴ͪ߹ΘͤΔ

Slide 18

Slide 18 text

Queue pushͱpop ۭͷͱ͖ʹpop͢Δͱpush͞ΕΔ·Ͱࢭ·Δ ʢෳ਺ͷpop͕ಉ࣌͋Δͱ͖΋͏·͘΍Δʣ

Slide 19

Slide 19 text

SizedQueue pushͱpop ۭͷͱ͖ʹpop͢Δͱpush͞ΕΔ·Ͱࢭ·Δ ʢෳ਺ͷpop͕ಉ࣌͋Δͱ͖΋͏·͘΍Δʣ ༰ྔΛӽ͑ͯpush͢Δͱۭ͘·Ͱࢭ·Δ

Slide 20

Slide 20 text

ґଘؔ܎ͱ଴ͪ߹Θͤ σʔλͷґଘؔ܎Λϓϩάϥϛϯά͢Δ͜ͱ Ͱฒߦॲཧ͕ॻ͚ͯ޷͖ʢࢲ͕ʣ ୯ͳΔ଴߹ͤΑΓ΋ϛε͠ʹ͍͘ʢࢲ͕ʣ

Slide 21

Slide 21 text

Goͷνϟωϧ εϨουؒʢͪΐͬͱӕʣͰ৘ใΛަ׵ ૹ৴ૢ࡞ͱड৴ૢ࡞ʢ<-ʣ chan <- obj it = <- chan ༰ྔʹ੍ݶ͕͋Δ SizedQueueʹࣅͯΔΑ͏ͳ...

Slide 22

Slide 22 text

ηϧϑϞνϕʔτ Α͘ௐ΂ͳ͍Ͱ࡞Δ΂͖ ௐ΂Δͱߴ͗͢Δϋʔυϧʹؾ͍ͮͯ͠·͏

Slide 23

Slide 23 text

ph.1 SizedQueue ୯ʹSizedQueueͰαϯϓϧΛॻ͖׵͑ ԋࢉࢠΊΜͲ͍͘͞ͷͰwrite, readʹͨ͠ ܕ΋ཁΒͳ͍

Slide 24

Slide 24 text

SizedQueueͦͷ΋ͷ def initialize(size) @writing = SizedQueue.new(size) end def read @writing.pop end def write(value) @writing.push(value) end

Slide 25

Slide 25 text

SizedQueue͡Όͳ͔ͬͨ 㱺 ͳΜ͔ҧ͏͜ͱʹؾ͍ͮͨ େ͖͕͞0ͷνϟωϧ ૹ৴ऀͱड৴ऀ͕ἧ͏·Ͱ଴߹ͤ େ͖͕͞1Ҏ্ͷͱ͖͸SizedQueueͱಉ͡ ࢓༷ΛΑ͘ௐ΂ͨ΄͏͕͍͍

Slide 26

Slide 26 text

ph.2 ࣗ෼ͰٳΉ࡞ઓ size͕0ͷͱ͖ͷڍಈΛಛผʹ͢Δ writer͸pushͷ͋ͱsleep͢Δ reader͸popͷ͋ͱwakeup͢Δ

Slide 27

Slide 27 text

ph.2 ࣗ෼ͰٳΉ࡞ઓ def initialize(size=0) @size = size if size == 0 @writing = SizedQueue.new(1) else @writing = SizedQueue.new(size) end end def read return @writing.pop if @size > 0 value, writer = @writing.pop return value ensure writer.wakeup if @size == 0 end def write(value) return @writing.push(value) if @size > 0 @writing.push([value, Thread.current]) sleep end 5ISFBE׾床׃ג 饯ֿ׃ג׮׵ֲ 5ISFBE׾床׃ג 饯ֿ׃ג׮׵ֲ

Slide 28

Slide 28 text

wakeupͷ͋ͱʹsleep... def initialize(size=0) @size = size if size == 0 @writing = SizedQueue.new(1) else @writing = SizedQueue.new(size) end end def read return @writing.pop if @size > 0 value, writer = @writing.pop return value ensure writer.wakeup if @size == 0 end def write(value) return @writing.push(value) if @size > 0 @writing.push([value, Thread.current]) sleep end ر٦ة ꟦麩ְ

Slide 29

Slide 29 text

͍·ͷ͸μϝͳྫ ࣗ෼Ͱsleepͱ͔͍͍ͨͯؒҧͬͯΔʢͷΛ ࢥ͍ग़ͨ͠ʣ Rubyʹ͍ͭͯΔ෦඼Λ࢖͏΄͏͕ྑ͍

Slide 30

Slide 30 text

ph.3 Χ΢ϯςΟϯάηϚϑΥ ࠷ॳ͔Βͦ͏͠Ζ ·͡Ίʹॻ͘ͷΊΜͲ͏ͳͷͰQueueͰ୅༻

Slide 31

Slide 31 text

όοϑΝΛ਺͑Δ܎ def initialize(size) @reading = Queue.new @writing = Queue.new size.times { @reading.push(true) } end def read @reading.push(true) @writing.pop end def write(value) @reading.pop @writing.push(value) end ر٦ة

Slide 32

Slide 32 text

QueueͰηϚϑΥ def initialize(size) @reading = Queue.new @writing = Queue.new size.times { @reading.push(true) } end def read @reading.push(true) @writing.pop end def write(value) @reading.pop @writing.push(value) end ず劍欽 ず劍欽 إوؿؓ

Slide 33

Slide 33 text

όοϑΝ෼up͠ͱ͘ def initialize(size) @reading = Queue.new @writing = Queue.new size.times { @reading.push(true) } end def read @reading.push(true) @writing.pop end def write(value) @reading.pop @writing.push(value) end غحؿ؋ⴓ

Slide 34

Slide 34 text

׬੒ͨ͠ͱࢥͬͨ Queue͸୯७ͰԠ༻΋؆୯ ಉظϝΧ࡞Γ΍͍͢ ͕ɺ΋͏ͪΐͬͱௐ΂ͨΒselect͕͋ͬͨ...

Slide 35

Slide 35 text

select Goνϟωϧʹ͸select͕͋ΔΒ͍͠ ଟݩ଴ͪ ෳ਺ͷνϟωϧʹ͍ͭͯɺಡΜͰ΋ϒϩοΫ ͠ͳ͍νϟωϧΛฦ͢

Slide 36

Slide 36 text

selectΊΜͲ͍͘͞ ෳ਺ͷνϟωϧͷ͏ͪɺͲΕ͔Ұ͕ͭ readableʹͳΔ·ͰͷϒϩοΫ Queue#pop͸ϒϩοΫͪ͠Ό͏

Slide 37

Slide 37 text

ෳ਺QueueͰselect ෳ਺ͷQueueΛ·ͱΊΔQueue࡞ઓ νϟωϧͷ਺͚ͩεϨουඞཁ popͰ͖ͨͱ͖ʹ͸ཁૉΛফඅͯ͠Δ selectͱ͍͏͔Βʹ͸ফඅ͠ͳ͍ํ͕Ϟς ಉ͡ޮՌͷΞϓϦέʔγϣϯ͸ॻ͚Δ͚Ͳಉ ͡ΠϯλʔϑΣΠε೉͍͠

Slide 38

Slide 38 text

΍ͬͺΓ Queueϕʔεͷ࡞ઓ͸μϝͳͷͰ͸...

Slide 39

Slide 39 text

Wait a moment ✓ +12:00ɹ ✓ Queueܥྻ͸ศར ✓ selectҎ֎͸؆୯ʹ࡞Εͦ͏ ✓ ࣍͸select΋Մೳͳ࣮૷

Slide 40

Slide 40 text

ph.4 TupleSpace࢖͏ ζϧ write, take, read takeͱreadʹ͸ύλʔϯ͕ࢦఆͰ͖Δ === ෳࡶͳঢ়ଶΛ͍͍ͩͨ଴ͯΔ readableͳνϟωϧΛಡΉʗ଴ͭ ͙͢Ͱ͖ͦ͏

Slide 41

Slide 41 text

࢖͍ํ͔Βઃܭ͢Δ chan1 = ChannelSpace.open(1) chan1.write('hello') p chan1.read chan2 = ChannelSpace.open(0) timeout = ChannelSpace.after(10) readable = ChannelSpace.select([chan1, chan2, timeout]) p readable.read

Slide 42

Slide 42 text

openͰੜ੒ chan1 = ChannelSpace.open(1) chan1.write('hello') p chan1.read chan2 = ChannelSpace.open(0) timeout = ChannelSpace.after(10) readable = ChannelSpace.select([chan1, chan2, timeout]) p readable.read إوؿؓ PQFO )BOEMF

Slide 43

Slide 43 text

write/read chan1 = ChannelSpace.open(1) chan1.write('hello') p chan1.read chan2 = ChannelSpace.open(0) timeout = ChannelSpace.after(10) readable = ChannelSpace.select([chan1, chan2, timeout]) p readable.read XSJUF SFBE

Slide 44

Slide 44 text

nඵޙʹͳʹ͔ૹΔνϟωϧ chan1 = ChannelSpace.open(1) chan1.write('hello') p chan1.read chan2 = ChannelSpace.open(0) timeout = ChannelSpace.after(10) readable = ChannelSpace.select([chan1, chan2, timeout]) p readable.read TFD

Slide 45

Slide 45 text

readableΛฦ͢ chan1 = ChannelSpace.open(1) chan1.write('hello') p chan1.read chan2 = ChannelSpace.open(0) timeout = ChannelSpace.after(10) readable = ChannelSpace.select([chan1, chan2, timeout]) p readable.read BSSBZ ׉ך䖓 SFBE

Slide 46

Slide 46 text

Ͱ͖ͨ # -*- coding: utf-8 -*- require 'rinda/tuplespace' class ChannelSpace include DRbUndumped class ChannelError < RuntimeError def initialize(str, handle) @channel = handle super(str) end attr_reader :channel end class Readable def ===(it) it.readable? end end class Any def initialize(ary) @ary = ary end def ===(it) @ary.include?(it) end end class Channel def initialize(ts, size, handle) @ts = ts @handle = handle @reader = [] @writer = [] @buf = [] @size = size @closed = false end def readable? _readable? || @closed end def _readable? @buf.size + @writer.size > 0 end def close @closed = true while writer = @writer.shift @ts.write([:write, @handle, writer[1], self]) end while reader = @reader.shift @ts.write([:read, @handle, reader, self]) end end def writer_shift return if @writer.empty? value, key = @writer.shift @buf << value @ts.write([:write, @handle, key, value]) end def buf_push(value) @writer << [value, Thread.current] if @buf.size < @size writer_shift end end def buf_shift writer_shift @buf.shift end def req_read if _readable? @ts.write([:read, @handle, Thread.current, buf_shift]) else raise ChannelError.new('closed channel.', @handle) if @closed @reader << Thread.current end end def req_write(value) raise ChannelError.new('closed channel.', @handle) if @closed buf_push(value) return if @reader.empty? @ts.write([:read, @handle, @reader.shift, buf_shift]) end end class Handle include DRbUndumped def initialize(cs) @cs = cs end def write(value) @cs.write(self, value) end def read @cs.read(self) end def close @cs.close(self) end end def initialize @ts = Rinda::TupleSpace.new @readable = Readable.new end def open(size=0) handle = Handle.new(self) @ts.write([handle, Channel.new(@ts, size, handle)]) handle end def close(handle) begin _, chan = @ts.take([handle, nil]) chan.close ensure @ts.write([handle, chan]) end end def write(handle, value) begin _, chan = @ts.take([handle, nil]) chan.req_write(value) ensure @ts.write([handle, chan]) end _, _, _, value = @ts.take([:write, handle, Thread.current, nil]) raise ChannelError.new('closed channel.', handle) if value == chan value end def read(handle) begin _, chan = @ts.take([handle, nil]) chan.req_read ensure @ts.write([handle, chan]) end _, _, _, value = @ts.take([:read, handle, Thread.current, nil]) raise ChannelError.new('closed channel.', handle) if value == chan value end def select(set) handle, _ = @ts.read([Any.new(set), @readable]) handle end def select_and_read(set) begin handle, chan = @ts.take([Any.new(set), @readable]) chan.req_read ensure @ts.write([handle, chan]) end _, _, _, value = @ts.take([:read, handle, Thread.current, nil]) raise ChannelError.new('closed channel.', handle) if value == chan return handle, value end def after(sec, value=nil) chan = open Thread.new {sleep sec; chan.write(value)} chan end @cs = self.new def self.open(size=0) @cs.open(size) end def self.after(sec, value=nil) @cs.after(sec, value) end def self.select(set) @cs.select(set) end def self.select_and_read(set) @cs.select_and_read(set) end end

Slide 47

Slide 47 text

TupleSpaceʹӅ͢ $IBOOFM4QBDF 5VQMF4QBDF $IBOOFM $IBOOFM $IBOOFM )BOEMF )BOEMF )BOEMF )BOEMF 銲稆ךUVQMF

Slide 48

Slide 48 text

ର৅ʹ஫໨ͨ͠ഉଞ੍ޚ def write(handle, value) begin _, chan = @ts.take([handle, nil]) chan.req_write(value) ensure @ts.write([handle, chan]) end _, _, _, value = @ts.take([:write, handle, Thread.current, nil]) raise ChannelError.new('closed channel.', handle) if value == chan value end def read(handle) begin _, chan = @ts.take([handle, nil]) chan.req_read ensure @ts.write([handle, chan]) end _, _, _, value = @ts.take([:read, handle, Thread.current, nil]) raise ChannelError.new('closed channel.', handle) if value == chan value end UBLF XSJUF UBLF XSJUF UBLF XSJUF UBLF XSJUF 㥨ֹז 乼⡲

Slide 49

Slide 49 text

Actor෩௨৴ def write(handle, value) begin _, chan = @ts.take([handle, nil]) chan.req_write(value) ensure @ts.write([handle, chan]) end _, _, _, value = @ts.take([:write, handle, Thread.current, nil]) raise ChannelError.new('closed channel.', handle) if value == chan value end def read(handle) begin _, chan = @ts.take([handle, nil]) chan.req_read ensure @ts.write([handle, chan]) end _, _, _, value = @ts.take([:read, handle, Thread.current, nil]) raise ChannelError.new('closed channel.', handle) if value == chan value end SFRVFTU SFR SFT SFT GSPN IBOEMF WBMVF LJOE

Slide 50

Slide 50 text

selectͷ࣮૷ def select(set) handle, _ = @ts.read([Any.new(set), @readable]) handle end ... class Readable def ===(it) it.readable? end end class Any def initialize(ary) @ary = ary end def ===(it) @ary.include?(it) end end  DIBOOFM IBOEMF DIBOOFM IBOEMF DIBOOFM IBOEMF 

Slide 51

Slide 51 text

selectͷ࣮૷ def select(set) handle, _ = @ts.read([Any.new(set), @readable]) handle end ... class Readable def ===(it) it.readable? end end class Any def initialize(ary) @ary = ary end def ===(it) @ary.include?(it) end end  DIBOOFM IBOEMF DIBOOFM IBOEMF DIBOOFM IBOEMF ػة٦ٝ UTSFBE

Slide 52

Slide 52 text

ph.5 MonitorͰॻ͖௚͢ ΍ͬͯͳ͍

Slide 53

Slide 53 text

ph.6 ֦ுϥΠϒϥϦԽ ΋ͪΖΜ΍ͬͯͳ͍

Slide 54

Slide 54 text

·ͱΊ Goνϟωϧ෩ಉظϝΧΛॻ͖ͳ͕Βɺ։ൃ ͷ༷ࢠͱςΫχοΫͷҰ෦Λࣔͨ͠ ಉظϝΧ͸ಉظϝΧͰॻ͚ΔͷͰ͍͍ͪͪͼͬ ͘Γ͠ͳ͍ TupleSpace͸ಉظϝΧͷϓϩτλΠϓʹྑ͍ ͷͰຊΛങ͓͏

Slide 55

Slide 55 text

·ͱΊ ΞϓϦέʔγϣϯͷϢʔεέʔεͷࢹ఺Ͱߟ ͑Δͱ΋ͬͱྑ͍౴͕͑͋Δʢͷ͸࿩͞ͳ͔ͬ ͨʣ