ConnectionQueue improvement (changes)

Peter Schuller peter.schuller at infidyne.com
Sun Jan 21 01:46:42 UTC 2001


Hello,

attached is a set of changes that adds blocking I/O to the ConnectionQueue
class. Specifically, it adds a waitForConnection method. It uses a semaphore
to achieve the blocking functionality. listenLoop and oldStyleListelLoop has
been changed to signal that semaphore when a connection is accepted.

This is something I personally want. Is it something that might get added to
"standard" Squeak?

If not, I'll re-write the functionality in a separate class. I don't want to
rely on non-standard modifications to standard classes.

-- 
/ Peter Schuller, InfiDyne Technologies HB

PGP userID: 0x5584BD98 or 'Peter Schuller <peter.schuller at infidyne.com>'
Key retrival: Send an E-Mail to getpgpkey at scode.infidyne.com
E-Mail: peter.schuller at infidyne.com Web: http://scode.infidyne.com

-------------- next part --------------
'From Squeak2.9alpha of 4 January 2001 [latest update: #3144] on 20 January 2001 at 8:42:33 pm'!
Object subclass: #ConnectionQueue
	instanceVariableNames: 'portNumber maxQueueLength connections accessSema socket process blockingSemaphore '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Network-Kernel'!

!ConnectionQueue methodsFor: 'public' stamp: 'PS 1/20/2001 20:41'!
waitForConnection
	| socketToReturn |
	"Answers a connected socket. This method will block forever until such
	 a socket becomes available."

	[ accessSema critical: [
		connections isEmpty ifFalse: [
			socketToReturn _ connections removeFirst.
			(socketToReturn isValid and: [socketToReturn isConnected.])
				ifTrue: [^ socketToReturn.]
				ifFalse: [ socketToReturn destroy.].].
			
		].
	  blockingSemaphore wait.
	] repeat.! !

!ConnectionQueue methodsFor: 'private' stamp: 'PS 1/20/2001 20:17'!
initPortNumber: anInteger queueLength: queueLength
	"Private!! Initialize the receiver to listen on the g!
iven port number. Up to queueLength connections will be queued."

	blockingSemaphore _ Semaphore new.
	portNumber _ anInteger.
	maxQueueLength _ queueLength.
	connections _ OrderedCollection new.
	accessSema _ Semaphore forMutualExclusion.
	socket _ nil.
	process _ [self listenLoop] newProcess.
	process priority: Processor highIOPriority.
	process resume.
! !

!ConnectionQueue methodsFor: 'private' stamp: 'PS 1/20/2001 20:18'!
listenLoop
	"Private!! This loop is run in a separate process. It will establish up to maxQueueLength connections on the given port."
	"Details: When out of sockets or queue is full, retry more frequently, since a socket may become available, space may open in the queue, or a previously queued connection may be aborted by the client, making it available for a fresh connection."
	"Note: If the machine is disconnected from the network while the server is running, the currently waiting socket will go from 'isWaitingForConnection' to 'unconnected', and attem!
pts to create new sockets will fail. When this happens, delete the broken socket and keep trying to create a socket in case the network connection is re-established. Connecting and disconnecting was tested under PPP on Mac system 8.1. It is not if this will work on other platforms."


	| newConnection |
	Socket initializeNetwork.
	socket _ Socket newTCP.
	"We'll accept four simultanous connections at the same time"
	socket listenOn: portNumber backlogSize: 4.
	"If the listener is not valid then the we cannot use the
	BSD style accept() mechanism."
	socket isValid ifFalse: [^self oldStyleListenLoop].
	[true] whileTrue: [
		socket isValid ifFalse: [
			"socket has stopped listening for some reason"
			socket destroy.
			(Delay forMilliseconds: 10) wait.
			^self listenLoop ].
		newConnection _ socket waitForAcceptUntil: (Socket deadlineSecs: 10).
		(newConnection notNil and:[newConnection isConnected]) ifTrue:
			[accessSema critical: [connections addLast: newConnection.
							!
	  blockingSemaphore signal.].
			newConnection _ nil].
		self pruneStaleConnections]. ! !

!ConnectionQueue methodsFor: 'private' stamp: 'PS 1/20/2001 20:18'!
oldStyleListenLoop
	"Private!! This loop is run in a separate process. It will establish up to maxQueueLength connections on the given port."
	"Details: When out of sockets or queue is full, retry more frequently, since a socket may become available, space may open in the queue, or a previously queued connection may be aborted by the client, making it available for a fresh connection."
	"Note: If the machine is disconnected from the network while the server is running, the currently waiting socket will go from 'isWaitingForConnection' to 'unconnected', and attempts to create new sockets will fail. When this happens, delete the broken socket and keep trying to create a socket in case the network connection is re-established. Connecting and disconnecting was tested under PPP on Mac system 8.1. It is not if this will work !
on other platforms."

	[true] whileTrue: [
		((socket == nil) and: [connections size < maxQueueLength]) ifTrue: [
			"try to create a new socket for listening"
			socket _ Socket createIfFail: [nil]].

		socket == nil
			ifTrue: [(Delay forMilliseconds: 100) wait]
			ifFalse: [
				socket isUnconnected ifTrue: [socket listenOn: portNumber].
				socket waitForConnectionUntil: (Socket deadlineSecs: 10).
				socket isConnected
					ifTrue: [  "connection established"
						accessSema critical: [connections addLast: socket.
											 blockingSemaphore signal.].
						socket _ nil]
					ifFalse: [
						socket isWaitingForConnection
							ifFalse: [socket destroy. socket _ nil]]].  "broken socket; start over"
		self pruneStaleConnections].
! !


More information about the Squeak-dev mailing list