Net-Curl

 view release on metacpan or  search on metacpan

examples/04-share-threads.pl  view on Meta::CPAN

	# create a shared share object
	my $self :shared = $class->SUPER::new( \%base );

	# share both cookies and dns
	$self->setopt( CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE );
	$self->setopt( CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS );

	# Net::Curl::Share locks each datum automatically, this will
	# prevent memory corruption.
	#
	# we use semaphore to lock share completely
	$self->{sem} = Thread::Semaphore->new();
	
	return $self;
}

# this locks way too much, but works as expected
sub lock
{
	my $share = shift;
	$share->{sem}->down();
	$share->{blocker} = threads->tid();
}

sub unlock
{
	my $share = shift;
	unless ( exists $share->{blocker} ) {
		warn "Tried to unlock share that wasn't locked\n";
		return;
	}
	unless ( $share->{blocker} == threads->tid() ) {
		warn "Tried to unlock share from another thread\n";
		return;
	}
	delete $share->{blocker};
	$share->{sem}->up();
}

1;

=head2 TEST Easy package

This Easy::Threads object will block whole share object for duration of dns
name resolution and until headers are completely received.

=cut
package Easy::Threads;
use strict;
use warnings;
use Net::Curl::Easy qw(/^CURLOPT_.*/);
use base qw(Net::Curl::Easy);

sub new
{
	my $class = shift;
	my $share = shift;

	my $easy = $class->SUPER::new( { body => '', head => '' } );
	$easy->setopt( CURLOPT_VERBOSE, 1 );
	$easy->setopt( CURLOPT_WRITEHEADER, \$easy->{head} );
	$easy->setopt( CURLOPT_FILE, \$easy->{body} );
	$easy->setopt( CURLOPT_HEADERFUNCTION, \&cb_header );
	$easy->setopt( CURLOPT_SHARE, $share );

	return $easy;
}

sub cb_header {
	my ( $easy, $data, $uservar ) = @_;

	if ( $data eq "\r\n" ) {
		# we have all the headers now, allow other threads to run
		$easy->share->unlock()
			unless $easy->{unlocked};

		$easy->{unlocked} = 1;
	}

	$$uservar .= $data;

	return length $data;
}

sub get
{
	my $easy = shift;
	my $uri = shift;

	$easy->setopt( CURLOPT_URL, $uri );
	$easy->{uri} = $uri;
	$easy->{body} = '';
	$easy->{head} = '';
	delete $easy->{unlocked};

	# lock share
	$easy->share->lock();

	# ok, now we can request
	eval {
		$easy->perform();
	};

	# There may have been some problem, make sure we unlock the share.
	# This should issue a warning, check $easy->{unlocked} to see
	# whether we really need to unlock.
	$easy->share->unlock();

	# return something
	return $easy->{body};
}

1;

=head2 TEST APPLICATION

Sample application using this module looks like this:

	#!perl
	use threads;
	use threads::shared;



( run in 1.438 second using v1.01-cache-2.11-cpan-39bf76dae61 )