BLIP/BLIPWriter.m
changeset 0 9d67172bb323
child 1 8267d5c429c4
     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 + */