Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add stream_await() for async stream "blocking"
Summary: As with cURL, use stream_await() to drop the fd into the asio event loop and get notified of read/write events. Reviewed By: @JoelMarcey Differential Revision: D1720052 Signature: t1:1720052:1418353349:c7c252f30e901d40e303e3e445ddf518aaf98d6d
- Loading branch information
Showing
14 changed files
with
342 additions
and
16 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#include "hphp/runtime/base/file-await.h" | ||
#include "hphp/runtime/base/file.h" | ||
#include "hphp/runtime/ext/asio/static_wait_handle.h" | ||
|
||
namespace HPHP { | ||
///////////////////////////////////////////////////////////////////////////// | ||
|
||
void FileTimeoutHandler::timeoutExpired() noexcept { | ||
if (m_fileAwait) { | ||
m_fileAwait->setFinished(FileAwait::TIMEOUT); | ||
} | ||
} | ||
|
||
void FileEventHandler::handlerReady(uint16_t events) noexcept { | ||
if (m_fileAwait) { | ||
m_fileAwait->setFinished(events ? FileAwait::READY : FileAwait::CLOSED); | ||
} | ||
} | ||
|
||
///////////////////////////////////////////////////////////////////////////// | ||
|
||
FileAwait::FileAwait(int fd, uint16_t events, double timeout) { | ||
assert(fd >= 0); | ||
assert(events & FileEventHandler::READ_WRITE); | ||
|
||
m_file = std::make_shared<FileEventHandler> | ||
(s_asio_event_base.get(), fd, this); | ||
m_file->registerHandler(events); | ||
|
||
int64_t timeout_ms = timeout * 1000.0; | ||
if (timeout_ms > 0) { | ||
m_timeout = std::make_shared<FileTimeoutHandler> | ||
(s_asio_event_base.get(), this); | ||
s_asio_event_base->runInEventBaseThread([this,timeout_ms]{ | ||
if (m_timeout) { | ||
m_timeout->scheduleTimeout(timeout_ms); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
FileAwait::~FileAwait() { | ||
if (m_file) { | ||
// Avoid possible race condition | ||
m_file->m_fileAwait = nullptr; | ||
|
||
m_file->unregisterHandler(); | ||
m_file.reset(); | ||
} | ||
if (m_timeout) { | ||
// Avoid race condition, we may (likely) finish destructing | ||
// before the timeout cancels | ||
m_timeout->m_fileAwait = nullptr; | ||
|
||
std::shared_ptr<FileTimeoutHandler> to = m_timeout; | ||
s_asio_event_base->runInEventBaseThread([to]{ | ||
to.get()->cancelTimeout(); | ||
}); | ||
m_timeout.reset(); | ||
} | ||
} | ||
|
||
void FileAwait::unserialize(Cell& c) { | ||
c.m_type = KindOfInt64; | ||
c.m_data.num = m_result; | ||
} | ||
|
||
void FileAwait::setFinished(int64_t status) { | ||
if (status > m_result) { | ||
m_result = status; | ||
} | ||
if (!m_finished) { | ||
markAsFinished(); | ||
m_finished = true; | ||
} | ||
} | ||
|
||
///////////////////////////////////////////////////////////////////////////// | ||
|
||
Object File::await(uint16_t events, double timeout) { | ||
if (isClosed()) { | ||
Cell closedResult; | ||
closedResult.m_type = KindOfInt64; | ||
closedResult.m_data.num = FileAwait::CLOSED; | ||
return c_StaticWaitHandle::CreateSucceeded(closedResult); | ||
} | ||
if (fd() < 0) { | ||
throw Object(SystemLib::AllocExceptionObject( | ||
"Unable to await on stream, invalid file descriptor")); | ||
} | ||
events = events & FileEventHandler::READ_WRITE; | ||
if (!events) { | ||
throw Object(SystemLib::AllocExceptionObject( | ||
"Must await for reading, writing, or both.")); | ||
} | ||
|
||
auto ev = new FileAwait(fd(), events, timeout); | ||
try { | ||
return ev->getWaitHandle(); | ||
} catch (...) { | ||
assert(false); | ||
ev->abandon(); | ||
throw; | ||
} | ||
} | ||
|
||
///////////////////////////////////////////////////////////////////////////// | ||
} // namespace HPHP |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#ifndef incl_HPHP_FILE_AWAIT_H | ||
#define incl_HPHP_FILE_AWAIT_H | ||
|
||
#include "hphp/runtime/base/base-includes.h" | ||
#include "hphp/runtime/ext/asio/asio_external_thread_event.h" | ||
#include "hphp/runtime/ext/asio/socket-event.h" | ||
|
||
namespace HPHP { | ||
///////////////////////////////////////////////////////////////////////////// | ||
|
||
class FileAwait; | ||
|
||
class FileTimeoutHandler : public AsioTimeoutHandler { | ||
friend class FileAwait; | ||
public: | ||
FileTimeoutHandler(AsioEventBase* base, FileAwait* fa): | ||
AsioTimeoutHandler(base), m_fileAwait(fa) {} | ||
|
||
void timeoutExpired() noexcept override; | ||
private: | ||
FileAwait* m_fileAwait; | ||
}; | ||
|
||
class FileEventHandler : public AsioEventHandler { | ||
friend class FileAwait; | ||
public: | ||
FileEventHandler(AsioEventBase* base, int fd, FileAwait* fa): | ||
AsioEventHandler(base, fd), m_fileAwait(fa) {} | ||
|
||
void handlerReady(uint16_t events) noexcept override; | ||
private: | ||
FileAwait* m_fileAwait; | ||
}; | ||
|
||
class FileAwait : public AsioExternalThreadEvent { | ||
public: | ||
enum Status { | ||
ERROR = -1, | ||
TIMEOUT = 0, | ||
READY, | ||
CLOSED, | ||
}; | ||
|
||
FileAwait(int fd, uint16_t events, double timeout); | ||
~FileAwait(); | ||
void unserialize(Cell& c) override; | ||
void setFinished(int64_t status); | ||
private: | ||
std::shared_ptr<FileEventHandler> m_file; | ||
std::shared_ptr<FileTimeoutHandler> m_timeout; | ||
int m_result{-1}; | ||
bool m_finished{false}; | ||
}; | ||
|
||
///////////////////////////////////////////////////////////////////////////// | ||
} // namespace HPHP | ||
#endif // incl_HPHP_FILE_AWAIT_H |
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
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
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?hh | ||
|
||
try { | ||
$wh = stream_await(fopen('php://memory', 'rw'), | ||
STREAM_AWAIT_READ | STREAM_AWAIT_WRITE, 0.0); | ||
var_dump($wh->join()); | ||
} catch (Exception $e) { | ||
echo "Exception: ", $e->getMessage(), "\n"; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Exception: Temporary stream does not support awaiting |
Oops, something went wrong.