File Coverage

blib/lib/Thread/Queue/Queueable.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #/**
2             # Abstract base class defining the interfaces, and providing
3             # simple marshalling methods, for complex object to be passed
4             # across a Thread::Queue::Duplex
5             # queue.
6             #

7             # Licensed under the Academic Free License version 2.1, as specified in the
8             # License.txt file included in this software package, or at
9             # OpenSource.org.
10             #
11             # @author D. Arnold
12             # @since 2005-12-01
13             # @self $obj
14             #*/
15             package Thread::Queue::Queueable;
16             #
17             # abstract class to permit an object to be
18             # marshalled in some way before pushing onto
19             # a Thread::Queue::Duplex queue
20             #
21             require 5.008;
22              
23 1     1   2293 use threads;
  0            
  0            
24             use threads::shared;
25              
26             use strict;
27             use warnings;
28              
29             our $VERSION = '0.90';
30              
31             #/**
32             # Marshal an object for queueing to a Thread::Queue::Duplex
33             # queue. Called by any of TQD's enqueue() methods,
34             # as well as respond() method.
35             #

36             # The default implementation the input
37             # object into either a shared array or shared hash (depending on the base structure
38             # of the object), and returns a list consisting of the object's class name, and the cursed object.
39             #
40             # @returnlist list of (object's class, object's marshalled representation)
41             #*/
42             sub onEnqueue {
43             my $obj = shift;
44             #
45             # capture class name, and create cursed
46             # version of object
47             #
48             return (ref $obj, $obj->curse());
49             }
50              
51             #/**
52             # Unmarshall an object after being dequeued. Called by any of TQD's
53             # dequeue() methods,
54             # as well as the various request side dequeueing
55             # methods (e.g., wait()).
56             #

57             # The default implementation redeem()'s the input object
58             # to copy the input shared arrayref or hashref into a nonshared equivalent, then
59             # blessing it into the specified class, returning the redeemed object.
60             #
61             # @param $object the marshalled representation of the object
62             # @return the unmarshalled aka "redeemed" object
63             #*/
64             sub onDequeue {
65             my ($class, $obj) = @_;
66             #
67             # reconstruct as non-shared by redeeming
68             #
69             return $class->redeem($obj);
70             }
71              
72             #/**
73             # Pure virtual function to apply any object-specific cancel processing. Called by TQD's
74             # respond() method
76             # when a cancelled operation is detected.
77             #
78             # @return 1
79             #*/
80             sub onCancel {
81             my $obj = shift;
82             return 1;
83             }
84             #/**
85             # Marshal an object into a value that can be passed via
86             # a Thread::Queue::Duplex object.
87             #

88             # Called by TQD's various enqueue() and
89             # respond() methods
90             # when the TQQ object is being enqueue'd. Should return an unblessed,
91             # shared version of the input object.
92             #

93             # Default returns a shared
94             # arrayref or hashref, depending on the object's base structure, with
95             # copies of all scalar members.
96             #

97             # Note that objects with more complex members will need to
98             # implement an object specific curse() to do any deepcopying,
99             # including curse()ing any subordinate objects.
100             #
101             # @return marshalled version of the object
102             #*/
103             sub curse {
104             my $obj = shift;
105             #
106             # if we're already shared, don't share again
107             #
108             return $obj if threads::shared::_id($obj);
109              
110             if ($obj->isa('HASH')) {
111             my %cursed : shared = ();
112             $cursed{$_} = $obj->{$_}
113             foreach (keys %$obj);
114             return \%cursed;
115             }
116              
117             my @cursed : shared = ();
118             $cursed[$_] = $obj->[$_]
119             foreach (0..$#$obj);
120             return \@cursed;
121             }
122             #/**
123             # Unmarshall an object back into its blessed form.
124             #

125             # Called by TQD's various dequeue() and
126             # wait methods to
127             # "redeem" (i.e., rebless) the object into its original class.
128             #

129             # Default creates non-shared copy of the input object structure,
130             # copying its scalar contents, and blessing it into the specified class.
131             #

132             # Note that objects with complex members need to implement
133             # an object specific redeem(), possibly recursively
134             # redeem()ing subordinate objects (be careful
135             # of circular references!)
136             #
137             # @param $object marshalled aka "cursed" version of the object
138             #
139             # @return unmarshalled, blessed version of the object
140             #*/
141             sub redeem {
142             my ($class, $obj) = @_;
143             #
144             # if object is already shared, just rebless it
145             # NOTE: we can only do this when threads::shared::_id() is defined
146             #
147             return bless $obj, $class
148             if threads::shared->can('_id') && threads::shared::_id($obj);
149             #
150             # we *could* just return the blessed object,
151             # which would be shared...but that might
152             # not be the expected behavior...
153             #
154             if (ref $obj eq 'HASH') {
155             my $redeemed = {};
156             $redeemed->{$_} = $obj->{$_}
157             foreach (keys %$obj);
158             return bless $redeemed, $class;
159             }
160              
161             my $redeemed = [];
162             $redeemed->[$_] = $obj->[$_]
163             foreach (0..$#$obj);
164             return bless $redeemed, $class;
165             }
166              
167             1;