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
;
49 CFRetainSafe(realValue
);
51 if (mDispatchQueue
== NULL
)
53 mBlock(realValue
, error
, isFinal
);
57 // ^{ mBlock } gets referenced via this (no retain), localBlock gets owned by
58 // the block passed to dispatch_async
59 SecMessageBlock localBlock
= mBlock
;
60 dispatch_async(mDispatchQueue
, ^{
61 localBlock(realValue
, error
, isFinal
);
68 BlockMonitor::BlockMonitor(dispatch_queue_t queue
, SecMessageBlock block
) : Monitor(CFSTR("BlockMonitor")), mDispatchQueue(queue
), mSeenFinal(FALSE
)
70 mBlock
= ^(CFTypeRef value
, CFErrorRef error
, Boolean isFinal
) {
71 block(value
, error
, isFinal
);
76 if (isFinal
&& mGroup
) {
80 mBlock
= Block_copy(mBlock
);
83 BlockMonitor::~BlockMonitor()
85 Block_release(mBlock
);
88 void BlockMonitor::LastValueSent()
90 // The initial execute did a retain on our parent to keep it from
91 // going out of scope. Since this chain is now done, release it.
92 // NOTE: this needs to be the last thing we do otherwise *this
93 // can be deleted out from under us, leading to a crash most frequently
94 // inside the block we dispatch_async, sometimes inside of mBlock.
95 Transform
*rootGroup
= this->GetRootGroup();
96 CFTypeRef rootGroupRef
= rootGroup
->GetCFObject();
97 dispatch_async(rootGroup
->mDispatchQueue
, ^{
98 CFReleaseSafe(rootGroupRef
);
102 CFTypeRef
BlockMonitor::Make(dispatch_queue_t queue
, SecMessageBlock block
)
104 return CoreFoundationHolder::MakeHolder(gInternalCFObjectName
, new BlockMonitor(queue
, block
));