source: xplcommon/src/xplcommon/BlockingStream.cc@ 29:54c2d451f8a0

Last change on this file since 29:54c2d451f8a0 was 29:54c2d451f8a0, checked in by István Váradi <ivaradi@…>, 11 years ago

Implemented a blocking stream and a corresponding trst program

File size: 5.0 KB
Line 
1// Copyright (c) 2013 by István Váradi
2
3// This file is part of libxplcommon, a common utility library for
4// development related to X-Plane
5
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8
9// 1. Redistributions of source code must retain the above copyright notice, this
10// list of conditions and the following disclaimer.
11// 2. Redistributions in binary form must reproduce the above copyright notice,
12// this list of conditions and the following disclaimer in the documentation
13// and/or other materials provided with the distribution.
14
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26// The views and conclusions contained in the software and documentation are those
27// of the authors and should not be interpreted as representing official policies,
28// either expressed or implied, of the FreeBSD Project.
29
30//------------------------------------------------------------------------------
31
32#include "BlockingStream.h"
33
34#include "ReadingBuffer.h"
35#include "WritingBuffer.h"
36
37#include <cstring>
38#include <cstdio>
39
40//------------------------------------------------------------------------------
41
42using xplcommon::BlockingStream;
43
44using std::min;
45
46//------------------------------------------------------------------------------
47
48bool BlockingStream::isInterrupted()
49{
50 if (failed()) return false;
51
52 if (!interrupted) {
53 interrupted = event.check();
54 if (!interrupted && event.failed()) {
55 setErrorCode(event.getErrorCode());
56 }
57 }
58
59 return interrupted;
60}
61
62//------------------------------------------------------------------------------
63
64bool BlockingStream::read(void* dest, size_t length)
65{
66 unsigned char* d = reinterpret_cast<unsigned char*>(dest);
67
68 ReadingBuffer& readingBuffer = stream.getReadingBuffer();
69 while (length>0) {
70 size_t toCopy = min(readingBuffer.getLength() - readingOffset, length);
71 if (toCopy>0) {
72 memcpy(d, readingBuffer.getData() + readingOffset, toCopy);
73 readingOffset += toCopy;
74 length -= toCopy;
75 d += toCopy;
76 }
77
78 if (length==0) break;
79
80 readingBuffer.reset();
81 readingOffset = 0;
82 while (!failed()) {
83 if (isInterrupted()) return false;
84
85 if (readingBuffer.read()) {
86 if (readingBuffer.isEmpty()) return false;
87 break;
88 } else if (readingBuffer.failed()) {
89 setErrorCode(readingBuffer.getErrorCode());
90 } else {
91 Waiter* waiter = stream.getWaiter();
92 waiter->wait();
93 if (waiter->failed()) {
94 setErrorCode(waiter->getErrorCode());
95 }
96 }
97 }
98 if (failed()) return false;
99 }
100
101 return true;
102}
103
104//------------------------------------------------------------------------------
105
106bool BlockingStream::write(const void* src, size_t length)
107{
108 const unsigned char* s = reinterpret_cast<const unsigned char*>(src);
109
110 WritingBuffer& writingBuffer = stream.getWritingBuffer();
111 while(length>0) {
112 size_t toCopy = min(length, writingBuffer.getAvailable());
113 if (toCopy>0) {
114 memcpy(writingBuffer.getData() + writingBuffer.getLength(),
115 s, toCopy);
116 writingBuffer.addLength(toCopy);
117 length -= toCopy;
118 s += toCopy;
119 }
120
121 if (length==0) break;
122 if (!flush()) return false;
123 }
124
125 return true;
126}
127
128//------------------------------------------------------------------------------
129
130bool BlockingStream::flush()
131{
132 WritingBuffer& writingBuffer = stream.getWritingBuffer();
133 while (!failed()) {
134 if (isInterrupted()) return false;
135
136 if (writingBuffer.write()) {
137 return true;
138 } else if (writingBuffer.failed()) {
139 setErrorCode(writingBuffer.getErrorCode());
140 return false;
141 } else {
142 Waiter* waiter = stream.getWaiter();
143 waiter->wait();
144 if (waiter->failed()) {
145 setErrorCode(waiter->getErrorCode());
146 }
147 }
148 }
149 return false;
150}
151
152//------------------------------------------------------------------------------
153
154// Local Variables:
155// mode: C++
156// c-basic-offset: 4
157// indent-tabs-mode: nil
158// End:
Note: See TracBrowser for help on using the repository browser.