24
24
#include < thread> // NOLINT
25
25
#include < vector>
26
26
27
- #include " firebase/ app.h"
28
- #include " firebase/future .h"
27
+ #include " app/src/callback .h"
28
+ #include " app/src/time .h"
29
29
#include " remote_config/src/common.h"
30
- #include " remote_config/src/desktop/config_data.h"
31
- #include " remote_config/src/desktop/file_manager.h"
32
30
#include " remote_config/src/desktop/rest.h"
33
- #include " remote_config/src/include/firebase/remote_config.h"
34
31
35
32
#ifndef SWIG
36
33
#include " firebase/variant.h"
@@ -40,6 +37,8 @@ namespace firebase {
40
37
namespace remote_config {
41
38
namespace internal {
42
39
40
+ using callback::NewCallback;
41
+
43
42
const char * const RemoteConfigInternal::kDefaultNamespace = " configns:firebase" ;
44
43
const char * const RemoteConfigInternal::kDefaultValueForString = " " ;
45
44
const int64_t RemoteConfigInternal::kDefaultValueForLong = 0L ;
@@ -48,39 +47,54 @@ const bool RemoteConfigInternal::kDefaultValueForBool = false;
48
47
49
48
static const char * kFilePathSuffix = " remote_config_data" ;
50
49
50
+ template <typename T>
51
+ struct RCDataHandle {
52
+ RCDataHandle (
53
+ ReferenceCountedFutureImpl* _future_api,
54
+ const SafeFutureHandle<T>& _future_handle,
55
+ RemoteConfigInternal* _rc_internal,
56
+ std::vector<std::string> _default_keys = std::vector<std::string>())
57
+ : future_api(_future_api),
58
+ future_handle (_future_handle),
59
+ rc_internal(_rc_internal),
60
+ default_keys(_default_keys) {}
61
+ ReferenceCountedFutureImpl* future_api;
62
+ SafeFutureHandle<T> future_handle;
63
+ RemoteConfigInternal* rc_internal;
64
+ std::vector<std::string> default_keys;
65
+ };
66
+
51
67
RemoteConfigInternal::RemoteConfigInternal (
52
68
const firebase::App& app, const RemoteConfigFileManager& file_manager)
53
69
: app_(app),
54
70
file_manager_(file_manager),
55
71
is_fetch_process_have_task_(false ),
56
- future_impl_(kRemoteConfigFnCount ) {
72
+ future_impl_(kRemoteConfigFnCount ),
73
+ safe_this_(this ) {
57
74
InternalInit ();
58
75
}
59
76
60
77
RemoteConfigInternal::RemoteConfigInternal (const firebase::App& app)
61
78
: app_(app),
62
79
file_manager_(kFilePathSuffix ),
63
80
is_fetch_process_have_task_(false ),
64
- future_impl_(kRemoteConfigFnCount ) {
81
+ future_impl_(kRemoteConfigFnCount ),
82
+ safe_this_(this ) {
65
83
InternalInit ();
66
84
}
67
85
68
86
RemoteConfigInternal::~RemoteConfigInternal () {
69
- fetch_channel_.Close ();
70
- if (fetch_thread_.joinable ()) {
71
- fetch_thread_.join ();
72
- }
73
-
74
87
save_channel_.Close ();
75
88
if (save_thread_.joinable ()) {
76
89
save_thread_.join ();
77
90
}
91
+
92
+ safe_this_.ClearReference ();
78
93
}
79
94
80
95
void RemoteConfigInternal::InternalInit () {
81
96
file_manager_.Load (&configs_);
82
97
AsyncSaveToFile ();
83
- AsyncFetch ();
84
98
}
85
99
86
100
bool RemoteConfigInternal::Initialized () const {
@@ -151,7 +165,7 @@ void RemoteConfigInternal::AsyncSaveToFile() {
151
165
while (save_channel_.Get ()) {
152
166
LayeredConfigs copy;
153
167
{
154
- std::unique_lock<std::mutex> lock (mutex_ );
168
+ MutexLock lock (internal_mutex_ );
155
169
copy = configs_;
156
170
}
157
171
file_manager_.Save (copy);
@@ -225,14 +239,14 @@ Future<void> RemoteConfigInternal::SetDefaults(const ConfigKeyValue* defaults,
225
239
void RemoteConfigInternal::SetDefaults (
226
240
const std::map<std::string, std::string>& defaults_map) {
227
241
{
228
- std::unique_lock<std::mutex> lock (mutex_ );
242
+ MutexLock lock (internal_mutex_ );
229
243
configs_.defaults .SetNamespace (defaults_map, kDefaultNamespace );
230
244
}
231
245
save_channel_.Put ();
232
246
}
233
247
234
248
std::string RemoteConfigInternal::GetConfigSetting (ConfigSetting setting) {
235
- std::unique_lock<std::mutex> lock (mutex_ );
249
+ MutexLock lock (internal_mutex_ );
236
250
return configs_.metadata .GetSetting (setting);
237
251
}
238
252
@@ -242,7 +256,7 @@ void RemoteConfigInternal::SetConfigSetting(ConfigSetting setting,
242
256
return ;
243
257
}
244
258
{
245
- std::unique_lock<std::mutex> lock (mutex_ );
259
+ MutexLock lock (internal_mutex_ );
246
260
configs_.metadata .AddSetting (setting, value);
247
261
}
248
262
save_channel_.Put ();
@@ -263,8 +277,7 @@ bool RemoteConfigInternal::CheckValueInConfig(
263
277
if (!key) return false ;
264
278
265
279
{
266
- // TODO(b/74461360): Replace the thread locks with firebase ones.
267
- std::unique_lock<std::mutex> lock (mutex_);
280
+ MutexLock lock (internal_mutex_);
268
281
if (!config.HasValue (key, kDefaultNamespace )) {
269
282
return false ;
270
283
}
@@ -418,7 +431,7 @@ std::vector<std::string> RemoteConfigInternal::GetKeysByPrefix(
418
431
if (prefix == nullptr ) return std::vector<std::string>();
419
432
std::set<std::string> unique_keys;
420
433
{
421
- std::unique_lock<std::mutex> lock (mutex_ );
434
+ MutexLock lock (internal_mutex_ );
422
435
configs_.active .GetKeysByPrefix (prefix, kDefaultNamespace , &unique_keys);
423
436
configs_.defaults .GetKeysByPrefix (prefix, kDefaultNamespace , &unique_keys);
424
437
}
@@ -433,7 +446,7 @@ std::map<std::string, Variant> RemoteConfigInternal::GetAll() {
433
446
434
447
bool RemoteConfigInternal::ActivateFetched () {
435
448
{
436
- std::unique_lock<std::mutex> lock (mutex_ );
449
+ MutexLock lock (internal_mutex_ );
437
450
// Fetched config not found or already activated.
438
451
if (configs_.fetched .timestamp () <= configs_.active .timestamp ())
439
452
return false ;
@@ -444,63 +457,24 @@ bool RemoteConfigInternal::ActivateFetched() {
444
457
}
445
458
446
459
const ConfigInfo RemoteConfigInternal::GetInfo () const {
447
- std::unique_lock<std::mutex> lock (mutex_ );
460
+ MutexLock lock (internal_mutex_ );
448
461
return configs_.metadata .info ();
449
462
}
450
463
451
- void RemoteConfigInternal::AsyncFetch () {
452
- fetch_thread_ = std::thread ([this ]() {
453
- SafeFutureHandle<void > handle;
454
- while (fetch_channel_.Get ()) {
455
- RemoteConfigREST* rest = nullptr ;
456
-
457
- {
458
- std::unique_lock<std::mutex> lock (mutex_);
459
- handle = fetch_handle_;
460
- rest = new RemoteConfigREST (app_.options (), configs_,
461
- cache_expiration_in_seconds_);
462
- }
463
-
464
- // Fetch fresh config from server.
465
- rest->Fetch (app_);
466
-
467
- {
468
- std::unique_lock<std::mutex> lock (mutex_);
469
-
470
- // Need to copy everything to `configs_.fetched`.
471
- configs_.fetched = rest->fetched ();
472
-
473
- // Need to copy only info and digests to `configs_.metadata`.
474
- const RemoteConfigMetadata& metadata = rest->metadata ();
475
- configs_.metadata .set_info (metadata.info ());
476
- configs_.metadata .set_digest_by_namespace (
477
- metadata.digest_by_namespace ());
478
-
479
- delete rest;
480
-
481
- is_fetch_process_have_task_ = false ;
482
- }
483
- FutureStatus futureResult =
484
- (GetInfo ().last_fetch_status == kLastFetchStatusSuccess )
485
- ? kFutureStatusSuccess
486
- : kFutureStatusFailure ;
487
-
488
- FutureData* future_data = FutureData::Get ();
489
- future_data->api ()->Complete (handle, futureResult);
490
- }
491
- });
492
- }
493
-
494
464
Future<void > RemoteConfigInternal::Fetch (uint64_t cache_expiration_in_seconds) {
495
- std::unique_lock<std::mutex> lock (mutex_ );
465
+ MutexLock lock (internal_mutex_ );
496
466
497
467
uint64_t milliseconds_since_epoch =
498
468
std::chrono::duration_cast<std::chrono::milliseconds>(
499
469
std::chrono::system_clock::now ().time_since_epoch ())
500
470
.count ();
501
471
502
472
uint64_t cache_expiration_timestamp =
503
- configs_.fetched .timestamp () + 1000 * cache_expiration_in_seconds;
473
+ configs_.fetched .timestamp () +
474
+ ::firebase::internal::kMillisecondsPerSecond *
475
+ cache_expiration_in_seconds;
476
+
477
+ const auto future_handle = future_impl_.SafeAlloc <void >(kRemoteConfigFnFetch );
504
478
505
479
// Need to fetch in two cases:
506
480
// - we are not fetching at this moment
@@ -511,19 +485,58 @@ Future<void> RemoteConfigInternal::Fetch(uint64_t cache_expiration_in_seconds) {
511
485
if (!is_fetch_process_have_task_ &&
512
486
((cache_expiration_in_seconds == 0 ) ||
513
487
(cache_expiration_timestamp < milliseconds_since_epoch))) {
514
- ReferenceCountedFutureImpl* api = FutureData::Get ()->api ();
515
- fetch_handle_ = api->SafeAlloc <void >(kRemoteConfigFnFetch );
488
+ auto data_handle =
489
+ MakeShared<RCDataHandle<void >>(&future_impl_, future_handle, this );
490
+
491
+ auto callback = NewCallback (
492
+ [](ThisRef ref, SharedPtr<RCDataHandle<void >> handle) {
493
+ ThisRefLock lock (&ref);
494
+ if (lock.GetReference () != nullptr ) {
495
+ MutexLock lock (handle->rc_internal ->internal_mutex_ );
496
+ RemoteConfigREST* rest = new RemoteConfigREST (
497
+ handle->rc_internal ->app_ .options (),
498
+ handle->rc_internal ->configs_ ,
499
+ handle->rc_internal ->cache_expiration_in_seconds_ );
500
+
501
+ // Fetch fresh config from server.
502
+ rest->Fetch (handle->rc_internal ->app_ );
503
+
504
+ // Need to copy everything to `configs_.fetched`.
505
+ handle->rc_internal ->configs_ .fetched = rest->fetched ();
506
+
507
+ // Need to copy only info and digests to `configs_.metadata`.
508
+ const RemoteConfigMetadata& metadata = rest->metadata ();
509
+ handle->rc_internal ->configs_ .metadata .set_info (metadata.info ());
510
+ handle->rc_internal ->configs_ .metadata .set_digest_by_namespace (
511
+ metadata.digest_by_namespace ());
512
+
513
+ delete rest;
514
+
515
+ handle->rc_internal ->is_fetch_process_have_task_ = false ;
516
+
517
+ FutureStatus futureResult =
518
+ (handle->rc_internal ->GetInfo ().last_fetch_status ==
519
+ kLastFetchStatusSuccess )
520
+ ? kFutureStatusSuccess
521
+ : kFutureStatusFailure ;
522
+ handle->future_api ->Complete (handle->future_handle , futureResult);
523
+ }
524
+ },
525
+ safe_this_, data_handle);
526
+
527
+ scheduler_.Schedule (callback);
516
528
is_fetch_process_have_task_ = true ;
517
- fetch_channel_.Put ();
518
529
cache_expiration_in_seconds_ = cache_expiration_in_seconds;
530
+ } else {
531
+ // Do not fetch, complete future immediately.
532
+ future_impl_.Complete (future_handle, kFutureStatusSuccess );
519
533
}
520
- return FetchLastResult ( );
534
+ return MakeFuture< void >(&future_impl_, future_handle );
521
535
}
522
536
523
537
Future<void > RemoteConfigInternal::FetchLastResult () {
524
- ReferenceCountedFutureImpl* api = FutureData::Get ()->api ();
525
538
return static_cast <const Future<void >&>(
526
- api-> LastResult (kRemoteConfigFnFetch ));
539
+ future_impl_. LastResult (kRemoteConfigFnFetch ));
527
540
}
528
541
529
542
} // namespace internal
0 commit comments