Subject: RE: [SWIPL] Thread Create using Sockets

From: "Douglas R. Miles" <[email-masked]>
Date: Wed, 26 Sep 2001 13:48:19 -0700

Hi,

The program below seems to work:

But I am wondering if the socket_in/1,socket_out/1 and answer_yes are
exclusive to each thread?

(Partially because I am new to using with_mutex/2.)

Also is "threads,  % Free Up Complete Threads" necessary?  Is there a way I
can call it that doesn't write to std*? 

:-use_module(library(socket)).      
:-dynamic(socket_in/1).
:-dynamic(socket_out/1).

run_swi_server(Port):- 
	thread_create(thread_le(Port),_,[]).

thread_le(Port):-
	tcp_socket(ServerSocket),
	please_tcp_bind(ServerSocket, Port),
	tcp_listen(ServerSocket, 666),
	repeat,
	once(work_on_server_socket(ServerSocket)),
	fail.

please_tcp_bind(ServerSocket, Port):-
	catch((
		tcp_bind(ServerSocket, Port),
		format(user_error,'~nOS gave me port ~w. ~n',[Port])
		),
		error(E,_),
		(
		format(user_error,'~nWaiting for port ~w. (sleeping 4 secs
because "~w")~n',[Port,E]),
		sleep(4),
		please_tcp_bind(ServerSocket, Port)
		)).
	
work_on_server_socket(ServerSocket):-
	tcp_open_socket(ServerSocket, AcceptFd, _Useless),
	tcp_accept(AcceptFd, ClientSocket, _PeerIP), 
	work_on_client_socket_mt(ClientSocket).

work_on_client_socket_mt(ClientSocket):-
      threads,  % Free Up Complete Threads
	thread_create((
		mutex_create(Id),
		mutex_lock(Id),!,
		with_mutex(Id,work_on_client_socket(ClientSocket)),
		mutex_unlock_all,
		thread_exit(complete)
	),_,[detatch(true)]).

work_on_client_socket(ClientSocket):-
	tcp_open_socket(ClientSocket, In, Out),!,
	thread_self(Self),
	format(user_error,'% thread="~w" input="~w" output="~w"
~n',[Self,In,Out]),
	flush_output(user_error),
	retractall(socket_in(_)),
	retractall(socket_out(_)),
	asserta(socket_in(In)),
	asserta(socket_out(Out)),
	
catch(service_telnet_request(In,Out),E,writeq(service_one_client(E))),
	ignore((
		catch(flush_output(Out),_,true),
		catch(tcp_close_socket(ClientSocket),_,true)
		)).

service_telnet_request(In,Out):-
	catch(thread_self(Self),_,true),
        format(Out,'<?xml version="1.0" encoding="ISO-8859-1"?>~n<answer
thread="~w">~n',
				[Self]),
	flush_output(Out),
      once(( catch(read_term(In,CMD,[variable_names(Vars)]),_,
			(format(Out,'<badinput/>~n',[]),flush_output(Out)))
		)),
	statistics(cputime,Start),
	invoke_cmd(Out,CMD,Vars),
	statistics(cputime,End),
	Elapsed is End - Start,
	format(Out,'<statistics cputime="~g"/>~n',[Elaspsed]),	
	format(Out,'</answer>~n',[]),
      catch(flush_output(Out),_,true).

invoke_cmd(Out,CMD,Vars):-
      tell(Out),
      retractall(answer_yes),
      catch(CMD,Err,(format('<error description="~w"/>',[Err]),!,fail)),
      assert(answer_yes),
      write_swi_vars_proc(Out,Vars),
      fail.

invoke_cmd(Out,_,_):-   
         (retract(answer_yes) -> 
                format(Out,'<yes/>~n',[]) 
                 ;
                format(Out,'<no/>~n',[])),!. 

write_swi_vars_proc(Out,[]):-!.
write_swi_vars_proc(Out,Vars):-
         write(Out,'<result>'),
         write_swi_vars(Out,Vars),
         format(Out,'</result>~n',[]).
                              
write_swi_vars(Out,[]):-!.
write_swi_vars(Out,[Term|REST]):-  !,Term=..[_,N,V],
         format(Out,'<var name="~w">~q</var>',[N,V]),
         write_swi_vars(Out,REST).

:-run_swi_server(5000).
:-run_swi_server(7000).

Thank you in adavance, 
	Douglas