Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
260b72e2
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
260b72e2
编写于
2月 03, 2020
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ipc: multicast events
上级
ec284758
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
64 addition
and
60 deletion
+64
-60
src/vs/base/common/arrays.ts
src/vs/base/common/arrays.ts
+4
-0
src/vs/base/parts/ipc/common/ipc.ts
src/vs/base/parts/ipc/common/ipc.ts
+57
-57
src/vs/base/parts/ipc/test/node/ipc.test.ts
src/vs/base/parts/ipc/test/node/ipc.test.ts
+3
-3
未找到文件。
src/vs/base/common/arrays.ts
浏览文件 @
260b72e2
...
...
@@ -584,3 +584,7 @@ export function mapArrayOrNot<T, U>(items: T | T[], fn: (_: T) => U): U | U[] {
export
function
asArray
<
T
>
(
x
:
T
|
T
[]):
T
[]
{
return
Array
.
isArray
(
x
)
?
x
:
[
x
];
}
export
function
getRandomElement
<
T
>
(
arr
:
T
[]):
T
{
return
arr
[
Math
.
floor
(
Math
.
random
()
*
arr
.
length
)];
}
src/vs/base/parts/ipc/common/ipc.ts
浏览文件 @
260b72e2
...
...
@@ -9,6 +9,7 @@ import { CancelablePromise, createCancelablePromise, timeout } from 'vs/base/com
import
{
CancellationToken
,
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
import
*
as
errors
from
'
vs/base/common/errors
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
getRandomElement
}
from
'
vs/base/common/arrays
'
;
/**
* An `IChannel` is an abstraction over a collection of commands.
...
...
@@ -117,8 +118,7 @@ export interface IClientRouter<TContext = string> {
* order to pick the right one.
*/
export
interface
IRoutingChannelClient
<
TContext
=
string
>
{
getChannel
<
T
extends
IChannel
>
(
channelName
:
string
,
router
:
IClientRouter
<
TContext
>
):
T
;
getBroadcastChannel
<
T
extends
IChannel
>
(
channelName
:
string
):
T
;
getChannel
<
T
extends
IChannel
>
(
channelName
:
string
,
router
?:
IClientRouter
<
TContext
>
):
T
;
}
interface
IReader
{
...
...
@@ -700,18 +700,26 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
});
}
getChannel
<
T
extends
IChannel
>
(
channelName
:
string
,
router
:
IClientRouter
<
TContext
>
):
T
{
getChannel
<
T
extends
IChannel
>
(
channelName
:
string
,
router
?
:
IClientRouter
<
TContext
>
):
T
{
const
that
=
this
;
return
{
call
(
command
:
string
,
arg
?:
any
,
cancellationToken
?:
CancellationToken
):
Promise
<
T
>
{
const
channelPromise
=
router
.
routeCall
(
that
,
command
,
arg
)
const
connectionPromise
=
router
?
router
.
routeCall
(
that
,
command
,
arg
)
:
Promise
.
resolve
(
getRandomElement
(
that
.
connections
));
const
channelPromise
=
connectionPromise
.
then
(
connection
=>
(
connection
as
Connection
<
TContext
>
).
channelClient
.
getChannel
(
channelName
));
return
getDelayedChannel
(
channelPromise
)
.
call
(
command
,
arg
,
cancellationToken
);
},
listen
(
event
:
string
,
arg
:
any
):
Event
<
T
>
{
if
(
!
router
)
{
return
that
.
getMulticastEvent
(
channelName
,
event
,
arg
);
}
const
channelPromise
=
router
.
routeEvent
(
that
,
event
,
arg
)
.
then
(
connection
=>
(
connection
as
Connection
<
TContext
>
).
channelClient
.
getChannel
(
channelName
));
...
...
@@ -721,64 +729,56 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
}
as
T
;
}
getBroadcastChannel
<
T
extends
IChannel
>
(
channelName
:
string
):
T
{
private
getMulticastEvent
<
T
extends
IChannel
>
(
channelName
:
string
,
eventName
:
string
,
arg
:
any
):
Event
<
T
>
{
const
that
=
this
;
let
disposables
=
new
DisposableStore
();
return
{
call
(
_
):
Promise
<
T
>
{
throw
new
Error
(
'
IPC broadcast channels are not supported for calls
'
);
},
listen
(
eventName
:
string
,
arg
:
any
):
Event
<
T
>
{
let
disposables
=
new
DisposableStore
();
// Create an emitter which hooks up to all clients
// as soon as first listener is added. It also
// disconnects from all clients as soon as the last listener
// is removed.
const
emitter
=
new
Emitter
<
T
>
({
onFirstListenerAdd
:
()
=>
{
disposables
=
new
DisposableStore
();
// The event multiplexer is useful since the active
// client list is dynamic. We need to hook up and disconnection
// to/from clients as they come and go.
const
eventMultiplexer
=
new
EventMultiplexer
<
T
>
();
const
map
=
new
Map
<
Connection
<
TContext
>
,
IDisposable
>
();
const
onDidAddConnection
=
(
connection
:
Connection
<
TContext
>
)
=>
{
const
channel
=
connection
.
channelClient
.
getChannel
(
channelName
);
const
event
=
channel
.
listen
<
T
>
(
eventName
,
arg
);
const
disposable
=
eventMultiplexer
.
add
(
event
);
map
.
set
(
connection
,
disposable
);
};
const
onDidRemoveConnection
=
(
connection
:
Connection
<
TContext
>
)
=>
{
const
disposable
=
map
.
get
(
connection
);
if
(
!
disposable
)
{
return
;
}
disposable
.
dispose
();
map
.
delete
(
connection
);
};
that
.
connections
.
forEach
(
onDidAddConnection
);
that
.
onDidAddConnection
(
onDidAddConnection
,
undefined
,
disposables
);
that
.
onDidRemoveConnection
(
onDidRemoveConnection
,
undefined
,
disposables
);
eventMultiplexer
.
event
(
emitter
.
fire
,
emitter
,
disposables
);
disposables
.
add
(
eventMultiplexer
);
},
onLastListenerRemove
:
()
=>
{
disposables
.
dispose
();
// Create an emitter which hooks up to all clients
// as soon as first listener is added. It also
// disconnects from all clients as soon as the last listener
// is removed.
const
emitter
=
new
Emitter
<
T
>
({
onFirstListenerAdd
:
()
=>
{
disposables
=
new
DisposableStore
();
// The event multiplexer is useful since the active
// client list is dynamic. We need to hook up and disconnection
// to/from clients as they come and go.
const
eventMultiplexer
=
new
EventMultiplexer
<
T
>
();
const
map
=
new
Map
<
Connection
<
TContext
>
,
IDisposable
>
();
const
onDidAddConnection
=
(
connection
:
Connection
<
TContext
>
)
=>
{
const
channel
=
connection
.
channelClient
.
getChannel
(
channelName
);
const
event
=
channel
.
listen
<
T
>
(
eventName
,
arg
);
const
disposable
=
eventMultiplexer
.
add
(
event
);
map
.
set
(
connection
,
disposable
);
};
const
onDidRemoveConnection
=
(
connection
:
Connection
<
TContext
>
)
=>
{
const
disposable
=
map
.
get
(
connection
);
if
(
!
disposable
)
{
return
;
}
});
return
emitter
.
event
;
disposable
.
dispose
();
map
.
delete
(
connection
);
};
that
.
connections
.
forEach
(
onDidAddConnection
);
that
.
onDidAddConnection
(
onDidAddConnection
,
undefined
,
disposables
);
that
.
onDidRemoveConnection
(
onDidRemoveConnection
,
undefined
,
disposables
);
eventMultiplexer
.
event
(
emitter
.
fire
,
emitter
,
disposables
);
disposables
.
add
(
eventMultiplexer
);
},
onLastListenerRemove
:
()
=>
{
disposables
.
dispose
();
}
}
as
T
;
});
return
emitter
.
event
;
}
registerChannel
(
channelName
:
string
,
channel
:
IServerChannel
<
TContext
>
):
void
{
...
...
src/vs/base/parts/ipc/test/node/ipc.test.ts
浏览文件 @
260b72e2
...
...
@@ -454,9 +454,9 @@ suite('Base IPC', function () {
client1
.
registerChannel
(
'
channel
'
,
clientChannel1
);
const
pings
:
string
[]
=
[];
const
broadcastChannel
=
server
.
getBroadcas
tChannel
(
'
channel
'
);
const
broadcastService
=
new
TestChannelClient
(
broadcastC
hannel
);
broadcastS
ervice
.
onPong
(
msg
=>
pings
.
push
(
msg
));
const
channel
=
server
.
ge
tChannel
(
'
channel
'
);
const
service
=
new
TestChannelClient
(
c
hannel
);
s
ervice
.
onPong
(
msg
=>
pings
.
push
(
msg
));
await
timeout
(
1
);
clientService1
.
ping
(
'
hello 1
'
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录