1implement Messages; 2 3# 4# message queues and their users 5# 6 7include "messages.m"; 8 9clientidgen := 1; 10 11init() 12{ 13 clientidgen = 1; 14} 15 16Msglist.new(): ref Msglist 17{ 18 msgs := ref Msglist; 19 msgs.tail = ref Msg; # valid Msg when .next != nil 20 return msgs; 21} 22 23Msglist.queue(msgs: self ref Msglist): ref Msg 24{ 25 return msgs.tail; 26} 27 28Msglist.wait(msgs: self ref Msglist, u: ref User, rd: ref Readreq) 29{ 30 msgs.readers = (u, rd) :: msgs.readers; # list reversed, but currently does not matter 31} 32 33Msglist.write(msgs: self ref Msglist, m: ref Msg): list of (ref User, ref Readreq) 34{ 35 tail := msgs.tail; 36 tail.from = m.from; 37 tail.data = m.data; 38 tail.next = ref Msg(nil, nil, nil); 39 msgs.tail = tail.next; # next message will be formed in tail.next 40 rl := msgs.readers; 41 msgs.readers = nil; 42 return rl; 43} 44 45Msglist.flushtag(msgs: self ref Msglist, tag: int) 46{ 47 rl := msgs.readers; 48 msgs.readers = nil; 49 for(; rl != nil; rl = tl rl){ 50 (nil, req) := hd rl; 51 if(req.tag != tag) 52 msgs.readers = hd rl :: msgs.readers; 53 } 54} 55 56Msglist.flushfid(msgs: self ref Msglist, fid: int) 57{ 58 rl := msgs.readers; 59 msgs.readers = nil; 60 for(; rl != nil; rl = tl rl){ 61 (nil, req) := hd rl; 62 if(req.fid != fid) 63 msgs.readers = hd rl :: msgs.readers; 64 } 65} 66 67User.new(fid: int, name: string): ref User 68{ 69 return ref User(clientidgen++, fid, name, nil); 70} 71 72User.initqueue(u: self ref User, msgs: ref Msglist) 73{ 74 u.queue = msgs.tail; 75} 76 77User.read(u: self ref User): ref Msg 78{ 79 if((m := u.queue).next != nil){ 80 u.queue = m.next; 81 m = ref *m; # copy to ensure no aliasing 82 m.next = nil; 83 return m; 84 } 85 return nil; 86} 87