Skip to content

Commit

Permalink
Allow post event from any thread to CHIP main event loop. (#7195)
Browse files Browse the repository at this point in the history
* Make access to CHIP Message Queue thread safe

* Use RAII style of locking

* Add support for thread-safe event queue in platform layer

* Refactor Front() and Pop() to PopFront()
  • Loading branch information
yufengwangca authored Jun 18, 2021
1 parent 8cfdf0a commit 0322eb1
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,17 @@ CHIP_ERROR GenericPlatformManagerImpl_POSIX<ImplClass>::_StartChipTimer(int64_t
template <class ImplClass>
void GenericPlatformManagerImpl_POSIX<ImplClass>::_PostEvent(const ChipDeviceEvent * event)
{
mChipEventQueue.push(*event); // Thread safe due to ChipStackLock taken by App thread
SysOnEventSignal(this); // Trigger wake select on CHIP thread
mChipEventQueue.Push(*event);
SysOnEventSignal(this); // Trigger wake select on CHIP thread
}

template <class ImplClass>
void GenericPlatformManagerImpl_POSIX<ImplClass>::ProcessDeviceEvents()
{
while (!mChipEventQueue.empty())
while (!mChipEventQueue.Empty())
{
Impl()->DispatchEvent(&mChipEventQueue.front());
mChipEventQueue.pop();
const ChipDeviceEvent event = mChipEventQueue.PopFront();
Impl()->DispatchEvent(&event);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#pragma once

#include <platform/DeviceSafeQueue.h>
#include <platform/internal/GenericPlatformManagerImpl.h>

#include <fcntl.h>
Expand Down Expand Up @@ -61,7 +62,6 @@ class GenericPlatformManagerImpl_POSIX : public GenericPlatformManagerImpl<ImplC

// OS-specific members (pthread)
pthread_mutex_t mChipStackLock;
std::queue<ChipDeviceEvent> mChipEventQueue;

enum TaskType
{
Expand Down Expand Up @@ -121,6 +121,7 @@ class GenericPlatformManagerImpl_POSIX : public GenericPlatformManagerImpl<ImplC

void ProcessDeviceEvents();

DeviceSafeQueue mChipEventQueue;
std::atomic<bool> mShouldRunEventLoop;
static void * EventLoopTaskMain(void * arg);
};
Expand Down
4 changes: 4 additions & 0 deletions src/platform/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ if (chip_device_platform != "none" && chip_device_platform != "external") {
"Darwin/PosixConfig.cpp",
"Darwin/PosixConfig.h",
"Darwin/SystemPlatformConfig.h",
"DeviceSafeQueue.cpp",
"DeviceSafeQueue.h",
]

if (chip_enable_ble) {
Expand Down Expand Up @@ -487,6 +489,8 @@ if (chip_device_platform != "none" && chip_device_platform != "external") {
public_deps += [ "${chip_root}/src/crypto" ]
} else if (chip_device_platform == "linux") {
sources += [
"DeviceSafeQueue.cpp",
"DeviceSafeQueue.h",
"Linux/BLEManagerImpl.cpp",
"Linux/BLEManagerImpl.h",
"Linux/BlePlatformConfig.h",
Expand Down
55 changes: 55 additions & 0 deletions src/platform/DeviceSafeQueue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file
* This file defines the CHIP device event queue which operates in a FIFO context (first-in first-out),
* and provides a specific set of member functions to access its elements wth thread safety.
*/

#include <platform/DeviceSafeQueue.h>

namespace chip {
namespace DeviceLayer {
namespace Internal {

void DeviceSafeQueue::Push(const ChipDeviceEvent & event)
{
std::unique_lock<std::mutex> lock(mEventQueueLock);
mEventQueue.push(event);
}

bool DeviceSafeQueue::Empty()
{
std::unique_lock<std::mutex> lock(mEventQueueLock);
return mEventQueue.empty();
}

const ChipDeviceEvent DeviceSafeQueue::PopFront()
{
std::unique_lock<std::mutex> lock(mEventQueueLock);

const ChipDeviceEvent event = mEventQueue.front();
mEventQueue.pop();

return event;
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
67 changes: 67 additions & 0 deletions src/platform/DeviceSafeQueue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file
* This file declares the CHIP device event queue which operates in a FIFO context (first-in first-out),
* and provides a specific set of member functions to access its elements wth thread safety.
*/

#pragma once

#include <mutex>
#include <queue>

#include <core/CHIPCore.h>
#include <platform/CHIPDeviceConfig.h>
#include <platform/CHIPDeviceEvent.h>

namespace chip {
namespace DeviceLayer {
namespace Internal {

/**
* @class DeviceSafeQueue
*
* @brief
* This class represents a thread-safe message queue implemented with C++ Standard Library, the message queue
* is used by the CHIP event loop to hold incoming messages. Each message is sequentially dequeued, decoded,
* and then an action is performed.
*
*/
class DeviceSafeQueue
{
public:
DeviceSafeQueue() = default;
~DeviceSafeQueue() = default;

void Push(const ChipDeviceEvent & event);
bool Empty();
const ChipDeviceEvent PopFront();

private:
std::queue<ChipDeviceEvent> mEventQueue;
std::mutex mEventQueueLock;

DeviceSafeQueue(const DeviceSafeQueue &) = delete;
DeviceSafeQueue & operator=(const DeviceSafeQueue &) = delete;
};

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
2 changes: 0 additions & 2 deletions src/platform/Linux/PlatformManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ void PlatformManagerImpl::WiFIIPChangeListener()
ChipLogDetail(DeviceLayer, "Got IP address on interface: %s IP: %s", name,
event.InternetConnectivityChange.address);

PlatformMgr().LockChipStack();
PlatformMgr().PostEvent(&event);
PlatformMgr().UnlockChipStack();
}
routeInfo = RTA_NEXT(routeInfo, rtl);
}
Expand Down

0 comments on commit 0322eb1

Please sign in to comment.