1 // This file is part of Desktop App Toolkit,
2 // a set of libraries for developing nice desktop applications.
3 //
4 // For license and copyright information please follow this link:
5 // https://github.com/desktop-app/legal/blob/master/LEGAL
6 //
7 #include "base/observer.h"
8 
9 namespace base {
10 namespace internal {
11 namespace {
12 
13 bool CantUseObservables = false;
14 void (*HandleDelayedMethod)() = nullptr;
15 
16 struct ObservableListWrap {
~ObservableListWrapbase::internal::__anon881c9c6d0111::ObservableListWrap17 	~ObservableListWrap() {
18 		CantUseObservables = true;
19 	}
20 	OrderedSet<ObservableCallHandlers*> list;
21 };
22 
PendingObservables()23 ObservableListWrap &PendingObservables() {
24 	static ObservableListWrap result;
25 	return result;
26 }
27 
ActiveObservables()28 ObservableListWrap &ActiveObservables() {
29 	static ObservableListWrap result;
30 	return result;
31 }
32 
33 } // namespace
34 
RegisterPendingObservable(ObservableCallHandlers * handlers)35 void RegisterPendingObservable(ObservableCallHandlers *handlers) {
36 	if (CantUseObservables) return;
37 	PendingObservables().list.insert(handlers);
38 	if (HandleDelayedMethod) {
39 		HandleDelayedMethod();
40 	}
41 }
42 
UnregisterActiveObservable(ObservableCallHandlers * handlers)43 void UnregisterActiveObservable(ObservableCallHandlers *handlers) {
44 	if (CantUseObservables) return;
45 	ActiveObservables().list.remove(handlers);
46 }
47 
UnregisterObservable(ObservableCallHandlers * handlers)48 void UnregisterObservable(ObservableCallHandlers *handlers) {
49 	if (CantUseObservables) return;
50 	PendingObservables().list.remove(handlers);
51 	ActiveObservables().list.remove(handlers);
52 }
53 
54 } // namespace internal
55 
InitObservables(void (* HandleDelayed)())56 void InitObservables(void(*HandleDelayed)()) {
57 	internal::HandleDelayedMethod = HandleDelayed;
58 }
59 
HandleObservables()60 void HandleObservables() {
61 	if (internal::CantUseObservables) return;
62 	auto &active = internal::ActiveObservables().list;
63 	qSwap(active, internal::PendingObservables().list);
64 	while (!active.empty()) {
65 		auto first = *active.begin();
66 		(*first)();
67 		if (!active.empty() && *active.begin() == first) {
68 			active.erase(active.begin());
69 		}
70 	}
71 }
72 
ObservableViewer(base::Observable<void> & observable)73 rpl::producer<> ObservableViewer(base::Observable<void> &observable) {
74 	return [&observable](const auto &consumer) {
75 		auto lifetime = rpl::lifetime();
76 		lifetime.make_state<base::Subscription>(
77 			observable.add_subscription([consumer]() {
78 				consumer.put_next({});
79 			}));
80 		return lifetime;
81 	};
82 }
83 
84 } // namespace base
85