Google format

This commit is contained in:
Ian Gulliver
2019-05-18 12:18:26 -07:00
parent 07c5e5661d
commit 83dfa81138
11 changed files with 397 additions and 250 deletions

151
.clang-format Normal file
View File

@@ -0,0 +1,151 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
...

View File

@@ -1,57 +1,57 @@
#include <atomic>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <sys/time.h>
#include <atomic>
#include <thread>
#include "server.h"
DEFINE_int32(port, 9000, "TCP port to bind");
int main(int argc, char *argv[]) {
google::InitGoogleLogging(argv[0]);
gflags::ParseCommandLineFlags(&argc, &argv, true);
int main(int argc, char* argv[]) {
google::InitGoogleLogging(argv[0]);
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::mutex mu;
std::unordered_set<firesse::Stream*> streams;
std::atomic<bool> running = true;
std::mutex mu;
std::unordered_set<firesse::Stream*> streams;
std::atomic<bool> running = true;
std::thread clock([&streams, &mu, &running]() {
while (running) {
sleep(1);
std::thread clock([&streams, &mu, &running]() {
while (running) {
sleep(1);
timeval tv;
PCHECK(gettimeofday(&tv, nullptr) == 0);
const uint64_t time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
const auto time_str = std::to_string(time_ms);
timeval tv;
PCHECK(gettimeofday(&tv, nullptr) == 0);
const uint64_t time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
const auto time_str = std::to_string(time_ms);
{
std::lock_guard l(mu);
for (auto* stream : streams) {
stream->WriteEvent(time_str, 0, "time");
}
}
}
});
{
std::lock_guard l(mu);
for (auto* stream : streams) {
stream->WriteEvent(time_str, 0, "time");
}
}
}
});
firesse::Server server(FLAGS_port, [&streams, &mu](firesse::Stream* stream) {
LOG(INFO) << "new stream: " << stream;
firesse::Server server(FLAGS_port, [&streams, &mu](firesse::Stream* stream) {
LOG(INFO) << "new stream: " << stream;
std::lock_guard l(mu);
streams.insert(stream);
stream->OnClose([stream, &streams, &mu]() {
LOG(INFO) << "stream closed: " << stream;
std::lock_guard l(mu);
streams.insert(stream);
stream->OnClose([stream, &streams, &mu]() {
LOG(INFO) << "stream closed: " << stream;
std::lock_guard l(mu);
streams.erase(stream);
});
});
server.RegisterSignalHandlers();
server.Serve();
std::lock_guard l(mu);
streams.erase(stream);
});
});
server.RegisterSignalHandlers();
server.Serve();
running = false;
clock.join();
running = false;
clock.join();
gflags::ShutDownCommandLineFlags();
google::ShutdownGoogleLogging();
gflags::ShutDownCommandLineFlags();
google::ShutdownGoogleLogging();
}

Submodule firecgi updated: a39ef8e25d...f9988beb88

142
index.cc
View File

@@ -3,92 +3,94 @@
namespace firesse {
void Index::Add(Stream* stream) {
std::lock_guard l(mu_);
std::lock_guard l(mu_);
stream->last_message_time_ = std::chrono::steady_clock::now();
stream->fresher_ = nullptr;
stream->staler_ = freshest_;
if (stream->staler_) {
stream->staler_->fresher_ = stream;
}
freshest_ = stream;
if (!stalest_) {
stalest_ = stream;
}
stream->last_message_time_ = std::chrono::steady_clock::now();
stream->fresher_ = nullptr;
stream->staler_ = freshest_;
if (stream->staler_) {
stream->staler_->fresher_ = stream;
}
freshest_ = stream;
if (!stalest_) {
stalest_ = stream;
}
}
void Index::Remove(Stream* stream) {
std::lock_guard l(mu_);
std::lock_guard l(mu_);
if (freshest_ == stream) {
freshest_ = stream->staler_;
}
if (stalest_ == stream) {
stalest_ = stream->fresher_;
}
if (stream->fresher_) {
stream->fresher_->staler_ = stream->staler_;
stream->fresher_ = nullptr;
}
if (stream->staler_) {
stream->staler_->fresher_ = stream->fresher_;
stream->staler_ = nullptr;
}
if (freshest_ == stream) {
freshest_ = stream->staler_;
}
if (stalest_ == stream) {
stalest_ = stream->fresher_;
}
if (stream->fresher_) {
stream->fresher_->staler_ = stream->staler_;
stream->fresher_ = nullptr;
}
if (stream->staler_) {
stream->staler_->fresher_ = stream->fresher_;
stream->staler_ = nullptr;
}
}
void Index::Freshen(Stream* stream) {
std::lock_guard l(mu_);
if (freshest_ == stream) {
// Shortcut
stream->last_message_time_ = std::chrono::steady_clock::now();
return;
}
Remove(stream);
Add(stream);
std::lock_guard l(mu_);
if (freshest_ == stream) {
// Shortcut
stream->last_message_time_ = std::chrono::steady_clock::now();
return;
}
Remove(stream);
Add(stream);
}
std::chrono::nanoseconds Index::WithStalest(std::function<void(Stream*)> callback, const std::chrono::nanoseconds& min_stale) {
Stream* stalest = nullptr;
std::chrono::nanoseconds ret;
const auto now = std::chrono::steady_clock::now();
const auto latest = now - min_stale;
std::chrono::nanoseconds Index::WithStalest(
std::function<void(Stream*)> callback,
const std::chrono::nanoseconds& min_stale) {
Stream* stalest = nullptr;
std::chrono::nanoseconds ret;
const auto now = std::chrono::steady_clock::now();
const auto latest = now - min_stale;
{
std::lock_guard l(mu_);
if (!stalest_) {
return min_stale;
}
if (stalest_->last_message_time_ > latest) {
return stalest_->last_message_time_ - latest;
}
{
std::lock_guard l(mu_);
if (!stalest_) {
return min_stale;
}
if (stalest_->last_message_time_ > latest) {
return stalest_->last_message_time_ - latest;
}
// stalest_ is valid for callback
stalest = stalest_;
// stalest_ is valid for callback
stalest = stalest_;
if (stalest->fresher_) {
if (stalest->fresher_->last_message_time_ > latest) {
ret = stalest_->fresher_->last_message_time_ - latest;
}
// Otherwise ret is 0 for immediate cycle
} else {
ret = min_stale;
}
if (stalest->fresher_) {
if (stalest->fresher_->last_message_time_ > latest) {
ret = stalest_->fresher_->last_message_time_ - latest;
}
// Otherwise ret is 0 for immediate cycle
} else {
ret = min_stale;
}
if (!stalest->mu_.try_lock()) {
// We're acquiring mutexes in the wrong order here; normally it's
// (Stream, Index), but we're doing (Index, Stream). That means we
// may deadlock. We take the lower-priority path and fail in case
// of deadlock.
return {};
}
if (!stalest->mu_.try_lock()) {
// We're acquiring mutexes in the wrong order here; normally it's
// (Stream, Index), but we're doing (Index, Stream). That means we
// may deadlock. We take the lower-priority path and fail in case
// of deadlock.
return {};
}
Freshen(stalest);
}
Freshen(stalest);
}
callback(stalest);
stalest->mu_.unlock();
callback(stalest);
stalest->mu_.unlock();
return ret;
return ret;
}
} // namespace firesse
} // namespace firesse

28
index.h
View File

@@ -11,20 +11,22 @@ namespace firesse {
// Avoids allocation and folds in iterators by using an intrusive list
// inside Stream.
class Index {
public:
void Add(Stream* stream);
void Remove(Stream* stream);
void Freshen(Stream* stream);
public:
void Add(Stream* stream);
void Remove(Stream* stream);
void Freshen(Stream* stream);
// Returns time to sleep until next stalest, or min_stale if none
// Only calls callback if stalest is at least min_stale
// Handles all locking and marks Stream as fresh after callback
std::chrono::nanoseconds WithStalest(std::function<void(Stream*)> callback, const std::chrono::nanoseconds& min_stale);
// Returns time to sleep until next stalest, or min_stale if none
// Only calls callback if stalest is at least min_stale
// Handles all locking and marks Stream as fresh after callback
std::chrono::nanoseconds WithStalest(
std::function<void(Stream*)> callback,
const std::chrono::nanoseconds& min_stale);
private:
std::recursive_mutex mu_;
Stream* freshest_ = nullptr;
Stream* stalest_ = nullptr;
private:
std::recursive_mutex mu_;
Stream* freshest_ = nullptr;
Stream* stalest_ = nullptr;
};
} // namespace firesse
} // namespace firesse

View File

@@ -6,42 +6,38 @@
namespace firesse {
KeepAlive::KeepAlive(const std::chrono::nanoseconds& max_stale, Index* index)
: max_stale_(max_stale),
index_(index),
shutdown_fd_(eventfd(0, 0)) {
PCHECK(shutdown_fd_ >= 0) << "eventfd()";
: max_stale_(max_stale), index_(index), shutdown_fd_(eventfd(0, 0)) {
PCHECK(shutdown_fd_ >= 0) << "eventfd()";
}
KeepAlive::~KeepAlive() {
PCHECK(close(shutdown_fd_) == 0);
}
KeepAlive::~KeepAlive() { PCHECK(close(shutdown_fd_) == 0); }
void KeepAlive::Start() {
thread_ = std::thread([this]() {
int timeout = 0;
constexpr auto num_fds = 1;
pollfd fds[num_fds] = {
{
.fd = shutdown_fd_,
.events = POLLIN,
},
};
while (running_ && (timeout == 0 || poll(fds, num_fds, timeout) <= 0)) {
auto sleep = index_->WithStalest([](Stream* stream) {
stream->WriteRaw(":\n");
}, max_stale_);
timeout = std::chrono::duration_cast<std::chrono::milliseconds>(sleep).count();
}
});
thread_ = std::thread([this]() {
int timeout = 0;
constexpr auto num_fds = 1;
pollfd fds[num_fds] = {
{
.fd = shutdown_fd_,
.events = POLLIN,
},
};
while (running_ && (timeout == 0 || poll(fds, num_fds, timeout) <= 0)) {
auto sleep = index_->WithStalest(
[](Stream* stream) { stream->WriteRaw(":\n"); }, max_stale_);
timeout =
std::chrono::duration_cast<std::chrono::milliseconds>(sleep).count();
}
});
}
void KeepAlive::Stop() {
CHECK(thread_.joinable());
CHECK(thread_.joinable());
running_ = false;
uint64_t shutdown = 1;
PCHECK(write(shutdown_fd_, &shutdown, sizeof(shutdown)) == sizeof(shutdown));
thread_.join();
running_ = false;
uint64_t shutdown = 1;
PCHECK(write(shutdown_fd_, &shutdown, sizeof(shutdown)) == sizeof(shutdown));
thread_.join();
}
} // namespace firesse
} // namespace firesse

View File

@@ -8,23 +8,23 @@
namespace firesse {
class KeepAlive {
public:
KeepAlive(const std::chrono::nanoseconds& max_stale, Index* index);
~KeepAlive();
public:
KeepAlive(const std::chrono::nanoseconds& max_stale, Index* index);
~KeepAlive();
void Start();
void Stop();
void Start();
void Stop();
private:
const std::chrono::nanoseconds max_stale_;
Index* index_;
private:
const std::chrono::nanoseconds max_stale_;
Index* index_;
// Two shutdown mechanisms, one for if we're in a tight no-syscall loop,
// and one for if we're sleeping in poll()
int shutdown_fd_;
std::atomic<bool> running_ = true;
// Two shutdown mechanisms, one for if we're in a tight no-syscall loop,
// and one for if we're sleeping in poll()
int shutdown_fd_;
std::atomic<bool> running_ = true;
std::thread thread_;
std::thread thread_;
};
} // namespace firesse
} // namespace firesse

View File

@@ -3,41 +3,38 @@
namespace firesse {
Server::Server(int port, const std::function<void(Stream*)>& callback)
: callback_(callback),
keep_alive_(std::chrono::seconds(15), &index_),
firecgi_server_(port,
[this](firecgi::Request* request) { OnRequest(request); },
1) {}
: callback_(callback),
keep_alive_(std::chrono::seconds(15), &index_),
firecgi_server_(
port, [this](firecgi::Request* request) { OnRequest(request); }, 1) {}
void Server::Serve() {
keep_alive_.Start();
firecgi_server_.Serve();
keep_alive_.Stop();
keep_alive_.Start();
firecgi_server_.Serve();
keep_alive_.Stop();
}
void Server::Shutdown() {
firecgi_server_.Shutdown();
}
void Server::Shutdown() { firecgi_server_.Shutdown(); }
void Server::RegisterSignalHandlers() {
firecgi_server_.RegisterSignalHandlers();
firecgi_server_.RegisterSignalHandlers();
}
void Server::OnRequest(firecgi::Request* request) {
request->WriteHeader("Content-Type", "text/event-stream; charset=utf-8");
request->WriteHeader("Cache-Control", "no-cache");
request->WriteHeader("X-Accel-Buffering", "no");
request->WriteBody("");
auto stream = new Stream(request, &index_);
request->WriteHeader("Content-Type", "text/event-stream; charset=utf-8");
request->WriteHeader("Cache-Control", "no-cache");
request->WriteHeader("X-Accel-Buffering", "no");
request->WriteBody("");
auto stream = new Stream(request, &index_);
{
request->OnClose([stream]() {
stream->Close();
delete stream;
});
}
{
request->OnClose([stream]() {
stream->Close();
delete stream;
});
}
callback_(stream);
callback_(stream);
}
} // namespace firesse
} // namespace firesse

View File

@@ -11,19 +11,19 @@
namespace firesse {
class Server {
public:
Server(int port, const std::function<void(Stream*)>& callback);
void Serve();
void Shutdown();
void RegisterSignalHandlers();
public:
Server(int port, const std::function<void(Stream*)>& callback);
void Serve();
void Shutdown();
void RegisterSignalHandlers();
private:
void OnRequest(firecgi::Request* request);
private:
void OnRequest(firecgi::Request* request);
std::function<void(Stream*)> callback_;
Index index_;
KeepAlive keep_alive_;
firecgi::Server firecgi_server_;
std::function<void(Stream*)> callback_;
Index index_;
KeepAlive keep_alive_;
firecgi::Server firecgi_server_;
};
} // namespace firesse
} // namespace firesse

View File

@@ -5,52 +5,50 @@
namespace firesse {
Stream::Stream(firecgi::Request* request, Index* index)
: request_(request),
index_(index) {
index_->Add(this);
: request_(request), index_(index) {
index_->Add(this);
}
Stream::~Stream() {
std::lock_guard l(mu_);
index_->Remove(this);
std::lock_guard l(mu_);
index_->Remove(this);
}
void Stream::OnClose(const std::function<void()>& callback) {
on_close_ = callback;
on_close_ = callback;
}
bool Stream::WriteEvent(const std::string_view& data, uint64_t id, const std::string& type) {
std::lock_guard l(mu_);
bool Stream::WriteEvent(const std::string_view& data, uint64_t id,
const std::string& type) {
std::lock_guard l(mu_);
index_->Freshen(this);
index_->Freshen(this);
return request_->InTransaction<bool>([=]() {
if (id) {
request_->WriteBody("id: ", std::to_string(id), "\n");
}
if (!type.empty()) {
request_->WriteBody("event: ", type, "\n");
}
request_->WriteBody("data: ", data, "\n\n");
return request_->Flush();
});
return request_->InTransaction<bool>([=]() {
if (id) {
request_->WriteBody("id: ", std::to_string(id), "\n");
}
if (!type.empty()) {
request_->WriteBody("event: ", type, "\n");
}
request_->WriteBody("data: ", data, "\n\n");
return request_->Flush();
});
}
bool Stream::WriteRaw(const std::string_view& data) {
std::lock_guard l(mu_);
std::lock_guard l(mu_);
request_->WriteBody(data);
return request_->Flush();
request_->WriteBody(data);
return request_->Flush();
}
bool Stream::End() {
return request_->End();
}
bool Stream::End() { return request_->End(); }
void Stream::Close() {
if (on_close_) {
on_close_();
}
if (on_close_) {
on_close_();
}
}
} // namespace firesse
} // namespace firesse

View File

@@ -9,30 +9,31 @@ namespace firesse {
class Index;
class Stream {
public:
Stream(firecgi::Request* request, Index* index);
~Stream();
public:
Stream(firecgi::Request* request, Index* index);
~Stream();
void OnClose(const std::function<void()>& callback);
void OnClose(const std::function<void()>& callback);
bool WriteEvent(const std::string_view& data, uint64_t id=0, const std::string& type="");
bool WriteRaw(const std::string_view& data);
bool End();
void Close();
bool WriteEvent(const std::string_view& data, uint64_t id = 0,
const std::string& type = "");
bool WriteRaw(const std::string_view& data);
bool End();
void Close();
private:
firecgi::Request* request_;
Index* index_;
private:
firecgi::Request* request_;
Index* index_;
std::function<void()> on_close_;
std::function<void()> on_close_;
// TODO: What exactly is this protecting?
std::recursive_mutex mu_;
std::chrono::steady_clock::time_point last_message_time_;
Stream* fresher_;
Stream* staler_;
// TODO: What exactly is this protecting?
std::recursive_mutex mu_;
std::chrono::steady_clock::time_point last_message_time_;
Stream* fresher_;
Stream* staler_;
friend class Index;
friend class Index;
};
} // namespace firesse
} // namespace firesse