Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions source/ExtBufStreambuf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#ifndef CODE_ExtBufStreambuf
#define CODE_ExtBufStreambuf

#include <streambuf>
#include <ios>

// A std::streambuf backed by a caller-owned, fixed-size char buffer (zero-copy).
//
// This replaces the non-portable idiom
// someStringStream.rdbuf()->pubsetbuf(externalBuffer, size);
// which STAR used to read/write reads and SAM/BAM records directly from/to a
// pre-allocated char array without copying.
//
// std::basic_stringbuf::setbuf() (what pubsetbuf() calls on a string stream) has
// implementation-defined behavior: libstdc++ (GCC/Linux) adopts the external
// buffer, but libc++ (clang/macOS) ignores it entirely. With libc++ the streams
// therefore stayed empty, which made STAR read 0 input reads and write empty
// SAM/BAM output. This class implements the buffer adoption explicitly so the
// behavior is identical on every standard library.
class ExtBufStreambuf : public std::streambuf {
public:
// Use the external buffer as the get (read) area: [base, base+n).
void setReadBuffer(char* base, std::streamsize n) {
setg(base, base, base + n);
}

// Use the external buffer as the put (write) area: [base, base+n).
void setWriteBuffer(char* base, std::streamsize n) {
setp(base, base + n);
}

protected:
pos_type seekoff(off_type off, std::ios_base::seekdir dir,
std::ios_base::openmode which) override {
if (which & std::ios_base::in) {
char* base = eback();
char* end = egptr();
char* newp = (dir == std::ios_base::beg) ? base + off
: (dir == std::ios_base::cur) ? gptr() + off
: end + off;
if (newp < base) newp = base;
if (newp > end) newp = end;
setg(base, newp, end);
return pos_type(newp - base);
}
if (which & std::ios_base::out) {
char* base = pbase();
char* end = epptr();
char* newp = (dir == std::ios_base::beg) ? base + off
: (dir == std::ios_base::cur) ? pptr() + off
: end + off;
if (newp < base) newp = base;
if (newp > end) newp = end;
setp(base, end);
pbump(static_cast<int>(newp - base));
return pos_type(newp - base);
}
return pos_type(off_type(-1));
}

pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
return seekoff(off_type(sp), std::ios_base::beg, which);
}
};

#endif
13 changes: 7 additions & 6 deletions source/ReadAlignChunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,23 @@ ReadAlignChunk::ReadAlignChunk(Parameters& Pin, Genome &genomeIn, Transcriptome
RA->iRead=0;

chunkIn=new char* [P.readNends];
readInStream=new istringstream* [P.readNends];

readInStream=new istream* [P.readNends];
readInStreamBuf=new ExtBufStreambuf [P.readNends];

for (uint ii=0;ii<P.readNends;ii++) {
chunkIn[ii]=new char[P.chunkInSizeBytesArray];//reserve more space to finish loading one read
memset(chunkIn[ii],'\n',P.chunkInSizeBytesArray);
readInStream[ii] = new istringstream;
readInStream[ii]->rdbuf()->pubsetbuf(chunkIn[ii],P.chunkInSizeBytesArray);
readInStreamBuf[ii].setReadBuffer(chunkIn[ii],P.chunkInSizeBytesArray);
readInStream[ii] = new istream(&readInStreamBuf[ii]);
RA->readInStream[ii]=readInStream[ii];
};


if (P.outSAMbool) {
chunkOutBAM=new char [P.chunkOutBAMsizeBytes];
RA->outBAMarray=chunkOutBAM;
chunkOutBAMstream=new ostringstream;
chunkOutBAMstream->rdbuf()->pubsetbuf(chunkOutBAM,P.chunkOutBAMsizeBytes);
chunkOutBAMstreamBuf.setWriteBuffer(chunkOutBAM,P.chunkOutBAMsizeBytes);
chunkOutBAMstream=new ostream(&chunkOutBAMstreamBuf);
RA->outSAMstream=chunkOutBAMstream;
RA->outSAMstream->seekp(0,ios::beg);
chunkOutBAMtotal=0;
Expand Down
7 changes: 5 additions & 2 deletions source/ReadAlignChunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Transcriptome.h"
#include "BAMoutput.h"
#include "Quantifications.h"
#include "ExtBufStreambuf.h"

class ReadAlignChunk {//chunk of reads and alignments
public:
Expand All @@ -25,8 +26,10 @@ class ReadAlignChunk {//chunk of reads and alignments
BAMoutput *chunkOutBAMcoord, *chunkOutBAMunsorted, *chunkOutBAMquant;
Quantifications *chunkQuants;

istringstream** readInStream;
ostringstream* chunkOutBAMstream;
istream** readInStream;
ExtBufStreambuf* readInStreamBuf; //external-buffer streambufs backing readInStream (one per mate)
ostream* chunkOutBAMstream;
ExtBufStreambuf chunkOutBAMstreamBuf; //external-buffer streambuf backing chunkOutBAMstream
ofstream chunkOutBAMfile;
string chunkOutBAMfileName;

Expand Down