transforms/Xtreams__TransformWriteStream.st
author mkobetic
Sun, 15 Jan 2012 22:38:15 +0000
changeset 50 475076a05319
parent 40 9cf7a05861e6
child 51 79cd91a589d8
permissions -rw-r--r--
packaging
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50
475076a05319 packaging
mkobetic
parents: 40
diff changeset
     1
'From Smalltalk/X, Version:6.2.1 on 15-01-2012 at 05:38:19 PM'                  !
40
9cf7a05861e6 sockets and files
mkobetic
parents: 35
diff changeset
     2
10
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
     3
"{ Package: 'stx:goodies/xtreams/transforms' }"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
     4
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
     5
"{ NameSpace: Xtreams }"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
     6
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
     7
WriteStream subclass:#TransformWriteStream
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
     8
	instanceVariableNames:'buffer block closeBlock process incompleteCount readReady
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
     9
		writeReady closeReady'
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    10
	classVariableNames:''
40
9cf7a05861e6 sockets and files
mkobetic
parents: 35
diff changeset
    11
	poolDictionaries:'XtreamsPool'
27
2cc5a8a3ca14 added XtreamsPool to fix DefaultBufferSize; set proper category names
mkobetic
parents: 10
diff changeset
    12
	category:'Xtreams-Transforms'
10
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    13
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    14
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    15
TransformWriteStream comment:'Transform write stream provides the most expressive form of transformation. The transformation is described by a binary block that is given two arguments, @input and @output. The @input is a virtual stream of elements written into the stream. The @output is the destination stream under the transform stream. The block can read arbitrary amount of elements from @input (including none) and write arbitrary amount of elements into @output (including none). The block will be invoked as many times as necessary to consume everything written into the stream, or until an Incomplete is raised by the destination.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    16
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    17
The closing behavior of the stream can be customized through the closeBlock. The default closeBlock simply propagates #close to the destination as with any other transform stream.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    18
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    19
In some cases it might be desirable to tweak the buffering strategy of the virtual input stream. In that case the buffer of the stream can be set manually to any kind of Buffer that matches the requirements of the transformation.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    20
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    21
From the point of view of the API, the TransformWriteStream is very much like the TransformReadStream. Notably any valid transform block should work the same way on either read or write stream without modification. However to preserve the invariants and expressivity of the transform block, the implementation is vastly different. Primarily it is necessary to convert all the writes into a virtual stream of written elements that can be passed into the transform block as the input stream. Consequently the transformation itself needs to be suspended if there weren''t enough elements written yet, to complete an iteration of the transform block. Therefore it needs to run in its own process. Any writes get redirected into an internal buffer and a background process repeatedly invokes the transform block to drain the contents of the buffer and produces output into the destination. Obviously buffer access has to be synchronized between any writing threads and the background process. The readReady/writeReady semaphores work in a lock-step mode, to interleave the background buffer draining with any writes.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    22
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    23
Instance Variables
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    24
	buffer	<Buffer> holds the contents of the virtual input stream
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    25
	block	<BlockClosure> binary transformation block that reads elements from input (first argument) and writes elements into output (second argument)
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    26
	closeBlock	<BlockClosure> binary block invoked in response to the #close message, allows customizing the close behavior
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    27
	process	<Process> background process that runs the transformation block
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    28
	incompleteCount	<Integer> indicates that the transformation raised or received Incomplete and how many elements were actually consumed by the transformation block so that we can reraise Incomplete with correct count in the client thread
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    29
	readReady	<Semaphore> signals to the background process that elements were written into the buffer
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    30
	writeReady	<Semaphore> gates any writes into the stream, making sure background process is not draining the buffer at the same time
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    31
	closeReady	<Semaphore> signals back to the user thread that the background process finished draining the buffer and the stream is properly closed, so the #close call can return
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    32
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    33
'
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    34
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    35
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    36
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    37
!TransformWriteStream class methodsFor:'instance creation'!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    38
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    39
on: aWriteStream block: block
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    40
	^self new on: aWriteStream block: block
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    41
! !
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    42
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    43
!TransformWriteStream methodsFor:'accessing'!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    44
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    45
block
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    46
	^block
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    47
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    48
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    49
buffer
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    50
	^buffer
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    51
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    52
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    53
closeBlock
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    54
	^closeBlock
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    55
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    56
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    57
insert: anInteger from: aSequenceableCollection at: startIndex
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    58
	| count amount |
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    59
	anInteger isZero ifTrue: [^0].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    60
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    61
	count := 0.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    62
	[count < anInteger] whileTrue:
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    63
		[amount := anInteger - count.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    64
		buffer hasFixedWriteSpace ifTrue: [amount := amount min: buffer cacheSize].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    65
		buffer insert: amount from: aSequenceableCollection at: startIndex + count.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    66
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    67
		"There is now data in the buffer for the drain to read"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    68
		readReady signal.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    69
		writeReady wait.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    70
		incompleteCount == nil ifFalse: [(Incomplete count: count + incompleteCount) raise].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    71
		count := count + amount ].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    72
	^anInteger
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    73
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    74
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    75
put: anObject
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    76
	incompleteCount == nil ifFalse: [Incomplete zero raise].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    77
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    78
	buffer put: anObject.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    79
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    80
	"There is now data in the buffer for the drain to read"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    81
	readReady signal.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    82
	writeReady wait
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    83
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    84
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    85
write: anInteger from: aSequenceableCollection at: startIndex
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    86
	| count amount |
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    87
	anInteger isZero ifTrue: [^0].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    88
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    89
	count := 0.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    90
	[count < anInteger] whileTrue:
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    91
		[amount := anInteger - count.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    92
		buffer hasFixedWriteSpace ifTrue: [amount := amount min: buffer cacheSize].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    93
		buffer write: amount from: aSequenceableCollection at: startIndex + count.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    94
		
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    95
		"There is now data in the buffer for the drain to read"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    96
		readReady signal.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    97
		writeReady wait.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    98
		incompleteCount == nil ifFalse: [(Incomplete count: count + incompleteCount) raise].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
    99
		count := count + amount ].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   100
	^anInteger
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   101
! !
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   102
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   103
!TransformWriteStream methodsFor:'initialize-release'!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   104
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   105
buffer: aBuffer
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   106
	buffer := aBuffer.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   107
	self drainBuffer
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   108
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   109
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   110
close
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   111
	buffer ifNil: [^self].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   112
	"Write nothing to the buffer, but signal that there is data to read, causing the drain to throw Incomplete"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   113
	readReady signal.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   114
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   115
	"Wait for the drain to finish up completely. Rearm the closeReady incase somebody calls #close again."
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   116
	closeReady wait.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   117
	closeReady signal.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   118
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   119
	closeBlock cull: destination cull: self.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   120
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   121
	buffer recycle.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   122
	buffer := nil
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   123
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   124
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   125
closeBlock: anObject
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   126
	closeBlock := anObject
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   127
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   128
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   129
contentsSpecies
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   130
	^buffer contentsSpecies
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   131
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   132
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   133
contentsSpecies: aClass
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   134
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   135
	self buffer: (buffer class new: buffer cacheSize class: aClass)
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   136
!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   137
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   138
on: aStreamable block: aBlock
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   139
	super on: aStreamable.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   140
	block := aBlock.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   141
	incompleteCount := nil.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   142
	closeBlock := [ :destinationStream | destinationStream close].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   143
	buffer := ElasticBuffer new: DefaultBufferSize class: aStreamable contentsSpecies.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   144
	self drainBuffer
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   145
! !
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   146
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   147
!TransformWriteStream methodsFor:'printing'!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   148
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   149
streamingPrintOn: aStream
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   150
	super streamingPrintOn: aStream.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   151
	aStream
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   152
		space;
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   153
		write: '#';
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   154
		write: block method homeMethod selector;
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   155
		write: ' buffered: ';
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   156
		print: buffer writeSize.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   157
	buffer writeSize isZero ifTrue: [^self].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   158
	aStream
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   159
		cr; tab;
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   160
		print: buffer contentsPast
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   161
! !
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   162
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   163
!TransformWriteStream methodsFor:'private'!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   164
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   165
drainBuffer
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   166
	| reading |
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   167
	process ifNotNil: [process terminate].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   168
	incompleteCount == nil ifFalse: [^self].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   169
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   170
	closeReady := Semaphore new.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   171
	readReady := Semaphore new.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   172
	writeReady := Semaphore new.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   173
	reading := buffer reading transforming: [:in :out |
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   174
		| count |
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   175
		"Wait for the main process to have written to the buffer"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   176
		readReady wait.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   177
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   178
		"If nothing was written to the buffer, this indicates we're closing, we raise Incomplete"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   179
		(count := buffer readSize) isZero ifTrue: [Incomplete zero raise].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   180
		out write: count from: in.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   181
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   182
		"Allow the main process to write to the buffer"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   183
		writeReady signal].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   184
	process := [
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   185
		[[block value: reading value: destination] repeat] on: Incomplete do: [].
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   186
		incompleteCount := reading buffer readPosition.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   187
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   188
		"Signal that we're closed so that an attempt to write or close will immediately complete"
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   189
		writeReady signal.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   190
		closeReady signal]
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   191
			newProcess.
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   192
	process resume
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   193
! !
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   194
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   195
!TransformWriteStream class methodsFor:'documentation'!
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   196
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   197
version_SVN
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   198
    ^ '$Id$'
3813193bdf4e first cut
Martin Kobetic <mkobetic@gmail.com>
parents:
diff changeset
   199
! !