1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/BLIP/BLIPWriter.m Fri May 23 17:37:36 2008 -0700
1.3 @@ -0,0 +1,150 @@
1.4 +//
1.5 +// BLIPFrameWriter.m
1.6 +// MYNetwork
1.7 +//
1.8 +// Created by Jens Alfke on 5/18/08.
1.9 +// Copyright 2008 Jens Alfke. All rights reserved.
1.10 +//
1.11 +
1.12 +#import "BLIPReader.h"
1.13 +#import "BLIPWriter.h"
1.14 +#import "BLIP_Internal.h"
1.15 +
1.16 +
1.17 +#define kDefaultFrameSize 4096
1.18 +
1.19 +
1.20 +@implementation BLIPWriter
1.21 +
1.22 +
1.23 +- (void) dealloc
1.24 +{
1.25 + [_outBox release];
1.26 + [super dealloc];
1.27 +}
1.28 +
1.29 +- (void) disconnect
1.30 +{
1.31 + [_outBox makeObjectsPerformSelector: @selector(_connectionClosed) withObject: nil];
1.32 + setObj(&_outBox,nil);
1.33 + [super disconnect];
1.34 +}
1.35 +
1.36 +@synthesize numQueriesSent=_numQueriesSent;
1.37 +
1.38 +
1.39 +- (BOOL) isBusy
1.40 +{
1.41 + return _outBox.count>0 || [super isBusy];
1.42 +}
1.43 +
1.44 +
1.45 +- (void) _queueMessage: (BLIPMessage*)msg isNew: (BOOL)isNew
1.46 +{
1.47 + int n = _outBox.count, index;
1.48 + if( msg.urgent && n > 1 ) {
1.49 + // High-priority gets queued after the last existing high-priority message,
1.50 + // leaving one regular-priority message in between if possible.
1.51 + for( index=n-1; index>0; index-- ) {
1.52 + BLIPMessage *otherMsg = [_outBox objectAtIndex: index];
1.53 + if( [otherMsg urgent] ) {
1.54 + index = MIN(index+2, n);
1.55 + break;
1.56 + } else if( isNew && otherMsg._bytesWritten==0 ) {
1.57 + // But have to keep message starts in order
1.58 + index = index+1;
1.59 + break;
1.60 + }
1.61 + }
1.62 + if( index==0 )
1.63 + index = 1;
1.64 + } else {
1.65 + // Regular priority goes at the end of the queue:
1.66 + index = n;
1.67 + }
1.68 + if( ! _outBox )
1.69 + _outBox = [[NSMutableArray alloc] init];
1.70 + [_outBox insertObject: msg atIndex: index];
1.71 +
1.72 + if( isNew ) {
1.73 + LogTo(BLIP,@"%@ queuing outgoing %@ at index %i",self,msg,index);
1.74 + if( n==0 )
1.75 + [self queueIsEmpty];
1.76 + }
1.77 +}
1.78 +
1.79 +
1.80 +- (BOOL) sendMessage: (BLIPMessage*)message
1.81 +{
1.82 + if( _shouldClose ) {
1.83 + Warn(@"%@: Attempt to send a message after the connection has started closing",self);
1.84 + return NO;
1.85 + }
1.86 + Assert(!message.sent,@"message has already been sent");
1.87 + [self _queueMessage: message isNew: YES];
1.88 + return YES;
1.89 +}
1.90 +
1.91 +
1.92 +- (BOOL) sendRequest: (BLIPRequest*)q response: (BLIPResponse*)response
1.93 +{
1.94 + if( !_shouldClose ) {
1.95 + [q _assignedNumber: ++_numQueriesSent];
1.96 + if( response ) {
1.97 + [response _assignedNumber: _numQueriesSent];
1.98 + [(BLIPReader*)self.reader _addPendingResponse: response];
1.99 + }
1.100 + }
1.101 + return [self sendMessage: q];
1.102 +}
1.103 +
1.104 +
1.105 +- (void) queueIsEmpty
1.106 +{
1.107 + if( _outBox.count > 0 ) {
1.108 + // Pop first message in queue:
1.109 + BLIPMessage *msg = [[_outBox objectAtIndex: 0] retain];
1.110 + [_outBox removeObjectAtIndex: 0];
1.111 +
1.112 + // As an optimization, allow message to send a big frame unless there's a higher-priority
1.113 + // message right behind it:
1.114 + size_t frameSize = kDefaultFrameSize;
1.115 + if( msg.urgent || _outBox.count==0 || ! [[_outBox objectAtIndex: 0] urgent] )
1.116 + frameSize *= 4;
1.117 +
1.118 + if( [msg _writeFrameTo: self maxSize: frameSize] ) {
1.119 + // add it back so it can send its next frame later:
1.120 + [self _queueMessage: msg isNew: NO];
1.121 + }
1.122 + [msg release];
1.123 + } else {
1.124 + LogTo(BLIPVerbose,@"%@: no more work for writer",self);
1.125 + }
1.126 +}
1.127 +
1.128 +
1.129 +
1.130 +@end
1.131 +
1.132 +
1.133 +/*
1.134 + Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
1.135 +
1.136 + Redistribution and use in source and binary forms, with or without modification, are permitted
1.137 + provided that the following conditions are met:
1.138 +
1.139 + * Redistributions of source code must retain the above copyright notice, this list of conditions
1.140 + and the following disclaimer.
1.141 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
1.142 + and the following disclaimer in the documentation and/or other materials provided with the
1.143 + distribution.
1.144 +
1.145 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
1.146 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
1.147 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
1.148 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1.149 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1.150 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1.151 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
1.152 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.153 + */