diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..3c316f8 --- /dev/null +++ b/.clang-format @@ -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: '^' + 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 +... + diff --git a/example_clock.cc b/example_clock.cc index 06b31f1..e926157 100644 --- a/example_clock.cc +++ b/example_clock.cc @@ -1,57 +1,57 @@ -#include #include #include #include +#include #include #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 streams; - std::atomic running = true; + std::mutex mu; + std::unordered_set streams; + std::atomic 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(); } diff --git a/firecgi b/firecgi index a39ef8e..f9988be 160000 --- a/firecgi +++ b/firecgi @@ -1 +1 @@ -Subproject commit a39ef8e25dc2450b9219da67e37cfe158bd4a3ec +Subproject commit f9988beb8830e42a6dda6c566c84d93c2ebc410b diff --git a/index.cc b/index.cc index 81c27c2..cd6d867 100644 --- a/index.cc +++ b/index.cc @@ -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 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 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 diff --git a/index.h b/index.h index 0c6c28f..fd8cdbc 100644 --- a/index.h +++ b/index.h @@ -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 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 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 diff --git a/keepalive.cc b/keepalive.cc index 0c53128..ba3eb24 100644 --- a/keepalive.cc +++ b/keepalive.cc @@ -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(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(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 diff --git a/keepalive.h b/keepalive.h index 5396370..013052c 100644 --- a/keepalive.h +++ b/keepalive.h @@ -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 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 running_ = true; - std::thread thread_; + std::thread thread_; }; -} // namespace firesse +} // namespace firesse diff --git a/server.cc b/server.cc index 1ee7521..d3d2ce9 100644 --- a/server.cc +++ b/server.cc @@ -3,41 +3,38 @@ namespace firesse { Server::Server(int port, const std::function& 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 diff --git a/server.h b/server.h index ee3b938..aa77f8a 100644 --- a/server.h +++ b/server.h @@ -11,19 +11,19 @@ namespace firesse { class Server { - public: - Server(int port, const std::function& callback); - void Serve(); - void Shutdown(); - void RegisterSignalHandlers(); + public: + Server(int port, const std::function& callback); + void Serve(); + void Shutdown(); + void RegisterSignalHandlers(); - private: - void OnRequest(firecgi::Request* request); + private: + void OnRequest(firecgi::Request* request); - std::function callback_; - Index index_; - KeepAlive keep_alive_; - firecgi::Server firecgi_server_; + std::function callback_; + Index index_; + KeepAlive keep_alive_; + firecgi::Server firecgi_server_; }; -} // namespace firesse +} // namespace firesse diff --git a/stream.cc b/stream.cc index 19e4e37..9818ddb 100644 --- a/stream.cc +++ b/stream.cc @@ -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& 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([=]() { - 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([=]() { + 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 diff --git a/stream.h b/stream.h index b113562..c636141 100644 --- a/stream.h +++ b/stream.h @@ -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& callback); + void OnClose(const std::function& 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 on_close_; + std::function 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