4 #include "GroupTransform.h"
13 bool Monitor::IsExternalizable()
15 return false; // monitors aren't really part of the transform
18 void BlockMonitor::AttributeChanged(CFStringRef name
, CFTypeRef value
)
20 // deliver the attribute to the queue
21 CFTypeRef realValue
= value
;
22 CFErrorRef error
= NULL
;
27 // A NULL and CFErrorRef might both be enqueued already, and the 2nd can race the teardown. Without this check we would trigger final processing
28 // more then once resulting in our own overlease issues, and could well cause our client to make similar errors.
32 if (realValue
!= NULL
)
34 // do some basic checking
35 if (CFGetTypeID(value
) == CFErrorGetTypeID())
38 error
= (CFErrorRef
) value
;
54 if (mDispatchQueue
== NULL
)
56 mBlock(realValue
, error
, isFinal
);
60 // ^{ mBlock } gets referenced via this (no retain), localBlock gets owned by
61 // the block passed to dispatch_async
62 SecMessageBlock localBlock
= mBlock
;
63 dispatch_async(mDispatchQueue
, ^{
64 localBlock(realValue
, error
, isFinal
);
71 BlockMonitor::BlockMonitor(dispatch_queue_t queue
, SecMessageBlock block
) : Monitor(CFSTR("BlockMonitor")), mDispatchQueue(queue
), mSeenFinal(FALSE
)
73 mBlock
= ^(CFTypeRef value
, CFErrorRef error
, Boolean isFinal
) {
74 block(value
, error
, isFinal
);
79 if (isFinal
&& mGroup
) {
83 mBlock
= Block_copy(mBlock
);
86 BlockMonitor::~BlockMonitor()
88 Block_release(mBlock
);
91 void BlockMonitor::LastValueSent()
93 // The initial execute did a retain on our parent to keep it from
94 // going out of scope. Since this chain is now done, release it.
95 // NOTE: this needs to be the last thing we do otherwise *this
96 // can be deleted out from under us, leading to a crash most frequently
97 // inside the block we dispatch_async, sometimes inside of mBlock.
98 Transform
*rootGroup
= this->GetRootGroup();
99 CFTypeRef rootGroupRef
= rootGroup
->GetCFObject();
100 dispatch_async(rootGroup
->mDispatchQueue
, ^{
101 CFRelease(rootGroupRef
);
105 CFTypeRef
BlockMonitor::Make(dispatch_queue_t queue
, SecMessageBlock block
)
107 return CoreFoundationHolder::MakeHolder(gInternalCFObjectName
, new BlockMonitor(queue
, block
));