Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * Copyright (c) 2018 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * Provides an implementation of the PlatformManager object.
22 : */
23 :
24 : #pragma once
25 :
26 : #include "lib/core/CHIPError.h"
27 : #include <condition_variable>
28 : #include <mutex>
29 :
30 : #include <platform/PlatformManager.h>
31 : #include <platform/internal/GenericPlatformManagerImpl_POSIX.h>
32 :
33 : #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP
34 : #include <gio/gio.h>
35 : #endif
36 :
37 : namespace chip {
38 : namespace DeviceLayer {
39 :
40 : /**
41 : * Concrete implementation of the PlatformManager singleton object for Linux platforms.
42 : */
43 : class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_POSIX<PlatformManagerImpl>
44 : {
45 : // Allow the PlatformManager interface class to delegate method calls to
46 : // the implementation methods provided by this class.
47 : friend PlatformManager;
48 :
49 : // Allow the generic implementation base class to call helper methods on
50 : // this class.
51 : #ifndef DOXYGEN_SHOULD_SKIP_THIS
52 : friend Internal::GenericPlatformManagerImpl_POSIX<PlatformManagerImpl>;
53 : #endif
54 :
55 : public:
56 : // ===== Platform-specific members that may be accessed directly by the application.
57 :
58 : #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP
59 :
60 : /**
61 : * @brief Invoke a function on the Matter GLib context.
62 : *
63 : * If execution of the function will have to be scheduled on other thread,
64 : * this call will block the current thread until the function is executed.
65 : *
66 : * @param[in] function The function to call.
67 : * @param[in] userData User data to pass to the function.
68 : * @returns The result of the function.
69 : */
70 : template <typename T>
71 : CHIP_ERROR GLibMatterContextInvokeSync(CHIP_ERROR (*func)(T *), T * userData)
72 : {
73 : struct
74 : {
75 : CHIP_ERROR returnValue = CHIP_NO_ERROR;
76 : CHIP_ERROR (*functionToCall)(T *);
77 : T * userData;
78 : } context;
79 :
80 : context.functionToCall = func;
81 : context.userData = userData;
82 :
83 : LambdaBridge bridge;
84 : bridge.Initialize([&context]() { context.returnValue = context.functionToCall(context.userData); });
85 :
86 : _GLibMatterContextInvokeSync(std::move(bridge));
87 : return context.returnValue;
88 : }
89 :
90 : unsigned int GLibMatterContextAttachSource(GSource * source)
91 : {
92 : VerifyOrDie(mGLibMainLoop != nullptr);
93 : return g_source_attach(source, g_main_loop_get_context(mGLibMainLoop));
94 : }
95 :
96 : #endif
97 :
98 : System::Clock::Timestamp GetStartTime() { return mStartTime; }
99 :
100 : private:
101 : // ===== Methods that implement the PlatformManager abstract interface.
102 :
103 : CHIP_ERROR _InitChipStack();
104 : void _Shutdown();
105 :
106 : // ===== Members for internal use by the following friends.
107 :
108 : friend PlatformManager & PlatformMgr();
109 : friend PlatformManagerImpl & PlatformMgrImpl();
110 : friend class Internal::BLEManagerImpl;
111 :
112 : System::Clock::Timestamp mStartTime = System::Clock::kZero;
113 :
114 : static PlatformManagerImpl sInstance;
115 :
116 : #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP
117 :
118 : struct GLibMatterContextInvokeData
119 : {
120 : LambdaBridge bridge;
121 : // Sync primitives to wait for the function to be executed
122 : std::condition_variable mDoneCond;
123 : bool mDone = false;
124 : };
125 :
126 : /**
127 : * @brief Invoke a function on the Matter GLib context.
128 : *
129 : * @param[in] bridge a LambdaBridge object that holds the lambda to be invoked within the GLib context.
130 : *
131 : * @note This function moves the LambdaBridge into the GLib context for invocation.
132 : * The LambdaBridge is created and initialised in GLibMatterContextInvokeSync().
133 : * use the GLibMatterContextInvokeSync() template function instead of this one.
134 : */
135 : void _GLibMatterContextInvokeSync(LambdaBridge && bridge);
136 :
137 : // XXX: Mutex for guarding access to glib main event loop callback indirection
138 : // synchronization primitives. This is a workaround to suppress TSAN warnings.
139 : // TSAN does not know that from the thread synchronization perspective the
140 : // g_source_attach() function should be treated as pthread_create(). Memory
141 : // access to shared data before the call to g_source_attach() without mutex
142 : // is not a race condition - the callback will not be executed on glib main
143 : // event loop thread before the call to g_source_attach().
144 : std::mutex mGLibMainLoopCallbackIndirectionMutex;
145 :
146 : GMainLoop * mGLibMainLoop = nullptr;
147 : GThread * mGLibMainLoopThread = nullptr;
148 :
149 : #endif // CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP
150 : };
151 :
152 : /**
153 : * Returns the public interface of the PlatformManager singleton object.
154 : *
155 : * chip applications should use this to access features of the PlatformManager object
156 : * that are common to all platforms.
157 : */
158 785 : inline PlatformManager & PlatformMgr()
159 : {
160 785 : return PlatformManagerImpl::sInstance;
161 : }
162 :
163 : /**
164 : * Returns the platform-specific implementation of the PlatformManager singleton object.
165 : *
166 : * chip applications can use this to gain access to features of the PlatformManager
167 : * that are specific to the platform.
168 : */
169 : inline PlatformManagerImpl & PlatformMgrImpl()
170 : {
171 : return PlatformManagerImpl::sInstance;
172 : }
173 :
174 : } // namespace DeviceLayer
175 : } // namespace chip
|