File: 40-threads.t

package info (click to toggle)
libvariable-magic-perl 0.64-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 476 kB
  • sloc: perl: 4,256; ansic: 633; makefile: 8
file content (130 lines) | stat: -rw-r--r-- 3,037 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!perl

use strict;
use warnings;

use lib 't/lib';
use VPIT::TestHelpers (
 threads => [ 'Variable::Magic' => 'Variable::Magic::VMG_THREADSAFE()' ],
);

use Test::Leaner 'no_plan';

my $destroyed : shared = 0;

sub try {
 my ($dispell, $op_info) = @_;
 my $tid = threads->tid;

 my $c = 0;
 my $wiz;

 {
  local $@;
  eval { require Variable::Magic; 1 } or return;
 }

 {
  local $@;
  $wiz = eval {
   Variable::Magic::wizard(
    data    => sub { $_[1] + $tid },
    get     => sub { ++$c; 0 },
    set     => sub {
     my $op = $_[-1];

     my $assign_op    = ("$]" < 5.037_003) ? 'sassign': 'padsv_store';
     my $assign_op_cl = ("$]" < 5.037_003) ? 'B::BINOP': 'B::UNOP';

     if ($op_info eq 'object') {
      is_deeply { class => ref($op),   name => $op->name },
                { class => $assign_op_cl, name => $assign_op },
                "op object in thread $tid is correct";
     } else {
      is $op, $assign_op, "op name in thread $tid is correct";
     }

     return 0;
    },
    free    => sub { lock $destroyed; ++$destroyed; 0 },
    op_info => $op_info eq 'object' ? Variable::Magic::VMG_OP_INFO_OBJECT()
                                    : Variable::Magic::VMG_OP_INFO_NAME()
   );
  };
  is $@,     '',    "wizard in thread $tid doesn't croak";
  isnt $wiz, undef, "wizard in thread $tid is defined";
  is $c,     0,     "wizard in thread $tid doesn't trigger magic";
 }

 my $a = 3;

 {
  local $@;
  my $res = eval { &Variable::Magic::cast(\$a, $wiz, sub { 5 }->()) };
  is $@, '', "cast in thread $tid doesn't croak";
  is $c, 0,  "cast in thread $tid doesn't trigger magic";
 }

 {
  local $@;
  my $b;
  eval { $b = $a };
  is $@, '', "get in thread $tid doesn't croak";
  is $b, 3,  "get in thread $tid returns the right thing";
  is $c, 1,  "get in thread $tid triggers magic";
 }

 {
  local $@;
  my $d = eval { &Variable::Magic::getdata(\$a, $wiz) };
  is $@, '',       "getdata in thread $tid doesn't croak";
  is $d, 5 + $tid, "getdata in thread $tid returns the right thing";
  is $c, 1,        "getdata in thread $tid doesn't trigger magic";
 }

 {
  local $@;
  eval { $a = 9 };
  is $@, '', "set in thread $tid (check opname) doesn't croak";
 }

 if ($dispell) {
  {
   local $@;
   my $res = eval { &Variable::Magic::dispell(\$a, $wiz) };
   is $@, '', "dispell in thread $tid doesn't croak";
   is $c, 1,  "dispell in thread $tid doesn't trigger magic";
  }

  {
   local $@;
   my $b;
   eval { $b = $a };
   is $@, '', "get in thread $tid after dispell doesn't croak";
   is $b, 9,  "get in thread $tid after dispell returns the right thing";
   is $c, 1,  "get in thread $tid after dispell doesn't trigger magic";
  }
 }

 return 1;
}

for my $dispell (1, 0) {
 {
  lock $destroyed;
  $destroyed = 0;
 }

 my $completed = 0;

 my @threads = map spawn(\&try, $dispell, $_), ('name') x 2, ('object') x 2;
 for my $thr (@threads) {
  my $res = $thr->join;
  $completed += $res if defined $res;
 }

 {
  lock $destroyed;
  is $destroyed, (1 - $dispell) * $completed, 'destructors';
 }
}