Last active
August 3, 2017 04:03
-
-
Save anhldbk/3ee4225e7c44209861e0bd18ae98d6a7 to your computer and use it in GitHub Desktop.
Thrift transport
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Generic interface for a method of transporting data. A TTransport may be | |
* capable of either reading or writing, but not necessarily both. | |
* | |
*/ | |
class TTransport { | |
/** | |
* Attempt to read up to the specified number of bytes into the string. | |
* | |
* @param buf Reference to the location to write the data | |
* @param len How many bytes to read | |
* @return How many bytes were actually read | |
* @throws TTransportException If an error occurs | |
*/ | |
uint32_t read(uint8_t* buf, uint32_t len) { | |
T_VIRTUAL_CALL(); | |
return read_virt(buf, len); | |
} | |
virtual uint32_t read_virt(uint8_t* /* buf */, uint32_t /* len */) { | |
throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot read."); | |
} | |
// ... | |
} | |
/** | |
* Helper class that provides default implementations of TTransport methods. | |
* | |
* This class provides default implementations of read(), readAll(), write(), | |
* borrow() and consume(). | |
* | |
* In the TTransport base class, each of these methods simply invokes its | |
* virtual counterpart. This class overrides them to always perform the | |
* default behavior, without a virtual function call. | |
* | |
* The primary purpose of this class is to serve as a base class for | |
* TVirtualTransport, and prevent infinite recursion if one of its subclasses | |
* does not override the TTransport implementation of these methods. (Since | |
* TVirtualTransport::read_virt() calls read(), and TTransport::read() calls | |
* read_virt().) | |
*/ | |
class TTransportDefaults : public TTransport { | |
public: | |
/* | |
* TTransport *_virt() methods provide reasonable default implementations. | |
* Invoke them non-virtually. | |
*/ | |
uint32_t read(uint8_t* buf, uint32_t len) { return this->TTransport::read_virt(buf, len); } | |
uint32_t readAll(uint8_t* buf, uint32_t len) { return this->TTransport::readAll_virt(buf, len); } | |
void write(const uint8_t* buf, uint32_t len) { this->TTransport::write_virt(buf, len); } | |
const uint8_t* borrow(uint8_t* buf, uint32_t* len) { | |
return this->TTransport::borrow_virt(buf, len); | |
} | |
void consume(uint32_t len) { this->TTransport::consume_virt(len); } | |
protected: | |
TTransportDefaults() {} | |
}; | |
/** | |
* Helper class to provide polymorphism for subclasses of TTransport. | |
* | |
* This class implements *_virt() methods of TTransport, to call the | |
* non-virtual versions of these functions in the proper subclass. | |
* | |
* To define your own transport class using TVirtualTransport: | |
* 1) Derive your subclass from TVirtualTransport<your class> | |
* e.g: class MyTransport : public TVirtualTransport<MyTransport> { | |
* 2) Provide your own implementations of read(), readAll(), etc. | |
* These methods should be non-virtual. | |
* | |
* Transport implementations that need to use virtual inheritance when | |
* inheriting from TTransport cannot use TVirtualTransport. | |
* | |
* @author Chad Walters <[email protected]> | |
*/ | |
template <class Transport_, class Super_ = TTransportDefaults> | |
class TVirtualTransport : public Super_ { | |
public: | |
/* | |
* Implementations of the *_virt() functions, to call the subclass's | |
* non-virtual implementation function. | |
*/ | |
virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { | |
return static_cast<Transport_*>(this)->read(buf, len); | |
} | |
} | |
/** | |
* Base class for all transports that use read/write buffers for performance. | |
* | |
* TBufferBase is designed to implement the fast-path "memcpy" style | |
* operations that work in the common case. It does so with small and | |
* (eventually) nonvirtual, inlinable methods. TBufferBase is an abstract | |
* class. Subclasses are expected to define the "slow path" operations | |
* that have to be done when the buffers are full or empty. | |
* | |
*/ | |
class TBufferBase : public TVirtualTransport<TBufferBase> { | |
public: | |
/** | |
* Fast-path read. | |
* | |
* When we have enough data buffered to fulfill the read, we can satisfy it | |
* with a single memcpy, then adjust our internal pointers. If the buffer | |
* is empty, we call out to our slow path, implemented by a subclass. | |
* This method is meant to eventually be nonvirtual and inlinable. | |
*/ | |
uint32_t read(uint8_t* buf, uint32_t len) { | |
uint8_t* new_rBase = rBase_ + len; | |
if (TDB_LIKELY(new_rBase <= rBound_)) { | |
std::memcpy(buf, rBase_, len); | |
rBase_ = new_rBase; | |
return len; | |
} | |
return readSlow(buf, len); | |
} | |
} | |
/** | |
* Buffered transport. For reads it will read more data than is requested | |
* and will serve future data out of a local buffer. For writes, data is | |
* stored to an in memory buffer before being written out. | |
* | |
*/ | |
class TBufferedTransport : public TVirtualTransport<TBufferedTransport, TBufferBase> { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment