Chris Knipe <sav...@savage.za.org> writes:

> Hi,
>
> Are there any Cache::* modules that are thread safe and can be used with
> Threading?
>
> Using Cache::Memory (even specifying the same NameSpace), two or more
> threads can't access the same keys in the cache,
>
> Using Cache::File, there are issues with the indexes (documented too under
> Caveats,
>
> Neither can be :shared, Invalid value for shared scalar
>
> I'm basically just looking for a key->value type of way to share data
> between the threads, but I would prefer not to use an external resource
> such as memcached or redis.

Looking at the code below, I would probably just use a database.  With
that, I could queue up, process and send data asynchronously with as
many processes as I want to and have no issues from threading.

> Master thread basically uses Thread::Queues to enqueue work received via an
> IO::Socket::INET, slaves process the work (while the client socket waits),
> and then the master thread returns the result from the queued work back
> over the TCP socket.
>
> With IO::Select and IO::Sockets, this is the rundown of the client loop...
>
> while (1) {
>   foreach my $ClientConnection ($Select->can_read(1)) {
>     if ($ClientConnection == $ServerSocket) {
>       $ClientConnection = $ServerSocket->accept();
>       $Select->add($ClientConnection);
>     } else {
>       my $Data = $ClientConnection->getline();
>       unless (defined($Data) && length($Data)) {
>         $Select->remove($ClientConnection);
>         $ClientConnection->shutdown(2);
>         close $ClientConnection;
>         next;
>       }

I think you need to dequeue data here when you're closing a client
connection because no data has been sent and it has taken longer than 2
seconds to process the data that has previously been sent.

Otherwise, don't close the data connection unless a response has been
sent to the client if data from it was enqueued and tell the client to
wait instead.  When the client is told to wait, it can decide for itself
if it wants to wait or not and close the connection at will when not,
like when it figures that the sever is down because it hasn't received
any response within a reasonable amount of time.

Of course, when a client closes a connection, you need to dequeue the
data it has sent (unless the server is down).

>       if ($RequestQueue->pending() > $MaxConnections*4) {
>         $ClientConnection->send("400 Too busy\r\n");
>         next;
>       } else {
>         $Data =~ s/[^ -~]//g;
>         $RequestQueue->enqueue($Data);

I'd move this:

>         my $Processed = 0;
>         my $TimeStamp = time();
>         if (defined($Data) && length($Data)) {
>           do {
>             # $Cache->set is called in the worker threads
>             my $Response = $Cache->get($Data);
>             if ($Response && $Response ne "") {
>               $ClientConnection->send($Response);
>               $Cache->remove($Data);
>               $Processed=1;
>             }
>           } until ($Processed==1 || time() - $TimeStamp >= 2);
>         }
>       }
>     }
>   }
> }

like so:

>         if (defined($Data) && length($Data)) {
>           my $Processed = 0;
>           my $TimeStamp = time();
>           do {
>             # $Cache->set is called in the worker threads
>             my $Response = $Cache->get($Data);
>             if ($Response && $Response ne "") {
>               $ClientConnection->send($Response);
>               $Cache->remove($Data);
>               $Processed=1;
>             }
>           } until ($Processed==1 || time() - $TimeStamp >= 2);
>         }
>       }
>     }
>   }
> }

How do you know for which client the data you get from the chache is?

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to