2020#include < pulsar/Client.h>
2121
2222#include < atomic>
23- #include < condition_variable>
2423#include < memory>
2524#include < mutex>
26- #include < queue>
27- #include < stdexcept>
25+ #include < optional>
2826#include < thread>
2927
3028#include " PulsarFriend.h"
@@ -36,70 +34,62 @@ DECLARE_LOG_OBJECT()
3634using namespace pulsar ;
3735using namespace std ::chrono_literals;
3836
39- class ServiceInfoQueue {
37+ class ServiceInfoHolder {
4038 public:
41- void push (ServiceInfo info) {
42- {
43- std::lock_guard<std::mutex> lock (mutex_);
44- queue_.push (std::move (info));
45- }
46- cond_.notify_all ();
47- }
39+ ServiceInfoHolder (ServiceInfo info) : serviceInfo_(std::move(info)) {}
4840
49- ServiceInfo pop () {
50- std::unique_lock<std::mutex> lock (mutex_);
51- cond_.wait (lock, [this ] { return !queue_.empty () || !running_; });
52- if (queue_.empty ()) {
53- throw std::runtime_error (" Queue is closed" );
41+ std::optional<ServiceInfo> getUpdatedValue () {
42+ std::lock_guard lock (mutex_);
43+ if (!owned_) {
44+ return std::nullopt ;
5445 }
55-
56- ServiceInfo info = std::move (queue_.front ());
57- queue_.pop ();
58- return info;
46+ owned_ = false ;
47+ return std::move (serviceInfo_);
5948 }
6049
61- void close () {
62- running_ = false ;
63- cond_.notify_all ();
50+ void updateValue (ServiceInfo info) {
51+ std::lock_guard lock (mutex_);
52+ serviceInfo_ = std::move (info);
53+ owned_ = true ;
6454 }
6555
6656 private:
57+ ServiceInfo serviceInfo_;
58+ bool owned_{true };
59+
6760 mutable std::mutex mutex_;
68- mutable std::condition_variable cond_;
69- std::queue<ServiceInfo> queue_;
70- std::atomic_bool running_{true };
7161};
7262
7363class TestServiceInfoProvider : public ServiceInfoProvider {
7464 public:
75- TestServiceInfoProvider (ServiceInfoQueue &queue ) : queue_(queue ) {}
65+ TestServiceInfoProvider (ServiceInfoHolder &serviceInfo ) : serviceInfo_(serviceInfo ) {}
7666
77- ServiceInfo getServiceInfo () const override { return queue_. pop (); }
67+ ServiceInfo initialServiceInfo () override { return serviceInfo_. getUpdatedValue (). value (); }
7868
7969 void initialize (std::function<void (ServiceInfo)> onServiceInfoUpdate) override {
80- onServiceInfoUpdate (queue_.pop ());
8170 thread_ = std::thread ([this , onServiceInfoUpdate] {
82- try {
83- while ( true ) {
84- ServiceInfo info = queue_. pop ();
85- onServiceInfoUpdate (std::move (info ));
71+ while (running_) {
72+ auto updatedValue = serviceInfo_. getUpdatedValue ();
73+ if (updatedValue) {
74+ onServiceInfoUpdate (std::move (*updatedValue ));
8675 }
87- } catch (const std::runtime_error &) {
76+ // Use a tight wait loop for tests
77+ std::this_thread::sleep_for (10ms);
8878 }
8979 });
9080 }
9181
9282 ~TestServiceInfoProvider () override {
93- queue_. close () ;
83+ running_ = false ;
9484 if (thread_.joinable ()) {
9585 thread_.join ();
9686 }
9787 }
9888
9989 private:
100- ServiceInfoQueue &queue_;
101-
10290 std::thread thread_;
91+ ServiceInfoHolder &serviceInfo_;
92+ std::atomic_bool running_{true };
10393 mutable std::mutex mutex_;
10494};
10595
@@ -114,10 +104,8 @@ TEST(ServiceInfoProviderTest, testSwitchCluster) {
114104 // Access "public/default" namespace in cluster 1, which doesn't require authentication
115105 ServiceInfo info3{" pulsar://localhost:6650" };
116106
117- ServiceInfoQueue queue;
118- queue.push (info1);
119-
120- auto client = Client::create (std::make_unique<TestServiceInfoProvider>(queue), {});
107+ ServiceInfoHolder serviceInfo{info1};
108+ auto client = Client::create (std::make_unique<TestServiceInfoProvider>(serviceInfo), {});
121109
122110 const auto topicRequiredAuth = " private/auth/testUpdateConnectionInfo-" + std::to_string (time (nullptr ));
123111 Producer producer;
@@ -141,7 +129,7 @@ TEST(ServiceInfoProviderTest, testSwitchCluster) {
141129
142130 // Switch to cluster 2 (started by ./build-support/start-mim-test-service-inside-container.sh)
143131 ASSERT_FALSE (PulsarFriend::getConnections (client).empty ());
144- queue. push (info2);
132+ serviceInfo. updateValue (info2);
145133 ASSERT_TRUE (waitUntil (1s, [&] {
146134 return PulsarFriend::getConnections (client).empty () && client.getServiceInfo () == info2;
147135 }));
@@ -152,7 +140,7 @@ TEST(ServiceInfoProviderTest, testSwitchCluster) {
152140 // Switch back to cluster 1 without any authentication, the previous authentication info configured for
153141 // cluster 2 will be cleared.
154142 ASSERT_FALSE (PulsarFriend::getConnections (client).empty ());
155- queue. push (info3);
143+ serviceInfo. updateValue (info3);
156144 ASSERT_TRUE (waitUntil (1s, [&] {
157145 return PulsarFriend::getConnections (client).empty () && client.getServiceInfo () == info3;
158146 }));
0 commit comments