1/*
2  Copyright (C) 2000-2005 SKYRIX Software AG
3
4  This file is part of SOPE.
5
6  SOPE is free software; you can redistribute it and/or modify it under
7  the terms of the GNU Lesser General Public License as published by the
8  Free Software Foundation; either version 2, or (at your option) any
9  later version.
10
11  SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14  License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with SOPE; see the file COPYING.  If not, write to the
18  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19  02111-1307, USA.
20*/
21
22#include <NGStreams/NGLockingStream.h>
23#include "common.h"
24
25@implementation NGLockingStream
26
27+ (id)filterWithSource:(id<NGStream>)_source lock:(id<NSObject,NSLocking>)_lock {
28  return [[[self alloc] initWithSource:_source lock:_lock] autorelease];
29}
30
31- (id)initWithSource:(id<NGStream>)_source lock:(id<NSObject,NSLocking>)_lock {
32  if ((self = [super initWithSource:_source])) {
33    if (_lock == nil) {
34      readLock  = [[NSRecursiveLock allocWithZone:[self zone]] init];
35      writeLock = [readLock retain];
36    }
37    else {
38      readLock  = [_lock    retain];
39      writeLock = [readLock retain];
40    }
41  }
42  return self;
43}
44
45- (id)initWithSource:(id<NGStream>)_source {
46  return [self initWithSource:_source lock:nil];
47}
48
49- (void)dealloc {
50  [self->readLock  release];
51  [self->writeLock release];
52  [super dealloc];
53}
54
55// primitives
56
57- (unsigned)readBytes:(void *)_buf count:(unsigned)_len {
58  volatile unsigned result = 0;
59
60  [readLock lock];
61
62  NS_DURING {
63    result = (readBytes != NULL)
64      ? (unsigned)readBytes(source, _cmd, _buf, _len)
65      : [source readBytes:_buf count:_len];
66  }
67  NS_HANDLER {
68    [readLock unlock];
69    [localException raise];
70  }
71  NS_ENDHANDLER;
72  [readLock unlock];
73
74  return result;
75}
76
77- (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len {
78  volatile unsigned result = 0;
79
80  [writeLock lock];
81
82  NS_DURING {
83    result = (writeBytes != NULL)
84      ? (unsigned)writeBytes(source, _cmd, _buf, _len)
85      : [source writeBytes:_buf count:_len];
86  }
87  NS_HANDLER {
88    [writeLock unlock];
89    [localException raise];
90  }
91  NS_ENDHANDLER;
92  [writeLock unlock];
93
94  return result;
95}
96
97- (BOOL)flush {
98  BOOL res = NO;
99
100  [writeLock lock];
101
102  NS_DURING {
103    res = [super flush];
104  }
105  NS_HANDLER {
106    [writeLock unlock];
107    [localException raise];
108  }
109  NS_ENDHANDLER;
110  [writeLock unlock];
111  return res;
112}
113
114- (BOOL)safeReadBytes:(void *)_buf  count:(unsigned)_len {
115  BOOL res = NO;
116
117  [readLock lock];
118
119  NS_DURING {
120    res = [super safeReadBytes:_buf count:_len];
121  }
122  NS_HANDLER {
123    [readLock unlock];
124    [localException raise];
125  }
126  NS_ENDHANDLER;
127  [readLock unlock];
128
129  return res;
130}
131
132- (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len {
133  BOOL res = NO;
134
135  [writeLock lock];
136
137  NS_DURING {
138    res = [super safeWriteBytes:_buf count:_len];
139  }
140  NS_HANDLER {
141    [writeLock unlock];
142    [localException raise];
143  }
144  NS_ENDHANDLER;
145  [writeLock unlock];
146  return res;
147}
148
149@end /* NGLockingStream */
150