Skip to content

Commit 3431393

Browse files
yyzhong-grestyled-commitsbzbarsky-apple
authored andcommitted
Remove Interaction Model Engine dependency in WriteHandler (#33426)
* Remove Interaction Model Engine dependency in WriteHandler * Add test * Add reference * Restyled by whitespace * Restyled by clang-format * Update src/app/WriteHandler.h Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * Update src/app/WriteHandler.h Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * Update src/app/WriteHandler.h Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> --------- Co-authored-by: Restyled.io <commits@restyled.io> Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
1 parent 4c51773 commit 3431393

8 files changed

+69
-16
lines changed

src/app/InteractionModelDelegatePointers.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ app::TimedHandlerDelegate * GlobalInstanceProvider<app::TimedHandlerDelegate>::I
3131
return app::InteractionModelEngine::GetInstance();
3232
}
3333

34+
template <>
35+
app::WriteHandlerDelegate * GlobalInstanceProvider<app::WriteHandlerDelegate>::InstancePointer()
36+
{
37+
return app::InteractionModelEngine::GetInstance();
38+
}
39+
3440
} // namespace chip
3541

3642
#endif

src/app/InteractionModelEngine.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnWriteRequest(Messa
869869
{
870870
if (writeHandler.IsFree())
871871
{
872-
VerifyOrReturnError(writeHandler.Init() == CHIP_NO_ERROR, Status::Busy);
872+
VerifyOrReturnError(writeHandler.Init(this) == CHIP_NO_ERROR, Status::Busy);
873873
return writeHandler.OnWriteRequest(apExchangeContext, std::move(aPayload), aIsTimedWrite);
874874
}
875875
}

src/app/InteractionModelEngine.h

+5-7
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
9191
public ReadHandler::ManagementCallback,
9292
public FabricTable::Delegate,
9393
public SubscriptionsInfoProvider,
94-
public TimedHandlerDelegate
94+
public TimedHandlerDelegate,
95+
public WriteHandlerDelegate
9596
{
9697
public:
9798
/**
@@ -235,6 +236,9 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
235236
void OnTimedWrite(TimedHandler * apTimedHandler, Messaging::ExchangeContext * apExchangeContext,
236237
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload) override;
237238

239+
// WriteHandlerDelegate implementation
240+
bool HasConflictWriteRequests(const WriteHandler * apWriteHandler, const ConcreteAttributePath & apath) override;
241+
238242
#if CHIP_CONFIG_ENABLE_READ_CLIENT
239243
/**
240244
* Activate the idle subscriptions.
@@ -279,12 +283,6 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
279283
*/
280284
size_t GetNumDirtySubscriptions() const;
281285

282-
/**
283-
* Returns whether the write operation to the given path is conflict with another write operations. (i.e. another write
284-
* transaction is in the middle of processing the chunked value of the given path.)
285-
*/
286-
bool HasConflictWriteRequests(const WriteHandler * apWriteHandler, const ConcreteAttributePath & aPath);
287-
288286
/**
289287
* Select the oldest (and the one that exceeds the per subscription resource minimum if there are any) read handler on the
290288
* fabric with the given fabric index. Evict it when the fabric uses more resources than the per fabric quota or aForceEvict is

src/app/WriteHandler.cpp

+11-5
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ using namespace Protocols::InteractionModel;
3636
using Status = Protocols::InteractionModel::Status;
3737
constexpr uint8_t kListAttributeType = 0x48;
3838

39-
CHIP_ERROR WriteHandler::Init()
39+
CHIP_ERROR WriteHandler::Init(WriteHandlerDelegate * apWriteHandlerDelegate)
4040
{
4141
VerifyOrReturnError(!mExchangeCtx, CHIP_ERROR_INCORRECT_STATE);
42+
VerifyOrReturnError(apWriteHandlerDelegate, CHIP_ERROR_INVALID_ARGUMENT);
4243

44+
mDelegate = apWriteHandlerDelegate;
4345
MoveToState(State::Initialized);
4446

4547
mACLCheckCache.ClearValue();
@@ -241,7 +243,8 @@ CHIP_ERROR WriteHandler::DeliverFinalListWriteEndForGroupWrite(bool writeWasSucc
241243

242244
processingConcreteAttributePath.mEndpointId = mapping.endpoint_id;
243245

244-
if (!InteractionModelEngine::GetInstance()->HasConflictWriteRequests(this, processingConcreteAttributePath))
246+
VerifyOrReturnError(mDelegate, CHIP_ERROR_INCORRECT_STATE);
247+
if (!mDelegate->HasConflictWriteRequests(this, processingConcreteAttributePath))
245248
{
246249
DeliverListWriteEnd(processingConcreteAttributePath, writeWasSuccessful);
247250
}
@@ -306,7 +309,8 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataIBs(TLV::TLVReader & aAttributeData
306309
dataAttributePath.mListOp = ConcreteDataAttributePath::ListOperation::ReplaceAll;
307310
}
308311

309-
if (InteractionModelEngine::GetInstance()->HasConflictWriteRequests(this, dataAttributePath) ||
312+
VerifyOrExit(mDelegate, err = CHIP_ERROR_INCORRECT_STATE);
313+
if (mDelegate->HasConflictWriteRequests(this, dataAttributePath) ||
310314
// Per chunking protocol, we are processing the list entries, but the initial empty list is not processed, so we reject
311315
// it with Busy status code.
312316
(dataAttributePath.IsListItemOperation() && !IsSameAttribute(mProcessingAttributePath, dataAttributePath)))
@@ -458,13 +462,15 @@ CHIP_ERROR WriteHandler::ProcessGroupAttributeDataIBs(TLV::TLVReader & aAttribut
458462
{
459463
auto processingConcreteAttributePath = mProcessingAttributePath.Value();
460464
processingConcreteAttributePath.mEndpointId = mapping.endpoint_id;
461-
if (!InteractionModelEngine::GetInstance()->HasConflictWriteRequests(this, processingConcreteAttributePath))
465+
VerifyOrExit(mDelegate, err = CHIP_ERROR_INCORRECT_STATE);
466+
if (mDelegate->HasConflictWriteRequests(this, processingConcreteAttributePath))
462467
{
463468
DeliverListWriteEnd(processingConcreteAttributePath, true /* writeWasSuccessful */);
464469
}
465470
}
466471

467-
if (InteractionModelEngine::GetInstance()->HasConflictWriteRequests(this, dataAttributePath))
472+
VerifyOrExit(mDelegate, err = CHIP_ERROR_INCORRECT_STATE);
473+
if (mDelegate->HasConflictWriteRequests(this, dataAttributePath))
468474
{
469475
ChipLogDetail(DataManagement,
470476
"Writing attribute endpoint=%u Cluster=" ChipLogFormatMEI " attribute=" ChipLogFormatMEI

src/app/WriteHandler.h

+27-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#pragma once
2020
#include <app/AttributeAccessToken.h>
2121
#include <app/AttributePathParams.h>
22+
#include <app/InteractionModelDelegatePointers.h>
2223
#include <app/MessageDef/WriteResponseMessage.h>
2324
#include <lib/core/CHIPCore.h>
2425
#include <lib/core/TLVDebug.h>
@@ -35,6 +36,21 @@
3536

3637
namespace chip {
3738
namespace app {
39+
40+
class WriteHandler;
41+
42+
class WriteHandlerDelegate
43+
{
44+
public:
45+
virtual ~WriteHandlerDelegate() = default;
46+
47+
/**
48+
* Returns whether the write operation to the given path is in conflict with another write operation.
49+
* (i.e. another write transaction is in the middle of processing a chunked write to the given path.)
50+
*/
51+
virtual bool HasConflictWriteRequests(const WriteHandler * apWriteHandler, const ConcreteAttributePath & aPath) = 0;
52+
};
53+
3854
/**
3955
* @brief The write handler is responsible for processing a write request and sending a write reply.
4056
*/
@@ -49,11 +65,13 @@ class WriteHandler : public Messaging::ExchangeDelegate
4965
* construction until a call to Close is made to terminate the
5066
* instance.
5167
*
68+
* @param[in] apWriteHandlerDelegate A Valid pointer to the WriteHandlerDelegate.
69+
*
5270
* @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to
5371
* kState_NotInitialized.
5472
* @retval #CHIP_NO_ERROR On success.
5573
*/
56-
CHIP_ERROR Init();
74+
CHIP_ERROR Init(WriteHandlerDelegate * apWriteHandlerDelegate);
5775

5876
/**
5977
* Process a write request. Parts of the processing may end up being asynchronous, but the WriteHandler
@@ -175,6 +193,14 @@ class WriteHandler : public Messaging::ExchangeDelegate
175193
// Where (1)-(3) will be consistent among the whole list write request, while (4) and (5) are not appliable to group writes.
176194
bool mAttributeWriteSuccessful = false;
177195
Optional<AttributeAccessToken> mACLCheckCache = NullOptional;
196+
197+
// This may be a "fake" pointer or a real delegate pointer, depending
198+
// on CHIP_CONFIG_STATIC_GLOBAL_INTERACTION_MODEL_ENGINE setting.
199+
//
200+
// When this is not a real pointer, it checks that the value is always
201+
// set to the global InteractionModelEngine and the size of this
202+
// member is 1 byte.
203+
InteractionModelDelegatePointer<WriteHandlerDelegate> mDelegate;
178204
};
179205
} // namespace app
180206
} // namespace chip

src/app/tests/TestWriteInteraction.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ void TestWriteInteraction::TestWriteHandler(nlTestSuite * apSuite, void * apCont
338338
app::WriteHandler writeHandler;
339339

340340
System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
341-
err = writeHandler.Init();
341+
err = writeHandler.Init(chip::app::InteractionModelEngine::GetInstance());
342342

343343
GenerateWriteRequest(apSuite, apContext, messageIsTimed, buf);
344344

src/lib/support/static_support_smart_ptr.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ template <class T>
5454
class CheckedGlobalInstanceReference
5555
{
5656
public:
57+
CheckedGlobalInstanceReference<T>() = default;
5758
CheckedGlobalInstanceReference(T * e) { VerifyOrDie(e == GlobalInstanceProvider<T>::InstancePointer()); }
5859
CheckedGlobalInstanceReference & operator=(T * value)
5960
{
@@ -63,6 +64,7 @@ class CheckedGlobalInstanceReference
6364

6465
inline T * operator->() { return GlobalInstanceProvider<T>::InstancePointer(); }
6566
inline const T * operator->() const { return GlobalInstanceProvider<T>::InstancePointer(); }
67+
inline operator bool() const { return true; }
6668
};
6769

6870
/// A class that acts as a wrapper to a pointer and provides
@@ -87,6 +89,7 @@ template <class T>
8789
class SimpleInstanceReference
8890
{
8991
public:
92+
SimpleInstanceReference<T>() = default;
9093
SimpleInstanceReference(T * e) : mValue(e) {}
9194
SimpleInstanceReference & operator=(T * value)
9295
{
@@ -96,9 +99,10 @@ class SimpleInstanceReference
9699

97100
T * operator->() { return mValue; }
98101
const T * operator->() const { return mValue; }
102+
inline operator bool() const { return mValue != nullptr; }
99103

100104
private:
101-
T * mValue;
105+
T * mValue = nullptr;
102106
};
103107

104108
} // namespace chip

src/lib/support/tests/TestStaticSupportSmartPtr.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ TEST(TestStaticSupportSmartPtr, TestCheckedGlobalInstanceReference)
5656
// We expect that sizes of global references is minimal
5757
EXPECT_EQ(sizeof(ref), 1u);
5858

59+
ASSERT_TRUE(ref);
5960
EXPECT_EQ(ref->num, 123);
6061
EXPECT_STREQ(ref->str, "abc");
6162

@@ -69,6 +70,7 @@ TEST(TestStaticSupportSmartPtr, TestCheckedGlobalInstanceReference)
6970

7071
CheckedGlobalInstanceReference<TestClass> ref2(&gTestClass);
7172

73+
ASSERT_TRUE(ref2);
7274
EXPECT_EQ(ref->num, ref2->num);
7375
EXPECT_STREQ(ref->str, ref2->str);
7476

@@ -82,6 +84,10 @@ TEST(TestStaticSupportSmartPtr, TestCheckedGlobalInstanceReference)
8284
EXPECT_EQ(ref2->num, 321);
8385
EXPECT_STREQ(ref2->str, "test");
8486
}
87+
88+
// Check default constructed CheckedGlobalInstanceReference
89+
CheckedGlobalInstanceReference<TestClass> ref_default;
90+
ASSERT_TRUE(ref_default);
8591
}
8692

8793
TEST(TestStaticSupportSmartPtr, TestSimpleInstanceReference)
@@ -95,6 +101,9 @@ TEST(TestStaticSupportSmartPtr, TestSimpleInstanceReference)
95101
// overhead of simple references should be a simple pointer
96102
EXPECT_LE(sizeof(ref_a), sizeof(void *));
97103

104+
ASSERT_TRUE(ref_a);
105+
ASSERT_TRUE(ref_b);
106+
98107
EXPECT_EQ(ref_a->num, 123);
99108
EXPECT_EQ(ref_b->num, 100);
100109

@@ -103,6 +112,10 @@ TEST(TestStaticSupportSmartPtr, TestSimpleInstanceReference)
103112

104113
EXPECT_EQ(a.num, 99);
105114
EXPECT_EQ(ref_b->num, 30);
115+
116+
// Check default constructed SimpleInstanceReference
117+
SimpleInstanceReference<TestClass> ref_default;
118+
ASSERT_FALSE(ref_default);
106119
}
107120

108121
} // namespace

0 commit comments

Comments
 (0)