@@ -10,10 +10,6 @@ import errors = require('vs/base/common/errors');
1010import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc' ;
1111import { LazyPromise } from "vs/workbench/services/extensions/node/lazyPromise" ;
1212
13- interface IRPCFunc {
14- ( rpcId : string , method : string , args : any [ ] ) : winjs . TPromise < any > ;
15- }
16-
1713let lastMessageId = 0 ;
1814const pendingRPCReplies : { [ msgId : string ] : LazyPromise ; } = { } ;
1915
@@ -41,22 +37,6 @@ class MessageFactory {
4137 }
4238}
4339
44- function createRPC ( serializeAndSend : ( value : string ) => void ) : IRPCFunc {
45-
46- return function rpc ( rpcId : string , method : string , args : any [ ] ) : winjs . TPromise < any > {
47- let req = String ( ++ lastMessageId ) ;
48- let result = new LazyPromise ( ( ) => {
49- serializeAndSend ( MessageFactory . cancel ( req ) ) ;
50- } ) ;
51-
52- pendingRPCReplies [ req ] = result ;
53-
54- serializeAndSend ( MessageFactory . request ( req , rpcId , method , args ) ) ;
55-
56- return result ;
57- } ;
58- }
59-
6040export interface IManyHandler {
6141 handle ( rpcId : string , method : string , args : any [ ] ) : any ;
6242}
@@ -66,20 +46,77 @@ export interface IRemoteCom {
6646 setManyHandler ( handler : IManyHandler ) : void ;
6747}
6848
69- export function createProxyProtocol ( protocol : IMessagePassingProtocol ) : IRemoteCom {
70- let rpc = createRPC ( sendDelayed ) ;
71- let bigHandler : IManyHandler = null ;
72- let invokedHandlers : { [ req : string ] : winjs . TPromise < any > ; } = Object . create ( null ) ;
73- let messagesToSend : string [ ] = [ ] ;
49+ /**
50+ * Sends/Receives multiple messages in one go:
51+ * - multiple messages to be sent from one stack get sent in bulk at `process.nextTick`.
52+ * - each incoming message is handled in a separate `process.nextTick`.
53+ */
54+ class RPCMultiplexer {
55+
56+ private readonly _protocol : IMessagePassingProtocol ;
57+ private readonly _onMessage : ( msg : string ) => void ;
58+ private readonly _receiveOneMessageBound : ( ) => void ;
59+ private readonly _sendAccumulatedBound : ( ) => void ;
60+
61+ private _messagesToSend : string [ ] ;
62+ private _messagesToReceive : string [ ] ;
63+
64+ constructor ( protocol : IMessagePassingProtocol , onMessage : ( msg : string ) => void ) {
65+ this . _protocol = protocol ;
66+ this . _onMessage = onMessage ;
67+ this . _receiveOneMessageBound = this . _receiveOneMessage . bind ( this ) ;
68+ this . _sendAccumulatedBound = this . _sendAccumulated . bind ( this ) ;
69+
70+ this . _messagesToSend = [ ] ;
71+ this . _messagesToReceive = [ ] ;
72+
73+ this . _protocol . onMessage ( data => {
74+ // console.log('RECEIVED ' + rawmsg.length + ' MESSAGES.');
75+ if ( this . _messagesToReceive . length === 0 ) {
76+ process . nextTick ( this . _receiveOneMessageBound ) ;
77+ }
7478
75- let messagesToReceive : string [ ] = [ ] ;
76- let receiveOneMessage = ( ) => {
77- let rawmsg = messagesToReceive . shift ( ) ;
79+ this . _messagesToReceive = this . _messagesToReceive . concat ( data ) ;
80+ } ) ;
81+ }
7882
79- if ( messagesToReceive . length > 0 ) {
80- process . nextTick ( receiveOneMessage ) ;
83+ private _receiveOneMessage ( ) : void {
84+ const rawmsg = this . _messagesToReceive . shift ( ) ;
85+
86+ if ( this . _messagesToReceive . length > 0 ) {
87+ process . nextTick ( this . _receiveOneMessageBound ) ;
8188 }
8289
90+ this . _onMessage ( rawmsg ) ;
91+ }
92+
93+ private _sendAccumulated ( ) : void {
94+ const tmp = this . _messagesToSend ;
95+ this . _messagesToSend = [ ] ;
96+ this . _protocol . send ( tmp ) ;
97+ }
98+
99+ public send ( msg : string ) : void {
100+ if ( this . _messagesToSend . length === 0 ) {
101+ process . nextTick ( this . _sendAccumulatedBound ) ;
102+ }
103+ this . _messagesToSend . push ( msg ) ;
104+ }
105+ }
106+
107+ export class RPCManager implements IRemoteCom {
108+
109+ private _bigHandler : IManyHandler ;
110+ private readonly _invokedHandlers : { [ req : string ] : winjs . TPromise < any > ; } ;
111+ private readonly _multiplexor : RPCMultiplexer ;
112+
113+ constructor ( protocol : IMessagePassingProtocol ) {
114+ this . _bigHandler = null ;
115+ this . _invokedHandlers = Object . create ( null ) ;
116+ this . _multiplexor = new RPCMultiplexer ( protocol , ( msg ) => this . _receiveOneMessage ( msg ) ) ;
117+ }
118+
119+ private _receiveOneMessage ( rawmsg : string ) : void {
83120 let msg = marshalling . parse ( rawmsg ) ;
84121
85122 if ( msg . seq ) {
@@ -107,8 +144,8 @@ export function createProxyProtocol(protocol: IMessagePassingProtocol): IRemoteC
107144 }
108145
109146 if ( msg . cancel ) {
110- if ( invokedHandlers [ msg . cancel ] ) {
111- invokedHandlers [ msg . cancel ] . cancel ( ) ;
147+ if ( this . _invokedHandlers [ msg . cancel ] ) {
148+ this . _invokedHandlers [ msg . cancel ] . cancel ( ) ;
112149 }
113150 return ;
114151 }
@@ -120,62 +157,49 @@ export function createProxyProtocol(protocol: IMessagePassingProtocol): IRemoteC
120157
121158 let rpcId = msg . rpcId ;
122159
123- if ( ! bigHandler ) {
160+ if ( ! this . _bigHandler ) {
124161 throw new Error ( 'got message before big handler attached!' ) ;
125162 }
126163
127164 let req = msg . req ;
128165
129- invokedHandlers [ req ] = invokeHandler ( rpcId , msg . method , msg . args ) ;
166+ this . _invokedHandlers [ req ] = this . _invokeHandler ( rpcId , msg . method , msg . args ) ;
130167
131- invokedHandlers [ req ] . then ( ( r ) => {
132- delete invokedHandlers [ req ] ;
133- sendDelayed ( MessageFactory . replyOK ( req , r ) ) ;
168+ this . _invokedHandlers [ req ] . then ( ( r ) => {
169+ delete this . _invokedHandlers [ req ] ;
170+ this . _multiplexor . send ( MessageFactory . replyOK ( req , r ) ) ;
134171 } , ( err ) => {
135- delete invokedHandlers [ req ] ;
136- sendDelayed ( MessageFactory . replyErr ( req , err ) ) ;
172+ delete this . _invokedHandlers [ req ] ;
173+ this . _multiplexor . send ( MessageFactory . replyErr ( req , err ) ) ;
137174 } ) ;
138- } ;
175+ }
139176
140- protocol . onMessage ( data => {
141- // console.log('RECEIVED ' + rawmsg.length + ' MESSAGES.');
142- if ( messagesToReceive . length === 0 ) {
143- process . nextTick ( receiveOneMessage ) ;
177+ private _invokeHandler ( rpcId : string , method : string , args : any [ ] ) : winjs . TPromise < any > {
178+ try {
179+ return winjs . TPromise . as ( this . _bigHandler . handle ( rpcId , method , args ) ) ;
180+ } catch ( err ) {
181+ return winjs . TPromise . wrapError ( err ) ;
144182 }
183+ }
145184
146- messagesToReceive = messagesToReceive . concat ( data ) ;
147- } ) ;
148-
149- let r : IRemoteCom = {
150- callOnRemote : rpc ,
151- setManyHandler : ( _bigHandler : IManyHandler ) : void => {
152- bigHandler = _bigHandler ;
153- }
154- } ;
185+ public callOnRemote ( proxyId : string , path : string , args : any [ ] ) : winjs . TPromise < any > {
186+ let req = String ( ++ lastMessageId ) ;
187+ let result = new LazyPromise ( ( ) => {
188+ this . _multiplexor . send ( MessageFactory . cancel ( req ) ) ;
189+ } ) ;
155190
156- function sendAccumulated ( ) : void {
157- let tmp = messagesToSend ;
158- messagesToSend = [ ] ;
191+ pendingRPCReplies [ req ] = result ;
159192
160- // console.log('SENDING ' + tmp.length + ' MESSAGES.');
161- protocol . send ( tmp ) ;
162- }
193+ this . _multiplexor . send ( MessageFactory . request ( req , proxyId , path , args ) ) ;
163194
164- function sendDelayed ( value : string ) : void {
165- if ( messagesToSend . length === 0 ) {
166- process . nextTick ( sendAccumulated ) ;
167- }
168- messagesToSend . push ( value ) ;
195+ return result ;
169196 }
170197
171- function invokeHandler ( rpcId : string , method : string , args : any [ ] ) : winjs . TPromise < any > {
172- try {
173- return winjs . TPromise . as ( bigHandler . handle ( rpcId , method , args ) ) ;
174- } catch ( err ) {
175- return winjs . TPromise . wrapError ( err ) ;
176- }
198+ public setManyHandler ( handler : IManyHandler ) : void {
199+ this . _bigHandler = handler ;
177200 }
178-
179- return r ;
180201}
181202
203+ export function createProxyProtocol ( protocol : IMessagePassingProtocol ) : IRemoteCom {
204+ return new RPCManager ( protocol ) ;
205+ }
0 commit comments