Commit 803cf0b2 authored by Jan Koester's avatar Jan Koester
Browse files

test

parent 6ad2e9b7
Loading
Loading
Loading
Loading
+26 −4
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

#pragma once

#include <concepts>
#include <functional>
#include <memory>
#include <mutex>
@@ -106,13 +107,34 @@ public:
private:
    friend class Handle;

    // A call site that forgets to Handle::discard() an object left mid-response
    // (e.g. a libhttppp::HttpClient stream that wasn't drained to completion,
    // or one the peer has asked to close) would otherwise hand a desynced
    // connection to the next caller — neither the pool nor HttpClient itself
    // catches that on its own (only a genuinely closed socket gets reset).
    // Detect the same signals HttpClient already exposes (isStreaming(),
    // wantsClose()) via ad-hoc requires-expressions (a named `concept` can't
    // be declared at class scope), and refuse to pool an object that reports
    // either one, so this is safe by construction even if a future call site
    // skips discard(). Types without these methods (e.g. plain
    // mediadb::Client) are pooled as before — nothing to detect.
    static bool _unsafeToPool(const T &obj) {
        bool unsafe = false;
        if constexpr (requires { { obj.isStreaming() } -> std::convertible_to<bool>; })
            unsafe = unsafe || obj.isStreaming();
        if constexpr (requires { { obj.wantsClose() } -> std::convertible_to<bool>; })
            unsafe = unsafe || obj.wantsClose();
        return unsafe;
    }

    void release(std::unique_ptr<T> obj) {
        std::lock_guard<std::mutex> lk(_mtx);
        if (_avail.size() < _maxSize)
        if (_avail.size() < _maxSize && !_unsafeToPool(*obj))
            _avail.push_back(std::move(obj));
        // else: pool already full (more concurrent checkouts than
        // maxSize happened) — just let this instance be destroyed instead
        // of growing the pool unbounded.
        // else: pool already full (more concurrent checkouts than maxSize
        // happened), or the object isn't safe to hand to the next caller —
        // just let this instance be destroyed instead of growing the pool
        // unbounded or leaking a desynced connection into circulation.
    }

    std::mutex _mtx;