1package Test2::IPC;
2use strict;
3use warnings;
4
5our $VERSION = '1.302133';
6
7
8use Test2::API::Instance;
9use Test2::Util qw/get_tid/;
10use Test2::API qw{
11    test2_init_done
12    test2_ipc
13    test2_has_ipc
14    test2_ipc_enable_polling
15    test2_pid
16    test2_stack
17    test2_tid
18    context
19};
20
21use Carp qw/confess/;
22
23our @EXPORT_OK = qw/cull/;
24BEGIN { require Exporter; our @ISA = qw(Exporter) }
25
26sub unimport { Test2::API::test2_ipc_disable() }
27
28sub import {
29    goto &Exporter::import if test2_has_ipc || !test2_init_done();
30
31    confess "IPC is disabled" if Test2::API::test2_ipc_disabled();
32    confess "Cannot add IPC in a child process (" . test2_pid() . " vs $$)" if test2_pid() != $$;
33    confess "Cannot add IPC in a child thread (" . test2_tid() . " vs " . get_tid() . ")"  if test2_tid() != get_tid();
34
35    Test2::API::_set_ipc(_make_ipc());
36    apply_ipc(test2_stack());
37
38    goto &Exporter::import;
39}
40
41sub _make_ipc {
42    # Find a driver
43    my ($driver) = Test2::API::test2_ipc_drivers();
44    unless ($driver) {
45        require Test2::IPC::Driver::Files;
46        $driver = 'Test2::IPC::Driver::Files';
47    }
48
49    return $driver->new();
50}
51
52sub apply_ipc {
53    my $stack = shift;
54
55    my ($root) = @$stack;
56
57    return unless $root;
58
59    confess "Cannot add IPC in a child process" if $root->pid != $$;
60    confess "Cannot add IPC in a child thread"  if $root->tid != get_tid();
61
62    my $ipc = $root->ipc || test2_ipc() || _make_ipc();
63
64    # Add the IPC to all hubs
65    for my $hub (@$stack) {
66        my $has = $hub->ipc;
67        confess "IPC Mismatch!" if $has && $has != $ipc;
68        next if $has;
69        $hub->set_ipc($ipc);
70        $ipc->add_hub($hub->hid);
71    }
72
73    test2_ipc_enable_polling();
74
75    return $ipc;
76}
77
78sub cull {
79    my $ctx = context();
80    $ctx->hub->cull;
81    $ctx->release;
82}
83
841;
85
86__END__
87
88=pod
89
90=encoding UTF-8
91
92=head1 NAME
93
94Test2::IPC - Turn on IPC for threading or forking support.
95
96=head1 SYNOPSIS
97
98You should C<use Test2::IPC;> as early as possible in your test file. If you
99import this module after API initialization it will attempt to retrofit IPC
100onto the existing hubs.
101
102=head2 DISABLING IT
103
104You can use C<no Test2::IPC;> to disable IPC for good. You can also use the
105T2_NO_IPC env var.
106
107=head1 EXPORTS
108
109All exports are optional.
110
111=over 4
112
113=item cull()
114
115Cull allows you to collect results from other processes or threads on demand.
116
117=back
118
119=head1 SOURCE
120
121The source code repository for Test2 can be found at
122F<http://github.com/Test-More/test-more/>.
123
124=head1 MAINTAINERS
125
126=over 4
127
128=item Chad Granum E<lt>exodist@cpan.orgE<gt>
129
130=back
131
132=head1 AUTHORS
133
134=over 4
135
136=item Chad Granum E<lt>exodist@cpan.orgE<gt>
137
138=back
139
140=head1 COPYRIGHT
141
142Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
143
144This program is free software; you can redistribute it and/or
145modify it under the same terms as Perl itself.
146
147See F<http://dev.perl.org/licenses/>
148
149=cut
150