@@ -93,6 +93,10 @@ void NtcChannelFactory::processListenerResult(
93
93
bslstl::SharedPtrUtil::dynamicCast (&alias, channel);
94
94
if (alias) {
95
95
int catalogHandle = d_channels.add (alias);
96
+
97
+ // Increment resource usage count for new channel
98
+ d_resourceMonitor.acquire ();
99
+
96
100
alias->setChannelId (catalogHandle);
97
101
alias->onClose (bdlf::BindUtil::bind (
98
102
&NtcChannelFactory::processChannelClosed,
@@ -123,16 +127,7 @@ void NtcChannelFactory::processListenerClosed(int handle)
123
127
<< BALL_LOG_END;
124
128
}
125
129
126
- bslmt::LockGuard<bslmt::Mutex> lock (&d_stateMutex); // LOCKED
127
- if (d_state == e_STATE_STOPPING) {
128
- if (d_channels.length () == 0 && d_listeners.length () == 0 ) {
129
- BALL_LOG_TRACE << " NTC factory channels and listeners have closed"
130
- << BALL_LOG_END;
131
-
132
- d_state = e_STATE_STOPPED;
133
- d_stateCondition.signal ();
134
- }
135
- }
130
+ d_resourceMonitor.release (); // Decrement resource usage count
136
131
}
137
132
138
133
void NtcChannelFactory::processChannelResult (
@@ -167,16 +162,7 @@ void NtcChannelFactory::processChannelClosed(int handle)
167
162
<< BALL_LOG_END;
168
163
}
169
164
170
- bslmt::LockGuard<bslmt::Mutex> lock (&d_stateMutex); // LOCKED
171
- if (d_state == e_STATE_STOPPING) {
172
- if (d_channels.length () == 0 && d_listeners.length () == 0 ) {
173
- BALL_LOG_TRACE << " NTC factory channels and listeners have closed"
174
- << BALL_LOG_END;
175
-
176
- d_state = e_STATE_STOPPED;
177
- d_stateCondition.signal ();
178
- }
179
- }
165
+ d_resourceMonitor.release (); // Decrement resource usage count
180
166
}
181
167
182
168
// CREATORS
@@ -190,9 +176,9 @@ NtcChannelFactory::NtcChannelFactory(
190
176
, d_createSignaler(basicAllocator)
191
177
, d_limitSignaler(basicAllocator)
192
178
, d_owned(false )
193
- , d_stateMutex( )
194
- , d_stateCondition( )
195
- , d_state(e_STATE_DEFAULT )
179
+ , d_validator( false )
180
+ , d_resourceMonitor( false )
181
+ , d_isInterfaceStarted( false )
196
182
, d_allocator_p(bslma::Default::allocator(basicAllocator))
197
183
{
198
184
}
@@ -207,9 +193,9 @@ NtcChannelFactory::NtcChannelFactory(
207
193
, d_createSignaler(basicAllocator)
208
194
, d_limitSignaler(basicAllocator)
209
195
, d_owned(true )
210
- , d_stateMutex( )
211
- , d_stateCondition( )
212
- , d_state(e_STATE_DEFAULT )
196
+ , d_validator( false )
197
+ , d_resourceMonitor( false )
198
+ , d_isInterfaceStarted( false )
213
199
, d_allocator_p(bslma::Default::allocator(basicAllocator))
214
200
{
215
201
bsl::shared_ptr<bdlbb::BlobBufferFactory> blobBufferFactory_sp (
@@ -233,7 +219,6 @@ NtcChannelFactory::~NtcChannelFactory()
233
219
d_interface_sp.reset ();
234
220
}
235
221
236
- BSLS_ASSERT_OPT (d_state == e_STATE_DEFAULT || d_state == e_STATE_STOPPED);
237
222
BSLS_ASSERT_OPT (d_listeners.length () == 0 );
238
223
BSLS_ASSERT_OPT (d_channels.length () == 0 );
239
224
BSLS_ASSERT_OPT (d_createSignaler.slotCount () == 0 );
@@ -244,65 +229,60 @@ NtcChannelFactory::~NtcChannelFactory()
244
229
// MANIPULATORS
245
230
int NtcChannelFactory::start ()
246
231
{
247
- ntsa::Error error ;
232
+ bmqu::AtomicValidatorGuard valGuard (&d_validator) ;
248
233
249
- bslmt::LockGuard<bslmt::Mutex> lock (&d_stateMutex); // LOCKED
234
+ if (valGuard.isValid ()) {
235
+ // Already started.
236
+ return 1 ; // RETURN
237
+ }
250
238
251
- switch (d_state) {
252
- case e_STATE_DEFAULT:
253
- error = d_interface_sp->start ();
239
+ if (!d_isInterfaceStarted) {
240
+ // Make sure we don't restart the same interface if we have
241
+ // `start()`, `stop()`, `start()` sequence.
242
+ d_isInterfaceStarted = true ;
243
+ const ntsa::Error error = d_interface_sp->start ();
254
244
if (error) {
255
245
return error.number (); // RETURN
256
246
}
257
- d_state = e_STATE_STARTED;
258
- return 0 ; // RETURN
259
- case e_STATE_STOPPED: d_state = e_STATE_STARTED; return 0 ; // RETURN
260
- case e_STATE_STARTED: return 0 ; // RETURN
261
- case e_STATE_STOPPING: return 1 ; // RETURN
262
- default : return 1 ; // RETURN
263
247
}
248
+
249
+ d_resourceMonitor.reset ();
250
+ d_validator.reset ();
251
+
252
+ return 0 ;
264
253
}
265
254
266
255
void NtcChannelFactory::stop ()
267
256
{
268
- bslmt::LockGuard<bslmt::Mutex> lock (&d_stateMutex); // LOCKED
257
+ bmqu::AtomicValidatorGuard valGuard (&d_validator);
269
258
270
- if (d_state != e_STATE_STARTED ) {
259
+ if (!valGuard. isValid () ) {
271
260
return ; // RETURN
272
261
}
273
262
274
- d_state = e_STATE_STOPPING;
263
+ valGuard.release ()->release ();
264
+ d_validator.invalidate (); // Disallow new listen/connect
275
265
276
266
BALL_LOG_TRACE << " NTC factory is stopping" << BALL_LOG_END;
277
267
278
- if (d_channels.length () == 0 && d_listeners.length () == 0 ) {
279
- d_state = e_STATE_STOPPED;
280
- }
281
- else {
282
- {
283
- ChannelIterator iterator (d_channels);
284
- while (iterator) {
285
- iterator.value ()->close (bmqio::Status ());
286
- ++iterator;
287
- }
288
- }
289
-
290
- {
291
- ListenerIterator iterator (d_listeners);
292
- while (iterator) {
293
- iterator.value ()->cancel ();
294
- ++iterator;
295
- }
268
+ {
269
+ ChannelIterator iterator (d_channels);
270
+ while (iterator) {
271
+ iterator.value ()->close (bmqio::Status ());
272
+ ++iterator;
296
273
}
274
+ }
297
275
298
- while (d_state != e_STATE_STOPPED) {
299
- d_stateCondition.wait (&d_stateMutex);
276
+ {
277
+ ListenerIterator iterator (d_listeners);
278
+ while (iterator) {
279
+ iterator.value ()->cancel ();
280
+ ++iterator;
300
281
}
301
282
}
302
283
303
- BSLS_ASSERT_OPT (d_state == e_STATE_STOPPED);
304
-
305
- lock.release ()->unlock ();
284
+ // Wait until all channels and listeners are finished
285
+ d_resourceMonitor.invalidate ();
306
286
307
287
d_createSignaler.disconnectAllSlots ();
308
288
d_limitSignaler.disconnectAllSlots ();
@@ -326,9 +306,9 @@ void NtcChannelFactory::listen(Status* status,
326
306
handle->reset ();
327
307
}
328
308
329
- bslmt::LockGuard<bslmt::Mutex> lock (&d_stateMutex); // LOCKED
309
+ bmqu::AtomicValidatorGuard valGuard (&d_validator);
330
310
331
- if (d_state != e_STATE_STARTED ) {
311
+ if (!valGuard. isValid () ) {
332
312
bmqio::NtcListenerUtil::fail (status,
333
313
bmqio::StatusCategory::e_GENERIC_ERROR,
334
314
" state" ,
@@ -364,6 +344,9 @@ void NtcChannelFactory::listen(Status* status,
364
344
return ; // RETURN
365
345
}
366
346
347
+ // Increment resource usage count for new listener
348
+ d_resourceMonitor.acquire ();
349
+
367
350
if (handle) {
368
351
bslma::ManagedPtr<bmqio::NtcListener> alias (listener.managedPtr ());
369
352
handle->loadAlias (alias, listener.get ());
@@ -390,9 +373,9 @@ void NtcChannelFactory::connect(Status* status,
390
373
handle->reset ();
391
374
}
392
375
393
- bslmt::LockGuard<bslmt::Mutex> lock (&d_stateMutex); // LOCKED
376
+ bmqu::AtomicValidatorGuard valGuard (&d_validator);
394
377
395
- if (d_state != e_STATE_STARTED ) {
378
+ if (!valGuard. isValid () ) {
396
379
bmqio::NtcChannelUtil::fail (status,
397
380
bmqio::StatusCategory::e_GENERIC_ERROR,
398
381
" state" ,
@@ -435,6 +418,9 @@ void NtcChannelFactory::connect(Status* status,
435
418
handle->loadAlias (alias, channel.get ());
436
419
}
437
420
421
+ // Increment resource usage count for new channel
422
+ d_resourceMonitor.acquire ();
423
+
438
424
BALL_LOG_TRACE << " NTC channel " << AddressFormatter (channel.get ())
439
425
<< " to " << channel->peerUri () << " registered"
440
426
<< BALL_LOG_END;
0 commit comments